(Qarith_error): Delete redundant definition.
[bpt/emacs.git] / src / window.c
index 5c67490..6d635a5 100644 (file)
@@ -1,6 +1,6 @@
 /* Window creation, deletion and examination for GNU Emacs.
    Does not include redisplay.
-   Copyright (C) 1985, 86, 87, 93, 94, 95 Free Software Foundation, Inc.
+   Copyright (C) 1985, 86, 87, 93, 94, 95, 96 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"
@@ -97,7 +98,7 @@ 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 
+/* Fdisplay_buffer always splits the largest window
    if that window is more than this high.  */
 int split_height_threshold;
 
@@ -107,22 +108,27 @@ int next_screen_context_lines;
 /* Incremented for each window created.  */
 static int sequence_number;
 
+/* Nonzero after init_window_once has finished.  */
+static int window_initialized;
+
 #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 WINDOWP (obj) ? 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 (WINDOWP (obj) && ! NILP (XWINDOW (obj)->buffer) ? Qt : Qnil);
+  return (WINDOWP (object) && ! NILP (XWINDOW (object)->buffer) ? Qt : Qnil);
 }
 
 Lisp_Object
@@ -242,7 +248,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);
@@ -307,15 +313,41 @@ NCOL should be zero or positive.")
 
   CHECK_NUMBER (ncol, 1);
   if (XINT (ncol) < 0) XSETFASTINT (ncol, 0);
-  if (XFASTINT (ncol) >= (1 << (SHORTBITS - 1)))
-    args_out_of_range (ncol, Qnil);
   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\
@@ -361,7 +393,7 @@ coordinates_in_window (w, x, y)
   if (*y == top + window_height - 1
       && ! MINI_WINDOW_P (w))
     return 2;
-  
+
   /* Is the character in the right border?  */
   if (*x == left + width - 1
       && left + width != FRAME_WIDTH (XFRAME (w->frame)))
@@ -404,7 +436,7 @@ If they are on the border between WINDOW and its right sibling,\n\
 
     case 2:                    /* In mode line of window. */
       return Qmode_line;
-      
+
     case 3:                    /* On right border of window.  */
       return Qvertical_line;
 
@@ -441,7 +473,7 @@ window_from_coordinates (frame, x, y, part)
       tem = Fnext_window (tem, Qt, Qlambda);
     }
   while (! EQ (tem, first));
-  
+
   return Qnil;
 }
 
@@ -491,7 +523,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;
 {
@@ -621,20 +654,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 (VECTORP (tem) && 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 (VECTORP (tem) && XVECTOR (tem)->size == DISP_TABLE_SIZE)
-    return XVECTOR (tem);
+  if (DISP_TABLE_P (tem))
+    return XCHAR_TABLE (tem);
   tem = Vstandard_display_table;
-  if (VECTORP (tem) && XVECTOR (tem)->size == DISP_TABLE_SIZE)
-    return XVECTOR (tem);
+  if (DISP_TABLE_P (tem))
+    return XCHAR_TABLE (tem);
   return 0;
 }
 
@@ -915,12 +948,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
@@ -991,13 +1029,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;
@@ -1008,7 +1048,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\
@@ -1054,13 +1094,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
@@ -1148,12 +1193,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;
 }
@@ -1164,15 +1211,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)
     {
@@ -1427,7 +1474,7 @@ window_loop (type, obj, mini, frames)
     }
 
   return best_window;
-}     
+}
 
 DEFUN ("get-lru-window", Fget_lru_window, Sget_lru_window, 0, 1, 0,
   "Return the window least recently selected or used for display.\n\
@@ -1525,12 +1572,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);
     }
