Contents in latest XEmacs 21.2 at 1999-06-24-19.
[chise/xemacs-chise.git.1] / src / window.c
index db9f884..90c1be3 100644 (file)
@@ -36,6 +36,8 @@ Boston, MA 02111-1307, USA.  */
 #include "glyphs.h"
 #include "redisplay.h"
 #include "window.h"
+#include "elhash.h"
+#include "commands.h"
 
 Lisp_Object Qwindowp, Qwindow_live_p, Qwindow_configurationp;
 Lisp_Object Qscroll_up, Qscroll_down, Qdisplay_buffer;
@@ -161,6 +163,8 @@ mark_window (Lisp_Object obj, void (*markobj) (Lisp_Object))
   MARK_DISP_VARIABLE (last_facechange);
   markobj (window->line_cache_last_updated);
   markobj (window->redisplay_end_trigger);
+  markobj (window->subwindow_instance_cache);
+
   mark_face_cachels (window->face_cachels, markobj);
   mark_glyph_cachels (window->glyph_cachels, markobj);
 
@@ -227,7 +231,7 @@ finalize_window (void *header, int for_disksave)
 
 DEFINE_LRECORD_IMPLEMENTATION ("window", window,
                                mark_window, print_window, finalize_window,
-                              0, 0, struct window);
+                              0, 0, 0, struct window);
 
 
 #define INIT_DISP_VARIABLE(field, initialization)      \
