(g2-UU+5B73): Add `=decomposition@hanyo-denshi'.
[chise/xemacs-chise.git.1] / src / window.c
index b981c91..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;
@@ -82,7 +84,7 @@ Lisp_Object Vvertical_divider_shadow_thickness;
 /* Divider surface width (not counting 3-d borders) */
 Lisp_Object Vvertical_divider_line_width;
 
-/* Spacing between outer egde of divider border and window edge */
+/* Spacing between outer edge of divider border and window edge */
 Lisp_Object Vvertical_divider_spacing;
 
 /* How much to scroll by per-line. */
@@ -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_EQUAL);
+  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
@@ -1020,7 +1024,7 @@ window_top_window_gutter_height (struct window *w)
 {
   if (!NILP (w->hchild) || !NILP (w->vchild))
     return 0;
-  
+
 #ifdef HAVE_SCROLLBARS
   if (!NILP (w->scrollbar_on_top_p))
     return window_scrollbar_height (w);
@@ -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, /*
@@ -1328,7 +1333,7 @@ currently displayed in a window.
 
 The names are somewhat confusing; here's a table to help out:
 
-                    width                         height               
+                    width                         height
 -------------------------------------------------------------------------
 w/o gutters
   (rows/columns)    window-width                  window-text-area-height
@@ -1510,7 +1515,7 @@ Return the number of columns by which WINDOW is scrolled from left margin.
 }
 
 DEFUN ("modeline-hscroll", Fmodeline_hscroll, 0, 1, 0, /*
-Return the horizontal scrolling ammount of WINDOW's modeline.
+Return the horizontal scrolling amount of WINDOW's modeline.
 If the window has no modeline, return nil.
 */
        (window))
@@ -1522,7 +1527,7 @@ If the window has no modeline, return nil.
 }
 
 DEFUN ("set-modeline-hscroll", Fset_modeline_hscroll, 2, 2, 0, /*
-Set the horizontal scrolling ammount of WINDOW's modeline to NCOL.
+Set the horizontal scrolling amount of WINDOW's modeline to NCOL.
 If NCOL is negative, it will silently be forced to 0.
 If the window has no modeline, return nil. Otherwise, return the actual
 value that was set.
@@ -1597,15 +1602,20 @@ 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))
 {
   struct window *w = decode_window (window);
+  struct frame *f = XFRAME (w->frame);
 
-  int left = w->pixel_left;
-  int top  = w->pixel_top;
+  int left =
+    w->pixel_left - FRAME_LEFT_BORDER_END (f) - FRAME_LEFT_GUTTER_BOUNDS (f);
+  int top =
+    w->pixel_top - FRAME_TOP_BORDER_END (f) - FRAME_TOP_GUTTER_BOUNDS (f);
 
   return list4 (make_int (left),
                make_int (top),
@@ -1616,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))
 {
@@ -1636,14 +1647,14 @@ top left corner of the window.
 
 DEFUN ("window-point", Fwindow_point, 0, 1, 0, /*
 Return current value of point in WINDOW.
-For a nonselected window, this is the value point would have
+For a non-selected window, this is the value point would have
 if that window were selected.
 
 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))
 {
@@ -1669,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))
 {
@@ -1797,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 */
@@ -1871,30 +1883,12 @@ replace_window (Lisp_Object old, Lisp_Object replacement)
   ERROR_CHECK_SUBWINDOW_CACHE (p);
 }
 
-static int
-window_unmap_subwindows_cache_mapper (Lisp_Object key, Lisp_Object value,
-                                     void *flag_closure)
-{
-  /* value can be nil; we cache failures as well as successes */
-  if (!NILP (value))
-    {
-      struct frame* f = XFRAME (XIMAGE_INSTANCE_FRAME (value));
-      unmap_subwindow (value);
-      /* In case GC doesn't catch up fast enough, remove from the frame
-        cache also. Otherwise code that checks the sanity of the instance
-        will fail. */
-      XWEAK_LIST_LIST (FRAME_SUBWINDOW_CACHE (f))
-       = delq_no_quit (value, XWEAK_LIST_LIST (FRAME_SUBWINDOW_CACHE (f)));
-    }
-  return 0;
-}
-
 static void
 window_unmap_subwindows (struct window* w)
 {
   assert (!NILP (w->subwindow_instance_cache));
-  elisp_maphash (window_unmap_subwindows_cache_mapper,
-                w->subwindow_instance_cache, 0);
+  elisp_maphash (unmap_subwindow_instance_cache_mapper,
+                w->subwindow_instance_cache, (void*)1);
 }
 
 /* we're deleting W; set the structure of W to indicate this. */
@@ -1945,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
@@ -2117,15 +2111,19 @@ 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;
 }
 
 \f
 DEFUN ("next-window", Fnext_window, 0, 4, 0, /*
-Return next window after WINDOW in canonical ordering of windows.
+Return the next window after WINDOW in the canonical ordering of windows.
 If omitted, WINDOW defaults to the selected window.
 
 Optional second arg MINIBUF t means count the minibuffer window even
@@ -2139,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 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 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;
@@ -2177,33 +2178,35 @@ windows, eventually ending up back at the window you started with.
     minibuf = (minibuf_level ? minibuf_window : Qlambda);
   else if (! EQ (minibuf, Qt))
     minibuf = Qlambda;
-  /* Now minibuf can be t => count all minibuffer windows,
-     lambda => count none of them,
+  /* Now `minibuf' is one of:
+     t      => count all minibuffer windows
+     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 t meaning search all frames,
-     nil meaning search just current frame,
-     visible meaning search just visible frames,
-     0 meaning search visible and iconified frames,
-     or a window, meaning search the frame that window belongs to.  */
+    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
+     0        => search visible and iconified frames
+     a window => search the frame that window belongs to.  */
 
   /* Do this loop at least once, to get the next window, and perhaps
      again, if we hit the minibuffer and that is not acceptable.  */
