]> code.delx.au - gnu-emacs/blobdiff - src/window.c
(Fbyte_code): Harmonize arguments with documentation.
[gnu-emacs] / src / window.c
index 95a51c3ecb9a1551ec2c58a1673150567f95246b..099730f05c578534c476f99ac36295ebe5ae629f 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.
 
@@ -88,6 +88,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;
@@ -105,7 +114,7 @@ DEFUN ("windowp", Fwindowp, Swindowp, 1, 1, 0,
   (obj)
      Lisp_Object obj;
 {
-  return XTYPE (obj) == Lisp_Window ? Qt : Qnil;
+  return WINDOWP (obj) ? Qt : Qnil;
 }
 
 DEFUN ("window-live-p", Fwindow_live_p, Swindow_live_p, 1, 1, 0,
@@ -113,37 +122,37 @@ DEFUN ("window-live-p", Fwindow_live_p, Swindow_live_p, 1, 1, 0,
      (obj)
      Lisp_Object obj;
 {
-  return ((XTYPE (obj) == Lisp_Window
-          && ! NILP (XWINDOW (obj)->buffer))
-         ? Qt : Qnil);
+  return (WINDOWP (obj) && ! NILP (XWINDOW (obj)->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 +172,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
@@ -233,7 +242,7 @@ POS defaults to point; WINDOW, to the selected window.")
        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);
@@ -297,16 +306,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\
@@ -448,7 +483,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
@@ -482,7 +517,8 @@ 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;
 {
@@ -524,8 +560,8 @@ does not update this value.")
     return Qnil;
 #endif
 
-  XSET (value, Lisp_Int,
-       BUF_Z (XBUFFER (buf)) - XFASTINT (w->window_end_pos));
+  XSETINT (value,
+          BUF_Z (XBUFFER (buf)) - XFASTINT (w->window_end_pos));
 
   return value;
 }
@@ -562,7 +598,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;
@@ -612,20 +648,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;
 }
 
@@ -750,6 +786,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?  */
   {
@@ -878,6 +915,7 @@ 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\
@@ -904,12 +942,17 @@ 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.  */
   if (NILP (all_frames))
-    all_frames = (EQ (minibuf, Qt)
+    all_frames = (! EQ (minibuf, Qlambda)
                  ? (FRAME_MINIBUF_WINDOW
                     (XFRAME
                      (WINDOW_FRAME
@@ -919,6 +962,10 @@ DEFUN ("next-window", Fnext_window, Snext_window, 0, 3, 0,
     ;
   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,
@@ -955,7 +1002,7 @@ DEFUN ("next-window", Fnext_window, Snext_window, 0, 3, 0,
                   If that happens, go back to the selected frame
                   so we can complete the cycle.  */
                if (EQ (tem, tem1))
-                 XSET (tem, Lisp_Frame, selected_frame);
+                 XSETFRAME (tem, selected_frame);
              }
 #endif
            tem = FRAME_ROOT_WINDOW (XFRAME (tem));
@@ -976,13 +1023,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;
@@ -993,7 +1042,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\
@@ -1011,6 +1060,7 @@ 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\
@@ -1038,13 +1088,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
@@ -1054,6 +1109,10 @@ DEFUN ("previous-window", Fprevious_window, Sprevious_window, 0, 3, 0,
     ;
   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,
@@ -1099,7 +1158,7 @@ DEFUN ("previous-window", Fprevious_window, Sprevious_window, 0, 3, 0,
                   If that happens, go back to the selected frame
                   so we can complete the cycle.  */
                if (EQ (tem, tem1))
-                 XSET (tem, Lisp_Frame, selected_frame);
+                 XSETFRAME (tem, selected_frame);
              }
 #endif
            /* If this frame has a minibuffer, find that window first,
@@ -1128,12 +1187,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;
 }
@@ -1227,7 +1288,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);
@@ -1287,21 +1348,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;
 
@@ -1423,7 +1514,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;
@@ -1475,12 +1566,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);
     }
@@ -1531,6 +1624,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.  */
 
@@ -1601,9 +1725,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)
@@ -1622,7 +1748,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);
 
@@ -1662,9 +1788,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)
@@ -1683,7 +1811,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);
 
@@ -1734,9 +1862,9 @@ BUFFER can be a buffer or buffer name.")
     }
 
   w->buffer = buffer;
-  XFASTINT (w->window_end_pos) = 0;
+  XSETFASTINT (w->window_end_pos, 0);
   w->window_end_valid = Qnil;
-  XFASTINT(w->hscroll) = 0;
+  XSETFASTINT(w->hscroll, 0);
   Fset_marker (w->pointm,
               make_number (BUF_PT (XBUFFER (buffer))),
               buffer);
@@ -1745,7 +1873,7 @@ 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);
@@ -1770,7 +1898,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;
 
@@ -1814,8 +1942,23 @@ before each command.")
   return window;
 }
 
+/* Deiconify the frame containing the window WINDOW, then return WINDOW.  */
+
+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))
+    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\
@@ -1836,23 +1979,60 @@ 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 or iconified frame.  */
-  window = Fget_buffer_window (buffer, pop_up_frames ? make_number (0) : 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)))
     {
-#ifdef MULTI_FRAME
-      if (FRAME_ICONIFIED_P (XFRAME (WINDOW_FRAME (XWINDOW (window)))))
-       Fmake_frame_visible (WINDOW_FRAME (XWINDOW (window)));
-#endif
-      return window;
+      return display_buffer_1 (window);
     }
 
   /* Certain buffer names get special handling.  */
@@ -1889,7 +2069,7 @@ 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 */
 
@@ -1907,7 +2087,7 @@ 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)
@@ -1935,17 +2115,23 @@ Returns the window displaying BUFFER.")
 #endif
        window = Fget_largest_window (frames);
 
