(g2-UU+5B73): Add `=decomposition@hanyo-denshi'.
[chise/xemacs-chise.git.1] / src / window.c
index cfa89b4..94be607 100644 (file)
@@ -50,6 +50,8 @@ Lisp_Object Qscrollbar_instances;
 #endif
 #endif
 
+extern int allow_deletion_of_last_visible_frame;
+
 EXFUN (Fnext_window, 4);
 
 static int window_pixel_width_to_char_width (struct window *w,
@@ -64,8 +66,8 @@ static int window_pixel_height_to_char_height (struct window *w,
 static int window_char_height_to_pixel_height (struct window *w,
                                               int char_height,
                                               int include_gutters_p);
-static void change_window_height (struct window *w, int delta, int widthflag,
-                                  int inpixels);
+static void change_window_height (Lisp_Object window, int delta,
+                                 Lisp_Object horizontalp, int inpixels);
 
 /* Thickness of shadow border around 3d modelines. */
 Lisp_Object Vmodeline_shadow_thickness;
@@ -111,18 +113,20 @@ Lisp_Object Vtemp_buffer_show_function;
 Lisp_Object Vtemp_buffer_show_hook;
 
 /* If a window gets smaller than either of these, it is removed. */
-int window_min_height;
-int window_min_width;
+Fixnum window_min_height;
+Fixnum window_min_width;
 
 /* Hook run at end of temp_output_buffer_show.  */
 Lisp_Object Qtemp_buffer_show_hook;
 
 /* Number of lines of continuity in scrolling by screenfuls.  */
-int next_screen_context_lines;
+Fixnum next_screen_context_lines;
 
 /* List of freed window configurations with 1 - 10 windows. */
 static Lisp_Object Vwindow_configuration_free_list[10];
 
+Lisp_Object Qtruncate_partial_width_windows;
+
 #define SET_LAST_MODIFIED(w, cache_too)                \
 do {                                           \
   (w)->last_modified[CURRENT_DISP] = Qzero;    \
@@ -281,9 +285,8 @@ 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 (30,
-                                                     HASH_TABLE_KEY_VALUE_WEAK,
-                                                     HASH_TABLE_EQ);
+  p->subwindow_instance_cache = make_image_instance_cache_hash_table ();
+
   p->line_cache_last_updated = Qzero;
   INIT_DISP_VARIABLE (last_point_x, 0);
   INIT_DISP_VARIABLE (last_point_y, 0);
@@ -489,7 +492,7 @@ real_window (struct window_mirror *mir, int no_abort)
   Lisp_Object retval = real_window_internal (mir->frame->root_window,
                                             mir->frame->root_mirror, mir);
   if (NILP (retval) && !no_abort)
-    abort ();
+    ABORT ();
 
   return retval;
 }
@@ -551,7 +554,7 @@ window_display_lines (struct window *w, int which)
     update_frame_window_mirror (XFRAME (w->frame));
   t = find_window_mirror (w);
   if (!t)
-    abort ();
+    ABORT ();
 
   if (which == CURRENT_DISP)
     return t->current_display_lines;
@@ -561,7 +564,7 @@ window_display_lines (struct window *w, int which)
     /* The CMOTION_DISP display lines are global. */
     return cmotion_display_lines;
   else
-    abort ();
+    ABORT ();
 
   return 0;    /* shut up compiler */
 }
@@ -575,7 +578,7 @@ window_display_buffer (struct window *w)
     update_frame_window_mirror (XFRAME (w->frame));
   t = find_window_mirror (w);
   if (!t)
-    abort ();
+    ABORT ();
 
   return t->buffer;
 }
@@ -589,7 +592,7 @@ set_window_display_buffer (struct window *w, struct buffer *b)
     update_frame_window_mirror (XFRAME (w->frame));
   t = find_window_mirror (w);
   if (!t)
-    abort ();
+    ABORT ();
 
   t->buffer = b;
 }
@@ -725,7 +728,8 @@ window_truncation_on (struct window *w)
 
   /* If truncate_partial_width_windows is true and the window is not
      the full width of the frame it is truncated. */
-  if (truncate_partial_width_windows
+  if (!NILP (symbol_value_in_buffer (Qtruncate_partial_width_windows,
+                                    w->buffer))
       && !(window_is_leftmost (w) && window_is_rightmost (w)))
     return 1;
 
@@ -919,7 +923,7 @@ window_modeline_height (struct window *w)
                modeline_height = (Dynarr_atp (dla, 0)->ascent +
                                   Dynarr_atp (dla, 0)->descent);
              else
-               /* This should be an abort except I'm not yet 100%
+               /* This should be an ABORT except I'm not yet 100%
                    confident that it won't ever get hit (though I
                    haven't been able to trigger it).  It is extremely
                    unlikely to cause any noticeable problem and even if
@@ -1112,19 +1116,20 @@ window_pixel_height (struct window* w)
 
 \f
 DEFUN ("windowp", Fwindowp, 1, 1, 0, /*
-Return t if OBJ is a window.
+Return t if OBJECT is a window.
 */
-       (obj))
+       (object))
 {
-  return WINDOWP (obj) ? Qt : Qnil;
+  return WINDOWP (object) ? Qt : Qnil;
 }
 
 DEFUN ("window-live-p", Fwindow_live_p, 1, 1, 0, /*
-Return t if OBJ is a window which is currently visible.
+Return t if OBJECT is a window which is currently visible.
 */
-       (obj))
+       (object))
 {
-  return WINDOWP (obj) && WINDOW_LIVE_P (XWINDOW (obj)) ? Qt : Qnil;
+  return WINDOWP (object) && WINDOW_LIVE_P (XWINDOW (object))
+    ? Qt : Qnil;
 }
 
 DEFUN ("selected-window", Fselected_window, 0, 1, 0, /*
@@ -1597,8 +1602,10 @@ Afterwards the end-trigger value is reset to nil.
 
 DEFUN ("window-pixel-edges", Fwindow_pixel_edges, 0, 1, 0, /*
 Return a list of the pixel edge coordinates of WINDOW.
-\(LEFT TOP RIGHT BOTTOM), all relative to 0, 0 at top left corner of frame.
-The frame toolbars, menubars and gutters are considered to be outside of this area.
+The returned list is of the form (LEFT TOP RIGHT BOTTOM),
+all relative to 0, 0 at the top left corner of WINDOW's frame.
+The frame toolbars, menubars and gutters are considered to be outside
+of this area, while the scrollbars are considered to be inside.
 */
        (window))
 {
@@ -1619,8 +1626,9 @@ The frame toolbars, menubars and gutters are considered to be outside of this ar
 DEFUN ("window-text-area-pixel-edges",
        Fwindow_text_area_pixel_edges, 0, 1, 0, /*
 Return a list of the pixel edge coordinates of the text area of WINDOW.
-Returns the list \(LEFT TOP RIGHT BOTTOM), all relative to 0, 0 at the
-top left corner of the window.
+The returned list is of the form (LEFT TOP RIGHT BOTTOM),
+all relative to 0, 0 at the top left corner of the total area allocated
+to the window, which includes the scrollbars.
 */
        (window))
 {
@@ -1646,7 +1654,7 @@ Note that, when WINDOW is the selected window and its buffer
 is also currently selected, the value returned is the same as (point).
 It would be more strictly correct to return the `top-level' value
 of point, outside of any save-excursion forms.