@@ -2220,12 +2223,11 @@ 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;
+               Lisp_Object tem1 = tem;
+               tem = next_frame (tem, which_frames, which_devices);
 
-               tem1 = tem;
-               tem = next_frame (tem, all_frames, console);
                /* 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.
@@ -2252,7 +2254,6 @@ windows, eventually ending up back at the window you started with.
          else break;
        }
     }
-  /* "acceptable" is the correct spelling. */
   /* Which windows are acceptable?
      Exit the loop and accept this window if
      this isn't a minibuffer window,
@@ -2268,7 +2269,7 @@ windows, eventually ending up back at the window you started with.
 }
 
 DEFUN ("previous-window", Fprevious_window, 0, 4, 0, /*
-Return the window preceding WINDOW in canonical ordering of windows.
+Return the window preceding WINDOW in the canonical ordering of windows.
 If omitted, WINDOW defaults to the selected window.
 
 Optional second arg MINIBUF t means count the minibuffer window even
@@ -2280,29 +2281,32 @@ Several frames may share a single minibuffer; if the minibuffer
 counts, all windows on all frames that share that minibuffer count
 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
-
-If 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 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 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.
+the minibuffer does not count, only windows from WINDOW's frame count.
+
+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;
@@ -2320,34 +2324,36 @@ windows, eventually ending up back at the window you started with.
     minibuf = (minibuf_level ? minibuf_window : Qlambda);
   else if (! EQ (minibuf, Qt))
     minibuf = Qlambda;
-  /* Now minibuf can be t => count all minibuffer windows,
-     lambda => count none of them,
+  /* Now `minibuf' is one of:
+     t      => count all minibuffer windows
+     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 t meaning search all frames,
-     nil meaning search just current frame,
-     visible meaning search just visible frames,
-     0 meaning search visible and iconified frames,
-     or a window, meaning search the frame that window belongs to.  */
+    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
+     0        => search visible and iconified frames
+     a window => search the frame that window belongs to.  */
 
   /* Do this loop at least once, to get the next window, and perhaps
      again, if we hit the minibuffer and that is not acceptable.  */
@@ -2364,8 +2370,8 @@ windows, eventually ending up back at the window you started with.
               Which frames are acceptable?  */
            tem = WINDOW_FRAME (XWINDOW (window));
 
