Update FSF's address in the preamble.
[bpt/emacs.git] / src / window.c
index 347a1f5..41b8967 100644 (file)
@@ -1,6 +1,6 @@
 /* Window creation, deletion and examination for GNU Emacs.
    Does not include redisplay.
-   Copyright (C) 1985, 1986, 1987, 1993, 1994 Free Software Foundation, Inc.
+   Copyright (C) 1985, 86, 87, 93, 94, 95 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -16,7 +16,8 @@ GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
 along with GNU Emacs; see the file COPYING.  If not, write to
-the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
 
 #include <config.h>
 #include "lisp.h"
@@ -88,6 +89,15 @@ Lisp_Object Vspecial_display_regexps;
 /* Function to pop up a special frame.  */
 Lisp_Object Vspecial_display_function;
 
+/* List of buffer *names* for buffers to appear in selected window.  */
+Lisp_Object Vsame_window_buffer_names;
+
+/* List of regexps for buffer names to appear in selected window.  */
+Lisp_Object Vsame_window_regexps;
+
+/* Hook run at end of temp_output_buffer_show.  */
+Lisp_Object Qtemp_buffer_show_hook;
+
 /* Fdisplay_buffer always splits the largest window 
    if that window is more than this high.  */
 int split_height_threshold;
@@ -99,51 +109,53 @@ int next_screen_context_lines;
 static int sequence_number;
 
 #define min(a, b) ((a) < (b) ? (a) : (b))
+
+extern Lisp_Object Qwindow_scroll_functions, Vwindow_scroll_functions;
 \f
 DEFUN ("windowp", Fwindowp, Swindowp, 1, 1, 0,
-  "Returns t if OBJ is a window.")
-  (obj)
-     Lisp_Object obj;
+  "Returns t if OBJECT is a window.")
+  (object)
+     Lisp_Object object;
 {
-  return XTYPE (obj) == Lisp_Window ? Qt : Qnil;
+  return WINDOWP (object) ? Qt : Qnil;
 }
 
 DEFUN ("window-live-p", Fwindow_live_p, Swindow_live_p, 1, 1, 0,
-  "Returns t if OBJ is a window which is currently visible.")
-     (obj)
-     Lisp_Object obj;
+  "Returns t if OBJECT is a window which is currently visible.")
+     (object)
+     Lisp_Object object;
 {
-  return ((XTYPE (obj) == Lisp_Window
-          && ! NILP (XWINDOW (obj)->buffer))
-         ? Qt : Qnil);
+  return (WINDOWP (object) && ! NILP (XWINDOW (object)->buffer) ? Qt : Qnil);
 }
 
 Lisp_Object
 make_window ()
 {
-  register Lisp_Object val;
+  Lisp_Object val;
   register struct window *p;
-
-  /* Add sizeof (Lisp_Object) here because sizeof (struct Lisp_Vector)
-     includes the first element.  */
-  val = Fmake_vector (
-    make_number ((sizeof (struct window) - sizeof (struct Lisp_Vector)
-                 + sizeof (Lisp_Object))
-                / sizeof (Lisp_Object)),
-    Qnil);
-  XSETTYPE (val, Lisp_Window);
-  p = XWINDOW (val);
-  XFASTINT (p->sequence_number) = ++sequence_number;
-  XFASTINT (p->left) = XFASTINT (p->top)
-    = XFASTINT (p->height) = XFASTINT (p->width)
-      = XFASTINT (p->hscroll) = 0;
-  XFASTINT (p->last_point_x) = XFASTINT (p->last_point_y) = 0;
+  register struct Lisp_Vector *vec;
+  int i;
+
+  vec = allocate_vectorlike ((EMACS_INT) VECSIZE (struct window));
+  for (i = 0; i < VECSIZE (struct window); i++)
+    vec->contents[i] = Qnil;
+  vec->size = VECSIZE (struct window);
+  p = (struct window *)vec;
+  XSETFASTINT (p->sequence_number, ++sequence_number);
+  XSETFASTINT (p->left, 0);
+  XSETFASTINT (p->top, 0);
+  XSETFASTINT (p->height, 0);
+  XSETFASTINT (p->width, 0);
+  XSETFASTINT (p->hscroll, 0);
+  XSETFASTINT (p->last_point_x, 0);
+  XSETFASTINT (p->last_point_y, 0);
   p->start = Fmake_marker ();
   p->pointm = Fmake_marker ();
-  XFASTINT (p->use_time) = 0;
+  XSETFASTINT (p->use_time, 0);
   p->frame = Qnil;
   p->display_table = Qnil;
   p->dedicated = Qnil;
+  XSETWINDOW (val, p);
   return val;
 }
 
@@ -163,7 +175,7 @@ used by that frame.")
 {
 #ifdef MULTI_FRAME
   if (NILP (frame))
-    XSET (frame, Lisp_Frame, selected_frame);
+    XSETFRAME (frame, selected_frame);
   else
     CHECK_LIVE_FRAME (frame, 0);
 #endif
@@ -228,8 +240,12 @@ POS defaults to point; WINDOW, to the selected window.")
       if (posint > BUF_ZV (buf))
        return Qnil;
 
+      /* w->start can be out of range.  If it is, do something reasonable.  */
+      if (top < BUF_BEGV (buf) || top > BUF_ZV (buf))
+       return Qnil;
+
       /* If that info is not correct, calculate afresh */
-      posval = *compute_motion (top, 0, (hscroll ? 1 - hscroll : 0),
+      posval = *compute_motion (top, 0, (hscroll ? 1 - hscroll : 0), 0,
                                posint, height, 0,
                                window_internal_width (w) - 1,
                                hscroll, 0, w);
@@ -293,16 +309,42 @@ NCOL should be zero or positive.")
   register struct window *w;
 
   CHECK_NUMBER (ncol, 1);
-  if (XINT (ncol) < 0) XFASTINT (ncol) = 0;
-  if (XFASTINT (ncol) >= (1 << (SHORTBITS - 1)))
-    args_out_of_range (ncol, Qnil);
+  if (XINT (ncol) < 0) XSETFASTINT (ncol, 0);
   w = decode_window (window);
   if (XINT (w->hscroll) != XINT (ncol))
-    clip_changed = 1;          /* Prevent redisplay shortcuts */
+    XBUFFER (w->buffer)->clip_changed = 1; /* Prevent redisplay shortcuts */
   w->hscroll = ncol;
   return ncol;
 }
 
+DEFUN ("window-redisplay-end-trigger", Fwindow_redisplay_end_trigger,
+       Swindow_redisplay_end_trigger, 0, 1, 0,
+  "Return WINDOW's redisplay end trigger value.\n\
+See `set-window-redisplay-end-trigger' for more information.")
+  (window)
+     Lisp_Object window;
+{
+  return decode_window (window)->redisplay_end_trigger;
+}
+
+DEFUN ("set-window-redisplay-end-trigger", Fset_window_redisplay_end_trigger,
+       Sset_window_redisplay_end_trigger, 2, 2, 0,
+  "Set WINDOW's redisplay end trigger value to VALUE.\n\
+VALUE should be a buffer position (typically a marker) or nil.\n\
+If it is a buffer position, then if redisplay in WINDOW reaches a position\n\
+beyond VALUE, the functions in `redisplay-end-trigger-functions' are called\n\
+with two arguments: WINDOW, and the end trigger value.\n\
+Afterwards the end-trigger value is reset to nil.")
+  (window, value)
+     register Lisp_Object window, value;
+{
+  register struct window *w;
+
+  w = decode_window (window);
+  w->redisplay_end_trigger = value;
+  return value;
+}
+
 DEFUN ("window-edges", Fwindow_edges, Swindow_edges, 0, 1, 0,
   "Return a list of the edge coordinates of WINDOW.\n\
 \(LEFT TOP RIGHT BOTTOM), all relative to 0, 0 at top left corner of frame.\n\
@@ -444,7 +486,7 @@ column 0.")
 
 #ifdef MULTI_FRAME
   if (NILP (frame))
-    XSET (frame, Lisp_Frame, selected_frame);
+    XSETFRAME (frame, selected_frame);
   else
     CHECK_LIVE_FRAME (frame, 2);
 #endif
@@ -478,15 +520,30 @@ But that is hard to define.")
 }
 
 DEFUN ("window-start", Fwindow_start, Swindow_start, 0, 1, 0,
-  "Return position at which display currently starts in WINDOW.")
+  "Return position at which display currently starts in WINDOW.\n\
+This is updated by redisplay or by calling `set-window-start'.")
   (window)
      Lisp_Object window;
 {
   return Fmarker_position (decode_window (window)->start);
 }
 