@@ -1581,6 +1630,26 @@ 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;
+{
+#ifdef MULTI_KBOARD
+  Lisp_Object tail, frame;
+
+  /* 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)
+    window_loop (UNSHOW_BUFFER, buffer, 0, frame);
+#else
+  window_loop (UNSHOW_BUFFER, buffer, 0, Qt);
+#endif
+}
 \f
 /* Set the height of WINDOW and all its inferiors.  */
 
@@ -1610,7 +1679,7 @@ check_frame_size (frame, rows, cols)
      int *rows, *cols;
 {
   /* For height, we have to see:
-     whether the frame has a minibuffer, 
+     whether the frame has a minibuffer,
      whether it wants a mode line, and
      whether it has a menu bar.  */
   int min_height =
@@ -1759,6 +1828,14 @@ set_window_width (window, width, nodelete)
 \f
 int window_select_count;
 
+Lisp_Object
+Fset_window_buffer_unwind (obuf)
+     Lisp_Object obuf;
+{
+  Fset_buffer (obuf);
+  return Qnil;
+}
+
 DEFUN ("set-window-buffer", Fset_window_buffer, Sset_window_buffer, 2, 2, 0,
   "Make WINDOW display BUFFER as its contents.\n\
 BUFFER can be a buffer or buffer name.")
@@ -1767,6 +1844,7 @@ BUFFER can be a buffer or buffer name.")
 {
   register Lisp_Object tem;
   register struct window *w = decode_window (window);
+  int count = specpdl_ptr - specpdl;
 
   buffer = Fget_buffer (buffer);
   CHECK_BUFFER (buffer, 1);
@@ -1790,7 +1868,7 @@ BUFFER can be a buffer or buffer name.")
   w->buffer = buffer;
   XSETFASTINT (w->window_end_pos, 0);
   w->window_end_valid = Qnil;
-  XSETFASTINT(w->hscroll, 0);
+  XSETFASTINT (w->hscroll, 0);
   Fset_marker (w->pointm,
               make_number (BUF_PT (XBUFFER (buffer))),
               buffer);
@@ -1801,8 +1879,25 @@ BUFFER can be a buffer or buffer name.")
   w->force_start = Qnil;
   XSETFASTINT (w->last_modified, 0);
   windows_or_buffers_changed++;
+
+  /* We must select BUFFER for running the window-scroll-functions.
+     If WINDOW is selected, switch permanently.
+     Otherwise, switch but go back to the ambient buffer afterward.  */
   if (EQ (window, selected_window))
     Fset_buffer (buffer);
+  /* We can't check ! NILP (Vwindow_scroll_functions) here
+     because that might itself be a local variable.  */
+  else if (window_initialized)
+    {
+      record_unwind_protect (Fset_window_buffer_unwind, Fcurrent_buffer ());
+      Fset_buffer (buffer);
+    }
+
+  if (! NILP (Vwindow_scroll_functions))
+    run_hook_with_args_2 (Qwindow_scroll_functions, window,
+                         Fmarker_position (w->start));
+
+  unbind_to (count, Qnil);
 
   return Qnil;
 }
@@ -1868,6 +1963,34 @@ 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 (f != selected_frame)
+    {
+      if (FRAME_ICONIFIED_P (f))
+       Fmake_frame_visible (WINDOW_FRAME (XWINDOW (window)));
+      else if (FRAME_VISIBLE_P (f))
+       Fraise_frame (WINDOW_FRAME (XWINDOW (window)));
+    }
+#endif
+  return window;
+}
+
 DEFUN ("display-buffer", Fdisplay_buffer, Sdisplay_buffer, 1, 2,
        "bDisplay buffer: \nP",
   "Make BUFFER appear in some window but don't select it.\n\
@@ -1876,7 +1999,11 @@ If BUFFER is shown already in some window, just use that one,\n\
 unless the window is the selected window and the optional second\n\
 argument NOT-THIS-WINDOW is non-nil (interactively, with prefix arg).\n\
 If `pop-up-frames' is non-nil, make a new frame if no window shows BUFFER.\n\
-Returns the window displaying BUFFER.")
+Returns the window displaying BUFFER.\n\
+\n\
+The variables `special-display-buffer-names', `special-display-regexps',\n\
+`same-window-buffer-names', and `same-window-regexps' customize how certain\n\
+buffer names are handled.")
   (buffer, not_this_window)
      register Lisp_Object buffer, not_this_window;
 {
@@ -1890,7 +2017,7 @@ 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.  */
@@ -1900,14 +2027,14 @@ Returns the window displaying BUFFER.")
       if (!NILP (tem))
        {
          Fswitch_to_buffer (buffer, Qnil);
-         return selected_window;
+         return display_buffer_1 (selected_window);
        }
 
       tem = Fassoc (XBUFFER (buffer)->name, Vsame_window_buffer_names);
       if (!NILP (tem))
        {
          Fswitch_to_buffer (buffer, Qnil);
-         return selected_window;
+         return display_buffer_1 (selected_window);
        }
 
       for (tem = Vsame_window_regexps; CONSP (tem); tem = XCONS (tem)->cdr)
@@ -1917,7 +2044,7 @@ Returns the window displaying BUFFER.")
              && fast_string_match (car, XBUFFER (buffer)->name) >= 0)
            {
              Fswitch_to_buffer (buffer, Qnil);
-             return selected_window;
+             return display_buffer_1 (selected_window);
            }
          else if (CONSP (car)
                   && STRINGP (XCONS (car)->car)
@@ -1925,7 +2052,7 @@ Returns the window displaying BUFFER.")
                                         XBUFFER (buffer)->name) >= 0)
            {
              Fswitch_to_buffer (buffer, Qnil);
-             return selected_window;
+             return display_buffer_1 (selected_window);
            }
        }
     }
@@ -1943,11 +2070,7 @@ Returns the window displaying BUFFER.")
   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.  */
@@ -1960,7 +2083,7 @@ Returns the window displaying 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)
        {
          Lisp_Object car = XCONS (tem)->car;
@@ -1984,7 +2107,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 */
 
@@ -1999,7 +2122,7 @@ Returns the window displaying BUFFER.")
     {
       Lisp_Object frames;
 
-      frames = Qnil;      
+      frames = Qnil;
 #ifdef MULTI_FRAME
       if (FRAME_MINIBUF_ONLY_P (selected_frame))
        XSETFRAME (frames, last_nonminibuf_frame);
@@ -2096,7 +2219,7 @@ Returns the window displaying BUFFER.")
     window = Fget_lru_window (Qnil);
 
   Fset_window_buffer (window, buffer);
-  return window;
+  return display_buffer_1 (window);
 }
 
 void
@@ -2112,7 +2235,7 @@ temp_output_buffer_show (buf)
   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))
@@ -2131,7 +2254,7 @@ temp_output_buffer_show (buf)
       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.  */ 
+      /* Run temp-buffer-show-hook, with the chosen window selected.  */
       if (!NILP (Vrun_hooks))
        {
          Lisp_Object tem;
@@ -2192,14 +2315,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;
@@ -2207,34 +2333,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))
        {
@@ -2245,9 +2377,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))
        {
@@ -2262,7 +2396,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 (XFRAME (WINDOW_FRAME (o))) = 1;
+  FRAME_WINDOW_SIZES_CHANGED (fo) = 1;
   new = make_window ();
   p = XWINDOW (new);
 
@@ -2283,17 +2417,18 @@ and put SIZE columns in the first of the pair.")
     {
       p->height = o->height;
       p->top = o->top;
-      XSETFASTINT (p->width, XFASTINT (o->width) - size);
-      XSETFASTINT (o->width, size);
-      XSETFASTINT (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;
-      XSETFASTINT (p->height, XFASTINT (o->height) - size);
-      XSETFASTINT (o->height, size);
-      XSETFASTINT (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;
@@ -2302,22 +2437,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;
 }
 
@@ -2531,6 +2666,10 @@ window_scroll (window, n, noerror)
   int lose;
   Lisp_Object bolp, nmoved;
 
+  /* 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);
 
@@ -2539,7 +2678,6 @@ window_scroll (window, n, noerror)
       Fvertical_motion (make_number (- (ht / 2)), window);
       XSETFASTINT (tem, PT);
       Fset_marker (w->start, tem, w->buffer);
-      w->force_start = Qt;
     }
 
   SET_PT (marker_position (w->start));
@@ -2624,10 +2762,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;
 }
 
@@ -2636,10 +2774,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
@@ -2696,8 +2834,8 @@ 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 defalt;
@@ -2716,16 +2854,16 @@ showing that buffer, popping the buffer up if necessary.")
   Fset_buffer (w->buffer);
   SET_PT (marker_position (w->pointm));
 
-  if (NILP (n))
+  if (NILP (arg))
     window_scroll (window, defalt, 1);
-  else if (EQ (n, Qminus))
+  else if (EQ (arg, Qminus))
     window_scroll (window, -defalt, 1);
   else
     {
-      if (CONSP (n))
-       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);
@@ -2773,39 +2911,36 @@ 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);
   struct position pos;
-  Lisp_Object window;
 
-  if (NILP (n))
+  if (NILP (arg))
     {
       extern int frame_garbaged;
 
       SET_FRAME_GARBAGED (XFRAME (WINDOW_FRAME (w)));
-      XSETFASTINT (n, ht / 2);
+      XSETFASTINT (arg, ht / 2);
     }
-  else if (CONSP (n)) /* Just C-u. */
+  else if (CONSP (arg)) /* Just C-u. */
     {
-      XSETFASTINT (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);
+  if (XINT (arg) < 0)
+    XSETINT (arg, XINT (arg) + ht);
 
-  XSETWINDOW (window, w);
-  pos = *vmotion (point, - XINT (n), window_internal_width (w) - 1,
-                 XINT (w->hscroll), window);
+  pos = *vmotion (point, - XINT (arg), w);
 
   Fset_marker (w->start, make_number (pos.bufpos), w->buffer);
   w->start_at_line_beg = ((pos.bufpos == BEGV
@@ -2892,11 +3027,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 (WINDOW_CONFIGURATIONP (obj))
+  if (WINDOW_CONFIGURATIONP (object))
     return Qt;
   return Qnil;
 }
@@ -2951,7 +3086,7 @@ 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
+#if defined (HAVE_WINDOW_SYSTEM) || (defined (MSDOS) && defined (MULTI_FRAME))
       if (XFASTINT (data->frame_menu_bar_lines)
          != previous_frame_menu_bar_lines)
        x_set_menu_bar_lines (f, data->frame_menu_bar_lines, 0);
@@ -2968,7 +3103,7 @@ by `current-window-configuration' (which see).")
       /* Kludge Alert!
         Mark all windows now on frame as "deleted".
         Restoring the new configuration "undeletes" any that are in it.
-        
+
         Save their current buffers in their height fields, since we may
         need it later, if a buffer saved in the configuration is now
         dead.  */
@@ -3089,8 +3224,9 @@ by `current-window-configuration' (which see).")
 #if 0 /* I don't understand why this is needed, and it causes problems
          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);
+      if (f != selected_frame && FRAME_WINDOW_P (f))
+       do_switch_frame (WINDOW_FRAME (XWINDOW (data->root_window)),
+                        Qnil, 0);
 #endif
 #endif
 
@@ -3099,7 +3235,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
+#if defined (HAVE_WINDOW_SYSTEM) || (defined (MSDOS) && defined (MULTI_FRAME))
       if (previous_frame_menu_bar_lines != FRAME_MENU_BAR_LINES (f))
        x_set_menu_bar_lines (f, previous_frame_menu_bar_lines, 0);
 #endif
@@ -3116,7 +3252,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))
@@ -3201,13 +3337,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
        {
@@ -3319,6 +3455,7 @@ 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;
@@ -3361,6 +3498,8 @@ init_window_once ()
      something newer than this.  */
   XSETFASTINT (XWINDOW (selected_window)->use_time, ++window_select_count);
 #endif /* not MULTI_FRAME */
+
+  window_initialized = 1;
 }
 
 syms_of_window ()
@@ -3513,6 +3652,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);