-           if (! NILP (all_frames))
-             /* It's actually important that we use prev_frame here,
+           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;
                 Fnext_window and Fprevious_window should go back and
@@ -2375,10 +2381,8 @@ windows, eventually ending up back at the window you started with.
                 window_loop assumes that these `ring' requirement are
                 met.  */
              {
-               Lisp_Object tem1;
-
-               tem1 = tem;
-               tem = prev_frame (tem, all_frames, console);
+               Lisp_Object tem1 = tem;
+               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.
@@ -2477,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);
@@ -2536,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 */
 };
@@ -2546,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;
@@ -2564,26 +2571,25 @@ window_loop (enum window_loop type,
   int lose_lose = 0;
   Lisp_Object devcons, concons;
 
-  /* FRAME_ARG is Qlambda to stick to one frame,
-     Qvisible to consider all visible frames,
-     or Qt otherwise.  */
-
   /* 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;
+
+  /* FRAME_ARG is Qlambda to stick to one frame,
+     Qvisible to consider all visible frames,
+     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)
     {
@@ -2598,7 +2604,10 @@ window_loop (enum window_loop type,
       if (NILP (the_frame))
        continue;
 
-      if (!device_matches_console_spec (the_frame, device, console))
+      if (!device_matches_device_spec (device,
+                                      NILP (which_devices) ?
+                                      FRAME_CONSOLE (XFRAME (the_frame)) :
+                                      which_devices))
        continue;
 
       /* Pick a window to start with.  */
@@ -2614,23 +2623,32 @@ 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.  */
-         next_window = Fnext_window (w, mini ? Qt : Qnil, frame_arg, Qt);
+         next_window = Fnext_window (w, mini ? Qt : Qnil, frame_arg, device);
 
          /* #### Still needed ?? */
          /* 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
@@ -2688,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
@@ -2708,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!  */
@@ -2770,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))
@@ -2865,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;
 
@@ -2902,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;
@@ -2918,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;
 }
@@ -3046,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
@@ -3302,13 +3411,14 @@ DEFUN ("set-window-buffer", Fset_window_buffer, 2, 3, 0, /*
 Make WINDOW display BUFFER as its contents.
 BUFFER can be a buffer or buffer name.
 
-With non-nil optional argument `norecord', do not modify the
+With non-nil optional argument NORECORD, do not modify the
 global or per-frame buffer ordering.
 */
        (window, buffer, norecord))
 {
   Lisp_Object tem;
   struct window *w = decode_window (window);
+  int old_buffer_local_face_property = 0;
 
   buffer = Fget_buffer (buffer);
   CHECK_BUFFER (buffer);
@@ -3340,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);
     }
 