-But that is hard to define.
+But that value is hard to find.
 */
        (window))
 {
@@ -1672,12 +1680,13 @@ This is updated by redisplay or by calling `set-window-start'.
 DEFUN ("window-end", Fwindow_end, 0, 2, 0, /*
 Return position at which display currently ends in WINDOW.
 This is updated by redisplay, when it runs to completion.
-Simply changing the buffer text or setting `window-start'
-does not update this value.
-If GUARANTEE is non-nil, then the return value is guaranteed to be
-the value of window-end at the end of the next full redisplay assuming
-nothing else changes in the meantime.  This function is potentially much
-slower with this flag set.
+Simply changing the buffer text or setting `window-start' does not
+update this value.  WINDOW defaults to the selected window.
+
+If optional arg GUARANTEE is non-nil, the return value is guaranteed
+to be the same value as this function would return at the end of the
+next full redisplay assuming nothing else changes in the meantime.
+This function is potentially much slower with this flag set.
 */
        (window, guarantee))
 {
@@ -1800,7 +1809,7 @@ unshow_buffer (struct window *w)
   Lisp_Object buf = w->buffer;
 
   if (XBUFFER (buf) != XMARKER (w->pointm[CURRENT_DISP])->buffer)
-    abort ();
+    ABORT ();
 
   /* FSF disables this check, so I'll do it too.  I hope it won't
      break things.  --ben */
@@ -1930,7 +1939,7 @@ mark_window_as_deleted (struct window *w)
 
 DEFUN ("delete-window", Fdelete_window, 0, 2, "", /*
 Remove WINDOW from the display.  Default is selected window.
-If window is the only one on the frame, the frame is destroyed.
+If window is the only one on its frame, the frame is deleted as well.
 Normally, you cannot delete the last non-minibuffer-only frame (you must
 use `save-buffers-kill-emacs' or `kill-emacs').  However, if optional
 second argument FORCE is non-nil, you can delete the last frame. (This
@@ -2102,9 +2111,13 @@ will automatically call `save-buffers-kill-emacs'.)
   else if (!NILP (w->vchild))
     delete_all_subwindows (XWINDOW (w->vchild));
 
+  /* Warning: mark_window_as_deleted calls window_unmap_subwindows and
+     therefore redisplay, so it requires the mirror structure to be
+     correct.  We must dirty the mirror before it is called.  */
+  f->mirror_dirty = 1;
+
   mark_window_as_deleted (w);
 
-  f->mirror_dirty = 1;
   return Qnil;
 }
 
@@ -2124,27 +2137,30 @@ too.  Therefore, `next-window' can be used to iterate through the
 set of windows even when the minibuffer is on another frame.  If the
 minibuffer does not count, only windows from WINDOW's frame count.
 
-Optional third arg ALL-FRAMES t means include windows on all frames.
-ALL-FRAMES nil or omitted means cycle within the frames as specified
-above.  ALL-FRAMES = `visible' means include windows on all visible frames.
-ALL-FRAMES = 0 means include windows on all visible and iconified frames.
-If ALL-FRAMES is a frame, restrict search to windows on that frame.
-Anything else means restrict to WINDOW's frame.
-
-Optional fourth arg CONSOLE controls which consoles or devices the
-returned window may be on.  If CONSOLE is a console, return windows only
-on that console.  If CONSOLE is a device, return windows only on that
-device.  If CONSOLE is a console type, return windows only on consoles
-of that type.  If CONSOLE is 'window-system, return any windows on any
-window-system consoles.  If CONSOLE is nil or omitted, return windows only
-on WINDOW's console.  Otherwise, all windows are considered.
-
-If you use consistent values for MINIBUF, ALL-FRAMES, and CONSOLE, you
-can use `next-window' to iterate through the entire cycle of acceptable
-windows, eventually ending up back at the window you started with.
+By default, only the windows in the selected frame are considered.
+The optional argument WHICH-FRAMES changes this behavior:
+WHICH-FRAMES = `visible' means search windows on all visible frames.
+WHICH-FRAMES = 0 means search windows on all visible and iconified frames.
+WHICH-FRAMES = t means search windows on all frames including invisible frames.
+WHICH-FRAMES = a frame means search only windows on that frame.
+Anything else means restrict to the selected frame.
+
+The optional fourth argument WHICH-DEVICES further clarifies on which
+devices to search for frames as specified by WHICH-FRAMES.  This value
+is only meaningful if WHICH-FRAMES is non-nil.
+If nil or omitted, search all devices on the selected console.
+If a device, only search that device.
+If a console, search all devices on that console.
+If a device type, search all devices of that type.
+If `window-system', search all window-system devices.
+Any other non-nil value means search all devices.
+
+If you use consistent values for MINIBUF, WHICH-FRAMES, and WHICH-DEVICES,
+you can use `next-window' to iterate through the entire cycle of
+acceptable windows, eventually ending up back at the window you started with.
 `previous-window' traverses the same cycle, in the reverse order.
 */
-     (window, minibuf, all_frames, console))
+     (window, minibuf, which_frames, which_devices))
 {
   Lisp_Object tem;
   Lisp_Object start_window;
@@ -2167,25 +2183,25 @@ windows, eventually ending up back at the window you started with.
      lambda => count none of them
      or a specific minibuffer window (the active one) to count.  */
 
-  /* all_frames == nil doesn't specify which frames to include.  */
-  if (NILP (all_frames))
-    all_frames = (! EQ (minibuf, Qlambda)
+  /* which_frames == nil doesn't specify which frames to include.  */
+  if (NILP (which_frames))
+    which_frames = (! EQ (minibuf, Qlambda)
                  ? (FRAME_MINIBUF_WINDOW
                     (XFRAME
                      (WINDOW_FRAME
                       (XWINDOW (window)))))
                  : Qnil);
-  else if (EQ (all_frames, Qvisible))
+  else if (EQ (which_frames, Qvisible))
     ;
-  else if (ZEROP (all_frames))
+  else if (ZEROP (which_frames))
     ;
-  else if (FRAMEP (all_frames) && ! EQ (all_frames, Fwindow_frame (window)))
-    /* If all_frames is a frame and window arg isn't on that frame, just
+  else if (FRAMEP (which_frames) && ! EQ (which_frames, Fwindow_frame (window)))
+    /* If which_frames is a frame and window arg isn't on that frame, just
        return the first window on the frame.  */
-    return frame_first_window (XFRAME (all_frames));
-  else if (! EQ (all_frames, Qt))
-    all_frames = Qnil;
-  /* Now `all_frames' is one of:
+    return frame_first_window (XFRAME (which_frames));
+  else if (! EQ (which_frames, Qt))
+    which_frames = Qnil;
+  /* Now `which_frames' is one of:
      t        => search all frames
      nil      => search just the current frame
      visible  => search just visible frames
@@ -2207,10 +2223,10 @@ windows, eventually ending up back at the window you started with.
               Which other frames are acceptable?  */
            tem = WINDOW_FRAME (XWINDOW (window));
 
-           if (! NILP (all_frames))
+           if (! NILP (which_frames))
              {
                Lisp_Object tem1 = tem;
-               tem = next_frame (tem, all_frames, console);
+               tem = next_frame (tem, which_frames, which_devices);
 
                /* In the case where the minibuffer is active,
                   and we include its frame as well as the selected one,
@@ -2267,27 +2283,30 @@ too.  Therefore, `previous-window' can be used to iterate through
 the set of windows even when the minibuffer is on another frame.  If
 the minibuffer does not count, only windows from WINDOW's frame count.
 
-Optional third arg ALL-FRAMES t means include windows on all frames.
-ALL-FRAMES nil or omitted means cycle within the frames as specified
-above.  ALL-FRAMES = `visible' means include windows on all visible frames.
-ALL-FRAMES = 0 means include windows on all visible and iconified frames.
-If ALL-FRAMES is a frame, restrict search to windows on that frame.
-Anything else means restrict to WINDOW's frame.
-
-Optional fourth arg CONSOLE controls which consoles or devices the
-returned window may be on.  If CONSOLE is a console, return windows only
-on that console.  If CONSOLE is a device, return windows only on that
-device.  If CONSOLE is a console type, return windows only on consoles
-of that type.  If CONSOLE is 'window-system, return any windows on any
-window-system consoles.  If CONSOLE is nil or omitted, return windows only
-on WINDOW's console.  Otherwise, all windows are considered.
-
-If you use consistent values for MINIBUF, ALL-FRAMES, and CONSOLE, you
-can use `previous-window' to iterate through the entire cycle of acceptable
-windows, eventually ending up back at the window you started with.
+By default, only the windows in the selected frame are considered.
+The optional argument WHICH-FRAMES changes this behavior:
+WHICH-FRAMES = `visible' means search windows on all visible frames.
+WHICH-FRAMES = 0 means search windows on all visible and iconified frames.
+WHICH-FRAMES = t means search windows on all frames including invisible frames.
+WHICH-FRAMES = a frame means search only windows on that frame.
+Anything else means restrict to the selected frame.
+
+The optional fourth argument WHICH-DEVICES further clarifies on which
+devices to search for frames as specified by WHICH-FRAMES.  This value
+is only meaningful if WHICH-FRAMES is non-nil.
+If nil or omitted, search all devices on the selected console.
+If a device, only search that device.
+If a console, search all devices on that console.
+If a device type, search all devices of that type.
+If `window-system', search all window-system devices.
+Any other non-nil value means search all devices.
+
+If you use consistent values for MINIBUF, WHICH-FRAMES, and WHICH-DEVICES,
+you can use `previous-window' to iterate through the entire cycle of
+acceptable windows, eventually ending up back at the window you started with.
 `next-window' traverses the same cycle, in the reverse order.
 */
-     (window, minibuf, all_frames, console))
+     (window, minibuf, which_frames, devices))
 {
   Lisp_Object tem;
   Lisp_Object start_window;
@@ -2310,26 +2329,26 @@ windows, eventually ending up back at the window you started with.
      lambda => count none of them
      or a specific minibuffer window (the active one) to count.  */
 
-  /* all_frames == nil doesn't specify which frames to include.
+  /* which_frames == nil doesn't specify which frames to include.
      Decide which frames it includes.  */
-  if (NILP (all_frames))
-    all_frames = (! EQ (minibuf, Qlambda)
+  if (NILP (which_frames))
+    which_frames = (! EQ (minibuf, Qlambda)
                  ? (FRAME_MINIBUF_WINDOW
                     (XFRAME
                      (WINDOW_FRAME
                       (XWINDOW (window)))))
                  : Qnil);
-  else if (EQ (all_frames, Qvisible))
+  else if (EQ (which_frames, Qvisible))
     ;
-  else if (ZEROP (all_frames))
+  else if (ZEROP (which_frames))
     ;
-  else if (FRAMEP (all_frames) && ! EQ (all_frames, Fwindow_frame (window)))
-    /* If all_frames is a frame and window arg isn't on that frame, just
+  else if (FRAMEP (which_frames) && ! EQ (which_frames, Fwindow_frame (window)))
+    /* If which_frames is a frame and window arg isn't on that frame, just
        return the first window on the frame.  */
-    return frame_first_window (XFRAME (all_frames));
-  else if (! EQ (all_frames, Qt))
-    all_frames = Qnil;
-  /* Now `all_frames' is one of:
+    return frame_first_window (XFRAME (which_frames));
+  else if (! EQ (which_frames, Qt))
+    which_frames = Qnil;
+  /* Now `which_frames' is one of:
      t        => search all frames
      nil      => search just the current frame
      visible  => search just visible frames
@@ -2351,7 +2370,7 @@ windows, eventually ending up back at the window you started with.
               Which frames are acceptable?  */
            tem = WINDOW_FRAME (XWINDOW (window));
 
-           if (! NILP (all_frames))
+           if (! NILP (which_frames))
              /* It's actually important that we use previous_frame here,
                 rather than next_frame.  All the windows acceptable
                 according to the given parameters should form a ring;
@@ -2363,7 +2382,7 @@ windows, eventually ending up back at the window you started with.
                 met.  */
              {
                Lisp_Object tem1 = tem;
-               tem = previous_frame (tem, all_frames, console);
+               tem = previous_frame (tem, which_frames, devices);
                /* In the case where the minibuffer is active,
                   and we include its frame as well as the selected one,
                   next_frame may get stuck in that frame.
@@ -2462,43 +2481,46 @@ Return the next window which is vertically after WINDOW.
 }
 
 DEFUN ("other-window", Fother_window, 1, 3, "p", /*
-Select the N'th different window on this frame.
+Select the COUNT'th different window on this frame.
 All windows on current frame are arranged in a cyclic order.
-This command selects the window N steps away in that order.
-A negative N moves in the opposite order.
-
-If optional argument FRAME is `visible', search all visible frames.
-If FRAME is 0, search all visible and iconified frames.
-If FRAME is t, search all frames.
-If FRAME is nil, search only the selected frame.
-If FRAME is a frame, search only that frame.
-
-Optional third argument CONSOLE controls which consoles or devices the
-returned window may be on.  If CONSOLE is a console, return windows only
-on that console.  If CONSOLE is a device, return windows only on that
-device.  If CONSOLE is a console type, return windows only on consoles
-of that type.  If CONSOLE is 'window-system, return any windows on any
-window-system consoles.  If CONSOLE is nil or omitted, return windows only
-on FRAME'S console, or on the selected console if FRAME is not a frame.
-Otherwise, all windows are considered.
+This command selects the window COUNT steps away in that order.
+A negative COUNT moves in the opposite order.
+
+By default, only the windows in the selected frame are considered.
+The optional argument WHICH-FRAMES changes this behavior:
+WHICH-FRAMES = `visible' means search windows on all visible frames.
+WHICH-FRAMES = 0 means search windows on all visible and iconified frames.
+WHICH-FRAMES = t means search windows on all frames including invisible frames.
+WHICH-FRAMES = a frame means search only windows on that frame.
+Anything else means restrict to the selected frame.
+
+The optional argument WHICH-DEVICES further clarifies on which devices
+to search for frames as specified by WHICH-FRAMES.  This value is only
+meaningful if WHICH-FRAMES is non-nil.
+If nil or omitted, search all devices on the selected console.
+If a device, only search that device.
+If a console, search all devices on that console.
+If a device type, search all devices of that type.
+If `window-system', search all window-system devices.
+Any other non-nil value means search all devices.
 */
-       (n, frame, console))
+       (count, which_frames, which_devices))
 {
   int i;
   Lisp_Object w;
 
-  CHECK_INT (n);
+  CHECK_INT (count);
   w = Fselected_window (Qnil);
-  i = XINT (n);
+  i = XINT (count);
 
   while (i > 0)
     {
-      w = Fnext_window (w, Qnil, frame, console);
+      w = Fnext_window (w, Qnil, which_frames, which_devices);
       i--;
     }
   while (i < 0)
     {
-      w = Fprevious_window (w, Qnil, frame, console);
+      w = Fprevious_window (w, Qnil, which_frames, which_devices);
       i++;
     }
   Fselect_window (w, Qnil);
@@ -2521,8 +2543,8 @@ enum window_loop
   GET_LRU_WINDOW,              /* Arg is t for full-width windows only */
   DELETE_OTHER_WINDOWS,                /* Arg is window not to delete */
   DELETE_BUFFER_WINDOWS,       /* Arg is buffer */
+  UNDEDICATE_BUFFER,            /* Arg is buffer */
   GET_LARGEST_WINDOW,
-  UNSHOW_BUFFER,               /* Arg is buffer */
   GET_BUFFER_WINDOW_COUNT,     /* Arg is buffer */
   GET_BUFFER_MRU_WINDOW                /* Arg is buffer */
 };
@@ -2531,11 +2553,11 @@ static Lisp_Object
 window_loop (enum window_loop type,
              Lisp_Object obj,
              int mini,
-             Lisp_Object frames,
+             Lisp_Object which_frames,
             int dedicated_too,
-            Lisp_Object console)
+            Lisp_Object which_devices)
 {
-  /* This function can GC if type == DELETE_BUFFER_WINDOWS or UNSHOW_BUFFER */
+  /* This function can GC if type == DELETE_BUFFER_WINDOWS */
   Lisp_Object w;
   Lisp_Object best_window = Qnil;
   Lisp_Object next_window;
@@ -2552,9 +2574,9 @@ window_loop (enum window_loop type,
   /* If we're only looping through windows on a particular frame,
      FRAME points to that frame.  If we're looping through windows
      on all frames, FRAME is 0.  */
-  if (FRAMEP (frames))
-    frame = XFRAME (frames);
-  else if (NILP (frames))
+  if (FRAMEP (which_frames))
+    frame = XFRAME (which_frames);
+  else if (NILP (which_frames))
     frame = selected_frame ();
   else
     frame = 0;
@@ -2564,10 +2586,10 @@ window_loop (enum window_loop type,
      or Qt otherwise.  */
   if (frame)
     frame_arg = Qlambda;
-  else if (ZEROP (frames))
-    frame_arg = frames;
-  else if (EQ (frames, Qvisible))
-    frame_arg = frames;
+  else if (ZEROP (which_frames))
+    frame_arg = which_frames;
+  else if (EQ (which_frames, Qvisible))
+    frame_arg = which_frames;
 
   DEVICE_LOOP_NO_BREAK (devcons, concons)
     {
@@ -2582,10 +2604,10 @@ window_loop (enum window_loop type,
       if (NILP (the_frame))
        continue;
 
-      if (!device_matches_console_spec (device,
-                                       NILP (console) ?
-                                       FRAME_CONSOLE (XFRAME (the_frame)) :
-                                       console))
+      if (!device_matches_device_spec (device,
+                                      NILP (which_devices) ?
+                                      FRAME_CONSOLE (XFRAME (the_frame)) :
+                                      which_devices))
        continue;
 
       /* Pick a window to start with.  */
@@ -2601,13 +2623,12 @@ window_loop (enum window_loop type,
         We can't just wait until we hit the first window again,
         because it might be deleted.  */
 
-      last_window = Fprevious_window (w, mini ? Qt : Qnil, frame_arg, Qt);
+      last_window = Fprevious_window (w, mini ? Qt : Qnil, frame_arg, device);
 
       best_window = Qnil;
       for (;;)
        {
          struct window *p = XWINDOW (w);
-         struct frame *w_frame = XFRAME (WINDOW_FRAME (p));
 
          /* Pick the next window now, since some operations will delete
             the current window.  */
@@ -2617,7 +2638,17 @@ window_loop (enum window_loop type,
          /* Given the outstanding quality of the rest of this code,
             I feel no shame about putting this piece of shit in. */
          if (++lose_lose >= 500)
-           return Qnil;
+           {
+             /* Call to ABORT() added by Darryl Okahata (16 Nov. 2001),
+                at Ben's request, to catch any remaining bugs.
+
+                If you find that XEmacs is ABORTing here, and you
+                need to be up and running ASAP, it should be safe to
+                comment out the following ABORT(), as long as you
+                leave the "break;" alone.  */
+             ABORT();
+             break;    /* <--- KEEP THIS HERE!  Do not delete!  */
+           }
 
          /* Note that we do not pay attention here to whether
             the frame is visible, since Fnext_window skips non-visible frames
@@ -2675,6 +2706,13 @@ window_loop (enum window_loop type,
                  break;
                }
 
+              case UNDEDICATE_BUFFER:
+                {
+                  if ((XBUFFER (p->buffer) == XBUFFER (obj)))
+                    p->dedicated = Qnil;
+                  break;
+                }
+
              case DELETE_OTHER_WINDOWS:
                {
                  /* Don't delete the last window on a frame; this can
@@ -2695,7 +2733,8 @@ window_loop (enum window_loop type,
                         of its own, kill the frame.  */
                      if (EQ (w, FRAME_ROOT_WINDOW (f))
                          && !NILP (p->dedicated)
-                         && other_visible_frames (f))
+                         && (allow_deletion_of_last_visible_frame
+                             || other_visible_frames (f)))
                        {
                          /* Skip the other windows on this frame.
                             There might be one, the minibuffer!  */
@@ -2757,59 +2796,8 @@ window_loop (enum window_loop type,
                  break;
                }
 
-             case UNSHOW_BUFFER:
-               {
-                 if (EQ (p->buffer, obj))
-                   {
-                     /* Find another buffer to show in this window.  */
-                     Lisp_Object another_buffer =
-                       Fother_buffer (obj, Qnil, Qnil);
-                     if (NILP (another_buffer))
-                       another_buffer
-                         = Fget_buffer_create (QSscratch);
-                     /* If this window is dedicated, and in a frame
-                        of its own, kill the frame.  */
-                     if (EQ (w, FRAME_ROOT_WINDOW (w_frame))
-                         && !NILP (p->dedicated)
-                         && other_visible_frames (w_frame))
-                       {
-                         /* Skip the other windows on this frame.
-                            There might be one, the minibuffer!  */
-                         if (! EQ (w, last_window))
-                           while (w_frame == XFRAME (WINDOW_FRAME
-                                                     (XWINDOW (next_window))))
-                             {
-                               /* As we go, check for the end of the
-                                  loop.  We mustn't start going
-                                  around a second time.  */
-                               if (EQ (next_window, last_window))
-                                 {
-                                   last_window = w;
-                                   break;
-                                 }
-                               next_window = Fnext_window (next_window,
-                                                           mini ? Qt : Qnil,
-                                                           frame_arg, Qt);
-                             }
-                         /* Now we can safely delete the frame.  */
-                         delete_frame_internal (XFRAME (WINDOW_FRAME (p)),
-                                                0, 0, 0);
-                       }
-                     else
-                       {
-                         /* Otherwise show a different buffer in the
-                             window.  */
-                         p->dedicated = Qnil;
-                         Fset_window_buffer (w, another_buffer, Qnil);
-                         if (EQ (w, Fselected_window (Qnil)))
-                           Fset_buffer (p->buffer);
-                       }
-                   }
-                 break;
-               }
-
              default:
-               abort ();
+               ABORT ();
              }
 
          if (EQ (w, last_window))
@@ -2852,34 +2840,44 @@ buffer_window_mru (struct window *w)
 
 #endif
 
+void
+undedicate_windows (Lisp_Object buffer, Lisp_Object frame)
+{
+    window_loop (UNDEDICATE_BUFFER, buffer, 0, frame, 1, Qnil);
+}
+
 \f
 DEFUN ("get-lru-window", Fget_lru_window, 0, 2, 0, /*
 Return the window least recently selected or used for display.
-If optional argument FRAME is `visible', search all visible frames.
-If FRAME is 0, search all visible and iconified frames.
-If FRAME is t, search all frames.
-If FRAME is nil, search only the selected frame.
-If FRAME is a frame, search only that frame.
-
-Optional second argument CONSOLE controls which consoles or devices the
-returned window may be on.  If CONSOLE is a console, return windows only
-on that console.  If CONSOLE is a device, return windows only on that
-device.  If CONSOLE is a console type, return windows only on consoles
-of that type.  If CONSOLE is 'window-system, return any windows on any
-window-system consoles.  If CONSOLE is nil or omitted, return windows only
-on FRAME'S console, or on the selected console if FRAME is not a frame.
-Otherwise, all windows are considered.
+
+By default, only the windows in the selected frame are considered.
+The optional argument WHICH-FRAMES changes this behavior:
+If optional argument WHICH-FRAMES is `visible', search all visible frames.
+If WHICH-FRAMES is 0, search all visible and iconified frames.
+If WHICH-FRAMES is t, search all frames.
+If WHICH-FRAMES is nil, search only the selected frame.
+If WHICH-FRAMES is a frame, search only that frame.
+
+The optional argument WHICH-DEVICES further clarifies on which devices
+to search for frames as specified by WHICH-FRAMES.  This value is only
+meaningful if WHICH-FRAMES is non-nil.
+If nil or omitted, search all devices on the selected console.
+If a device, only search that device.
+If a console, search all devices on that console.
+If a device type, search all devices of that type.
+If `window-system', search all devices on window-system consoles.
+Any other non-nil value means search all devices.
 */
-       (frame, console))
+       (which_frames, which_devices))
 {
   Lisp_Object w;
   /* First try for a non-dedicated window that is full-width */
-  w = window_loop (GET_LRU_WINDOW, Qt, 0, frame, 0, console);
+  w = window_loop (GET_LRU_WINDOW, Qt, 0, which_frames, 0, which_devices);
   if (!NILP (w) && !EQ (w, Fselected_window (Qnil)))
     return w;
 
   /* Then try for any non-dedicated window */
-  w = window_loop (GET_LRU_WINDOW, Qnil, 0, frame, 0, console);
+  w = window_loop (GET_LRU_WINDOW, Qnil, 0, which_frames, 0, which_devices);
   if (!NILP (w) && !EQ (w, Fselected_window (Qnil)))
     return w;
 
@@ -2889,15 +2887,15 @@ Otherwise, all windows are considered.
      shit is so disgusting and awful that it needs to be rethought
      from scratch. */
   /* then try for a dedicated window that is full-width */
-  w = window_loop (GET_LRU_WINDOW, Qt, 0, frame, 1, console);
+  w = window_loop (GET_LRU_WINDOW, Qt, 0, which_frames, 1, which_devices);
   if (!NILP (w) && !EQ (w, Fselected_window (Qnil)))
     return w;
 
   /* If none of them, then all windows, dedicated or not. */
-  w = window_loop (GET_LRU_WINDOW, Qnil, 0, frame, 1, console);
+  w = window_loop (GET_LRU_WINDOW, Qnil, 0, which_frames, 1, which_devices);
 
   /* At this point we damn well better have found something. */
-  if (NILP (w)) abort ();
+  if (NILP (w)) ABORT ();
 #endif
 
   return w;
@@ -2905,52 +2903,62 @@ Otherwise, all windows are considered.
 
 DEFUN ("get-largest-window", Fget_largest_window, 0, 2, 0, /*
 Return the window largest in area.
-If optional argument FRAME is `visible', search all visible frames.
-If FRAME is 0, search all visible and iconified frames.
-If FRAME is t, search all frames.
-If FRAME is nil, search only the selected frame.
-If FRAME is a frame, search only that frame.
-
-Optional second argument CONSOLE controls which consoles or devices the
-returned window may be on.  If CONSOLE is a console, return windows only
-on that console.  If CONSOLE is a device, return windows only on that
-device.  If CONSOLE is a console type, return windows only on consoles
-of that type.  If CONSOLE is 'window-system, return any windows on any
-window-system consoles.  If CONSOLE is nil or omitted, return windows only
-on FRAME'S console, or on the selected console if FRAME is not a frame.
-Otherwise, all windows are considered.
+
+By default, only the windows in the selected frame are considered.
+The optional argument WHICH-FRAMES changes this behavior:
+If optional argument WHICH-FRAMES is `visible', search all visible frames.
+If WHICH-FRAMES is 0, search all visible and iconified frames.
+If WHICH-FRAMES is t, search all frames.
+If WHICH-FRAMES is nil, search only the selected frame.
+If WHICH-FRAMES is a frame, search only that frame.
+
+The optional argument WHICH-DEVICES further clarifies on which devices
+to search for frames as specified by WHICH-FRAMES.  This value is only
+meaningful if WHICH-FRAMES is non-nil.
+If nil or omitted, search all devices on the selected console.
+If a device, only search that device.
+If a console, search all devices on that console.
+If a device type, search all devices of that type.
+If `window-system', search all devices on window-system consoles.
+Any other non-nil value means search all devices.
 */
-       (frame, console))
+       (which_frames, which_devices))
 {
   /* Don't search dedicated windows because FSFmacs doesn't.
      This stuff is all black magic so don't try to apply common
      sense to it. */
-  return window_loop (GET_LARGEST_WINDOW, Qnil, 0, frame, 0, console);
+  return window_loop (GET_LARGEST_WINDOW, Qnil, 0,
+                     which_frames, 0, which_devices);
 }
 
 DEFUN ("get-buffer-window", Fget_buffer_window, 1, 3, 0, /*
 Return a window currently displaying BUFFER, or nil if none.
-If optional argument FRAME is `visible', search all visible frames.
-If optional argument FRAME is 0, search all visible and iconified frames.
-If FRAME is t, search all frames.
-If FRAME is nil, search only the selected frame.
-If FRAME is a frame, search only that frame.
-
-Optional third argument CONSOLE controls which consoles or devices the
-returned window may be on.  If CONSOLE is a console, return windows only
-on that console.  If CONSOLE is a device, return windows only on that
-device.  If CONSOLE is a console type, return windows only on consoles
-of that type.  If CONSOLE is 'window-system, return any windows on any
-window-system consoles.  If CONSOLE is nil or omitted, return windows only
-on FRAME'S console, or on the selected console if FRAME is not a frame.
-Otherwise, all windows are considered.
+
+By default, only the windows in the selected frame are considered.
+The optional argument WHICH-FRAMES changes this behavior:
+If optional argument WHICH-FRAMES is `visible', search all visible frames.
+If WHICH-FRAMES is 0, search all visible and iconified frames.
+If WHICH-FRAMES is t, search all frames.
+If WHICH-FRAMES is nil, search only the selected frame.
+If WHICH-FRAMES is a frame, search only that frame.
+
+The optional argument WHICH-DEVICES further clarifies on which devices
+to search for frames as specified by WHICH-FRAMES.  This value is only
+meaningful if WHICH-FRAMES is non-nil.
+If nil or omitted, search all devices on the selected console.
+If a device, only search that device.
+If a console, search all devices on that console.
+If a device type, search all devices of that type.
+If `window-system', search all devices on window-system consoles.
+Any other non-nil value means search all devices.
 */
-       (buffer, frame, console))
+       (buffer, which_frames, which_devices))
 {
   buffer = Fget_buffer (buffer);
   if (BUFFERP (buffer))
     /* Search dedicated windows too. (Doesn't matter here anyway.) */
-    return window_loop (GET_BUFFER_WINDOW, buffer, 1, frame, 1, console);
+    return window_loop (GET_BUFFER_WINDOW, buffer, 1,
+                       which_frames, 1, which_devices);
   else
     return Qnil;
 }
@@ -3033,53 +3041,167 @@ value is reasonable when this function is called.
 DEFUN ("delete-windows-on", Fdelete_windows_on, 1, 3,
        "bDelete windows on (buffer): ", /*
 Delete all windows showing BUFFER.
-Optional second argument FRAME controls which frames are affected.
+
+Optional second argument WHICH-FRAMES controls which frames are affected.
 If nil or omitted, delete all windows showing BUFFER in any frame.
 If t, delete only windows showing BUFFER in the selected frame.
 If `visible', delete all windows showing BUFFER in any visible frame.
 If a frame, delete only windows showing BUFFER in that frame.
-
-Optional third argument CONSOLE controls which consoles or devices the
-returned window may be on.  If CONSOLE is a console, return windows only
-on that console.  If CONSOLE is a device, return windows only on that
-device.  If CONSOLE is a console type, return windows only on consoles
-of that type.  If CONSOLE is 'window-system, return any windows on any
-window-system consoles.  If CONSOLE is nil or omitted, return windows only
-on FRAME'S console, or on the selected console if FRAME is not a frame.
-Otherwise, all windows are considered.
+Warning: WHICH-FRAMES has the same meaning as with `next-window',
+except that the meanings of nil and t are reversed.
+
+The optional third argument WHICH-DEVICES further clarifies on which
+devices to search for frames as specified by WHICH-FRAMES.  This value
+is only meaningful if WHICH-FRAMES is not t.
+If nil or omitted, search only the selected console.
+If a device, only search that device.
+If a console, search all devices on that console.
+If a device type, search all devices of that type.
+If `window-system', search all devices on a window system.
+Any other non-nil value means search all devices.
 */
-       (buffer, frame, console))
+       (buffer, which_frames, which_devices))
 {
   /* This function can GC */
-  /* FRAME uses t and nil to mean the opposite of what window_loop
-     expects. */
-  if (!FRAMEP (frame))
-    frame = NILP (frame) ? Qt : Qnil;
+  buffer = Fget_buffer (buffer);
+  CHECK_BUFFER (buffer);
 
-  if (!NILP (buffer))
+  /* WHICH-FRAMES values t and nil mean the opposite of what
+     window_loop expects. */
+  if (EQ (which_frames, Qnil))
+    which_frames = Qt;
+  else if (EQ (which_frames, Qt))
+    which_frames = Qnil;
+
+  /* Ignore dedicated windows. */
+  window_loop (DELETE_BUFFER_WINDOWS, buffer, 0,
+              which_frames, 0, which_devices);
+  return Qnil;
+}
+
+static Lisp_Object
+list_windows (struct window *w, Lisp_Object value)
+{
+  for (;;)
     {
-      buffer = Fget_buffer (buffer);
-      CHECK_BUFFER (buffer);
-      /* Ignore dedicated windows. */
-      window_loop (DELETE_BUFFER_WINDOWS, buffer, 0, frame, 0, console);
+      if (!NILP (w->hchild))
+       value = list_windows (XWINDOW (w->hchild), value);
+      else if (!NILP (w->vchild))
+       value = list_windows (XWINDOW (w->vchild), value);
+      else
+       {
+         Lisp_Object window;
+         XSETWINDOW (window, w);
+         value = Fcons (window, value);
+       }
+      if (NILP (w->next))
+       break;
+      w = XWINDOW (w->next);
     }
-  return Qnil;
+  return value;
+}
+
+static Lisp_Object
+list_all_windows (Lisp_Object frame_spec, Lisp_Object device_spec)
+{
+  Lisp_Object devcons, concons;
+  Lisp_Object retval = Qnil;
+
+  DEVICE_LOOP_NO_BREAK (devcons, concons)
+    {
+      Lisp_Object frame_list, the_window;
+      Lisp_Object device, tail;
+
+      device = XCAR (devcons);
+      frame_list = DEVICE_FRAME_LIST (XDEVICE (device));
+
+      LIST_LOOP (tail, frame_list)
+       {
+         if ((NILP (frame_spec)
+              && !EQ (XCAR (tail), DEVICE_SELECTED_FRAME (XDEVICE (device))))
+             || (EQ (frame_spec, Qvisible)
+                 && !FRAME_VISIBLE_P (XFRAME (XCAR (tail))))
+             || (FRAMEP (frame_spec)
+                 && !EQ (frame_spec, XCAR (tail)))
+             || (!NILP (frame_spec)
+                  && !device_matches_device_spec (device,
+                                                  NILP (device_spec) ?
+                                                  Vselected_console :
+                                                  device_spec)))
+           continue;
+         the_window = FRAME_ROOT_WINDOW (XFRAME (XCAR (tail)));
+         retval = list_windows (XWINDOW (the_window), retval);
+       }
+    }
+  return Fnreverse (retval);
 }
 
-DEFUN ("replace-buffer-in-windows", Freplace_buffer_in_windows, 1, 1,
+DEFUN ("replace-buffer-in-windows", Freplace_buffer_in_windows, 1, 3,
        "bReplace buffer in windows: ", /*
 Replace BUFFER with some other buffer in all windows showing it.
+
+Optional second argument WHICH-FRAMES controls which frames are affected.
+If nil or omitted, all frames are affected.
+If t, only the selected frame is affected.
+If `visible', all visible frames are affected.
+If a frame, only that frame is affected.
+Warning: WHICH-FRAMES has the same meaning as with `next-window',
+except that the meanings of nil and t are reversed.
+
+The optional third argument WHICH-DEVICES further clarifies on which
+devices to search for frames as specified by WHICH-FRAMES.  This value
+is only meaningful if WHICH-FRAMES is not t.
+If nil or omitted, search only the selected console.
+If a device, only search that device.
+If a console, search all devices on that console.
+If a device type, search all devices of that type.
+If `window-system', search all devices on a window system.
+Any other non-nil value means search all devices.
 */
-       (buffer))
+       (buffer, which_frames, which_devices))
 {
   /* This function can GC */
-  if (!NILP (buffer))
+  Lisp_Object window_list;
+  Lisp_Object tail;
+  struct gcpro gcpro1, gcpro2;
+
+  if (EQ (which_frames, Qnil))
+    which_frames = Qt;
+  else if (EQ (which_frames, Qt))
+    which_frames = Qnil;
+  window_list = list_all_windows (which_frames, which_devices);
+
+  buffer = Fget_buffer (buffer);
+  CHECK_BUFFER (buffer);
+
+  GCPRO2 (window_list, buffer);
+  LIST_LOOP (tail, window_list)
     {
-      buffer = Fget_buffer (buffer);
-      CHECK_BUFFER (buffer);
-      /* Ignore dedicated windows. */
-      window_loop (UNSHOW_BUFFER, buffer, 0, Qt, 0, Qnil);
+      Lisp_Object window = XCAR (tail);
+      if (!MINI_WINDOW_P (XWINDOW (window))
+         && EQ (XWINDOW (window)->buffer, buffer))
+       {
+         Lisp_Object another_buffer = Fother_buffer (buffer, Qnil, Qnil);
+         Lisp_Object frame = WINDOW_FRAME (XWINDOW (window));
+         if (NILP (another_buffer))
+           another_buffer = Fget_buffer_create (QSscratch);
+         if (!NILP (XWINDOW (window)->dedicated)
+             && EQ (window,
+                    FRAME_ROOT_WINDOW (XFRAME (frame)))
+             && (allow_deletion_of_last_visible_frame
+                 || other_visible_frames (XFRAME (frame))))
+           {
+             delete_frame_internal (XFRAME (frame), 0, 0, 0); /* GC */
+           }
+         else
+           {
+             Fset_window_buffer (window, another_buffer, Qnil);
+             if (EQ (window, Fselected_window (Qnil)))
+               Fset_buffer (XWINDOW (window)->buffer);
+           }
+       }
     }
+  UNGCPRO;
   return Qnil;
 }
 \f
@@ -3296,6 +3418,7 @@ global or per-frame buffer ordering.
 {
   Lisp_Object tem;
   struct window *w = decode_window (window);
+  int old_buffer_local_face_property = 0;
 
   buffer = Fget_buffer (buffer);
   CHECK_BUFFER (buffer);
@@ -3327,6 +3450,8 @@ global or per-frame buffer ordering.
        error ("Window is dedicated to buffer %s",
               XSTRING_DATA (XBUFFER (tem)->name));
 
+      old_buffer_local_face_property =
+       XBUFFER (w->buffer)->buffer_local_face_property;
       unshow_buffer (w);
     }
 
@@ -3348,6 +3473,14 @@ global or per-frame buffer ordering.
   SET_LAST_MODIFIED (w, 1);
   SET_LAST_FACECHANGE (w);
   MARK_WINDOWS_CHANGED (w);
+  {
+    int new_buffer_local_face_property =
+      XBUFFER (w->buffer)->buffer_local_face_property;
+
+    if (new_buffer_local_face_property
+       || new_buffer_local_face_property != old_buffer_local_face_property)
+      MARK_WINDOW_FACES_CHANGED (w);
+  }
   recompute_all_cached_specifiers_in_window (w);
   if (EQ (window, Fselected_window (Qnil)))
     {
@@ -3505,9 +3638,7 @@ make_dummy_parent (Lisp_Object window)
   p->face_cachels     = Dynarr_new (face_cachel);
   p->glyph_cachels    = Dynarr_new (glyph_cachel);
   p->subwindow_instance_cache =
-    make_lisp_hash_table (30,
-                         HASH_TABLE_KEY_VALUE_WEAK,
-                         HASH_TABLE_EQ);
+    make_image_instance_cache_hash_table ();
 
   /* Put new into window structure in place of window */
   replace_window (window, new);
@@ -3530,16 +3661,17 @@ make_dummy_parent (Lisp_Object window)
 
 DEFUN ("split-window", Fsplit_window, 0, 3, "", /*
 Split WINDOW, putting SIZE lines in the first of the pair.
-WINDOW defaults to selected one and SIZE to half its size.
-If optional third arg HORFLAG is non-nil, split side by side
-and put SIZE columns in the first of the pair.
+WINDOW defaults to the selected one and SIZE to half its size.
+If optional third arg HORFLAG is non-nil, split side by side and put
+SIZE columns in the first of the pair. The newly created window is
+returned.
 */
-       (window, chsize, horflag))
+       (window, size, horflag))
 {
   Lisp_Object new;
   struct window *o, *p;
   struct frame *f;
-  int size;
+  int csize;
   int psize;
 
   if (NILP (window))
@@ -3550,29 +3682,29 @@ and put SIZE columns in the first of the pair.
   o = XWINDOW (window);
   f = XFRAME (WINDOW_FRAME (o));
 
-  if (NILP (chsize))
+  if (NILP (size))
     {
       if (!NILP (horflag))
        /* In the new scheme, we are symmetric with respect to separators
           so there is no need to do weird things here. */
        {
-         psize = WINDOW_WIDTH (o) >> 1;
-         size = window_pixel_width_to_char_width (o, psize, 0);
+         psize = (WINDOW_WIDTH (o) + window_divider_width (o)) >> 1;
+         csize = window_pixel_width_to_char_width (o, psize, 0);
         }
       else
         {
          psize = WINDOW_HEIGHT (o) >> 1;
-         size = window_pixel_height_to_char_height (o, psize, 1);
+         csize = window_pixel_height_to_char_height (o, psize, 1);
         }
     }
   else
     {
-      CHECK_INT (chsize);
-      size = XINT (chsize);
+      CHECK_INT (size);
+      csize = XINT (size);
       if (!NILP (horflag))
-       psize = window_char_width_to_pixel_width (o, size, 0);
+       psize = window_char_width_to_pixel_width (o, csize, 0);
       else
-       psize = window_char_height_to_pixel_height (o, size, 1);
+       psize = window_char_height_to_pixel_height (o, csize, 1);
     }
 
   if (MINI_WINDOW_P (o))
@@ -3584,16 +3716,21 @@ and put SIZE columns in the first of the pair.
 
   if (NILP (horflag))
     {
-      if (size < window_min_height)
-       error ("Window height %d too small (after splitting)", size);
-      if (size + window_min_height > window_char_height (o, 1))
+      if (csize < window_min_height)
+       error ("Window height %d too small (after splitting)", csize);
+      if (csize + window_min_height > window_char_height (o, 1))
        error ("Window height %d too small (after splitting)",
-              window_char_height (o, 1) - size);
+              window_char_height (o, 1) - csize);
       if (NILP (o->parent)
          || NILP (XWINDOW (o->parent)->vchild))
        {
          make_dummy_parent (window);
+#if 0
+         /* #### I can't understand why you have to reset face
+            cachels here.  This can cause crash so let's disable it
+            and see the difference.  See redisplay-tests.el  --yh */
          reset_face_cachels (XWINDOW (window));
+#endif
          new = o->parent;
          XWINDOW (new)->vchild = window;
          XFRAME (o->frame)->mirror_dirty = 1;
@@ -3601,16 +3738,19 @@ and put SIZE columns in the first of the pair.
     }
   else
     {
-      if (size < window_min_width)
-       error ("Window width %d too small (after splitting)", size);
-      if (size + window_min_width > window_char_width (o, 0))
+      if (csize < window_min_width)
+       error ("Window width %d too small (after splitting)", csize);
+      if (csize + window_min_width > window_char_width (o, 0))
        error ("Window width %d too small (after splitting)",
-              window_char_width (o, 0) - size);
+              window_char_width (o, 0) - csize);
       if (NILP (o->parent)
          || NILP (XWINDOW (o->parent)->hchild))
        {
          make_dummy_parent (window);
+#if 0
+         /* #### See above. */
          reset_face_cachels (XWINDOW (window));
+#endif
          new = o->parent;
          XWINDOW (new)->hchild = window;
          XFRAME (o->frame)->mirror_dirty = 1;
@@ -3660,65 +3800,61 @@ and put SIZE columns in the first of the pair.
   XFRAME (p->frame)->mirror_dirty = 1;
   /* do this last (after the window is completely initialized and
      the mirror-dirty flag is set) so that specifier recomputation
-     caused as a result of this will work properly and not abort. */
+     caused as a result of this will work properly and not ABORT. */
   Fset_window_buffer (new, o->buffer, Qt);
   return new;
 }
 \f
 
 DEFUN ("enlarge-window", Fenlarge_window, 1, 3, "_p", /*
-Make the selected window N lines bigger.
-From program, optional second arg SIDE non-nil means grow sideways N columns,
-and optional third arg WINDOW specifies the window to change instead of the
-selected window.
+Make the selected window COUNT lines taller.
+From program, optional second arg HORIZONTALP non-nil means grow
+sideways COUNT columns, and optional third arg WINDOW specifies the
+window to change instead of the selected window.
 */
-       (n, side, window))
+       (count, horizontalp, window))
 {
-  struct window *w = decode_window (window);
-  CHECK_INT (n);
-  change_window_height (w, XINT (n), !NILP (side), /* inpixels */ 0);
+  CHECK_INT (count);
+  change_window_height (window, XINT (count), horizontalp, /* inpixels */ 0);
   return Qnil;
 }
 
 DEFUN ("enlarge-window-pixels", Fenlarge_window_pixels, 1, 3, "_p", /*
-Make the selected window N pixels bigger.
-From program, optional second arg SIDE non-nil means grow sideways N pixels,
-and optional third arg WINDOW specifies the window to change instead of the
-selected window.
+Make the selected window COUNT pixels taller.
+From program, optional second arg HORIZONTALP non-nil means grow
+sideways COUNT pixels, and optional third arg WINDOW specifies the
+window to change instead of the selected window.
 */
-       (n, side, window))
+       (count, horizontalp, window))
 {
-  struct window *w = decode_window (window);
-  CHECK_INT (n);
-  change_window_height (w, XINT (n), !NILP (side), /* inpixels */ 1);
+  CHECK_INT (count);
+  change_window_height (window, XINT (count), horizontalp, /* inpixels */ 1);
   return Qnil;
 }
 
 DEFUN ("shrink-window", Fshrink_window, 1, 3, "_p", /*
-Make the selected window N lines smaller.
-From program, optional second arg SIDE non-nil means shrink sideways N columns,
-and optional third arg WINDOW specifies the window to change instead of the
-selected window.
+Make the selected window COUNT lines shorter.
+From program, optional second arg HORIZONTALP non-nil means shrink
+sideways COUNT columns, and optional third arg WINDOW specifies the
+window to change instead of the selected window.
 */
-       (n, side, window))
+       (count, horizontalp, window))
 {
-  CHECK_INT (n);
-  change_window_height (decode_window (window), -XINT (n), !NILP (side),
-                        /* inpixels */ 0);
+  CHECK_INT (count);
+  change_window_height (window, -XINT (count), horizontalp, /* inpixels */ 0);
   return Qnil;
 }
 
 DEFUN ("shrink-window-pixels", Fshrink_window_pixels, 1, 3, "_p", /*
-Make the selected window N pixels smaller.
-From program, optional second arg SIDE non-nil means shrink sideways N pixels,
-and optional third arg WINDOW specifies the window to change instead of the
-selected window.
+Make the selected window COUNT pixels smaller.
+From program, optional second arg HORIZONTALP non-nil means shrink
+sideways COUNT pixels, and optional third arg WINDOW specifies the
+window to change instead of the selected window.
 */
-       (n, side, window))
+       (count, horizontalp, window))
 {
-  CHECK_INT (n);
-  change_window_height (decode_window (window), -XINT (n), !NILP (side),
-                        /* inpixels */ 1);
+  CHECK_INT (count);
+  change_window_height (window, -XINT (count), horizontalp, /* inpixels */ 1);
   return Qnil;
 }
 
@@ -3963,11 +4099,12 @@ window_pixheight (Lisp_Object w)
    keep everything consistent. */
 
 static void
-change_window_height (struct window *win, int delta, int widthflag,
+change_window_height (Lisp_Object window, int delta, Lisp_Object horizontalp,
                       int inpixels)
 {
+  struct window *win = decode_window (window);
+  int widthflag = !NILP (horizontalp);
   Lisp_Object parent;
-  Lisp_Object window;
   struct window *w;
   struct frame *f;
   int *sizep;
@@ -4119,10 +4256,11 @@ change_window_height (struct window *win, int delta, int widthflag,
 
 \f
 
-/* Scroll contents of window WINDOW up N lines. If N < (top line height /
-   average line height) then we just adjust the top clip.  */
+/* Scroll contents of window WINDOW up COUNT lines.
+   If COUNT < (top line height / average line height) then we just adjust
+   the top clip.  */
 void
-window_scroll (Lisp_Object window, Lisp_Object n, int direction,
+window_scroll (Lisp_Object window, Lisp_Object count, int direction,
               Error_behavior errb)
 {
   struct window *w = XWINDOW (window);
@@ -4166,14 +4304,14 @@ window_scroll (Lisp_Object window, Lisp_Object n, int direction,
       MARK_WINDOWS_CHANGED (w);
     }
 
-  if (!NILP (n))
+  if (!NILP (count))
     {
-      if (EQ (n, Qminus))
+      if (EQ (count, Qminus))
        direction *= -1;
       else
        {
-         n = Fprefix_numeric_value (n);
-         value = XINT (n) * direction;
+         count = Fprefix_numeric_value (count);
+         value = XINT (count) * direction;
 
          if (!value)
            return;     /* someone just made a pointless call */
@@ -4182,7 +4320,7 @@ window_scroll (Lisp_Object window, Lisp_Object n, int direction,
 
   /* If the user didn't specify how far to scroll then we have to figure it
      out by ourselves. */
-  if (NILP (n) || EQ (n, Qminus))
+  if (NILP (count) || EQ (count, Qminus))
     {
       /* Going forwards is easy.  If that is what we are doing then just
         set value and the section which handles the user specifying a
@@ -4229,7 +4367,7 @@ window_scroll (Lisp_Object window, Lisp_Object n, int direction,
          &&
          Dynarr_length (dla) >= (1 + modeline)
          &&
-         (dl->ascent - dl->top_clip) - fheight * value > 0)
+         (dl->ascent - dl->top_clip) > fheight * value)
        {
          WINDOW_TEXT_TOP_CLIP (w) += value * fheight;
          MARK_WINDOWS_CHANGED (w);
@@ -4404,32 +4542,42 @@ window_scroll (Lisp_Object window, Lisp_Object n, int direction,
 }
 \f
 DEFUN ("scroll-up", Fscroll_up, 0, 1, "_P", /*
-Scroll text of current window upward N lines; or near full screen if no arg.
+Scroll text of current window up COUNT lines; or near full screen if no arg.
 A near full screen is `next-screen-context-lines' less than a full screen.
-Negative N means scroll downward.
+Negative COUNT means scroll downward.
 When calling from a program, supply an integer as argument or nil.
 On attempt to scroll past end of buffer, `end-of-buffer' is signaled.
 On attempt to scroll past beginning of buffer, `beginning-of-buffer' is
 signaled.
+
+The characters that are moved over may be added to the current selection
+\(i.e. active region) if the Shift key is held down, a motion key is used
+to invoke this command, and `shifted-motion-keys-select-region' is t; see
+the documentation for this variable for more details.
 */
-       (n))
+       (count))
 {
-  window_scroll (Fselected_window (Qnil), n, 1, ERROR_ME);
+  window_scroll (Fselected_window (Qnil), count, 1, ERROR_ME);
   return Qnil;
 }
 
 DEFUN ("scroll-down", Fscroll_down, 0, 1, "_P", /*
-Scroll text of current window downward N lines; or near full screen if no arg.
+Scroll text of current window down COUNT lines; or near full screen if no arg.
 A near full screen is `next-screen-context-lines' less than a full screen.
-Negative N means scroll upward.
+Negative COUNT means scroll upward.
 When calling from a program, supply a number as argument or nil.
 On attempt to scroll past end of buffer, `end-of-buffer' is signaled.
 On attempt to scroll past beginning of buffer, `beginning-of-buffer' is
 signaled.
+
+The characters that are moved over may be added to the current selection
+\(i.e. active region) if the Shift key is held down, a motion key is used
+to invoke this command, and `shifted-motion-keys-select-region' is t; see
+the documentation for this variable for more details.
 */
-       (n))
+       (count))
 {
-  window_scroll (Fselected_window (Qnil), n, -1, ERROR_ME);
+  window_scroll (Fselected_window (Qnil), count, -1, ERROR_ME);
   return Qnil;
 }
 \f
@@ -4479,9 +4627,9 @@ showing that buffer is used.
  }
 
 DEFUN ("scroll-other-window", Fscroll_other_window, 0, 1, "_P", /*
-Scroll next window upward N lines; or near full frame if no arg.
+Scroll next window upward COUNT lines; or near full frame if no arg.
 The next window is the one below the current one; or the one at the top
-if the current one is at the bottom.  Negative N means scroll downward.
+if the current one is at the bottom.  Negative COUNT means scroll downward.
 When calling from a program, supply a number as argument or nil.
 
 If in the minibuffer, `minibuffer-scroll-window' if non-nil
@@ -4489,40 +4637,50 @@ specifies the window to scroll.
 If `other-window-scroll-buffer' is non-nil, scroll the window
 showing that buffer, popping the buffer up if necessary.
 */
-       (n))
+       (count))
 {
-  window_scroll (Fother_window_for_scrolling (), n, 1, ERROR_ME);
+  window_scroll (Fother_window_for_scrolling (), count, 1, ERROR_ME);
   return Qnil;
 }
 \f
 DEFUN ("scroll-left", Fscroll_left, 0, 1, "_P", /*
-Scroll selected window display N columns left.
-Default for N is window width minus 2.
+Scroll selected window display COUNT columns left.
+Default for COUNT is window width minus 2.
+
+The characters that are moved over may be added to the current selection
+\(i.e. active region) if the Shift key is held down, a motion key is used
+to invoke this command, and `shifted-motion-keys-select-region' is t; see
+the documentation for this variable for more details.
 */
-       (n))
+       (count))
 {
   Lisp_Object window = Fselected_window (Qnil);
   struct window *w = XWINDOW (window);
-  int count = (NILP (n) ?
-              window_char_width (w, 0) - 2 :
-              XINT (Fprefix_numeric_value (n)));
+  int n = (NILP (count) ?
+          window_char_width (w, 0) - 2 :
+          XINT (Fprefix_numeric_value (count)));
 
-  return Fset_window_hscroll (window, make_int (w->hscroll + count));
+  return Fset_window_hscroll (window, make_int (w->hscroll + n));
 }
 
 DEFUN ("scroll-right", Fscroll_right, 0, 1, "_P", /*
-Scroll selected window display N columns right.
-Default for N is window width minus 2.
+Scroll selected window display COUNT columns right.
+Default for COUNT is window width minus 2.
+
+The characters that are moved over may be added to the current selection
+\(i.e. active region) if the Shift key is held down, a motion key is used
+to invoke this command, and `shifted-motion-keys-select-region' is t; see
+the documentation for this variable for more details.
 */
-       (n))
+       (count))
 {
   Lisp_Object window = Fselected_window (Qnil);
   struct window *w = XWINDOW (window);
-  int count = (NILP (n) ?
-              window_char_width (w, 0) - 2 :
-              XINT (Fprefix_numeric_value (n)));
+  int n = (NILP (count) ?
+          window_char_width (w, 0) - 2 :
+          XINT (Fprefix_numeric_value (count)));
 
-  return Fset_window_hscroll (window, make_int (w->hscroll - count));
+  return Fset_window_hscroll (window, make_int (w->hscroll - n));
 }
 \f
 DEFUN ("center-to-window-line", Fcenter_to_window_line, 0, 2, "_P", /*
@@ -4904,7 +5062,7 @@ struct window_config
   /* Record the values of window-min-width and window-min-height
      so that window sizes remain consistent with them.  */
   int min_width, min_height;
-  int saved_windows_count;
+  unsigned int saved_windows_count;
   /* Zero-sized arrays aren't ANSI C */
   struct saved_window saved_windows[1];
 };
@@ -4919,7 +5077,7 @@ static Lisp_Object
 mark_window_config (Lisp_Object obj)
 {
   struct window_config *config = XWINDOW_CONFIGURATION (obj);
-  int i;
+  unsigned int i;
   mark_object (config->current_window);
   mark_object (config->current_buffer);
   mark_object (config->minibuffer_scroll_window);
@@ -4948,12 +5106,11 @@ mark_window_config (Lisp_Object obj)
   return Qnil;
 }
 
-static size_t
-sizeof_window_config_for_n_windows (int n)
+inline static size_t
+sizeof_window_config_for_n_windows (unsigned int n)
 {
-  return (sizeof (struct window_config) +
-         /* n - 1 because zero-sized arrays aren't ANSI C */
-         (n - 1) *sizeof (struct saved_window));
+  return FLEXIBLE_ARRAY_STRUCT_SIZEOF (struct window_config,
+                                      struct saved_window, saved_windows, n);
 }
 
 static size_t
@@ -5018,7 +5175,7 @@ static int
 window_config_equal (Lisp_Object conf1, Lisp_Object conf2)
 {
   struct window_config *fig1, *fig2;
-  int i;
+  unsigned int i;
 
   /* First check if they are truly the same. */
   if (EQ (conf1, conf2))
@@ -5050,9 +5207,9 @@ window_config_equal (Lisp_Object conf1, Lisp_Object conf2)
 DEFUN ("window-configuration-p", Fwindow_configuration_p, 1, 1, 0, /*
 Return t if OBJECT is a window-configuration object.
 */
-       (obj))
+       (object))
 {
-  return WINDOW_CONFIGURATIONP (obj) ? Qt : Qnil;
+  return WINDOW_CONFIGURATIONP (object) ? Qt : Qnil;
 }
 
 static int
@@ -5073,7 +5230,7 @@ mark_windows_in_use (struct frame *f, int mark)
 static Lisp_Object
 free_window_configuration (Lisp_Object window_config)
 {
-  int i;
+  unsigned int i;
   struct window_config *config = XWINDOW_CONFIGURATION (window_config);
 
   /* Free all the markers.  It's not completely necessary that
@@ -5125,7 +5282,7 @@ by `current-window-configuration' (which see).
   struct window_config *config;
   struct saved_window *p;
   Lisp_Object new_current_buffer;
-  int k;
+  unsigned int k;
   Lisp_Object frame;
   struct frame *f;
   struct gcpro gcpro1;
@@ -5373,9 +5530,8 @@ by `current-window-configuration' (which see).
             set. */
          if (NILP (w->subwindow_instance_cache))
            w->subwindow_instance_cache =
-             make_lisp_hash_table (30,
-                                   HASH_TABLE_KEY_VALUE_WEAK,
-                                   HASH_TABLE_EQ);
+             make_image_instance_cache_hash_table ();
+
          SET_LAST_MODIFIED (w, 1);
          SET_LAST_FACECHANGE (w);
          w->config_mark = 0;
@@ -5574,7 +5730,7 @@ by `current-window-configuration' (which see).
   if (FRAME_LIVE_P (f))
     {
       /* Do this before calling recompute_all_cached_specifiers_in_window()
-        so that things like redisplay_redraw_cursor() won't abort due
+        so that things like redisplay_redraw_cursor() won't ABORT due
         to no window mirror present. */
       f->mirror_dirty = 1;
 
@@ -5624,7 +5780,7 @@ delete_all_subwindows (struct window *w)
 }
 
 \f
-static int
+static unsigned int
 count_windows (struct window *window)
 {
   return 1 +
@@ -5642,7 +5798,7 @@ saved_window_index (Lisp_Object window, struct window_config *config, int lim)
       if (EQ (SAVED_WINDOW_N (config, j)->window, window))
        return j;
     }
-  abort ();
+  ABORT ();
   return 0;    /* suppress compiler warning */
 }
 
@@ -5729,8 +5885,9 @@ DEFUN ("current-window-configuration", Fcurrent_window_configuration, 0, 1, 0, /
 Return an object representing the current window configuration of FRAME.
 If FRAME is nil or omitted, use the selected frame.
 This describes the number of windows, their sizes and current buffers,
-and for each displayed buffer, where display starts, and the positions of
-point and mark.  An exception is made for point in the current buffer:
+and for each window on FRAME the displayed buffer, where display
+starts, and the positions of point and mark.
+An exception is made for point in the current buffer:
 its value is -not- saved.
 */
        (frame))
@@ -5738,7 +5895,7 @@ its value is -not- saved.
   Lisp_Object result;
   struct frame *f = decode_frame (frame);
   struct window_config *config;
-  int n_windows = count_windows (XWINDOW (FRAME_ROOT_WINDOW (f)));
+  unsigned int n_windows = count_windows (XWINDOW (FRAME_ROOT_WINDOW (f)));
   int minibuf_height;
   int real_font_height;
 
@@ -5755,14 +5912,20 @@ its value is -not- saved.
   /*
   config->frame_width = FRAME_WIDTH (f);
   config->frame_height = FRAME_HEIGHT (f); */
-  /* When using `push-window-configuration', often the minibuffer ends
+  /* #### When using `push-window-configuration', often the minibuffer ends
      up as the selected window because functions run as the result of
      user interaction e.g. hyper-apropos. It seems to me the sensible
-     thing to do is not record the minibuffer here. */
+     thing to do is not record the minibuffer here. 
+
+     #### Unfortunately this is a change to previous behaviour, however logical
+     it may be, so revert for the moment. */
+#if 0
   if (FRAME_MINIBUF_ONLY_P (f) || minibuf_level)
     config->current_window = FRAME_SELECTED_WINDOW (f);
   else
     config->current_window = FRAME_LAST_NONMINIBUF_WINDOW (f);
+#endif
+  config->current_window = FRAME_SELECTED_WINDOW (f);
   XSETBUFFER (config->current_buffer, current_buffer);
   config->minibuffer_scroll_window = Vminibuffer_scroll_window;
   config->root_window = FRAME_ROOT_WINDOW (f);
@@ -5956,6 +6119,8 @@ syms_of_window (void)
   /* Qother in general.c */
 #endif
 
+  DEFSYMBOL (Qtruncate_partial_width_windows);
+  
   DEFSUBR (Fselected_window);
   DEFSUBR (Flast_nonminibuf_window);
   DEFSUBR (Fminibuffer_window);
@@ -6044,7 +6209,7 @@ syms_of_window (void)
 void
 reinit_vars_of_window (void)
 {
-  int i;
+  unsigned int i;
   /* Make sure all windows get marked */
   minibuf_window = Qnil;
   staticpro_nodump (&minibuf_window);
@@ -6136,7 +6301,7 @@ This is a specifier; use `set-specifier' to change it.
   set_specifier_caching (Vmodeline_shadow_thickness,
                         offsetof (struct window, modeline_shadow_thickness),
                         modeline_shadow_thickness_changed,
-                        0, 0);
+                        0, 0, 0);
 
   DEFVAR_SPECIFIER ("has-modeline-p", &Vhas_modeline_p /*
 *Whether the modeline should be displayed.
@@ -6152,7 +6317,7 @@ This is a specifier; use `set-specifier' to change it.
                            has changed, but not one to indicate that
                            the modeline has been turned off or on. */
                         some_window_value_changed,
-                        0, 0);
+                        0, 0, 0);
 
   DEFVAR_SPECIFIER ("vertical-divider-always-visible-p",
                    &Vvertical_divider_always_visible_p /*
@@ -6171,7 +6336,7 @@ This is a specifier; use `set-specifier' to change it.
                         offsetof (struct window,
                                   vertical_divider_always_visible_p),
                         vertical_divider_changed_in_window,
-                        0, 0);
+                        0, 0, 0);
 
   DEFVAR_SPECIFIER ("vertical-divider-shadow-thickness", &Vvertical_divider_shadow_thickness /*
 *How thick to draw 3D shadows around vertical dividers.
@@ -6186,7 +6351,7 @@ This is a specifier; use `set-specifier' to change it.
                         offsetof (struct window,
                                   vertical_divider_shadow_thickness),
                         vertical_divider_changed_in_window,
-                        0, 0);
+                        0, 0, 0);
   DEFVAR_SPECIFIER ("vertical-divider-line-width", &Vvertical_divider_line_width /*
 *The width of the vertical dividers, not including shadows.
 
@@ -6204,6 +6369,9 @@ This is a specifier; use `set-specifier' to change it.
 #ifdef HAVE_TTY
     fb = Fcons (Fcons (list1 (Qtty), make_int (1)), fb);
 #endif
+#ifdef HAVE_GTK
+    fb = Fcons (Fcons (list1 (Qgtk), make_int (3)), fb);
+#endif
 #ifdef HAVE_X_WINDOWS
     fb = Fcons (Fcons (list1 (Qx), make_int (3)), fb);
 #endif
@@ -6217,7 +6385,7 @@ This is a specifier; use `set-specifier' to change it.
                          offsetof (struct window,
                                   vertical_divider_line_width),
                         vertical_divider_changed_in_window,
-                         0, 0);
+                         0, 0, 0);
 
   DEFVAR_SPECIFIER ("vertical-divider-spacing", &Vvertical_divider_spacing /*
 *How much space to leave around the vertical dividers.
@@ -6238,6 +6406,9 @@ This is a specifier; use `set-specifier' to change it.
        Should not the same value be the fallback under X? - kkm */
     fb = Fcons (Fcons (list1 (Qx), make_int (2)), fb);
 #endif
+#ifdef HAVE_GTK
+    fb = Fcons (Fcons (list1 (Qgtk), Qzero), fb);
+#endif
 #ifdef HAVE_MS_WINDOWS
     fb = Fcons (Fcons (list1 (Qmswindows), Qzero), fb);
 #endif
@@ -6246,5 +6417,5 @@ This is a specifier; use `set-specifier' to change it.
   set_specifier_caching (Vvertical_divider_spacing,
                         offsetof (struct window, vertical_divider_spacing),
                         vertical_divider_changed_in_window,
-                        0, 0);
+                        0, 0, 0);
 }