+/* This is text temporarily removed from the doc string below.
+
+This function returns nil if the position is not currently known.\n\
+That happens when redisplay is preempted and doesn't finish.\n\
+If in that case you want to compute where the end of the window would\n\
+have been if redisplay had finished, do this:\n\
+    (save-excursion\n\
+      (goto-char (window-start window))\n\
+      (vertical-motion (1- (window-height window)) window)\n\
+      (point))")  */
+
 DEFUN ("window-end", Fwindow_end, Swindow_end, 0, 1, 0,
-  "Return position at which display currently ends in WINDOW.")
+  "Return position at which display currently ends in WINDOW.\n\
+This is updated by redisplay, when it runs to completion.\n\
+Simply changing the buffer text or setting `window-start'\n\
+does not update this value.")
   (window)
      Lisp_Object window;
 {
@@ -497,8 +554,17 @@ DEFUN ("window-end", Fwindow_end, Swindow_end, 0, 1, 0,
   buf = w->buffer;
   CHECK_BUFFER (buf, 0);
 
-  XSET (value, Lisp_Int,
-       BUF_Z (XBUFFER (buf)) - XFASTINT (w->window_end_pos));
+#if 0 /* This change broke some things.  We should make it later.  */
+  /* If we don't know the end position, return nil.
+     The user can compute it with vertical-motion if he wants to.
+     It would be nicer to do it automatically,
+     but that's so slow that it would probably bother people.  */
+  if (NILP (w->window_end_valid))
+    return Qnil;
+#endif
+
+  XSETINT (value,
+          BUF_Z (XBUFFER (buf)) - XFASTINT (w->window_end_pos));
 
   return value;
 }
@@ -535,7 +601,7 @@ from overriding motion of point in order to display at this exact start.")
   if (NILP (noforce))
     w->force_start = Qt;
   w->update_mode_line = Qt;
-  XFASTINT (w->last_modified) = 0;
+  XSETFASTINT (w->last_modified, 0);
   if (!EQ (window, selected_window))
     windows_or_buffers_changed++;
   return pos;
@@ -585,20 +651,20 @@ DEFUN ("window-display-table", Fwindow_display_table, Swindow_display_table,
    Ignore the specified tables if they are not valid;
    if no valid table is specified, return 0.  */
 
-struct Lisp_Vector *
+struct Lisp_Char_Table *
 window_display_table (w)
      struct window *w;
 {
   Lisp_Object tem;
   tem = w->display_table;
-  if (XTYPE (tem) == Lisp_Vector && XVECTOR (tem)->size == DISP_TABLE_SIZE)
-    return XVECTOR (tem);
+  if (DISP_TABLE_P (tem))
+    return XCHAR_TABLE (tem);
   tem = XBUFFER (w->buffer)->display_table;
-  if (XTYPE (tem) == Lisp_Vector && XVECTOR (tem)->size == DISP_TABLE_SIZE)
-    return XVECTOR (tem);
+  if (DISP_TABLE_P (tem))
+    return XCHAR_TABLE (tem);
   tem = Vstandard_display_table;
-  if (XTYPE (tem) == Lisp_Vector && XVECTOR (tem)->size == DISP_TABLE_SIZE)
-    return XVECTOR (tem);
+  if (DISP_TABLE_P (tem))
+    return XCHAR_TABLE (tem);
   return 0;
 }
 
@@ -723,6 +789,7 @@ DEFUN ("delete-window", Fdelete_window, Sdelete_window, 0, 1, "",
   par = XWINDOW (parent);
 
   windows_or_buffers_changed++;
+  FRAME_WINDOW_SIZES_CHANGED (XFRAME (WINDOW_FRAME (p))) = 1;
 
   /* Are we trying to delete any frame's selected window?  */
   {
@@ -843,13 +910,15 @@ minibuffer even if it is active.\n\
 \n\
 Several frames may share a single minibuffer; if the minibuffer\n\
 counts, all windows on all frames that share that minibuffer count\n\
-too.  This means that next-window may be used to iterate through the\n\
+too.  Therefore, `next-window' can be used to iterate through the\n\
 set of windows even when the minibuffer is on another frame.  If the\n\
 minibuffer does not count, only windows from WINDOW's frame count.\n\
 \n\
 Optional third arg ALL-FRAMES t means include windows on all frames.\n\
 ALL-FRAMES nil or omitted means cycle within the frames as specified\n\
 above.  ALL-FRAMES = `visible' means include windows on all visible frames.\n\
+ALL-FRAMES = 0 means include windows on all visible and iconified frames.\n\
+If ALL-FRAMES is a frame, restrict search to windows on that frame.\n\
 Anything else means restrict to WINDOW's frame.\n\
 \n\
 If you use consistent values for MINIBUF and ALL-FRAMES, you can use\n\
@@ -876,24 +945,36 @@ DEFUN ("next-window", Fnext_window, Snext_window, 0, 3, 0,
   /* minibuf == nil may or may not include minibuffers.
      Decide if it does.  */
   if (NILP (minibuf))
-    minibuf = (minibuf_level ? Qt : Qlambda);
+    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,
+     or a specific minibuffer window (the active one) to count.  */
 
 #ifdef MULTI_FRAME
-  /* all_frames == nil doesn't specify which frames to include.
-     Decide which frames it includes.  */
+  /* all_frames == nil doesn't specify which frames to include.  */
   if (NILP (all_frames))
-    all_frames = (EQ (minibuf, Qt)
-                  ? (FRAME_MINIBUF_WINDOW
-                     (XFRAME
-                      (WINDOW_FRAME
-                       (XWINDOW (window)))))
-                  : Qnil);
+    all_frames = (! EQ (minibuf, Qlambda)
+                 ? (FRAME_MINIBUF_WINDOW
+                    (XFRAME
+                     (WINDOW_FRAME
+                      (XWINDOW (window)))))
+                 : Qnil);
   else if (EQ (all_frames, Qvisible))
     ;
+  else if (XFASTINT (all_frames) == 0)
+    ;
+  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
+       return the first window on the frame.  */
+    return Fframe_first_window (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.  */
 #endif
 
@@ -913,7 +994,19 @@ DEFUN ("next-window", Fnext_window, Snext_window, 0, 3, 0,
            tem = WINDOW_FRAME (XWINDOW (window));
 #ifdef MULTI_FRAME
            if (! NILP (all_frames))
-             tem = next_frame (tem, all_frames);
+             {
+               Lisp_Object tem1;
+
+               tem1 = tem;
+               tem = next_frame (tem, all_frames);
+               /* 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.
+                  If that happens, go back to the selected frame
+                  so we can complete the cycle.  */
+               if (EQ (tem, tem1))
+                 XSETFRAME (tem, selected_frame);
+             }
 #endif
            tem = FRAME_ROOT_WINDOW (XFRAME (tem));
 
@@ -933,13 +1026,15 @@ DEFUN ("next-window", Fnext_window, Snext_window, 0, 3, 0,
          else break;
        }
     }
-  /* Which windows are acceptible?
+  /* Which windows are acceptable?
      Exit the loop and accept this window if
-     this isn't a minibuffer window, or
-     we're accepting minibuffer windows, or
+     this isn't a minibuffer window,
+     or we're accepting all minibuffer windows,
+     or this is the active minibuffer and we are accepting that one, or
      we've come all the way around and we're back at the original window.  */
   while (MINI_WINDOW_P (XWINDOW (window))
         && ! EQ (minibuf, Qt)
+        && ! EQ (minibuf, window)
         && ! EQ (window, start_window));
 
   return window;
@@ -950,7 +1045,7 @@ DEFUN ("next-window", Fnext_window, Snext_window, 0, 3, 0,
    due to limits in the Unix cpp.
 
 DEFUN ("previous-window", Ffoo, Sfoo, 0, 3, 0,
-  "Return the window preceeding WINDOW in canonical ordering of windows.\n\
+  "Return the window preceding WINDOW in canonical ordering of windows.\n\
 If omitted, WINDOW defaults to the selected window.\n\
 \n\
 Optional second arg MINIBUF t means count the minibuffer window even\n\
@@ -960,14 +1055,15 @@ minibuffer even if it is active.\n\
 \n\
 Several frames may share a single minibuffer; if the minibuffer\n\
 counts, all windows on all frames that share that minibuffer count\n\
-too.  This means that previous-window may be used to iterate through\n\
+too.  Therefore, `previous-window' can be used to iterate through\n\
 the set of windows even when the minibuffer is on another frame.  If\n\
-the minibuffer does not count, only windows from WINDOW's frame\n\
-count.\n\
+the minibuffer does not count, only windows from WINDOW's frame count\n\
 \n\
 Optional third arg ALL-FRAMES t means include windows on all frames.\n\
 ALL-FRAMES nil or omitted means cycle within the frames as specified\n\
 above.  ALL-FRAMES = `visible' means include windows on all visible frames.\n\
+ALL-FRAMES = 0 means include windows on all visible and iconified frames.\n\
+If ALL-FRAMES is a frame, restrict search to windows on that frame.\n\
 Anything else means restrict to WINDOW's frame.\n\
 \n\
 If you use consistent values for MINIBUF and ALL-FRAMES, you can use\n\
@@ -995,13 +1091,18 @@ DEFUN ("previous-window", Fprevious_window, Sprevious_window, 0, 3, 0,
   /* minibuf == nil may or may not include minibuffers.
      Decide if it does.  */
   if (NILP (minibuf))
-    minibuf = (minibuf_level ? Qt : Qlambda);
+    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,
+     or a specific minibuffer window (the active one) to count.  */
 
 #ifdef MULTI_FRAME
   /* all_frames == nil doesn't specify which frames to include.
      Decide which frames it includes.  */
   if (NILP (all_frames))
-    all_frames = (EQ (minibuf, Qt)
+    all_frames = (! EQ (minibuf, Qlambda)
                   ? (FRAME_MINIBUF_WINDOW
                      (XFRAME
                       (WINDOW_FRAME
@@ -1009,10 +1110,18 @@ DEFUN ("previous-window", Fprevious_window, Sprevious_window, 0, 3, 0,
                   : Qnil);
   else if (EQ (all_frames, Qvisible))
     ;
+  else if (XFASTINT (all_frames) == 0)
+    ;
+  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
+       return the first window on the frame.  */
+    return Fframe_first_window (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.  */
 #endif
 
@@ -1041,7 +1150,19 @@ DEFUN ("previous-window", Fprevious_window, Sprevious_window, 0, 3, 0,
                 paths through the set of acceptable windows.
                 window_loop assumes that these `ring' requirement are
                 met.  */
-             tem = prev_frame (tem, all_frames);
+             {
+               Lisp_Object tem1;
+
+               tem1 = tem;
+               tem = prev_frame (tem, all_frames);
+               /* 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.
+                  If that happens, go back to the selected frame
+                  so we can complete the cycle.  */
+               if (EQ (tem, tem1))
+                 XSETFRAME (tem, selected_frame);
+             }
 #endif
            /* If this frame has a minibuffer, find that window first,
               because it is conceptually the last window in that frame.  */
@@ -1069,12 +1190,14 @@ DEFUN ("previous-window", Fprevious_window, Sprevious_window, 0, 3, 0,
     }
   /* Which windows are acceptable?
      Exit the loop and accept this window if
-     this isn't a minibuffer window, or
-     we're accepting minibuffer windows, or
+     this isn't a minibuffer window,
+     or we're accepting all minibuffer windows,
+     or this is the active minibuffer and we are accepting that one, or
      we've come all the way around and we're back at the original window.  */
   while (MINI_WINDOW_P (XWINDOW (window))
-        && !EQ (minibuf, Qt)
-        && !EQ (window, start_window));
+        && ! EQ (minibuf, Qt)
+        && ! EQ (minibuf, window)
+        && ! EQ (window, start_window));
 
   return window;
 }
@@ -1085,15 +1208,15 @@ All windows on current frame are arranged in a cyclic order.\n\
 This command selects the window ARG steps away in that order.\n\
 A negative ARG moves in the opposite order.  If the optional second\n\
 argument ALL_FRAMES is non-nil, cycle through all frames.")
-  (n, all_frames)
-     register Lisp_Object n, all_frames;
+  (arg, all_frames)
+     register Lisp_Object arg, all_frames;
 {
   register int i;
   register Lisp_Object w;
 
-  CHECK_NUMBER (n, 0);
+  CHECK_NUMBER (arg, 0);
   w = selected_window;
-  i = XINT (n);
+  i = XINT (arg);
 
   while (i > 0)
     {
@@ -1155,6 +1278,8 @@ window_loop (type, obj, mini, frames)
     frame = 0;
   if (frame)
     frame_arg = Qlambda;
+  else if (XFASTINT (frames) == 0)
+    frame_arg = frames;
   else if (EQ (frames, Qvisible))
     frame_arg = frames;
 #else
@@ -1166,7 +1291,7 @@ window_loop (type, obj, mini, frames)
      or Qt otherwise.  */
 
   /* Pick a window to start with.  */
-  if (XTYPE (obj) == Lisp_Window)
+  if (WINDOWP (obj))
     w = obj;
   else if (frame)
     w = FRAME_SELECTED_WINDOW (frame);
@@ -1226,21 +1351,51 @@ window_loop (type, obj, mini, frames)
          case DELETE_BUFFER_WINDOWS:
            if (EQ (XWINDOW (w)->buffer, obj))
              {
-               /* If we're deleting the buffer displayed in the only window
-                  on the frame, find a new buffer to display there.  */
-               if (NILP (XWINDOW (w)->parent))
+#ifdef MULTI_FRAME
+               FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (w)));
+
+               /* If this window is dedicated, and in a frame of its own,
+                  kill the frame.  */
+               if (EQ (w, FRAME_ROOT_WINDOW (f))
+                   && !NILP (XWINDOW (w)->dedicated)
+                   && other_visible_frames (f))
                  {
-                   Lisp_Object new_buffer;
-                   new_buffer = Fother_buffer (obj, Qnil);
-                   if (NILP (new_buffer))
-                     new_buffer
-                       = Fget_buffer_create (build_string ("*scratch*"));
-                   Fset_window_buffer (w, new_buffer);
-                   if (EQ (w, selected_window))
-                     Fset_buffer (XWINDOW (w)->buffer);
+                   /* Skip the other windows on this frame.
+                      There might be one, the minibuffer!  */
+                   if (! EQ (w, last_window))
+                     while (f == 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);
+                       }
+                   /* Now we can safely delete the frame.  */
+                   Fdelete_frame (WINDOW_FRAME (XWINDOW (w)), Qnil);
                  }
                else
-                 Fdelete_window (w);
+#endif
+                 /* If we're deleting the buffer displayed in the only window
+                    on the frame, find a new buffer to display there.  */
+                 if (NILP (XWINDOW (w)->parent))
+                   {
+                     Lisp_Object new_buffer;
+                     new_buffer = Fother_buffer (obj, Qnil);
+                     if (NILP (new_buffer))
+                       new_buffer
+                         = Fget_buffer_create (build_string ("*scratch*"));
+                     Fset_window_buffer (w, new_buffer);
+                     if (EQ (w, selected_window))
+                       Fset_buffer (XWINDOW (w)->buffer);
+                   }
+                 else
+                   Fdelete_window (w);
              }
            break;
 
@@ -1276,7 +1431,26 @@ window_loop (type, obj, mini, frames)
                if (EQ (w, FRAME_ROOT_WINDOW (f))
                    && !NILP (XWINDOW (w)->dedicated)
                    && other_visible_frames (f))
-                 Fdelete_frame (WINDOW_FRAME (XWINDOW (w)), Qnil);
+                 {
+                   /* Skip the other windows on this frame.
+                      There might be one, the minibuffer!  */
+                   if (! EQ (w, last_window))
+                     while (f == 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);
+                       }
+                   /* Now we can safely delete the frame.  */
+                   Fdelete_frame (WINDOW_FRAME (XWINDOW (w)), Qnil);
+                 }
                else
 #endif
                  {
@@ -1302,6 +1476,7 @@ window_loop (type, obj, mini, frames)
 DEFUN ("get-lru-window", Fget_lru_window, Sget_lru_window, 0, 1, 0,
   "Return the window least recently selected or used for display.\n\
 If optional argument FRAME is `visible', search all visible frames.\n\
+If FRAME is 0, search all visible and iconified frames.\n\
 If FRAME is t, search all frames.\n\
 If FRAME is nil, search only the selected frame.\n\
 If FRAME is a frame, search only that frame.")
@@ -1320,6 +1495,7 @@ If FRAME is a frame, search only that frame.")
 DEFUN ("get-largest-window", Fget_largest_window, Sget_largest_window, 0, 1, 0,
   "Return the largest window in area.\n\
 If optional argument FRAME is `visible', search all visible frames.\n\
+If FRAME is 0, search all visible and iconified frames.\n\
 If FRAME is t, search all frames.\n\
 If FRAME is nil, search only the selected frame.\n\
 If FRAME is a frame, search only that frame.")
@@ -1333,6 +1509,7 @@ If FRAME is a frame, search only that frame.")
 DEFUN ("get-buffer-window", Fget_buffer_window, Sget_buffer_window, 1, 2, 0,
   "Return a window currently displaying BUFFER, or nil if none.\n\
 If optional argument FRAME is `visible', search all visible frames.\n\
+If optional argument FRAME is 0, search all visible and iconified frames.\n\
 If FRAME is t, search all frames.\n\
 If FRAME is nil, search only the selected frame.\n\
 If FRAME is a frame, search only that frame.")
@@ -1340,7 +1517,7 @@ If FRAME is a frame, search only that frame.")
     Lisp_Object buffer, frame;
 {
   buffer = Fget_buffer (buffer);
-  if (XTYPE (buffer) == Lisp_Buffer)
+  if (BUFFERP (buffer))
     return window_loop (GET_BUFFER_WINDOW, buffer, 1, frame);
   else
     return Qnil;
@@ -1369,9 +1546,13 @@ value is reasonable when this function is called.")
     CHECK_LIVE_WINDOW (window, 0);
 
   w = XWINDOW (window);
+
   startpos = marker_position (w->start);
   top = XFASTINT (w->top) - FRAME_MENU_BAR_LINES (XFRAME (WINDOW_FRAME (w)));
 
+  if (MINI_WINDOW_P (w) && top > 0)
+    error ("Can't expand minibuffer to full frame");
+
   window_loop (DELETE_OTHER_WINDOWS, window, 0, WINDOW_FRAME (w));
 
   /* Try to minimize scrolling, by setting the window start to the point
@@ -1388,12 +1569,14 @@ value is reasonable when this function is called.")
       Fset_buffer (w->buffer);
       /* This computation used to temporarily move point, but that can
         have unwanted side effects due to text properties.  */
-      pos = *vmotion (startpos, -top, window_internal_width (w) - 1,
-                     XINT (w->hscroll), window);
+      pos = *vmotion (startpos, -top, w);
       Fset_marker (w->start, make_number (pos.bufpos), w->buffer);
       w->start_at_line_beg = ((pos.bufpos == BEGV
                               || FETCH_CHAR (pos.bufpos - 1) == '\n') ? Qt
                              : Qnil);
+      /* We need to do this, so that the window-scroll-functions
+        get called.  */
+      w->force_start = Qt;
 
       set_buffer_internal (obuf);
     }
@@ -1444,6 +1627,37 @@ DEFUN ("replace-buffer-in-windows", Freplace_buffer_in_windows,
     }
   return Qnil;
 }
+
+/* Replace BUFFER with some other buffer in all windows
+   of all frames, even those on other keyboards.  */
+
+void
+replace_buffer_in_all_windows (buffer)
+     Lisp_Object buffer;
+{
+  Lisp_Object tail, frame;
+
+#ifdef MULTI_FRAME
+  Lisp_Object old_selected;
+
+  old_selected = selected_window;
+
+  /* A single call to window_loop won't do the job
+     because it only considers frames on the current keyboard.
+     So loop manually over frames, and handle each one.  */
+  FOR_EACH_FRAME (tail, frame)
+    {
+      Fselect_window (FRAME_SELECTED_WINDOW (XFRAME (frame)));
+
+      window_loop (UNSHOW_BUFFER, buffer, 0, frame);
+    }
+
+  if (!NILP (Fwindow_live_p (old_selected)))
+    Fselect_window (old_selected);
+#else
+  window_loop (UNSHOW_BUFFER, buffer, 0, Qt);
+#endif
+}
 \f
 /* Set the height of WINDOW and all its inferiors.  */
 
@@ -1514,9 +1728,11 @@ set_window_height (window, height, nodelete)
       return;
     }
 
-  XFASTINT (w->last_modified) = 0;
+  XSETFASTINT (w->last_modified, 0);
   windows_or_buffers_changed++;
-  XFASTINT (w->height) = height;
+  FRAME_WINDOW_SIZES_CHANGED (XFRAME (WINDOW_FRAME (w))) = 1;
+
+  XSETFASTINT (w->height, height);
   if (!NILP (w->hchild))
     {
       for (child = w->hchild; !NILP (child); child = XWINDOW (child)->next)
@@ -1535,7 +1751,7 @@ set_window_height (window, height, nodelete)
 
          opos = lastobot + XFASTINT (c->height);
 
-         XFASTINT (c->top) = lastbot;
+         XSETFASTINT (c->top, lastbot);
 
          pos = (((opos * height) << 1) + oheight) / (oheight << 1);
 
@@ -1575,9 +1791,11 @@ set_window_width (window, width, nodelete)
       return;
     }
 
-  XFASTINT (w->last_modified) = 0;
+  XSETFASTINT (w->last_modified, 0);
   windows_or_buffers_changed++;
-  XFASTINT (w->width) = width;
+  FRAME_WINDOW_SIZES_CHANGED (XFRAME (WINDOW_FRAME (w))) = 1;
+
+  XSETFASTINT (w->width, width);
   if (!NILP (w->vchild))
     {
       for (child = w->vchild; !NILP (child); child = XWINDOW (child)->next)
@@ -1596,7 +1814,7 @@ set_window_width (window, width, nodelete)
 
          opos = lastoright + XFASTINT (c->width);
 
-         XFASTINT (c->left) = lastright;
+         XSETFASTINT (c->left, lastright);
 
          pos = (((opos * width) << 1) + owidth) / (owidth << 1);
 
@@ -1647,9 +1865,9 @@ BUFFER can be a buffer or buffer name.")
     }
 
   w->buffer = buffer;
-  w->window_end_pos = 0;
+  XSETFASTINT (w->window_end_pos, 0);
   w->window_end_valid = Qnil;
-  w->hscroll = 0;
+  XSETFASTINT (w->hscroll, 0);
   Fset_marker (w->pointm,
               make_number (BUF_PT (XBUFFER (buffer))),
               buffer);
@@ -1658,10 +1876,13 @@ BUFFER can be a buffer or buffer name.")
                         buffer);
   w->start_at_line_beg = Qnil;
   w->force_start = Qnil;
-  XFASTINT (w->last_modified) = 0;
+  XSETFASTINT (w->last_modified, 0);
   windows_or_buffers_changed++;
   if (EQ (window, selected_window))
     Fset_buffer (buffer);
+  if (! NILP (Vwindow_scroll_functions))
+    run_hook_with_args_2 (Qwindow_scroll_functions, window,
+                         Fmarker_position (w->start));
 
   return Qnil;
 }
@@ -1683,7 +1904,7 @@ before each command.")
   if (NILP (w->buffer))
     error ("Trying to select deleted window or non-leaf window");
 
-  XFASTINT (w->use_time) = ++window_select_count;
+  XSETFASTINT (w->use_time, ++window_select_count);
   if (EQ (window, selected_window))
     return window;
 
@@ -1717,7 +1938,7 @@ before each command.")
     register int new_point = marker_position (w->pointm);
     if (new_point < BEGV)
       SET_PT (BEGV);
-    if (new_point > ZV)
+    else if (new_point > ZV)
       SET_PT (ZV);
     else
       SET_PT (new_point);
@@ -1727,8 +1948,32 @@ before each command.")
   return window;
 }
 
+/* Deiconify the frame containing the window WINDOW,
+   unless it is the selected frame;
+   then return WINDOW.
+
+   The reason for the exception for the selected frame
+   is that it seems better not to change the selected frames visibility
+   merely because of displaying a different buffer in it.
+   The deiconification is useful when a buffer gets shown in
+   another frame that you were not using lately.  */
+
+static Lisp_Object
+display_buffer_1 (window)
+     Lisp_Object window;
+{
+#ifdef MULTI_FRAME
+  FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (window)));
+  FRAME_SAMPLE_VISIBILITY (f);
+  if (FRAME_ICONIFIED_P (f)
+      && f != selected_frame)
+    Fmake_frame_visible (WINDOW_FRAME (XWINDOW (window)));
+#endif
+  return window;
+}
+
 DEFUN ("display-buffer", Fdisplay_buffer, Sdisplay_buffer, 1, 2,
-       "BDisplay buffer: \nP",
+       "bDisplay buffer: \nP",
   "Make BUFFER appear in some window but don't select it.\n\
 BUFFER can be a buffer or a buffer name.\n\
 If BUFFER is shown already in some window, just use that one,\n\
@@ -1749,18 +1994,61 @@ Returns the window displaying BUFFER.")
 
   if (NILP (not_this_window)
       && XBUFFER (XWINDOW (selected_window)->buffer) == XBUFFER (buffer))
-    return selected_window;
+    return display_buffer_1 (selected_window);
+
+  /* See if the user has specified this buffer should appear
+     in the selected window.  */
+  if (NILP (not_this_window))
+    {
+      tem = Fmember (XBUFFER (buffer)->name, Vsame_window_buffer_names);
+      if (!NILP (tem))
+       {
+         Fswitch_to_buffer (buffer, Qnil);
+         return display_buffer_1 (selected_window);
+       }
+
+      tem = Fassoc (XBUFFER (buffer)->name, Vsame_window_buffer_names);
+      if (!NILP (tem))
+       {
+         Fswitch_to_buffer (buffer, Qnil);
+         return display_buffer_1 (selected_window);
+       }
+
+      for (tem = Vsame_window_regexps; CONSP (tem); tem = XCONS (tem)->cdr)
+       {
+         Lisp_Object car = XCONS (tem)->car;
+         if (STRINGP (car)
+             && fast_string_match (car, XBUFFER (buffer)->name) >= 0)
+           {
+             Fswitch_to_buffer (buffer, Qnil);
+             return display_buffer_1 (selected_window);
+           }
+         else if (CONSP (car)
+                  && STRINGP (XCONS (car)->car)
+                  && fast_string_match (XCONS (car)->car,
+                                        XBUFFER (buffer)->name) >= 0)
+           {
+             Fswitch_to_buffer (buffer, Qnil);
+             return display_buffer_1 (selected_window);
+           }
+       }
+    }
 
 #ifdef MULTI_FRAME
   /* If pop_up_frames,
-     look for a window showing BUFFER on any visible frame.  */
-  window = Fget_buffer_window (buffer, pop_up_frames ? Qvisible : Qnil);
-#else
-  window = Fget_buffer_window (buffer, Qnil);
+     look for a window showing BUFFER on any visible or iconified frame.
+     Otherwise search only the current frame.  */
+  if (pop_up_frames || last_nonminibuf_frame == 0)
+    XSETFASTINT (tem, 0);
+  else
 #endif
+    XSETFRAME (tem, last_nonminibuf_frame);
+  window = Fget_buffer_window (buffer, tem);
   if (!NILP (window)
       && (NILP (not_this_window) || !EQ (window, selected_window)))
-    return window;
+    {
+      return display_buffer_1 (window);
+    }
 
   /* Certain buffer names get special handling.  */
   if (! NILP (Vspecial_display_function))
@@ -1769,9 +2057,24 @@ Returns the window displaying BUFFER.")
       if (!NILP (tem))
        return call1 (Vspecial_display_function, buffer);
 
+      tem = Fassoc (XBUFFER (buffer)->name, Vspecial_display_buffer_names);
+      if (!NILP (tem))
+       return call2 (Vspecial_display_function, buffer, XCONS (tem)->cdr);
+      
       for (tem = Vspecial_display_regexps; CONSP (tem); tem = XCONS (tem)->cdr)
-       if (fast_string_match (XCONS (tem)->car, XBUFFER (buffer)->name) >= 0)
-         return call1 (Vspecial_display_function, buffer);
+       {
+         Lisp_Object car = XCONS (tem)->car;
+         if (STRINGP (car)
+             && fast_string_match (car, XBUFFER (buffer)->name) >= 0)
+           return call1 (Vspecial_display_function, buffer);
+         else if (CONSP (car)
+                  && STRINGP (XCONS (car)->car)
+                  && fast_string_match (XCONS (car)->car,
+                                        XBUFFER (buffer)->name) >= 0)
+           return call2 (Vspecial_display_function,
+                         buffer,
+                         XCONS (car)->cdr);
+       }
     }
 
 #ifdef MULTI_FRAME
@@ -1781,13 +2084,16 @@ Returns the window displaying BUFFER.")
     {
       window = Fframe_selected_window (call0 (Vpop_up_frame_function));
       Fset_window_buffer (window, buffer);
-      return window;
+      return display_buffer_1 (window);
     }
 #endif /* MULTI_FRAME */
 
   if (pop_up_windows
 #ifdef MULTI_FRAME
       || FRAME_MINIBUF_ONLY_P (selected_frame)
+      /* If the current frame is a special display frame,
+        don't try to reuse its windows.  */
+      || !NILP (XWINDOW (FRAME_ROOT_WINDOW (selected_frame))->dedicated)
 #endif
       )
     {
@@ -1796,33 +2102,101 @@ Returns the window displaying BUFFER.")
       frames = Qnil;      
 #ifdef MULTI_FRAME
       if (FRAME_MINIBUF_ONLY_P (selected_frame))
-       XSET (frames, Lisp_Frame, last_nonminibuf_frame);
+       XSETFRAME (frames, last_nonminibuf_frame);
 #endif
       /* Don't try to create a window if would get an error */
       if (split_height_threshold < window_min_height << 1)
        split_height_threshold = window_min_height << 1;
 
-      window = Fget_largest_window (frames);
+      /* Note that both Fget_largest_window and Fget_lru_window
+        ignore minibuffers and dedicated windows.
+        This means they can return nil.  */
+
+#ifdef MULTI_FRAME
+      /* If the frame we would try to split cannot be split,
+        try other frames.  */
+      if (FRAME_NO_SPLIT_P (NILP (frames) ? selected_frame
+                           : last_nonminibuf_frame))
+       {
+         /* Try visible frames first.  */
+         window = Fget_largest_window (Qvisible);
+         /* If that didn't work, try iconified frames.  */
+         if (NILP (window))
+           window = Fget_largest_window (make_number (0));
+         if (NILP (window))
+           window = Fget_largest_window (Qt);
+       }
+      else
+#endif
+       window = Fget_largest_window (frames);
 
+      /* If we got a tall enough full-width window that can be split,
+        split it.  */
       if (!NILP (window)
+         && ! FRAME_NO_SPLIT_P (XFRAME (XWINDOW (window)->frame))
          && window_height (window) >= split_height_threshold
          && (XFASTINT (XWINDOW (window)->width)
              == FRAME_WIDTH (XFRAME (WINDOW_FRAME (XWINDOW (window))))))
        window = Fsplit_window (window, Qnil, Qnil);
       else
        {
+         Lisp_Object upper, lower, other;
+
          window = Fget_lru_window (frames);
-         if ((EQ (window, selected_window)
-              || EQ (XWINDOW (window)->parent, Qnil))
+         /* If the LRU window is selected, and big enough,
+            and can be split, split it.  */
+         if (!NILP (window)
+             && ! FRAME_NO_SPLIT_P (XFRAME (XWINDOW (window)->frame))
+             && (EQ (window, selected_window)
+                 || EQ (XWINDOW (window)->parent, Qnil))
              && window_height (window) >= window_min_height << 1)
            window = Fsplit_window (window, Qnil, Qnil);
+#ifdef MULTI_FRAME
+         /* If Fget_lru_window returned nil, try other approaches.  */
+         /* Try visible frames first.  */
+         if (NILP (window))
+           window = Fget_largest_window (Qvisible);
+         /* If that didn't work, try iconified frames.  */
+         if (NILP (window))
+           window = Fget_largest_window (make_number (0));
+         /* Try invisible frames.  */
+         if (NILP (window))
+           window = Fget_largest_window (Qt);
+         /* As a last resort, make a new frame.  */
+         if (NILP (window))
+           window = Fframe_selected_window (call0 (Vpop_up_frame_function));
+#else
+         /* As a last resort, use a non minibuffer window.  */
+         if (NILP (window))
+           window = Fframe_first_window (Fselected_frame ());
+#endif
+         /* If window appears above or below another,
+            even out their heights.  */
+         other = upper = lower = Qnil;
+         if (!NILP (XWINDOW (window)->prev))
+           other = upper = XWINDOW (window)->prev, lower = window;
+         if (!NILP (XWINDOW (window)->next))
+           other = lower = XWINDOW (window)->next, upper = window;
+         if (!NILP (other)
+             /* Check that OTHER and WINDOW are vertically arrayed.  */
+             && XWINDOW (other)->top != XWINDOW (window)->top
+             && XWINDOW (other)->height > XWINDOW (window)->height)
+           {
+             int total = XWINDOW (other)->height + XWINDOW (window)->height;
+             Lisp_Object old_selected_window;
+             old_selected_window = selected_window;
+
+             selected_window = upper;
+             change_window_height (total / 2 - XWINDOW (upper)->height, 0);
+             selected_window = old_selected_window;
+           }
        }
     }
   else
     window = Fget_lru_window (Qnil);
 
   Fset_window_buffer (window, buffer);
-  return window;
+  return display_buffer_1 (window);
 }
 
 void
@@ -1834,11 +2208,11 @@ temp_output_buffer_show (buf)
   register struct window *w;
 
   Fset_buffer (buf);
-  XBUFFER (buf)->save_modified = MODIFF;
+  BUF_SAVE_MODIFF (XBUFFER (buf)) = MODIFF;
   BEGV = BEG;
   ZV = Z;
   SET_PT (BEG);
-  clip_changed = 1;
+  XBUFFER (buf)->clip_changed = 1;
   set_buffer_internal (old);
 
   if (!EQ (Vtemp_buffer_show_function, Qnil))
@@ -1853,9 +2227,32 @@ temp_output_buffer_show (buf)
 #endif /* MULTI_FRAME */
       Vminibuf_scroll_window = window;
       w = XWINDOW (window);
-      XFASTINT (w->hscroll) = 0;
+      XSETFASTINT (w->hscroll, 0);
       set_marker_restricted (w->start, make_number (1), buf);
       set_marker_restricted (w->pointm, make_number (1), buf);
+
+      /* Run temp-buffer-show-hook, with the chosen window selected.  */ 
+      if (!NILP (Vrun_hooks))
+       {
+         Lisp_Object tem;
+         tem = Fboundp (Qtemp_buffer_show_hook);
+         if (!NILP (tem))
+           {
+             tem = Fsymbol_value (Qtemp_buffer_show_hook);
+             if (!NILP (tem))
+               {
+                 int count = specpdl_ptr - specpdl;
+
+                 /* Select the window that was chosen, for running the hook.  */
+                 record_unwind_protect (Fset_window_configuration,
+                                        Fcurrent_window_configuration (Qnil));
+
+                 Fselect_window (window);
+                 call1 (Vrun_hooks, Qtemp_buffer_show_hook);
+                 unbind_to (count, Qnil);
+               }
+           }
+       }
     }
 }
 \f
@@ -1863,17 +2260,20 @@ static
 make_dummy_parent (window)
      Lisp_Object window;
 {
-  register Lisp_Object old, new;
+  Lisp_Object new;
   register struct window *o, *p;
+  register struct Lisp_Vector *vec;
+  int i;
 
-  old = window;
-  XSETTYPE (old, Lisp_Vector);
-  new = Fcopy_sequence (old);
-  XSETTYPE (new, Lisp_Window);
+  o = XWINDOW (window);
+  vec = allocate_vectorlike ((EMACS_INT)VECSIZE (struct window));
+  for (i = 0; i < VECSIZE (struct window); ++i)
+    vec->contents[i] = ((struct Lisp_Vector *)o)->contents[i];
+  vec->size = VECSIZE (struct window);
+  p = (struct window *)vec;
+  XSETWINDOW (new, p);
 
-  o = XWINDOW (old);
-  p = XWINDOW (new);
-  XFASTINT (p->sequence_number) = ++sequence_number;
+  XSETFASTINT (p->sequence_number, ++sequence_number);
 
   /* Put new into window structure in place of window */
   replace_window (window, new);
@@ -1892,14 +2292,17 @@ make_dummy_parent (window)
 DEFUN ("split-window", Fsplit_window, Ssplit_window, 0, 3, "",
   "Split WINDOW, putting SIZE lines in the first of the pair.\n\
 WINDOW defaults to selected one and SIZE to half its size.\n\
-If optional third arg HOR-FLAG is non-nil, split side by side\n\
+If optional third arg HORFLAG is non-nil, split side by side\n\
 and put SIZE columns in the first of the pair.")
-  (window, chsize, horflag)
-     Lisp_Object window, chsize, horflag;
+  (window, size, horflag)
+     Lisp_Object window, size, horflag;
 {
   register Lisp_Object new;
   register struct window *o, *p;
-  register int size;
+  FRAME_PTR fo;
+  register int size_int;
+  int internal_width;
+  int separator_width = 1;
 
   if (NILP (window))
     window = selected_window;
@@ -1907,34 +2310,40 @@ and put SIZE columns in the first of the pair.")
     CHECK_LIVE_WINDOW (window, 0);
 
   o = XWINDOW (window);
+  fo = XFRAME (WINDOW_FRAME (o));
+  if (FRAME_HAS_VERTICAL_SCROLL_BARS (fo))
+    separator_width = FRAME_SCROLL_BAR_COLS (fo);
+  internal_width = window_internal_width (o);
 
-  if (NILP (chsize))
+  if (NILP (size))
     {
       if (!NILP (horflag))
-       /* Round odd size up, since this is for the left-hand window,
-          and it will lose a column for the separators.  */
-       size = ((XFASTINT (o->width) + 1) & -2) >> 1;
+       /* Calculate the size of the left-hand window, by dividing
+          the usable space in columns by two. */
+       size_int = (internal_width - separator_width) >> 1;
       else
-       size = XFASTINT (o->height) >> 1;
+       size_int = XFASTINT (o->height) >> 1;
     }
   else
     {
-      CHECK_NUMBER (chsize, 1);
-      size = XINT (chsize);
+      CHECK_NUMBER (size, 1);
+      size_int = XINT (size);
     }
 
   if (MINI_WINDOW_P (o))
     error ("Attempt to split minibuffer window");
-  else if (FRAME_NO_SPLIT_P (XFRAME (WINDOW_FRAME (o))))
+  else if (FRAME_NO_SPLIT_P (fo))
     error ("Attempt to split unsplittable frame");
 
   check_min_window_sizes ();
 
   if (NILP (horflag))
     {
-      if (size < window_min_height
-         || size + window_min_height > XFASTINT (o->height))
-       args_out_of_range_3 (window, chsize, horflag);
+      if (size_int < window_min_height)
+       error ("Window height %d too small (after splitting)", size_int);
+      if (size_int + window_min_height > XFASTINT (o->height))
+       error ("Window height %d too small (after splitting)", 
+              XFASTINT (o->height) - size_int);
       if (NILP (o->parent)
          || NILP (XWINDOW (o->parent)->vchild))
        {
@@ -1945,9 +2354,11 @@ and put SIZE columns in the first of the pair.")
     }
   else
     {
-      if (size < window_min_width
-         || size + window_min_width > XFASTINT (o->width))
-       args_out_of_range_3 (window, chsize, horflag);
+      if (size_int < window_min_width)
+       error ("Window width %d too small (after splitting)", size_int);
+      if (internal_width - size_int - separator_width < window_min_width)
+       error ("Window width %d too small (after splitting)", 
+              internal_width - size_int - separator_width);
       if (NILP (o->parent)
          || NILP (XWINDOW (o->parent)->hchild))
        {
@@ -1962,6 +2373,7 @@ and put SIZE columns in the first of the pair.")
      if we are making side-by-side windows */
 
   windows_or_buffers_changed++;
+  FRAME_WINDOW_SIZES_CHANGED (fo) = 1;
   new = make_window ();
   p = XWINDOW (new);
 
@@ -1982,17 +2394,18 @@ and put SIZE columns in the first of the pair.")
     {
       p->height = o->height;
       p->top = o->top;
-      XFASTINT (p->width) = XFASTINT (o->width) - size;
-      XFASTINT (o->width) = size;
-      XFASTINT (p->left) = XFASTINT (o->left) + size;
+      size_int += separator_width;
+      XSETFASTINT (p->width, internal_width - size_int);
+      XSETFASTINT (o->width, size_int);
+      XSETFASTINT (p->left, XFASTINT (o->left) + size_int);
     }
   else
     {
       p->left = o->left;
       p->width = o->width;
-      XFASTINT (p->height) = XFASTINT (o->height) - size;
-      XFASTINT (o->height) = size;
-      XFASTINT (p->top) = XFASTINT (o->top) + size;
+      XSETFASTINT (p->height, XFASTINT (o->height) - size_int);
+      XSETFASTINT (o->height, size_int);
+      XSETFASTINT (p->top, XFASTINT (o->top) + size_int);
     }
 
   return new;
@@ -2001,22 +2414,22 @@ and put SIZE columns in the first of the pair.")
 DEFUN ("enlarge-window", Fenlarge_window, Senlarge_window, 1, 2, "p",
   "Make current window ARG lines bigger.\n\
 From program, optional second arg non-nil means grow sideways ARG columns.")
-  (n, side)
-     register Lisp_Object n, side;
+  (arg, side)
+     register Lisp_Object arg, side;
 {
-  CHECK_NUMBER (n, 0);
-  change_window_height (XINT (n), !NILP (side));
+  CHECK_NUMBER (arg, 0);
+  change_window_height (XINT (arg), !NILP (side));
   return Qnil;
 }
 
 DEFUN ("shrink-window", Fshrink_window, Sshrink_window, 1, 2, "p",
   "Make current window ARG lines smaller.\n\
-From program, optional second arg non-nil means shrink sideways ARG columns.")
-  (n, side)
-     register Lisp_Object n, side;
+From program, optional second arg non-nil means shrink sideways arg columns.")
+  (arg, side)
+     register Lisp_Object arg, side;
 {
-  CHECK_NUMBER (n, 0);
-  change_window_height (-XINT (n), !NILP (side));
+  CHECK_NUMBER (arg, 0);
+  change_window_height (-XINT (arg), !NILP (side));
   return Qnil;
 }
 
@@ -2158,7 +2571,7 @@ change_window_height (delta, widthflag)
       (*setsizefun) (parent, opht, 0);
     }
 
-  XFASTINT (p->last_modified) = 0;
+  XSETFASTINT (p->last_modified, 0);
 }
 #undef MINSIZE
 #undef CURBEG
@@ -2206,7 +2619,7 @@ window_internal_width (w)
 
   /* Scroll bars occupy a few columns.  */
   if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
-    return width - VERTICAL_SCROLL_BAR_WIDTH;
+    return width - FRAME_SCROLL_BAR_COLS (f);
 
   /* The column of `|' characters separating side-by-side windows
      occupies one column only.  */
@@ -2230,15 +2643,18 @@ window_scroll (window, n, noerror)
   int lose;
   Lisp_Object bolp, nmoved;
 
-  XFASTINT (tem) = PT;
+  /* Always set force_start so that redisplay_window will run
+     the window-scroll-functions.  */
+  w->force_start = Qt;
+
+  XSETFASTINT (tem, PT);
   tem = Fpos_visible_in_window_p (tem, window);
 
   if (NILP (tem))
     {
       Fvertical_motion (make_number (- (ht / 2)), window);
-      XFASTINT (tem) = PT;
+      XSETFASTINT (tem, PT);
       Fset_marker (w->start, tem, w->buffer);
-      w->force_start = Qt;
     }
 
   SET_PT (marker_position (w->start));
@@ -2261,7 +2677,7 @@ window_scroll (window, n, noerror)
       set_marker_restricted (w->start, make_number (pos), w->buffer);
       w->start_at_line_beg = bolp;
       w->update_mode_line = Qt;
-      XFASTINT (w->last_modified) = 0;
+      XSETFASTINT (w->last_modified, 0);
       if (pos > opoint)
        SET_PT (pos);
       if (n < 0)
@@ -2323,10 +2739,10 @@ DEFUN ("scroll-up", Fscroll_up, Sscroll_up, 0, 1, "P",
 A near full screen is `next-screen-context-lines' less than a full screen.\n\
 Negative ARG means scroll downward.\n\
 When calling from a program, supply a number as argument or nil.")
-  (n)
-     Lisp_Object n;
+  (arg)
+     Lisp_Object arg;
 {
-  scroll_command (n, 1);
+  scroll_command (arg, 1);
   return Qnil;
 }
 
@@ -2335,10 +2751,10 @@ DEFUN ("scroll-down", Fscroll_down, Sscroll_down, 0, 1, "P",
 A near full screen is `next-screen-context-lines' less than a full screen.\n\
 Negative ARG means scroll upward.\n\
 When calling from a program, supply a number as argument or nil.")
-  (n)
-     Lisp_Object n;
+  (arg)
+     Lisp_Object arg;
 {
-  scroll_command (n, -1);
+  scroll_command (arg, -1);
   return Qnil;
 }
 \f
@@ -2348,6 +2764,7 @@ If in the minibuffer, `minibuffer-scroll-window' if non-nil\n\
 specifies the window.\n\
 If `other-window-scroll-buffer' is non-nil, a window\n\
 showing that buffer is used.")
+  ()
 {
   Lisp_Object window;
 
@@ -2394,18 +2811,19 @@ If in the minibuffer, `minibuffer-scroll-window' if non-nil\n\
 specifies the window to scroll.\n\
 If `other-window-scroll-buffer' is non-nil, scroll the window\n\
 showing that buffer, popping the buffer up if necessary.")
-  (n)
-     register Lisp_Object n;
+  (arg)
+     register Lisp_Object arg;
 {
   register Lisp_Object window;
-  register int ht;
+  register int defalt;
   register struct window *w;
   register int count = specpdl_ptr - specpdl;
 
   window = Fother_window_for_scrolling ();
 
   w = XWINDOW (window);
-  ht = window_internal_height (w);
+  defalt = window_internal_height (w) - next_screen_context_lines;
+  if (defalt < 1) defalt = 1;
 
   /* Don't screw up if window_scroll gets an error.  */
   record_unwind_protect (save_excursion_restore, save_excursion_save ());
@@ -2413,16 +2831,16 @@ showing that buffer, popping the buffer up if necessary.")
   Fset_buffer (w->buffer);
   SET_PT (marker_position (w->pointm));
 
-  if (NILP (n))
-    window_scroll (window, ht - next_screen_context_lines, 1);
-  else if (EQ (n, Qminus))
-    window_scroll (window, next_screen_context_lines - ht, 1);
+  if (NILP (arg))
+    window_scroll (window, defalt, 1);
+  else if (EQ (arg, Qminus))
+    window_scroll (window, -defalt, 1);
   else
     {
-      if (XTYPE (n) == Lisp_Cons)
-       n = Fcar (n);
-      CHECK_NUMBER (n, 0);
-      window_scroll (window, XINT (n), 1);
+      if (CONSP (arg))
+       arg = Fcar (arg);
+      CHECK_NUMBER (arg, 0);
+      window_scroll (window, XINT (arg), 1);
     }
 
   Fset_marker (w->pointm, make_number (PT), Qnil);
@@ -2439,7 +2857,7 @@ Default for ARG is window width minus 2.")
 {
 
   if (NILP (arg))
-    XFASTINT (arg) = window_internal_width (XWINDOW (selected_window)) - 2;
+    XSETFASTINT (arg, window_internal_width (XWINDOW (selected_window)) - 2);
   else
     arg = Fprefix_numeric_value (arg);
 
@@ -2456,7 +2874,7 @@ Default for ARG is window width minus 2.")
      register Lisp_Object arg;
 {
   if (NILP (arg))
-    XFASTINT (arg) = window_internal_width (XWINDOW (selected_window)) - 2;
+    XSETFASTINT (arg, window_internal_width (XWINDOW (selected_window)) - 2);
   else
     arg = Fprefix_numeric_value (arg);
 
@@ -2470,44 +2888,41 @@ DEFUN ("recenter", Frecenter, Srecenter, 0, 1, "P",
   "Center point in window and redisplay frame.  With ARG, put point on line ARG.\n\
 The desired position of point is always relative to the current window.\n\
 Just C-u as prefix means put point in the center of the window.\n\
-No arg (i.e., it is nil) erases the entire frame and then\n\
+If ARG is omitted or nil, erases the entire frame and then\n\
 redraws with point in the center of the current window.")
-  (n)
-     register Lisp_Object n;
+  (arg)
+     register Lisp_Object arg;
 {
   register struct window *w = XWINDOW (selected_window);
   register int ht = window_internal_height (w);
-  register int opoint = PT;
-  Lisp_Object window;
+  struct position pos;
 
-  if (NILP (n))
+  if (NILP (arg))
     {
       extern int frame_garbaged;
 
       SET_FRAME_GARBAGED (XFRAME (WINDOW_FRAME (w)));
-      XFASTINT (n) = ht / 2;
+      XSETFASTINT (arg, ht / 2);
     }
-  else if (XTYPE (n) == Lisp_Cons) /* Just C-u. */
+  else if (CONSP (arg)) /* Just C-u. */
     {
-      XFASTINT (n) = ht / 2;
+      XSETFASTINT (arg, ht / 2);
     }
   else
     {
-      n = Fprefix_numeric_value (n);
-      CHECK_NUMBER (n, 0);
+      arg = Fprefix_numeric_value (arg);
+      CHECK_NUMBER (arg, 0);
     }
 
-  if (XINT (n) < 0)
-    XSETINT (n, XINT (n) + ht);
-
-  XSETINT (n, - XINT (n));
+  if (XINT (arg) < 0)
+    XSETINT (arg, XINT (arg) + ht);
 
-  XSET (window, Lisp_Window, w);
-  Fvertical_motion (n, window);
-  Fset_marker (w->start, make_number (PT), w->buffer);
-  w->start_at_line_beg = Fbolp ();
+  pos = *vmotion (point, - XINT (arg), w);
 
-  SET_PT (opoint);
+  Fset_marker (w->start, make_number (pos.bufpos), w->buffer);
+  w->start_at_line_beg = ((pos.bufpos == BEGV
+                          || FETCH_CHAR (pos.bufpos - 1) == '\n')
+                         ? Qt : Qnil);
   w->force_start = Qt;
 
   return Qnil;
@@ -2516,7 +2931,7 @@ redraws with point in the center of the current window.")
 DEFUN ("move-to-window-line", Fmove_to_window_line, Smove_to_window_line,
   1, 1, "P",
   "Position point relative to window.\n\
-With no argument, position text at center of window.\n\
+With no argument, position point at center of window.\n\
 An argument specifies frame line; zero means top of window,\n\
 negative means relative to bottom of window.")
   (arg)
@@ -2528,7 +2943,7 @@ negative means relative to bottom of window.")
   Lisp_Object window;
 
   if (NILP (arg))
-    XFASTINT (arg) = height / 2;
+    XSETFASTINT (arg, height / 2);
   else
     {
       arg = Fprefix_numeric_value (arg);
@@ -2537,7 +2952,7 @@ negative means relative to bottom of window.")
     }
 
   start = marker_position (w->start);
-  XSET (window, Lisp_Window, w);
+  XSETWINDOW (window, w);
   if (start < BEGV || start > ZV)
     {
       Fvertical_motion (make_number (- (height / 2)), window);
@@ -2562,18 +2977,13 @@ struct save_window_data
     Lisp_Object minibuf_scroll_window;
     Lisp_Object root_window;
     Lisp_Object focus_frame;
+    /* Record the values of window-min-width and window-min-height
+       so that window sizes remain consistent with them.  */
+    Lisp_Object min_width, min_height;
     /* A vector, interpreted as a struct saved_window */
     Lisp_Object saved_windows;
   };
 
-/* Arg to Fmake_vector */
-#define SAVE_WINDOW_DATA_SIZE                                          \
-  ((sizeof (struct save_window_data)                                   \
-    - (sizeof (struct Lisp_Vector)                                     \
-       /* Don't count the contents member of the struct Lisp_Vector */ \
-       - sizeof (Lisp_Object)))                                                \
-   / sizeof (Lisp_Object))
-
 /* This is saved as a Lisp_Vector */
 struct saved_window
   {
@@ -2594,11 +3004,11 @@ struct saved_window
   ((struct saved_window *) (XVECTOR ((swv)->contents[(n)])))
 
 DEFUN ("window-configuration-p", Fwindow_configuration_p, Swindow_configuration_p, 1, 1, 0,
-  "T if OBJECT is a window-configration object.")
-  (obj)
-     Lisp_Object obj;
+  "T if OBJECT is a window-configuration object.")
+  (object)
+     Lisp_Object object;
 {
-  if (XTYPE (obj) == Lisp_Window_Configuration)
+  if (WINDOW_CONFIGURATIONP (object))
     return Qt;
   return Qnil;
 }
@@ -2618,7 +3028,7 @@ by `current-window-configuration' (which see).")
   Lisp_Object frame;
   FRAME_PTR f;
 
-  while (XTYPE (configuration) != Lisp_Window_Configuration)
+  while (!WINDOW_CONFIGURATIONP (configuration))
     {
       configuration = wrong_type_argument (intern ("window-configuration-p"),
                                           configuration);
@@ -2653,13 +3063,19 @@ by `current-window-configuration' (which see).")
       if (XFASTINT (data->frame_height) != previous_frame_height
          || XFASTINT (data->frame_width) != previous_frame_width)
        change_frame_size (f, data->frame_height, data->frame_width, 0, 0);
-#ifdef HAVE_X_WINDOWS
+#ifdef HAVE_WINDOW_SYSTEM
       if (XFASTINT (data->frame_menu_bar_lines)
          != previous_frame_menu_bar_lines)
        x_set_menu_bar_lines (f, data->frame_menu_bar_lines, 0);
 #endif
 
       windows_or_buffers_changed++;
+      FRAME_WINDOW_SIZES_CHANGED (f) = 1;
+
+      /* Temporarily avoid any problems with windows that are smaller
+        than they are supposed to be.  */
+      window_min_height = 1;
+      window_min_width = 1;
 
       /* Kludge Alert!
         Mark all windows now on frame as "deleted".
@@ -2708,7 +3124,7 @@ by `current-window-configuration' (which see).")
 
          /* If we squirreled away the buffer in the window's height,
             restore it now.  */
-         if (XTYPE (w->height) == Lisp_Buffer)
+         if (BUFFERP (w->height))
            w->buffer = w->height;
          w->left = p->left;
          w->top = p->top;
@@ -2716,7 +3132,7 @@ by `current-window-configuration' (which see).")
          w->height = p->height;
          w->hscroll = p->hscroll;
          w->display_table = p->display_table;
-         XFASTINT (w->last_modified) = 0;
+         XSETFASTINT (w->last_modified, 0);
 
          /* Reinstall the saved buffer and pointers into it.  */
          if (NILP (p->buffer))
@@ -2777,7 +3193,7 @@ by `current-window-configuration' (which see).")
 
 #ifdef MULTI_FRAME
       if (NILP (data->focus_frame)
-         || (XTYPE (data->focus_frame) == Lisp_Frame
+         || (FRAMEP (data->focus_frame)
              && FRAME_LIVE_P (XFRAME (data->focus_frame))))
        Fredirect_frame_focus (frame, data->focus_frame);
 #endif
@@ -2786,7 +3202,8 @@ by `current-window-configuration' (which see).")
          when the frame's old selected window has been deleted.  */
 #ifdef MULTI_FRAME
       if (f != selected_frame && ! FRAME_TERMCAP_P (f))
-       Fhandle_switch_frame (WINDOW_FRAME (XWINDOW (data->root_window)), Qnil);
+       do_switch_frame (WINDOW_FRAME (XWINDOW (data->root_window)),
+                        Qnil, 0);
 #endif
 #endif
 
@@ -2795,12 +3212,16 @@ by `current-window-configuration' (which see).")
          || previous_frame_width != FRAME_WIDTH (f))
        change_frame_size (f, previous_frame_height, previous_frame_width,
                           0, 0);
-#ifdef HAVE_X_WINDOWS
+#ifdef HAVE_WINDOW_SYSTEM
       if (previous_frame_menu_bar_lines != FRAME_MENU_BAR_LINES (f))
        x_set_menu_bar_lines (f, previous_frame_menu_bar_lines, 0);
 #endif
     }
 
+  /* Restore the minimum heights recorded in the configuration.  */
+  window_min_height = XINT (data->min_height);
+  window_min_width = XINT (data->min_width);
+
 #ifdef MULTI_FRAME
   /* Fselect_window will have made f the selected frame, so we
      reselect the proper frame here.  Fhandle_switch_frame will change the
@@ -2808,7 +3229,7 @@ by `current-window-configuration' (which see).")
      Fselect_window above totally superfluous; it still sets f's
      selected window.  */
   if (FRAME_LIVE_P (XFRAME (data->selected_frame)))
-    Fhandle_switch_frame (data->selected_frame, Qnil);
+    do_switch_frame (data->selected_frame, Qnil, 0);
 #endif
 
   if (!NILP (new_current_buffer))
@@ -2872,7 +3293,7 @@ save_window_save (window, vector, i)
       p = SAVED_WINDOW_N (vector, i);
       w = XWINDOW (window);
 
-      XFASTINT (w->temslot) = i++;
+      XSETFASTINT (w->temslot, i++);
       p->window = window;
       p->buffer = w->buffer;
       p->left = w->left;
@@ -2893,13 +3314,13 @@ save_window_save (window, vector, i)
                           w->buffer);
            }
          else
-           p->pointm = Fcopy_marker (w->pointm);
+           p->pointm = Fcopy_marker (w->pointm, Qnil);
 
-         p->start = Fcopy_marker (w->start);
+         p->start = Fcopy_marker (w->start, Qnil);
          p->start_at_line_beg = w->start_at_line_beg;
 
          tem = XBUFFER (w->buffer)->mark;
-         p->mark = Fcopy_marker (tem);
+         p->mark = Fcopy_marker (tem, Qnil);
        }
       else
        {
@@ -2944,6 +3365,7 @@ redirection (see `redirect-frame-focus').")
   register Lisp_Object tem;
   register int n_windows;
   register struct save_window_data *data;
+  register struct Lisp_Vector *vec;
   register int i;
   FRAME_PTR f;
 
@@ -2956,20 +3378,25 @@ redirection (see `redirect-frame-focus').")
     }
 
   n_windows = count_windows (XWINDOW (FRAME_ROOT_WINDOW (f)));
-  data = (struct save_window_data *)
-           XVECTOR (Fmake_vector (make_number (SAVE_WINDOW_DATA_SIZE),
-                                 Qnil));
-  XFASTINT (data->frame_width) = FRAME_WIDTH (f);
-  XFASTINT (data->frame_height) = FRAME_HEIGHT (f);
-  XFASTINT (data->frame_menu_bar_lines) = FRAME_MENU_BAR_LINES (f);
+  vec = allocate_vectorlike (VECSIZE (struct save_window_data));
+  for (i = 0; i < VECSIZE (struct save_window_data); i++)
+    vec->contents[i] = Qnil;
+  vec->size = VECSIZE (struct save_window_data);
+  data = (struct save_window_data *)vec;
+
+  XSETFASTINT (data->frame_width, FRAME_WIDTH (f));
+  XSETFASTINT (data->frame_height, FRAME_HEIGHT (f));
+  XSETFASTINT (data->frame_menu_bar_lines, FRAME_MENU_BAR_LINES (f));
 #ifdef MULTI_FRAME
-  XSET (data->selected_frame, Lisp_Frame, selected_frame);
+  XSETFRAME (data->selected_frame, selected_frame);
 #endif
   data->current_window = FRAME_SELECTED_WINDOW (f);
-  XSET (data->current_buffer, Lisp_Buffer, current_buffer);
+  XSETBUFFER (data->current_buffer, current_buffer);
   data->minibuf_scroll_window = Vminibuf_scroll_window;
   data->root_window = FRAME_ROOT_WINDOW (f);
   data->focus_frame = FRAME_FOCUS_FRAME (f);
+  XSETINT (data->min_height, window_min_height);
+  XSETINT (data->min_width, window_min_width);
   tem = Fmake_vector (make_number (n_windows), Qnil);
   data->saved_windows = tem;
   for (i = 0; i < n_windows; i++)
@@ -2977,15 +3404,17 @@ redirection (see `redirect-frame-focus').")
       = Fmake_vector (make_number (SAVED_WINDOW_VECTOR_SIZE), Qnil);
   save_window_save (FRAME_ROOT_WINDOW (f),
                    XVECTOR (tem), 0);
-  XSET (tem, Lisp_Window_Configuration, data);
+  XSETWINDOW_CONFIGURATION (tem, data);
   return (tem);
 }
 
 DEFUN ("save-window-excursion", Fsave_window_excursion, Ssave_window_excursion,
   0, UNEVALLED, 0,
   "Execute body, preserving window sizes and contents.\n\
-Restores which buffer appears in which window, where display starts,\n\
-as well as the current buffer.\n\
+Restore which buffer appears in which window, where display starts,\n\
+and the value of point and mark for each window.\n\
+Also restore which buffer is current.\n\
+But do not preserve point in the current buffer.\n\
 Does not restore the value of point in current buffer.")
   (args)
      Lisp_Object args;
@@ -3003,12 +3432,15 @@ init_window_once ()
 {
 #ifdef MULTI_FRAME
   selected_frame = make_terminal_frame ();
+  XSETFRAME (Vterminal_frame, selected_frame);
   minibuf_window = selected_frame->minibuffer_window;
   selected_window = selected_frame->selected_window;
   last_nonminibuf_frame = selected_frame;
 #else /* not MULTI_FRAME */
   extern Lisp_Object get_minibuffer ();
 
+  selected_frame = last_nonminibuf_frame = &the_only_frame;
+
   minibuf_window = make_window ();
   FRAME_ROOT_WINDOW (selected_frame) = make_window ();
 
@@ -3020,12 +3452,12 @@ init_window_once ()
      just so that there is "something there."
      Correct values are put in in init_xdisp */
 
-  XFASTINT (XWINDOW (FRAME_ROOT_WINDOW (selected_frame))->width) = 10;
-  XFASTINT (XWINDOW (minibuf_window)->width) = 10;
+  XSETFASTINT (XWINDOW (FRAME_ROOT_WINDOW (selected_frame))->width, 10);
+  XSETFASTINT (XWINDOW (minibuf_window)->width, 10);
 
-  XFASTINT (XWINDOW (FRAME_ROOT_WINDOW (selected_frame))->height) = 9;
-  XFASTINT (XWINDOW (minibuf_window)->top) = 9;
-  XFASTINT (XWINDOW (minibuf_window)->height) = 1;
+  XSETFASTINT (XWINDOW (FRAME_ROOT_WINDOW (selected_frame))->height, 9);
+  XSETFASTINT (XWINDOW (minibuf_window)->top, 9);
+  XSETFASTINT (XWINDOW (minibuf_window)->height, 1);
 
   /* Prevent error in Fset_window_buffer.  */
   XWINDOW (FRAME_ROOT_WINDOW (selected_frame))->buffer = Qt;
@@ -3041,7 +3473,7 @@ init_window_once ()
      a newly-created, never-selected window.  Increment
      window_select_count so the first selection ever will get
      something newer than this.  */
-  XFASTINT (XWINDOW (selected_window)->use_time) = ++window_select_count;
+  XSETFASTINT (XWINDOW (selected_window)->use_time, ++window_select_count);
 #endif /* not MULTI_FRAME */
 }
 
@@ -3053,6 +3485,9 @@ syms_of_window ()
   Qwindow_live_p = intern ("window-live-p");
   staticpro (&Qwindow_live_p);
 
+  Qtemp_buffer_show_hook = intern ("temp-buffer-show-hook");
+  staticpro (&Qtemp_buffer_show_hook);
+
 #ifndef MULTI_FRAME
   /* Make sure all windows get marked */
   staticpro (&minibuf_window);
@@ -3060,7 +3495,10 @@ syms_of_window ()
 
   DEFVAR_LISP ("temp-buffer-show-function", &Vtemp_buffer_show_function,
     "Non-nil means call as function to display a help buffer.\n\
-Used by `with-output-to-temp-buffer'.");
+The function is called with one argument, the buffer to be displayed.\n\
+Used by `with-output-to-temp-buffer'.\n\
+If this function is used, then it must do the entire job of showing\n\
+the buffer; `temp-buffer-show-hook' is not run unless this function runs it.");
   Vtemp_buffer_show_function = Qnil;
 
   DEFVAR_LISP ("display-buffer-function", &Vdisplay_buffer_function,
@@ -3094,27 +3532,69 @@ where `pop-up-frame-alist' would hold the default frame parameters.");
   DEFVAR_LISP ("special-display-buffer-names", &Vspecial_display_buffer_names,
     "*List of buffer names that should have their own special frames.\n\
 Displaying a buffer whose name is in this list makes a special frame for it\n\
-using `special-display-function'.  See also `special-display-regexps'.");
+using `special-display-function'.\n\
+\n\
+An element of the list can be a cons cell instead of just a string.\n\
+Then the car should be a buffer name, and the cdr specifies frame\n\
+parameters for creating the frame for that buffer.\n\
+More precisely, the cdr is passed as the second argument to\n\
+the function found in `special-display-function', when making that frame.\n\
+See also `special-display-regexps'.");
   Vspecial_display_buffer_names = Qnil;
 
   DEFVAR_LISP ("special-display-regexps", &Vspecial_display_regexps,
     "*List of regexps saying which buffers should have their own special frames.\n\
 If a buffer name matches one of these regexps, it gets its own frame.\n\
 Displaying a buffer whose name is in this list makes a special frame for it\n\
-using `special-display-function'.  See also `special-display-buffer-names'.");
+using `special-display-function'.\n\
+\n\
+An element of the list can be a cons cell instead of just a string.\n\
+Then the car should be the regexp, and the cdr specifies frame\n\
+parameters for creating the frame for buffers that match.\n\
+More precisely, the cdr is passed as the second argument to\n\
+the function found in `special-display-function', when making that frame.\n\
+See also `special-display-buffer-names'.");
   Vspecial_display_regexps = Qnil;
 
   DEFVAR_LISP ("special-display-function", &Vspecial_display_function,
     "Function to call to make a new frame for a special buffer.\n\
-It is called with one argument, the buffer,\n\
-and should return a window displaying that buffer.\n\
+It is called with two arguments, the buffer and optional buffer specific\n\
+data, and should return a window displaying that buffer.\n\
 The default value makes a separate frame for the buffer,\n\
-using `special-display-alist' to specify the frame parameters.\n\
+using `special-display-frame-alist' to specify the frame parameters.\n\
 \n\
 A buffer is special if its is listed in `special-display-buffer-names'\n\
 or matches a regexp in `special-display-regexps'.");
   Vspecial_display_function = Qnil;
 
+  DEFVAR_LISP ("same-window-buffer-names", &Vsame_window_buffer_names,
+    "*List of buffer names that should appear in the selected window.\n\
+Displaying one of these buffers using `display-buffer' or `pop-to-buffer'\n\
+switches to it in the selected window, rather than making it appear\n\
+in some other window.\n\
+\n\
+An element of the list can be a cons cell instead of just a string.\n\
+Then the car must be a string, which specifies the buffer name.\n\
+This is for compatibility with `special-display-buffer-names';\n\
+the cdr of the cons cell is ignored.\n\
+\n\
+See also `same-window-regexps'.");
+  Vsame_window_buffer_names = Qnil;
+
+  DEFVAR_LISP ("same-window-regexps", &Vsame_window_regexps,
+    "*List of regexps saying which buffers should appear in the selected window.\n\
+If a buffer name matches one of these regexps, then displaying it\n\
+using `display-buffer' or `pop-to-buffer' switches to it\n\
+in the selected window, rather than making it appear in some other window.\n\
+\n\
+An element of the list can be a cons cell instead of just a string.\n\
+Then the car must be a string, which specifies the buffer name.\n\
+This is for compatibility with `special-display-buffer-names';\n\
+the cdr of the cons cell is ignored.\n\
+\n\
+See also `same-window-buffer-names'.");
+  Vsame_window_regexps = Qnil;
+
   DEFVAR_BOOL ("pop-up-windows", &pop_up_windows,
     "*Non-nil means display-buffer should make new windows.");
   pop_up_windows = 1;
@@ -3147,6 +3627,8 @@ If there is only one window, it is split regardless of this value.");
   defsubr (&Swindow_width);
   defsubr (&Swindow_hscroll);
   defsubr (&Sset_window_hscroll);
+  defsubr (&Swindow_redisplay_end_trigger);
+  defsubr (&Sset_window_redisplay_end_trigger);
   defsubr (&Swindow_edges);
   defsubr (&Scoordinates_in_window_p);
   defsubr (&Swindow_at);