@@ -248,7 +252,7 @@ Lisp_Object
 allocate_window (void)
 {
   Lisp_Object val;
-  struct window *p = alloc_lcrecord_type (struct window, lrecord_window);
+  struct window *p = alloc_lcrecord_type (struct window, &lrecord_window);
 
   zero_lcrecord (p);
   XSETWINDOW (val, p);
@@ -273,6 +277,9 @@ allocate_window (void)
   p->face_cachels     = Dynarr_new (face_cachel);
   p->glyph_cachels    = Dynarr_new (glyph_cachel);
   p->line_start_cache = Dynarr_new (line_start_cache);
+  p->subwindow_instance_cache = make_lisp_hash_table (10,
+                                                     HASH_TABLE_KEY_WEAK,
+                                                     HASH_TABLE_EQ);
   p->line_cache_last_updated = Qzero;
   INIT_DISP_VARIABLE (last_point_x, 0);
   INIT_DISP_VARIABLE (last_point_y, 0);
@@ -1338,7 +1345,7 @@ is non-nil, do not include space occupied by clipped lines.
   if (NILP (window))
     window = Fselected_window (Qnil);
 
-  CHECK_WINDOW (window);
+  CHECK_LIVE_WINDOW (window);
   w = XWINDOW (window);
 
   start  = marker_position (w->start[CURRENT_DISP]);
@@ -3312,7 +3319,7 @@ make_dummy_parent (Lisp_Object window)
 {
   Lisp_Object new;
   struct window *o = XWINDOW (window);
-  struct window *p = alloc_lcrecord_type (struct window, lrecord_window);
+  struct window *p = alloc_lcrecord_type (struct window, &lrecord_window);
 
   XSETWINDOW (new, p);
   copy_lcrecord (p, o);
@@ -3359,7 +3366,7 @@ and put SIZE columns in the first of the pair.
   if (NILP (window))
     window = Fselected_window (Qnil);
   else
-    CHECK_WINDOW (window);
+    CHECK_LIVE_WINDOW (window);
 
   o = XWINDOW (window);
   f = XFRAME (WINDOW_FRAME (o));
@@ -4297,7 +4304,7 @@ If WINDOW is nil, the selected window is used.
   if (NILP (window))
     window = Fselected_window (Qnil);
   else
-    CHECK_WINDOW (window);
+    CHECK_LIVE_WINDOW (window);
   w = XWINDOW (window);
   b = XBUFFER (w->buffer);
 
@@ -4614,8 +4621,8 @@ struct saved_window
 struct window_config
 {
   struct lcrecord_header header;
-  int frame_width;
-  int frame_height;
+  /*  int frame_width; No longer needed, JV
+      int frame_height; */
 #if 0 /* FSFmacs */
   Lisp_Object selected_frame;
 #endif
@@ -4623,6 +4630,7 @@ struct window_config
   Lisp_Object current_buffer;
   Lisp_Object minibuffer_scroll_window;
   Lisp_Object root_window;
+  int minibuf_height; /* 0 = no minibuffer, <0, size in lines, >0 in pixels */
   /* Record the values of window-min-width and window-min-height
      so that window sizes remain consistent with them.  */
   int min_width, min_height;
@@ -4703,7 +4711,7 @@ DEFINE_LRECORD_SEQUENCE_IMPLEMENTATION ("window-configuration",
                                        window_configuration,
                                        mark_window_config,
                                        print_window_config,
-                                       0, 0, 0, sizeof_window_config,
+                                       0, 0, 0, 0, sizeof_window_config,
                                        struct window_config);
 
 
@@ -4754,9 +4762,10 @@ window_config_equal (Lisp_Object conf1, Lisp_Object conf2)
        EQ (fig1->current_window,           fig2->current_window) &&
        EQ (fig1->current_buffer,           fig2->current_buffer) &&
        EQ (fig1->root_window,              fig2->root_window) &&
-       EQ (fig1->minibuffer_scroll_window, fig2->minibuffer_scroll_window) &&
+       EQ (fig1->minibuffer_scroll_window, fig2->minibuffer_scroll_window)))
+       /* &&
        fig1->frame_width  == fig2->frame_width &&
-       fig1->frame_height == fig2->frame_height))
+       fig1->frame_height == fig2->frame_height)) */
     return 0;
 
   for (i = 0; i < fig1->saved_windows_count; i++)
@@ -4852,8 +4861,15 @@ by `current-window-configuration' (which see).
   struct frame *f;
   struct gcpro gcpro1;
   Lisp_Object old_window_config;
-  int previous_frame_height;
-  int previous_frame_width;
+  /*  int previous_frame_height;
+      int previous_frame_width;*/
+  int previous_pixel_top;
+  int previous_pixel_height;
+  int previous_pixel_left;
+  int previous_pixel_width;
+  int previous_minibuf_height, previous_minibuf_top,previous_minibuf_width;
+  int real_font_height;
+  int converted_minibuf_height,target_minibuf_height; 
   int specpdl_count = specpdl_depth ();
 
   GCPRO1 (configuration);
@@ -4918,6 +4934,20 @@ by `current-window-configuration' (which see).
 
       mark_windows_in_use (f, 1);
 
+#if 0
+      /* JV: This is bogus,
+        First of all, the units are inconsistent. The frame sizes are measured
+        in characters but the window sizes are stored in pixels. So if a 
+        font size change happened between saving and restoring, the
+        frame "sizes" maybe equal but the windows still should be
+        resized. This is tickled alot by the new "character size
+        stays constant" policy in 21.0. It leads to very wierd
+        glitches (and possibly craches when asserts are tickled).
+
+        Just changing the units doens't help because changing the
+        toolbar configuration can also change the pixel positions.
+        Luckily there is a much simpler way of doing this, see below.
+       */
       previous_frame_width = FRAME_WIDTH (f);
       previous_frame_height = FRAME_HEIGHT (f);
       /* If the frame has been resized since this window configuration was
@@ -4927,7 +4957,37 @@ by `current-window-configuration' (which see).
       if (config->frame_height != FRAME_HEIGHT (f)
          || config->frame_width != FRAME_WIDTH (f))
        change_frame_size (f, config->frame_height, config->frame_width, 0);
-
+#endif
+      
+      previous_pixel_top = XWINDOW (FRAME_ROOT_WINDOW (f))->pixel_top;
+      previous_pixel_height = XWINDOW (FRAME_ROOT_WINDOW (f))->pixel_height;
+      previous_pixel_left = XWINDOW (FRAME_ROOT_WINDOW (f))->pixel_left;
+      previous_pixel_width = XWINDOW (FRAME_ROOT_WINDOW (f))->pixel_width;
+
+      /* remember some properties of the minibuffer */
+
+      default_face_height_and_width (frame, &real_font_height, 0);
+      assert(real_font_height > 0);
+  
+      if (FRAME_HAS_MINIBUF_P (f) && ! FRAME_MINIBUF_ONLY_P (f))
+       {
+         previous_minibuf_height
+           = XWINDOW(FRAME_MINIBUF_WINDOW(f))->pixel_height;
+         previous_minibuf_top
+           = XWINDOW(FRAME_MINIBUF_WINDOW(f))->pixel_top;
+         previous_minibuf_width
+           = XWINDOW(FRAME_MINIBUF_WINDOW(f))->pixel_width;
+       }
+      else
+       {
+         previous_minibuf_height = 0;
+         previous_minibuf_width = 0;
+       }
+      converted_minibuf_height =
+       (previous_minibuf_height % real_font_height) == 0 ?
+       - (previous_minibuf_height / real_font_height ) :    /* lines */
+           previous_minibuf_height;   /* pixels */
+           
       /* Temporarily avoid any problems with windows that are smaller
         than they are supposed to be.  */
       window_min_height = 1;
@@ -5093,11 +5153,61 @@ by `current-window-configuration' (which see).
         currently selected, or just set the selected window of the
         window config's frame. */
 
+#if 0
       /* Set the frame height to the value it had before this function.  */
       if (previous_frame_height != FRAME_HEIGHT (f)
          || previous_frame_width != FRAME_WIDTH (f))
        change_frame_size (f, previous_frame_height, previous_frame_width, 0);
-
+#endif
+      /* We just reset the size and position of the minibuffer, to its old
+        value, which needn't be valid. So we do some magic to see which value
+        to actually take. Then we set it.
+
+        The magic:
+        We take the old value if is in the same units but differs from the
+        current value.
+
+         #### Now we get more cases correct then ever before, but
+        are we treating all? For instance what if the frames minibuf window
+        is no longer the same one? 
+      */
+      target_minibuf_height = previous_minibuf_height;
+      if (converted_minibuf_height &&
+         (converted_minibuf_height * config->minibuf_height) > 0 &&
+         (converted_minibuf_height !=  config->minibuf_height))
+       {
+         target_minibuf_height = config->minibuf_height < 0 ?
+           - (config->minibuf_height * real_font_height) :
+           config->minibuf_height;
+         target_minibuf_height =
+           max(target_minibuf_height,real_font_height);
+       }
+      if (previous_minibuf_height)
+       {
+         XWINDOW (FRAME_MINIBUF_WINDOW (f))->pixel_top
+           = previous_minibuf_top -
+                 (target_minibuf_height - previous_minibuf_height);
+         set_window_pixheight (FRAME_MINIBUF_WINDOW (f),
+                               target_minibuf_height, 0);
+         set_window_pixwidth  (FRAME_MINIBUF_WINDOW (f),
+                           previous_minibuf_width, 0);
+       }
+       
+      /* This is a better way to deal with frame resizing, etc.
+        What we _actually_ want is for the old (just restored)
+        root window to fit
+        into the place of the new one. So we just do that. Simple! */
+      XWINDOW (FRAME_ROOT_WINDOW (f))->pixel_top = previous_pixel_top;
+      /* Note that this function also updates the subwindow
+        "pixel_top"s */
+      set_window_pixheight (FRAME_ROOT_WINDOW (f),
+         previous_pixel_height -
+                 (target_minibuf_height - previous_minibuf_height), 0);
+      XWINDOW (FRAME_ROOT_WINDOW (f))->pixel_left = previous_pixel_left;
+      /* Note that this function also updates the subwindow
+        "pixel_left"s */
+      set_window_pixwidth (FRAME_ROOT_WINDOW (f), previous_pixel_width, 0);
+      
       /* If restoring in the current frame make the window current,
         otherwise just update the frame selected_window slot to be
         the restored current_window. */
@@ -5312,6 +5422,8 @@ its value is -not- saved.
   struct frame *f = decode_frame (frame);
   struct window_config *config;
   int n_windows = count_windows (XWINDOW (FRAME_ROOT_WINDOW (f)));
+  int minibuf_height;
+  int real_font_height;
 
   if (n_windows <= countof (Vwindow_configuration_free_list))
     config = XWINDOW_CONFIGURATION (allocate_managed_lcrecord
@@ -5321,11 +5433,11 @@ its value is -not- saved.
     /* More than ten windows; just allocate directly */
     config = (struct window_config *)
       alloc_lcrecord (sizeof_window_config_for_n_windows (n_windows),
-                     lrecord_window_configuration);
+                     &lrecord_window_configuration);
   XSETWINDOW_CONFIGURATION (result, config);
-
+  /*
   config->frame_width = FRAME_WIDTH (f);
-  config->frame_height = FRAME_HEIGHT (f);
+  config->frame_height = FRAME_HEIGHT (f); */
   config->current_window = FRAME_SELECTED_WINDOW (f);
   XSETBUFFER (config->current_buffer, current_buffer);
   config->minibuffer_scroll_window = Vminibuffer_scroll_window;
@@ -5334,6 +5446,22 @@ its value is -not- saved.
   config->min_width = window_min_width;
   config->saved_windows_count = n_windows;
   save_window_save (FRAME_ROOT_WINDOW (f), config, 0);
+
+  /* save the minibuffer height using the heuristics from
+     change_frame_size_1 */
+  
+  XSETFRAME (frame, f); /* frame could have been nil ! */
+  default_face_height_and_width (frame, &real_font_height, 0);
+  assert(real_font_height > 0);
+  
+  if (FRAME_HAS_MINIBUF_P (f) && ! FRAME_MINIBUF_ONLY_P (f))
+    minibuf_height = XWINDOW(FRAME_MINIBUF_WINDOW(f))->pixel_height;
+  else
+    minibuf_height = 0;
+  config->minibuf_height = (minibuf_height % real_font_height) == 0 ?
+    - (minibuf_height / real_font_height ) :    /* lines */
+    minibuf_height;   /* pixels */
+
   return result;
 }
 
@@ -5570,7 +5698,7 @@ If non-nil, this is a buffer and \\[scroll-other-window] should scroll its windo
       {
        Vwindow_configuration_free_list[i] =
          make_lcrecord_list (sizeof_window_config_for_n_windows (i + 1),
-                             lrecord_window_configuration);
+                             &lrecord_window_configuration);
        staticpro (&Vwindow_configuration_free_list[i]);
       }
   }