-      /* If we got a tall enough full-width window, split it.  */
+      /* 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 the LRU window is selected, and big enough, split it.  */
+         /* 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)
@@ -1969,13 +2155,33 @@ Returns the window displaying BUFFER.")
          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
@@ -1987,11 +2193,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))
@@ -2006,9 +2212,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
@@ -2016,17 +2245,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);
@@ -2045,14 +2277,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;
@@ -2060,34 +2295,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))
        {
@@ -2098,9 +2339,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))
        {
@@ -2115,6 +2358,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);
 
@@ -2135,17 +2379,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;
@@ -2311,7 +2556,7 @@ change_window_height (delta, widthflag)
       (*setsizefun) (parent, opht, 0);
     }
 
-  XFASTINT (p->last_modified) = 0;
+  XSETFASTINT (p->last_modified, 0);
 }
 #undef MINSIZE
 #undef CURBEG
@@ -2383,15 +2628,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
+     thw 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));
@@ -2414,7 +2662,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)
@@ -2552,14 +2800,15 @@ showing that buffer, popping the buffer up if necessary.")
      register Lisp_Object n;
 {
   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 ());
@@ -2568,12 +2817,12 @@ showing that buffer, popping the buffer up if necessary.")
   SET_PT (marker_position (w->pointm));
 
   if (NILP (n))
-    window_scroll (window, ht - next_screen_context_lines, 1);
+    window_scroll (window, defalt, 1);
   else if (EQ (n, Qminus))
-    window_scroll (window, next_screen_context_lines - ht, 1);
+    window_scroll (window, -defalt, 1);
   else
     {
-      if (XTYPE (n) == Lisp_Cons)
+      if (CONSP (n))
        n = Fcar (n);
       CHECK_NUMBER (n, 0);
       window_scroll (window, XINT (n), 1);
@@ -2593,7 +2842,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);
 
@@ -2610,7 +2859,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);
 
@@ -2631,19 +2880,18 @@ redraws with point in the center of the current window.")
 {
   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))
     {
       extern int frame_garbaged;
 
       SET_FRAME_GARBAGED (XFRAME (WINDOW_FRAME (w)));
-      XFASTINT (n) = ht / 2;
+      XSETFASTINT (n, ht / 2);
     }
-  else if (XTYPE (n) == Lisp_Cons) /* Just C-u. */
+  else if (CONSP (n)) /* Just C-u. */
     {
-      XFASTINT (n) = ht / 2;
+      XSETFASTINT (n, ht / 2);
     }
   else
     {
@@ -2654,14 +2902,12 @@ redraws with point in the center of the current window.")
   if (XINT (n) < 0)
     XSETINT (n, XINT (n) + ht);
 
-  XSETINT (n, - XINT (n));
-
-  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 (n), 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;
@@ -2682,7 +2928,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);
@@ -2691,7 +2937,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);
@@ -2723,14 +2969,6 @@ struct save_window_data
     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
   {
@@ -2751,11 +2989,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.")
+  "T if OBJECT is a window-configuration object.")
   (obj)
      Lisp_Object obj;
 {
-  if (XTYPE (obj) == Lisp_Window_Configuration)
+  if (WINDOW_CONFIGURATIONP (obj))
     return Qt;
   return Qnil;
 }
@@ -2775,7 +3013,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);
@@ -2810,13 +3048,14 @@ 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.  */
@@ -2870,7 +3109,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;
@@ -2878,7 +3117,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))
@@ -2939,7 +3178,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
@@ -2948,7 +3187,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
 
@@ -2957,7 +3197,7 @@ 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
@@ -2974,7 +3214,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))
@@ -3038,7 +3278,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;
@@ -3059,13 +3299,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
        {
@@ -3110,6 +3350,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;
 
@@ -3122,22 +3363,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);
-  XSET (data->min_height, Lisp_Int, window_min_height);
-  XSET (data->min_width, Lisp_Int, window_min_width);
+  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++)
@@ -3145,7 +3389,7 @@ 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);
 }
 
@@ -3173,12 +3417,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 ();
 
@@ -3190,12 +3437,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;
@@ -3211,7 +3458,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 */
 }
 
@@ -3223,6 +3470,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);
@@ -3230,7 +3480,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,
@@ -3265,9 +3518,12 @@ where `pop-up-frame-alist' would hold the default frame parameters.");
     "*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'.\n\
-Instead of a buffer name, the list entries can be cons cells.  In that\n\
-case the car should be a buffer name, and the cdr data to be passed as a 
-second argument to `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;
 
@@ -3276,9 +3532,12 @@ See also `special-display-regexps'.");
 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'.\n\
-Instead of a buffer name, the list entries can be cons cells.  In that\n\
-case the car should be the regexp, and the cdr data to be passed as a 
-second argument to `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;
 
@@ -3287,12 +3546,40 @@ See also `special-display-buffer-names'.");
 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;
@@ -3325,6 +3612,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);