@@ -3361,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)))
     {
@@ -3377,7 +3497,7 @@ Select WINDOW.  Most editing will apply to WINDOW's buffer.
 The main editor command loop selects the buffer of the selected window
 before each command.
 
-With non-nil optional argument `norecord', do not modify the
+With non-nil optional argument NORECORD, do not modify the
 global or per-frame buffer ordering.
 */
        (window, norecord))
@@ -3391,7 +3511,7 @@ global or per-frame buffer ordering.
   /* we have already caught dead-window errors */
   if (!NILP (w->hchild) || !NILP (w->vchild))
     error ("Trying to select non-leaf window");
-  
+
   w->use_time = make_int (++window_select_count);
 
   if (EQ (window, old_selected_window))
@@ -3517,10 +3637,8 @@ make_dummy_parent (Lisp_Object window)
   p->line_start_cache = Dynarr_new (line_start_cache);
   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_EQUAL);
+  p->subwindow_instance_cache =
+    make_image_instance_cache_hash_table ();
 
   /* Put new into window structure in place of window */
   replace_window (window, new);
@@ -3543,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 HOR-FLAG 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))
@@ -3563,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))
@@ -3597,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;
@@ -3614,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;
@@ -3673,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;
 }
 
@@ -3976,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;
@@ -4132,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);
@@ -4179,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 */
@@ -4195,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
@@ -4242,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);
@@ -4417,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
@@ -4492,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
@@ -4502,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", /*
@@ -4917,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];
 };
@@ -4932,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);
@@ -4961,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
@@ -5031,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))
@@ -5063,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
@@ -5086,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
@@ -5138,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;
@@ -5215,23 +5359,32 @@ by `current-window-configuration' (which see).
       record_unwind_protect (free_window_configuration, old_window_config);
 
       mark_windows_in_use (f, 1);
-
-      /* Force subwindows to be reinstantiated. They are all going
-         anyway and if we don't do this GC may not happen between now
-         and the next time we check their integrity. */
+#ifdef BROKEN_SUBWINDOW_REDISPLAY
+      /* Force subwindows to be remapped. This is overkill but saves
+       us having to rely on the redisplay code to unmap any extant
+       subwindows.
+
+       #### It does cause some extra flashing though which we could
+       possibly avoid. So consider trying to get redisplay to work
+       correctly.
+
+       Removing the instances from the frame cache is wrong because
+       an instance is only put in the frame cache when it is
+       instantiated. So if we do this there is a chance that stuff
+       will never get put back in the frame cache. */
       reset_frame_subwindow_instance_cache (f);
-
+#endif
 #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
+        resized. This is tickled a lot by the new "character size
+        stays constant" policy in 21.0. It leads to very weird
         glitches (and possibly crashes when asserts are tickled).
 
-        Just changing the units doens't help because changing the
+        Just changing the units doesn'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.
        */
@@ -5363,18 +5516,27 @@ by `current-window-configuration' (which see).
          w->hscroll = p->hscroll;
          w->modeline_hscroll = p->modeline_hscroll;
          w->line_cache_last_updated = Qzero;
-         /* The subwindow instance cache isn't preserved across
-            window configurations, and in fact doing so would be
-            wrong. We just reset to zero and then redisplay will fill
-            it up as needed. */
-         w->subwindow_instance_cache =
-           make_lisp_hash_table (30,
-                                 HASH_TABLE_KEY_VALUE_WEAK,
-                                 HASH_TABLE_EQUAL);
+         /* When we restore a window's configuration, the identity of
+            the window hasn't actually changed - so there is no
+            reason why we shouldn't preserve the instance cache for
+            it - unless it was originally deleted. This will often
+            buy us something as we will not have to re-instantiate
+            all the instances. This is because this is an instance
+            cache - not a display cache. Preserving the display cache
+            would definitely be wrong.
+
+            We specifically want to do this for tabs, since for some
+            reason finding a file will cause the configuration to be
+            set. */
+         if (NILP (w->subwindow_instance_cache))
+           w->subwindow_instance_cache =
+             make_image_instance_cache_hash_table ();
+
          SET_LAST_MODIFIED (w, 1);
          SET_LAST_FACECHANGE (w);
          w->config_mark = 0;
 
+         /* #### Consider making the instance cache a winslot. */
 #define WINDOW_SLOT(slot, compare) w->slot = p->slot
 #include "winslots.h"
 
@@ -5568,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;
 
@@ -5618,7 +5780,7 @@ delete_all_subwindows (struct window *w)
 }
 
 \f
-static int
+static unsigned int
 count_windows (struct window *window)
 {
   return 1 +
@@ -5636,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 */
 }
 
@@ -5723,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))
@@ -5732,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;
 
@@ -5749,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-apropros. It seems to me the sensible
-     thing to do is not record the minibuffer here. */
+     user interaction e.g. hyper-apropos. It seems to me the sensible
+     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);
@@ -5868,7 +6037,7 @@ a non-nil result to be returned.
     }
   else
     {
-      /* optimised case */
+      /* optimized case */
       dl = Dynarr_atp (dla, y);
       db = get_display_block_from_line (dl, TEXT);
 
@@ -5950,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);
@@ -6038,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);
@@ -6073,6 +6244,7 @@ The function is called with one argument, the buffer to be displayed.
 Used by `with-output-to-temp-buffer'.
 If this function is used, then it must do the entire job of showing
 the buffer; `temp-buffer-show-hook' is not run unless this function runs it.
+\(`temp-buffer-show-hook' is obsolete.  Do not use in new code.)
 */ );
   Vtemp_buffer_show_function = Qnil;
 
@@ -6129,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.
@@ -6145,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 /*
@@ -6164,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.
@@ -6179,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.
 
@@ -6197,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
@@ -6210,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.
@@ -6231,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
@@ -6239,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);
 }