Convert (most) functions in src to standard C.
[bpt/emacs.git] / src / window.c
index d1e3225..f3c6393 100644 (file)
@@ -1,15 +1,15 @@
 /* Window creation, deletion and examination for GNU Emacs.
    Does not include redisplay.
    Copyright (C) 1985, 1986, 1987, 1993, 1994, 1995, 1996, 1997, 1998, 2000,
-                 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
+                 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
                  Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
-GNU Emacs is free software; you can redistribute it and/or modify
+GNU Emacs is free software: you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 3, or (at your option)
-any later version.
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
 
 GNU Emacs is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -17,12 +17,11 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 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, Inc., 51 Franklin Street, Fifth Floor,
-Boston, MA 02110-1301, USA.  */
+along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 
 #include <config.h>
 #include <stdio.h>
+#include <setjmp.h>
 
 #include "lisp.h"
 #include "buffer.h"
@@ -48,42 +47,44 @@ Boston, MA 02110-1301, USA.  */
 #ifdef MSDOS
 #include "msdos.h"
 #endif
-#ifdef MAC_OS
-#include "macterm.h"
+#ifdef HAVE_NS
+#include "nsterm.h"
 #endif
 
 
 Lisp_Object Qwindowp, Qwindow_live_p, Qwindow_configuration_p;
-Lisp_Object Qscroll_up, Qscroll_down;
+Lisp_Object Qdisplay_buffer;
+Lisp_Object Qscroll_up, Qscroll_down, Qscroll_command;
 Lisp_Object Qwindow_size_fixed;
+
 extern Lisp_Object Qleft_margin, Qright_margin;
 
-static int displayed_window_lines P_ ((struct window *));
-static struct window *decode_window P_ ((Lisp_Object));
-static int count_windows P_ ((struct window *));
-static int get_leaf_windows P_ ((struct window *, struct window **, int));
-static void window_scroll P_ ((Lisp_Object, int, int, int));
-static void window_scroll_pixel_based P_ ((Lisp_Object, int, int, int));
-static void window_scroll_line_based P_ ((Lisp_Object, int, int, int));
-static int window_min_size_1 P_ ((struct window *, int));
-static int window_min_size_2 P_ ((struct window *, int));
-static int window_min_size P_ ((struct window *, int, int, int *));
-static void size_window P_ ((Lisp_Object, int, int, int, int, int));
-static int freeze_window_start P_ ((struct window *, void *));
-static int window_fixed_size_p P_ ((struct window *, int, int));
-static void enlarge_window P_ ((Lisp_Object, int, int));
-static Lisp_Object window_list P_ ((void));
-static int add_window_to_list P_ ((struct window *, void *));
-static int candidate_window_p P_ ((Lisp_Object, Lisp_Object, Lisp_Object,
-                                  Lisp_Object));
-static Lisp_Object next_window P_ ((Lisp_Object, Lisp_Object,
-                                   Lisp_Object, int));
-static void decode_next_window_args P_ ((Lisp_Object *, Lisp_Object *,
-                                        Lisp_Object *));
-static int foreach_window_1 P_ ((struct window *,
-                                int (* fn) (struct window *, void *),
-                                void *));
-static Lisp_Object window_list_1 P_ ((Lisp_Object, Lisp_Object, Lisp_Object));
+static int displayed_window_lines (struct window *);
+static struct window *decode_window (Lisp_Object);
+static int count_windows (struct window *);
+static int get_leaf_windows (struct window *, struct window **, int);
+static void window_scroll (Lisp_Object, int, int, int);
+static void window_scroll_pixel_based (Lisp_Object, int, int, int);
+static void window_scroll_line_based (Lisp_Object, int, int, int);
+static int window_min_size_1 (struct window *, int, int);
+static int window_min_size_2 (struct window *, int, int);
+static int window_min_size (struct window *, int, int, int, int *);
+static void size_window (Lisp_Object, int, int, int, int, int);
+static int freeze_window_start (struct window *, void *);
+static int window_fixed_size_p (struct window *, int, int);
+static void enlarge_window (Lisp_Object, int, int);
+static Lisp_Object window_list (void);
+static int add_window_to_list (struct window *, void *);
+static int candidate_window_p (Lisp_Object, Lisp_Object, Lisp_Object,
+                               Lisp_Object);
+static Lisp_Object next_window (Lisp_Object, Lisp_Object,
+                                Lisp_Object, int);
+static void decode_next_window_args (Lisp_Object *, Lisp_Object *,
+                                     Lisp_Object *);
+static int foreach_window_1 (struct window *,
+                             int (* fn) (struct window *, void *),
+                             void *);
+static Lisp_Object window_list_1 (Lisp_Object, Lisp_Object, Lisp_Object);
 
 /* This is the window in which the terminal's cursor should
    be left when nothing is being done with it.  This must
@@ -141,63 +142,10 @@ int mode_line_in_non_selected_windows;
 EMACS_INT window_min_height;
 EMACS_INT window_min_width;
 
-/* Nonzero implies Fdisplay_buffer should create windows. */
-
-int pop_up_windows;
-
-/* Nonzero implies make new frames for Fdisplay_buffer.  */
-
-int pop_up_frames;
-
-/* Nonzero means reuse existing frames for displaying buffers.  */
-
-int display_buffer_reuse_frames;
-
-/* Non-nil means use this function instead of default */
-
-Lisp_Object Vpop_up_frame_function;
-
-/* Function to call to handle Fdisplay_buffer.  */
-
-Lisp_Object Vdisplay_buffer_function;
-
-/* Non-nil means that Fdisplay_buffer should even the heights of windows.  */
-
-Lisp_Object Veven_window_heights;
-
-/* List of buffer *names* for buffers that should have their own frames.  */
-
-Lisp_Object Vspecial_display_buffer_names;
-
-/* List of regexps for buffer names that should have their own frames.  */
-
-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.  */
-
-EMACS_INT split_height_threshold;
-
-/* How to split windows (horizontally/vertically/hybrid).  */
-
-Lisp_Object Vsplit_window_preferred_function;
-
 /* Number of lines of continuity in scrolling by screenfuls.  */
 
 EMACS_INT next_screen_context_lines;
@@ -212,22 +160,32 @@ static int window_initialized;
 
 /* Hook to run when window config changes.  */
 
-Lisp_Object Qwindow_configuration_change_hook;
-Lisp_Object Vwindow_configuration_change_hook;
+static Lisp_Object Qwindow_configuration_change_hook;
+static Lisp_Object Vwindow_configuration_change_hook;
 
 /* Non-nil means scroll commands try to put point
    at the same screen height as previously.  */
 
 Lisp_Object Vscroll_preserve_screen_position;
 
+/* Non-nil means that text is inserted before window's markers.  */
+
+Lisp_Object Vwindow_point_insertion_type;
+
 /* Incremented by 1 whenever a window is deleted.  */
 
 int window_deletion_count;
 
 /* Used by the function window_scroll_pixel_based */
 
+static int window_scroll_pixel_based_preserve_x;
 static int window_scroll_pixel_based_preserve_y;
 
+/* Same for window_scroll_line_based.  */
+
+static int window_scroll_preserve_hpos;
+static int window_scroll_preserve_vpos;
+
 #if 0 /* This isn't used anywhere.  */
 /* Nonzero means we can split a frame even if it is "unsplittable".  */
 static int inhibit_frame_unsplittable;
@@ -236,9 +194,17 @@ static int inhibit_frame_unsplittable;
 extern EMACS_INT scroll_margin;
 
 extern Lisp_Object Qwindow_scroll_functions, Vwindow_scroll_functions;
+
+/* If non-nil, then the `recenter' command with a nil argument
+   the entire frame to be redrawn; the special value `tty' causes the
+   frame to be redrawn only if it is a tty frame.  */
+
+static Lisp_Object Vrecenter_redisplay;
+extern Lisp_Object Qtty;
+
 \f
 DEFUN ("windowp", Fwindowp, Swindowp, 1, 1, 0,
-       doc: /* Returns t if OBJECT is a window.  */)
+       doc: /* Return t if OBJECT is a window.  */)
      (object)
      Lisp_Object object;
 {
@@ -246,7 +212,7 @@ DEFUN ("windowp", Fwindowp, Swindowp, 1, 1, 0,
 }
 
 DEFUN ("window-live-p", Fwindow_live_p, Swindow_live_p, 1, 1, 0,
-       doc: /* Returns t if OBJECT is a window which is currently visible.  */)
+       doc: /* Return t if OBJECT is a window which is currently visible.  */)
      (object)
      Lisp_Object object;
 {
@@ -254,7 +220,7 @@ DEFUN ("window-live-p", Fwindow_live_p, Swindow_live_p, 1, 1, 0,
 }
 
 Lisp_Object
-make_window ()
+make_window (void)
 {
   Lisp_Object val;
   register struct window *p;
@@ -275,6 +241,7 @@ make_window ()
   p->frame = Qnil;
   p->display_table = Qnil;
   p->dedicated = Qnil;
+  p->window_parameters = Qnil;
   p->pseudo_window_p = 0;
   bzero (&p->cursor, sizeof (p->cursor));
   bzero (&p->last_cursor, sizeof (p->last_cursor));
@@ -299,6 +266,7 @@ make_window ()
   p->fringes_outside_margins = Qnil;
   p->scroll_bar_width = Qnil;
   p->vertical_scroll_bar_type = Qt;
+  p->resize_proportionally = Qnil;
 
   Vwindow_list = Qnil;
   return val;
@@ -325,7 +293,7 @@ used by that frame.  */)
 }
 
 DEFUN ("window-minibuffer-p", Fwindow_minibuffer_p, Swindow_minibuffer_p, 0, 1, 0,
-       doc: /* Returns non-nil if WINDOW is a minibuffer window.
+       doc: /* Return non-nil if WINDOW is a minibuffer window.
 WINDOW defaults to the selected window.  */)
      (window)
      Lisp_Object window;
@@ -515,8 +483,7 @@ Return nil if window display is not up-to-date.  In that case, use
 
 \f
 static struct window *
-decode_window (window)
-     register Lisp_Object window;
+decode_window (register Lisp_Object window)
 {
   if (NILP (window))
     return XWINDOW (selected_window);
@@ -526,8 +493,7 @@ decode_window (window)
 }
 
 static struct window *
-decode_any_window (window)
-     register Lisp_Object window;
+decode_any_window (register Lisp_Object window)
 {
   if (NILP (window))
     return XWINDOW (selected_window);
@@ -546,8 +512,10 @@ WINDOW defaults to the selected window.  */)
 }
 
 DEFUN ("window-height", Fwindow_height, Swindow_height, 0, 1, 0,
-       doc: /* Return the number of lines in WINDOW (including its mode line).
-WINDOW defaults to the selected window.  */)
+       doc: /* Return the number of lines in WINDOW.
+WINDOW defaults to the selected window.
+
+The return value includes WINDOW's mode line and header line, if any.  */)
      (window)
      Lisp_Object window;
 {
@@ -556,9 +524,11 @@ WINDOW defaults to the selected window.  */)
 
 DEFUN ("window-width", Fwindow_width, Swindow_width, 0, 1, 0,
        doc: /* Return the number of display columns in WINDOW.
-This is the width that is usable columns available for text in WINDOW.
-If you want to find out how many columns WINDOW takes up,
-use  (let ((edges (window-edges))) (- (nth 2 edges) (nth 0 edges))).  */)
+WINDOW defaults to the selected window.
+
+Note: The return value is the number of columns available for text in
+WINDOW.  If you want to find out how many columns WINDOW takes up, use
+(let ((edges (window-edges))) (- (nth 2 edges) (nth 0 edges))).  */)
      (window)
      Lisp_Object window;
 {
@@ -637,12 +607,15 @@ Afterwards the end-trigger value is reset to nil.  */)
 
 DEFUN ("window-edges", Fwindow_edges, Swindow_edges, 0, 1, 0,
        doc: /* Return a list of the edge coordinates of WINDOW.
-\(LEFT TOP RIGHT BOTTOM), all relative to 0, 0 at top left corner of frame.
-RIGHT is one more than the rightmost column occupied by WINDOW,
-and BOTTOM is one more than the bottommost row occupied by WINDOW.
-The edges include the space used by the window's scroll bar,
-display margins, fringes, header line, and mode line, if it has them.
-To get the edges of the actual text area, use `window-inside-edges'.  */)
+The list has the form (LEFT TOP RIGHT BOTTOM).
+TOP and BOTTOM count by lines, and LEFT and RIGHT count by columns,
+all relative to 0, 0 at top left corner of frame.
+
+RIGHT is one more than the rightmost column occupied by WINDOW.
+BOTTOM is one more than the bottommost row occupied by WINDOW.
+The edges include the space used by WINDOW's scroll bar, display
+margins, fringes, header line, and/or mode line.  For the edges of
+just the text area, use `window-inside-edges'.  */)
      (window)
      Lisp_Object window;
 {
@@ -657,12 +630,14 @@ To get the edges of the actual text area, use `window-inside-edges'.  */)
 
 DEFUN ("window-pixel-edges", Fwindow_pixel_edges, Swindow_pixel_edges, 0, 1, 0,
        doc: /* Return a list of the edge pixel coordinates of WINDOW.
-\(LEFT TOP RIGHT BOTTOM), all relative to 0, 0 at top left corner of frame.
-RIGHT is one more than the rightmost x position occupied by WINDOW,
-and BOTTOM is one more than the bottommost y position occupied by WINDOW.
-The pixel edges include the space used by the window's scroll bar,
-display margins, fringes, header line, and mode line, if it has them.
-To get the edges of the actual text area, use `window-inside-pixel-edges'.  */)
+The list has the form (LEFT TOP RIGHT BOTTOM), all relative to 0, 0 at
+the top left corner of the frame.
+
+RIGHT is one more than the rightmost x position occupied by WINDOW.
+BOTTOM is one more than the bottommost y position occupied by WINDOW.
+The pixel edges include the space used by WINDOW's scroll bar, display
+margins, fringes, header line, and/or mode line.  For the pixel edges
+of just the text area, use `window-inside-pixel-edges'.  */)
      (window)
      Lisp_Object window;
 {
@@ -675,13 +650,58 @@ To get the edges of the actual text area, use `window-inside-pixel-edges'.  */)
                Qnil))));
 }
 
+static void
+calc_absolute_offset(struct window *w, int *add_x, int *add_y)
+{
+  struct frame *f = XFRAME (w->frame);
+  *add_y = f->top_pos;
+#ifdef FRAME_MENUBAR_HEIGHT
+  *add_y += FRAME_MENUBAR_HEIGHT (f);
+#endif
+#ifdef FRAME_TOOLBAR_HEIGHT
+  *add_y += FRAME_TOOLBAR_HEIGHT (f);
+#endif
+#ifdef FRAME_NS_TITLEBAR_HEIGHT
+  *add_y += FRAME_NS_TITLEBAR_HEIGHT (f);
+#endif
+  *add_x = f->left_pos;
+}
+
+DEFUN ("window-absolute-pixel-edges", Fwindow_absolute_pixel_edges,
+       Swindow_absolute_pixel_edges, 0, 1, 0,
+       doc: /* Return a list of the edge pixel coordinates of WINDOW.
+The list has the form (LEFT TOP RIGHT BOTTOM), all relative to 0, 0 at
+the top left corner of the display.
+
+RIGHT is one more than the rightmost x position occupied by WINDOW.
+BOTTOM is one more than the bottommost y position occupied by WINDOW.
+The pixel edges include the space used by WINDOW's scroll bar, display
+margins, fringes, header line, and/or mode line.  For the pixel edges
+of just the text area, use `window-inside-absolute-pixel-edges'.  */)
+     (window)
+     Lisp_Object window;
+{
+  register struct window *w = decode_any_window (window);
+  int add_x, add_y;
+  calc_absolute_offset(w, &add_x, &add_y);
+
+  return Fcons (make_number (WINDOW_LEFT_EDGE_X (w) + add_x),
+         Fcons (make_number (WINDOW_TOP_EDGE_Y (w) + add_y),
+        Fcons (make_number (WINDOW_RIGHT_EDGE_X (w) + add_x),
+        Fcons (make_number (WINDOW_BOTTOM_EDGE_Y (w) + add_y),
+               Qnil))));
+}
+
 DEFUN ("window-inside-edges", Fwindow_inside_edges, Swindow_inside_edges, 0, 1, 0,
        doc: /* Return a list of the edge coordinates of WINDOW.
-\(LEFT TOP RIGHT BOTTOM), all relative to 0, 0 at top left corner of frame.
-RIGHT is one more than the rightmost column used by text in WINDOW,
-and BOTTOM is one more than the bottommost row used by text in WINDOW.
-The inside edges do not include the space used by the window's scroll bar,
-display margins, fringes, header line, and/or mode line.  */)
+The list has the form (LEFT TOP RIGHT BOTTOM).
+TOP and BOTTOM count by lines, and LEFT and RIGHT count by columns,
+all relative to 0, 0 at top left corner of frame.
+
+RIGHT is one more than the rightmost column of WINDOW's text area.
+BOTTOM is one more than the bottommost row of WINDOW's text area.
+The inside edges do not include the space used by the WINDOW's scroll
+bar, display margins, fringes, header line, and/or mode line.  */)
      (window)
      Lisp_Object window;
 {
@@ -701,10 +721,12 @@ display margins, fringes, header line, and/or mode line.  */)
 
 DEFUN ("window-inside-pixel-edges", Fwindow_inside_pixel_edges, Swindow_inside_pixel_edges, 0, 1, 0,
        doc: /* Return a list of the edge pixel coordinates of WINDOW.
-\(LEFT TOP RIGHT BOTTOM), all relative to 0, 0 at top left corner of frame.
-RIGHT is one more than the rightmost x position used by text in WINDOW,
-and BOTTOM is one more than the bottommost y position used by text in WINDOW.
-The inside edges do not include the space used by the window's scroll bar,
+The list has the form (LEFT TOP RIGHT BOTTOM), all relative to 0, 0 at
+the top left corner of the frame.
+
+RIGHT is one more than the rightmost x position of WINDOW's text area.
+BOTTOM is one more than the bottommost y position of WINDOW's text area.
+The inside edges do not include the space used by WINDOW's scroll bar,
 display margins, fringes, header line, and/or mode line.  */)
      (window)
      Lisp_Object window;
@@ -723,6 +745,36 @@ display margins, fringes, header line, and/or mode line.  */)
                             - WINDOW_MODE_LINE_HEIGHT (w)));
 }
 
+DEFUN ("window-inside-absolute-pixel-edges",
+       Fwindow_inside_absolute_pixel_edges,
+       Swindow_inside_absolute_pixel_edges, 0, 1, 0,
+       doc: /* Return a list of the edge pixel coordinates of WINDOW.
+The list has the form (LEFT TOP RIGHT BOTTOM), all relative to 0, 0 at
+the top left corner of the display.
+
+RIGHT is one more than the rightmost x position of WINDOW's text area.
+BOTTOM is one more than the bottommost y position of WINDOW's text area.
+The inside edges do not include the space used by WINDOW's scroll bar,
+display margins, fringes, header line, and/or mode line.  */)
+     (window)
+     Lisp_Object window;
+{
+  register struct window *w = decode_any_window (window);
+  int add_x, add_y;
+  calc_absolute_offset(w, &add_x, &add_y);
+
+  return list4 (make_number (WINDOW_BOX_LEFT_EDGE_X (w)
+                            + WINDOW_LEFT_MARGIN_WIDTH (w)
+                            + WINDOW_LEFT_FRINGE_WIDTH (w) + add_x),
+               make_number (WINDOW_TOP_EDGE_Y (w)
+                            + WINDOW_HEADER_LINE_HEIGHT (w) + add_y),
+               make_number (WINDOW_BOX_RIGHT_EDGE_X (w)
+                            - WINDOW_RIGHT_MARGIN_WIDTH (w)
+                            - WINDOW_RIGHT_FRINGE_WIDTH (w) + add_x),
+               make_number (WINDOW_BOTTOM_EDGE_Y (w)
+                            - WINDOW_MODE_LINE_HEIGHT (w) + add_y));
+}
+
 /* Test if the character at column *X, row *Y is within window W.
    If it is not, return ON_NOTHING;
    if it is in the window's text area,
@@ -745,9 +797,7 @@ display margins, fringes, header line, and/or mode line.  */)
    X and Y are frame relative pixel coordinates.  */
 
 static enum window_part
-coordinates_in_window (w, x, y)
-     register struct window *w;
-     register int *x, *y;
+coordinates_in_window (register struct window *w, register int *x, register int *y)
 {
   struct frame *f = XFRAME (WINDOW_FRAME (w));
   int left_x, right_x, top_y, bottom_y;
@@ -795,7 +845,7 @@ coordinates_in_window (w, x, y)
     header_vertical_border_check:
       /* We're somewhere on the mode line.  We consider the place
         between mode lines of horizontally adjacent mode lines
-        as the vertical border.    If scroll bars on the left,
+        as the vertical border.  If scroll bars on the left,
         return the right window.  */
       if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w)
          || WINDOW_RIGHTMOST_P (w))
@@ -811,7 +861,11 @@ coordinates_in_window (w, x, y)
        }
       else
        {
-         if (eabs (*x - x1) < grabbable_width)
+         /* Make sure we're not at the rightmost position of a
+            mode-/header-line and there's yet another window on
+            the right.  (Bug#1372)  */
+         if ((WINDOW_RIGHTMOST_P (w) || *x < x1)
+             && eabs (*x - x1) < grabbable_width)
            {
              /* Convert X and Y to window relative coordinates.
                 Vertical border is at the right edge of window.  */
@@ -936,7 +990,7 @@ DEFUN ("coordinates-in-window-p", Fcoordinates_in_window_p,
        doc: /* Return non-nil if COORDINATES are in WINDOW.
 COORDINATES is a cons of the form (X . Y), X and Y being distances
 measured in characters from the upper-left corner of the frame.
-\(0 .  0) denotes the character in the upper left corner of the
+\(0 . 0) denotes the character in the upper left corner of the
 frame.
 If COORDINATES are in the text portion of WINDOW,
    the coordinates relative to the window are returned.
@@ -1026,9 +1080,7 @@ struct check_window_data
 };
 
 static int
-check_window_containing (w, user_data)
-     struct window *w;
-     void *user_data;
+check_window_containing (struct window *w, void *user_data)
 {
   struct check_window_data *cw = (struct check_window_data *) user_data;
   enum window_part found;
@@ -1066,12 +1118,7 @@ check_window_containing (w, user_data)
    case.  */
 
 Lisp_Object
-window_from_coordinates (f, x, y, part, wx, wy, tool_bar_p)
-     struct frame *f;
-     int x, y;
-     enum window_part *part;
-     int *wx, *wy;
-     int tool_bar_p;
+window_from_coordinates (struct frame *f, int x, int y, enum window_part *part, int *wx, int *wy, int tool_bar_p)
 {
   Lisp_Object window;
   struct check_window_data cw;
@@ -1275,9 +1322,9 @@ Return POS.  */)
 
 DEFUN ("set-window-start", Fset_window_start, Sset_window_start, 2, 3, 0,
        doc: /* Make display in WINDOW start at position POS in WINDOW's buffer.
-Return POS.
-Optional third arg NOFORCE non-nil inhibits next redisplay
-from overriding motion of point in order to display at this exact start.  */)
+WINDOW defaults to the selected window.  Return POS.
+Optional third arg NOFORCE non-nil inhibits next redisplay from
+overriding motion of point in order to display at this exact start.  */)
      (window, pos, noforce)
      Lisp_Object window, pos, noforce;
 {
@@ -1298,10 +1345,25 @@ from overriding motion of point in order to display at this exact start.  */)
   return pos;
 }
 
+
 DEFUN ("window-dedicated-p", Fwindow_dedicated_p, Swindow_dedicated_p,
-       1, 1, 0,
-       doc: /* Return WINDOW's dedicated object, usually t or nil.
-See also `set-window-dedicated-p'.  */)
+       0, 1, 0,
+       doc: /* Return non-nil when WINDOW is dedicated to its buffer.
+More precisely, return the value assigned by the last call of
+`set-window-dedicated-p' for WINDOW.  Return nil if that function was
+never called with WINDOW as its argument, or the value set by that
+function was internally reset since its last call.  WINDOW defaults to
+the selected window.
+
+When a window is dedicated to its buffer, `display-buffer' will refrain
+from displaying another buffer in it.  `get-lru-window' and
+`get-largest-window' treat dedicated windows specially.
+`delete-windows-on', `replace-buffer-in-windows', `quit-window' and
+`kill-buffer' can delete a dedicated window and the containing frame.
+
+Functions like `set-window-buffer' may change the buffer displayed by a
+window, unless that window is "strongly" dedicated to its buffer, that
+is the value returned by `window-dedicated-p' is t.  */)
      (window)
      Lisp_Object window;
 {
@@ -1310,21 +1372,76 @@ See also `set-window-dedicated-p'.  */)
 
 DEFUN ("set-window-dedicated-p", Fset_window_dedicated_p,
        Sset_window_dedicated_p, 2, 2, 0,
-       doc: /* Control whether WINDOW is dedicated to the buffer it displays.
-If it is dedicated, Emacs will not automatically change
-which buffer appears in it.
-The second argument is the new value for the dedication flag;
-non-nil means yes. */)
-     (window, arg)
-     Lisp_Object window, arg;
+       doc: /* Mark WINDOW as dedicated according to FLAG.
+WINDOW defaults to the selected window.  FLAG non-nil means mark WINDOW
+as dedicated to its buffer.  FLAG nil means mark WINDOW as non-dedicated.
+Return FLAG.
+
+When a window is dedicated to its buffer, `display-buffer' will refrain
+from displaying another buffer in it.  `get-lru-window' and
+`get-largest-window' treat dedicated windows specially.
+`delete-windows-on', `replace-buffer-in-windows', `quit-window' and
+`kill-buffer' can delete a dedicated window and the containing
+frame.
+
+As a special case, if FLAG is t, mark WINDOW as "strongly" dedicated to
+its buffer.  Functions like `set-window-buffer' may change the buffer
+displayed by a window, unless that window is strongly dedicated to its
+buffer.  If and when `set-window-buffer' displays another buffer in a
+window, it also makes sure that the window is not marked as dedicated.  */)
+     (window, flag)
+     Lisp_Object window, flag;
 {
   register struct window *w = decode_window (window);
 
-  w->dedicated = arg;
-
+  w->dedicated = flag;
   return w->dedicated;
 }
 
+
+DEFUN ("window-parameters", Fwindow_parameters, Swindow_parameters,
+       0, 1, 0,
+       doc: /* Return the parameters of WINDOW and their values.
+WINDOW defaults to the selected window.  The return value is a list of
+elements of the form (PARAMETER . VALUE). */)
+     (window)
+     Lisp_Object window;
+{
+  return Fcopy_alist (decode_window (window)->window_parameters);
+}
+
+DEFUN ("window-parameter", Fwindow_parameter, Swindow_parameter,
+       2, 2, 0,
+       doc:  /* Return WINDOW's value for PARAMETER.
+WINDOW defaults to the selected window.  */)
+     (window, parameter)
+     Lisp_Object window, parameter;
+{
+  Lisp_Object result;
+
+  result = Fassq (parameter, decode_window (window)->window_parameters);
+  return CDR_SAFE (result);
+}
+
+DEFUN ("set-window-parameter", Fset_window_parameter,
+       Sset_window_parameter, 3, 3, 0,
+       doc: /* Set WINDOW's value of PARAMETER to VALUE.
+WINDOW defaults to the selected window.  Return VALUE.  */)
+     (window, parameter, value)
+     Lisp_Object window, parameter, value;
+{
+  register struct window *w = decode_window (window);
+  Lisp_Object old_alist_elt;
+
+  old_alist_elt = Fassq (parameter, w->window_parameters);
+  if (NILP (old_alist_elt))
+    w->window_parameters = Fcons (Fcons (parameter, value), w->window_parameters);
+  else
+    Fsetcdr (old_alist_elt, value);
+  return value;
+}
+
+
 DEFUN ("window-display-table", Fwindow_display_table, Swindow_display_table,
        0, 1, 0,
        doc: /* Return the display-table that WINDOW is using.
@@ -1341,8 +1458,7 @@ WINDOW defaults to the selected window.  */)
    return 0.  */
 
 struct Lisp_Char_Table *
-window_display_table (w)
-     struct window *w;
+window_display_table (struct window *w)
 {
   struct Lisp_Char_Table *dp = NULL;
 
@@ -1376,8 +1492,7 @@ DEFUN ("set-window-display-table", Fset_window_display_table, Sset_window_displa
 /* Record info on buffer window w is displaying
    when it is about to cease to display that buffer.  */
 static void
-unshow_buffer (w)
-     register struct window *w;
+unshow_buffer (register struct window *w)
 {
   Lisp_Object buf;
   struct buffer *b;
@@ -1425,8 +1540,7 @@ unshow_buffer (w)
 
 /* Put replacement into the window structure in place of old. */
 static void
-replace_window (old, replacement)
-     Lisp_Object old, replacement;
+replace_window (Lisp_Object old, Lisp_Object replacement)
 {
   register Lisp_Object tem;
   register struct window *o = XWINDOW (old), *p = XWINDOW (replacement);
@@ -1479,22 +1593,28 @@ children be children of that parent instead.  ***/
 }
 
 DEFUN ("delete-window", Fdelete_window, Sdelete_window, 0, 1, "",
-       doc: /* Remove WINDOW from the display.  Default is selected window.  */)
+       doc: /* Remove WINDOW from its frame.
+WINDOW defaults to the selected window.  Return nil.
+Signal an error when WINDOW is the only window on its frame.  */)
      (window)
      register Lisp_Object window;
 {
+  struct frame *f;
+  if (NILP (window))
+    window = selected_window;
+  else
+    CHECK_LIVE_WINDOW (window);
+
+  f = XFRAME (WINDOW_FRAME (XWINDOW (window)));
   delete_window (window);
 
-  if (! NILP (Vwindow_configuration_change_hook)
-      && ! NILP (Vrun_hooks))
-    call1 (Vrun_hooks, Qwindow_configuration_change_hook);
+  run_window_configuration_change_hook (f);
 
   return Qnil;
 }
 
 void
-delete_window (window)
-     register Lisp_Object window;
+delete_window (register Lisp_Object window)
 {
   register Lisp_Object tem, parent, sib;
   register struct window *p;
@@ -1504,10 +1624,7 @@ delete_window (window)
   /* Because this function is called by other C code on non-leaf
      windows, the CHECK_LIVE_WINDOW macro would choke inappropriately,
      so we can't decode_window here.  */
-  if (NILP (window))
-    window = selected_window;
-  else
-    CHECK_WINDOW (window);
+  CHECK_WINDOW (window);
   p = XWINDOW (window);
 
   /* It's a no-op to delete an already-deleted window.  */
@@ -1711,9 +1828,7 @@ delete_window (window)
    function window_list.  */
 
 static int
-add_window_to_list (w, user_data)
-     struct window *w;
-     void *user_data;
+add_window_to_list (struct window *w, void *user_data)
 {
   Lisp_Object *list = (Lisp_Object *) user_data;
   Lisp_Object window;
@@ -1728,7 +1843,7 @@ add_window_to_list (w, user_data)
    list, cache it in Vwindow_list, and return that.  */
 
 static Lisp_Object
-window_list ()
+window_list (void)
 {
   if (!CONSP (Vwindow_list))
     {
@@ -1769,8 +1884,7 @@ window_list ()
                a frame means consider windows on that frame, only.  */
 
 static int
-candidate_window_p (window, owindow, minibuf, all_frames)
-     Lisp_Object window, owindow, minibuf, all_frames;
+candidate_window_p (Lisp_Object window, Lisp_Object owindow, Lisp_Object minibuf, Lisp_Object all_frames)
 {
   struct window *w = XWINDOW (window);
   struct frame *f = XFRAME (w->frame);
@@ -1835,8 +1949,7 @@ candidate_window_p (window, owindow, minibuf, all_frames)
    ALL_FRAMES.  */
 
 static void
-decode_next_window_args (window, minibuf, all_frames)
-     Lisp_Object *window, *minibuf, *all_frames;
+decode_next_window_args (Lisp_Object *window, Lisp_Object *minibuf, Lisp_Object *all_frames)
 {
   if (NILP (*window))
     *window = selected_window;
@@ -1876,15 +1989,13 @@ decode_next_window_args (window, minibuf, all_frames)
 }
 
 
-/* Return the next or previous window of WINDOW in canonical ordering
+/* Return the next or previous window of WINDOW in cyclic ordering
    of windows.  NEXT_P non-zero means return the next window.  See the
    documentation string of next-window for the meaning of MINIBUF and
    ALL_FRAMES.  */
 
 static Lisp_Object
-next_window (window, minibuf, all_frames, next_p)
-     Lisp_Object window, minibuf, all_frames;
-     int next_p;
+next_window (Lisp_Object window, Lisp_Object minibuf, Lisp_Object all_frames, int next_p)
 {
   decode_next_window_args (&window, &minibuf, &all_frames);
 
@@ -1948,26 +2059,36 @@ next_window (window, minibuf, all_frames, next_p)
 
 
 DEFUN ("next-window", Fnext_window, Snext_window, 0, 3, 0,
-       doc: /* Return next window after WINDOW in canonical ordering of windows.
-If omitted, WINDOW defaults to the selected window.
+       doc: /* Return window following WINDOW in cyclic ordering of windows.
+WINDOW defaults to the selected window. The optional arguments
+MINIBUF and ALL-FRAMES specify the set of windows to consider.
 
-Optional second arg MINIBUF t means count the minibuffer window even
-if not active.  MINIBUF nil or omitted means count the minibuffer iff
-it is active.  MINIBUF neither t nor nil means not to count the
-minibuffer even if it is active.
+MINIBUF t means consider the minibuffer window even if the
+minibuffer is not active.  MINIBUF nil or omitted means consider
+the minibuffer window only if the minibuffer is active.  Any
+other value means do not consider the minibuffer window even if
+the minibuffer is active.
 
 Several frames may share a single minibuffer; if the minibuffer
-counts, all windows on all frames that share that minibuffer count
-too.  Therefore, `next-window' can be used to iterate through the
-set of windows even when the minibuffer is on another frame.  If the
-minibuffer does not count, only windows from WINDOW's frame count.
-
-Optional third arg ALL-FRAMES t means include windows on all frames.
-ALL-FRAMES nil or omitted means cycle within the frames as specified
-above.  ALL-FRAMES = `visible' means include windows on all visible frames.
-ALL-FRAMES = 0 means include windows on all visible and iconified frames.
-If ALL-FRAMES is a frame, restrict search to windows on that frame.
-Anything else means restrict to WINDOW's frame.
+is active, all windows on all frames that share that minibuffer
+are considered too.  Therefore, if you are using a separate
+minibuffer frame and the minibuffer is active and MINIBUF says it
+counts, `next-window' considers the windows in the frame from
+which you entered the minibuffer, as well as the minibuffer
+window.
+
+ALL-FRAMES nil or omitted means consider all windows on WINDOW's
+ frame, plus the minibuffer window if specified by the MINIBUF
+ argument, see above.  If the minibuffer counts, consider all
+ windows on all frames that share that minibuffer too.
+ALL-FRAMES t means consider all windows on all existing frames.
+ALL-FRAMES `visible' means consider all windows on all visible
+ frames.
+ALL-FRAMES 0 means consider all windows on all visible and
+ iconified frames.
+ALL-FRAMES a frame means consider all windows on that frame only.
+Anything else means consider all windows on WINDOW's frame and no
+ others.
 
 If you use consistent values for MINIBUF and ALL-FRAMES, you can use
 `next-window' to iterate through the entire cycle of acceptable
@@ -1981,31 +2102,16 @@ windows, eventually ending up back at the window you started with.
 
 
 DEFUN ("previous-window", Fprevious_window, Sprevious_window, 0, 3, 0,
-       doc: /* Return the window preceding WINDOW in canonical ordering of windows.
-If omitted, WINDOW defaults to the selected window.
-
-Optional second arg MINIBUF t means count the minibuffer window even
-if not active.  MINIBUF nil or omitted means count the minibuffer iff
-it is active.  MINIBUF neither t nor nil means not to count the
-minibuffer even if it is active.
-
-Several frames may share a single minibuffer; if the minibuffer
-counts, all windows on all frames that share that minibuffer count
-too.  Therefore, `previous-window' can be used to iterate through
-the set of windows even when the minibuffer is on another frame.  If
-the minibuffer does not count, only windows from WINDOW's frame count
-
-Optional third arg ALL-FRAMES t means include windows on all frames.
-ALL-FRAMES nil or omitted means cycle within the frames as specified
-above.  ALL-FRAMES = `visible' means include windows on all visible frames.
-ALL-FRAMES = 0 means include windows on all visible and iconified frames.
-If ALL-FRAMES is a frame, restrict search to windows on that frame.
-Anything else means restrict to WINDOW's frame.
-
-If you use consistent values for MINIBUF and ALL-FRAMES, you can use
-`previous-window' to iterate through the entire cycle of acceptable
-windows, eventually ending up back at the window you started with.
-`next-window' traverses the same cycle, in the reverse order.  */)
+       doc: /* Return window preceding WINDOW in cyclic ordering of windows.
+WINDOW defaults to the selected window. The optional arguments
+MINIBUF and ALL-FRAMES specify the set of windows to consider.
+For the precise meaning of these arguments see `next-window'.
+
+If you use consistent values for MINIBUF and ALL-FRAMES, you can
+use `previous-window' to iterate through the entire cycle of
+acceptable windows, eventually ending up back at the window you
+started with.  `next-window' traverses the same cycle, in the
+reverse order.  */)
      (window, minibuf, all_frames)
      Lisp_Object window, minibuf, all_frames;
 {
@@ -2014,21 +2120,28 @@ windows, eventually ending up back at the window you started with.
 
 
 DEFUN ("other-window", Fother_window, Sother_window, 1, 2, "p",
-       doc: /* Select the ARG'th different window on this frame.
-All windows on current frame are arranged in a cyclic order.
-This command selects the window ARG steps away in that order.
-A negative ARG moves in the opposite order.  The optional second
-argument ALL-FRAMES has the same meaning as in `next-window', which see.  */)
-     (arg, all_frames)
-     Lisp_Object arg, all_frames;
+       doc: /* Select another window in cyclic ordering of windows.
+COUNT specifies the number of windows to skip, starting with the
+selected window, before making the selection.  If COUNT is
+positive, skip COUNT windows forwards.  If COUNT is negative,
+skip -COUNT windows backwards.  COUNT zero means do not skip any
+window, so select the selected window.  In an interactive call,
+COUNT is the numeric prefix argument.  Return nil.
+
+This function uses `next-window' for finding the window to select.
+The argument ALL-FRAMES has the same meaning as in `next-window',
+but the MINIBUF argument of `next-window' is always effectively
+nil.  */)
+     (count, all_frames)
+     Lisp_Object count, all_frames;
 {
   Lisp_Object window;
   int i;
 
-  CHECK_NUMBER (arg);
+  CHECK_NUMBER (count);
   window = selected_window;
 
-  for (i = XINT (arg); i > 0; --i)
+  for (i = XINT (count); i > 0; --i)
     window = Fnext_window (window, Qnil, all_frames);
   for (; i < 0; ++i)
     window = Fprevious_window (window, Qnil, all_frames);
@@ -2062,12 +2175,11 @@ MINIBUF neither nil nor t means never include the minibuffer window.  */)
 }
 
 
-/* Return a list of windows in canonical ordering.  Arguments are like
+/* Return a list of windows in cyclic ordering.  Arguments are like
    for `next-window'.  */
 
 static Lisp_Object
-window_list_1 (window, minibuf, all_frames)
-     Lisp_Object window, minibuf, all_frames;
+window_list_1 (Lisp_Object window, Lisp_Object minibuf, Lisp_Object all_frames)
 {
   Lisp_Object tail, list, rest;
 
@@ -2115,10 +2227,7 @@ enum window_loop
 };
 
 static Lisp_Object
-window_loop (type, obj, mini, frames)
-     enum window_loop type;
-     Lisp_Object obj, frames;
-     int mini;
+window_loop (enum window_loop type, Lisp_Object obj, int mini, Lisp_Object frames)
 {
   Lisp_Object window, windows, best_window, frame_arg;
   struct frame *f;
@@ -2233,7 +2342,7 @@ window_loop (type, obj, mini, frames)
                      windows = XCDR (windows);
 
                    /* Now we can safely delete the frame.  */
-                   Fdelete_frame (w->frame, Qnil);
+                   delete_frame (w->frame, Qnil);
                  }
                else if (NILP (w->parent))
                  {
@@ -2242,6 +2351,8 @@ window_loop (type, obj, mini, frames)
                       display there.  */
                    Lisp_Object buffer;
                    buffer = Fother_buffer (obj, Qnil, w->frame);
+                   /* Reset dedicated state of window.  */
+                   w->dedicated = Qnil;
                    Fset_window_buffer (window, buffer, Qnil);
                    if (EQ (window, selected_window))
                      Fset_buffer (w->buffer);
@@ -2292,7 +2403,7 @@ window_loop (type, obj, mini, frames)
                      windows = XCDR (windows);
 
                    /* Now we can safely delete the frame.  */
-                   Fdelete_frame (w->frame, Qnil);
+                   delete_frame (w->frame, Qnil);
                  }
                else if (!NILP (w->dedicated) && !NILP (w->parent))
                  {
@@ -2343,7 +2454,7 @@ window_loop (type, obj, mini, frames)
 /* Used for debugging.  Abort if any window has a dead buffer.  */
 
 void
-check_all_windows ()
+check_all_windows (void)
 {
   window_loop (CHECK_ALL_WINDOWS, Qnil, 1, Qt);
 }
@@ -2394,18 +2505,25 @@ If FRAME is a frame, search only that frame.  */)
                      frame);
 }
 
-DEFUN ("get-buffer-window", Fget_buffer_window, Sget_buffer_window, 1, 2, 0,
-       doc: /* Return a window currently displaying BUFFER, or nil if none.
-BUFFER can be a buffer or a buffer name.
+DEFUN ("get-buffer-window", Fget_buffer_window, Sget_buffer_window, 0, 2, 0,
+       doc: /* Return a window currently displaying BUFFER-OR-NAME, or nil if none.
+BUFFER-OR-NAME may be a buffer or a buffer name and defaults to the
+current buffer.
 If optional argument FRAME is `visible', search all visible frames.
 If optional argument FRAME is 0, search all visible and iconified frames.
 If FRAME is t, search all frames.
 If FRAME is nil, search only the selected frame.
 If FRAME is a frame, search only that frame.  */)
-     (buffer, frame)
-     Lisp_Object buffer, frame;
+     (buffer_or_name, frame)
+     Lisp_Object buffer_or_name, frame;
 {
-  buffer = Fget_buffer (buffer);
+  Lisp_Object buffer;
+
+  if (NILP (buffer_or_name))
+    buffer = Fcurrent_buffer ();
+  else
+    buffer = Fget_buffer (buffer_or_name);
+
   if (BUFFERP (buffer))
     return window_loop (GET_BUFFER_WINDOW, buffer, 1, frame);
   else
@@ -2416,12 +2534,11 @@ DEFUN ("delete-other-windows", Fdelete_other_windows, Sdelete_other_windows,
        0, 1, "",
        doc: /* Make WINDOW (or the selected window) fill its frame.
 Only the frame WINDOW is on is affected.
-This function tries to reduce display jumps
-by keeping the text previously visible in WINDOW
-in the same place on the frame.  Doing this depends on
-the value of (window-start WINDOW), so if calling this function
-in a program gives strange scrolling, make sure the window-start
-value is reasonable when this function is called.  */)
+This function tries to reduce display jumps by keeping the text
+previously visible in WINDOW in the same place on the frame.  Doing this
+depends on the value of (window-start WINDOW), so if calling this
+function in a program gives strange scrolling, make sure the
+window-start value is reasonable when this function is called.  */)
      (window)
      Lisp_Object window;
 {
@@ -2477,18 +2594,24 @@ value is reasonable when this function is called.  */)
 }
 
 DEFUN ("delete-windows-on", Fdelete_windows_on, Sdelete_windows_on,
-       1, 2, "bDelete windows on (buffer): ",
-       doc: /* Delete all windows showing BUFFER.
-BUFFER must be a buffer or the name of an existing buffer.
+       0, 2, "bDelete windows on (buffer): ",
+       doc: /* Delete all windows showing BUFFER-OR-NAME.
+BUFFER-OR-NAME may be a buffer or the name of an existing buffer and
+defaults to the current buffer.
+
 Optional second argument FRAME controls which frames are affected.
 If optional argument FRAME is `visible', search all visible frames.
 If FRAME is 0, search all visible and iconified frames.
 If FRAME is nil, search all frames.
 If FRAME is t, search only the selected frame.
-If FRAME is a frame, search only that frame.  */)
-     (buffer, frame)
-     Lisp_Object buffer, frame;
+If FRAME is a frame, search only that frame.
+When a window showing BUFFER-OR-NAME is dedicated and the only window of
+its frame, that frame is deleted when there are other frames left.  */)
+     (buffer_or_name, frame)
+     Lisp_Object buffer_or_name, frame;
 {
+  Lisp_Object buffer;
+
   /* FRAME uses t and nil to mean the opposite of what window_loop
      expects.  */
   if (NILP (frame))
@@ -2496,30 +2619,45 @@ If FRAME is a frame, search only that frame.  */)
   else if (EQ (frame, Qt))
     frame = Qnil;
 
-  if (!NILP (buffer))
+  if (NILP (buffer_or_name))
+    buffer = Fcurrent_buffer ();
+  else
     {
-      buffer = Fget_buffer (buffer);
+      buffer = Fget_buffer (buffer_or_name);
       CHECK_BUFFER (buffer);
-      window_loop (DELETE_BUFFER_WINDOWS, buffer, 0, frame);
     }
 
+  window_loop (DELETE_BUFFER_WINDOWS, buffer, 0, frame);
+
   return Qnil;
 }
 
 DEFUN ("replace-buffer-in-windows", Freplace_buffer_in_windows,
        Sreplace_buffer_in_windows,
-       1, 1, "bReplace buffer in windows: ",
-       doc: /* Replace BUFFER with some other buffer in all windows showing it.
-BUFFER may be a buffer or the name of an existing buffer.  */)
-     (buffer)
-     Lisp_Object buffer;
-{
-  if (!NILP (buffer))
+       0, 1, "bReplace buffer in windows: ",
+       doc: /* Replace BUFFER-OR-NAME with some other buffer in all windows showing it.
+BUFFER-OR-NAME may be a buffer or the name of an existing buffer and
+defaults to the current buffer.
+
+When a window showing BUFFER-OR-NAME is dedicated that window is
+deleted.  If that window is the only window on its frame, that frame is
+deleted too when there are other frames left.  If there are no other
+frames left, some other buffer is displayed in that window.  */)
+     (buffer_or_name)
+     Lisp_Object buffer_or_name;
+{
+  Lisp_Object buffer;
+
+  if (NILP (buffer_or_name))
+    buffer = Fcurrent_buffer ();
+  else
     {
-      buffer = Fget_buffer (buffer);
+      buffer = Fget_buffer (buffer_or_name);
       CHECK_BUFFER (buffer);
-      window_loop (UNSHOW_BUFFER, buffer, 0, Qt);
     }
+
+  window_loop (UNSHOW_BUFFER, buffer, 0, Qt);
+
   return Qnil;
 }
 
@@ -2527,10 +2665,8 @@ BUFFER may be a buffer or the name of an existing buffer.  */)
    of all frames, even those on other keyboards.  */
 
 void
-replace_buffer_in_all_windows (buffer)
-     Lisp_Object buffer;
+replace_buffer_in_all_windows (Lisp_Object buffer)
 {
-#ifdef MULTI_KBOARD
   Lisp_Object tail, frame;
 
   /* A single call to window_loop won't do the job
@@ -2538,9 +2674,6 @@ replace_buffer_in_all_windows (buffer)
      So loop manually over frames, and handle each one.  */
   FOR_EACH_FRAME (tail, frame)
     window_loop (UNSHOW_BUFFER, buffer, 1, frame);
-#else
-  window_loop (UNSHOW_BUFFER, buffer, 1, Qt);
-#endif
 }
 \f
 /* Set the height of WINDOW and all its inferiors.  */
@@ -2551,26 +2684,17 @@ replace_buffer_in_all_windows (buffer)
 #define MIN_SAFE_WINDOW_WIDTH  (2)
 #define MIN_SAFE_WINDOW_HEIGHT (1)
 
-/* Make sure that window_min_height and window_min_width are
-   not too small; if they are, set them to safe minima.  */
+/* For wp non-zero the total number of columns of window w.  Otherwise
+   the total number of lines of w.  */
 
-static void
-check_min_window_sizes ()
-{
-  /* Smaller values might permit a crash.  */
-  if (window_min_width < MIN_SAFE_WINDOW_WIDTH)
-    window_min_width = MIN_SAFE_WINDOW_WIDTH;
-  if (window_min_height < MIN_SAFE_WINDOW_HEIGHT)
-    window_min_height = MIN_SAFE_WINDOW_HEIGHT;
-}
+#define WINDOW_TOTAL_SIZE(w, wp) \
+  (wp ? WINDOW_TOTAL_COLS (w) : WINDOW_TOTAL_LINES (w))
 
 /* If *ROWS or *COLS are too small a size for FRAME, set them to the
    minimum allowable size.  */
 
 void
-check_frame_size (frame, rows, cols)
-     FRAME_PTR frame;
-     int *rows, *cols;
+check_frame_size (FRAME_PTR frame, int *rows, int *cols)
 {
   /* For height, we have to see:
      how many windows the frame has at minimum (one or two),
@@ -2596,9 +2720,7 @@ check_frame_size (frame, rows, cols)
    either.  */
 
 static int
-window_fixed_size_p (w, width_p, check_siblings_p)
-     struct window *w;
-     int width_p, check_siblings_p;
+window_fixed_size_p (struct window *w, int width_p, int check_siblings_p)
 {
   int fixed_p;
   struct window *c;
@@ -2609,7 +2731,7 @@ window_fixed_size_p (w, width_p, check_siblings_p)
 
       if (width_p)
        {
-         /* A horiz. combination is fixed-width if all of if its
+         /* A horizontal combination is fixed-width if all of if its
             children are.  */
          while (c && window_fixed_size_p (c, width_p, 0))
            c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
@@ -2617,7 +2739,7 @@ window_fixed_size_p (w, width_p, check_siblings_p)
        }
       else
        {
-         /* A horiz. combination is fixed-height if one of if its
+         /* A horizontal combination is fixed-height if one of if its
             children is.  */
          while (c && !window_fixed_size_p (c, width_p, 0))
            c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
@@ -2630,7 +2752,7 @@ window_fixed_size_p (w, width_p, check_siblings_p)
 
       if (width_p)
        {
-         /* A vert. combination is fixed-width if one of if its
+         /* A vertical combination is fixed-width if one of if its
             children is.  */
          while (c && !window_fixed_size_p (c, width_p, 0))
            c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
@@ -2638,7 +2760,7 @@ window_fixed_size_p (w, width_p, check_siblings_p)
        }
       else
        {
-         /* A vert. combination is fixed-height if all of if its
+         /* A vertical combination is fixed-height if all of if its
             children are.  */
          while (c && window_fixed_size_p (c, width_p, 0))
            c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
@@ -2690,120 +2812,124 @@ window_fixed_size_p (w, width_p, check_siblings_p)
   return fixed_p;
 }
 
-/* Return the minimum size for leaf window W.  WIDTH_P non-zero means
-   take into account fringes and the scrollbar of W.  WIDTH_P zero means
-   take into account mode-line of W.  Return 1 for the minibuffer.  */
+/* Return minimum size of leaf window W.  WIDTH_P non-zero means return
+   the minimum width of W, WIDTH_P zero means return the minimum height
+   of W.  SAFE_P non-zero means ignore window-min-height|width but just
+   return values that won't crash Emacs and don't hide components like
+   fringes, scrollbars, or modelines.  If WIDTH_P is zero and W is the
+   minibuffer window, always return 1.  */
 
 static int
-window_min_size_2 (w, width_p)
-     struct window *w;
-     int width_p;
+window_min_size_2 (struct window *w, int width_p, int safe_p)
 {
-  int size;
-  
+  /* We should consider buffer-local values of window_min_height and
+     window_min_width here.  */
   if (width_p)
-    size = max (window_min_width,
-               (MIN_SAFE_WINDOW_WIDTH
-                + WINDOW_FRINGE_COLS (w)
-                + WINDOW_SCROLL_BAR_COLS (w)));
+    {
+      int safe_size = (MIN_SAFE_WINDOW_WIDTH
+                      + WINDOW_FRINGE_COLS (w)
+                      + WINDOW_SCROLL_BAR_COLS (w));
+
+      return safe_p ? safe_size : max (window_min_width, safe_size);
+    }
   else if (MINI_WINDOW_P (w))
-    size = 1;
+    return 1;
   else
-    size = max (window_min_height,
-               (MIN_SAFE_WINDOW_HEIGHT
-                /* Don't count the header-line here.  It would break
-                   splitting a window with a header-line when the new
-                   window shall have a height of two (calculator does
-                   that). */
-                + (WINDOW_WANTS_MODELINE_P (w) ? 1 : 0)));
+    {
+      int safe_size = (MIN_SAFE_WINDOW_HEIGHT
+                      + ((BUFFERP (w->buffer)
+                          && !NILP (XBUFFER (w->buffer)->mode_line_format))
+                         ? 1 : 0));
 
-  return size;
+      return safe_p ? safe_size : max (window_min_height, safe_size);
+    }
 }
 
-/* Return the minimum size of window W, not taking fixed-width windows
-   into account.  WIDTH_P non-zero means return the minimum width,
-   otherwise return the minimum height.  If W is a combination window,
-   compute the minimum size from the minimum sizes of W's children.  */
+/* Return minimum size of window W, not taking fixed-width windows into
+   account.  WIDTH_P non-zero means return the minimum width, otherwise
+   return the minimum height.  SAFE_P non-zero means ignore
+   window-min-height|width but just return values that won't crash Emacs
+   and don't hide components like fringes, scrollbars, or modelines.  If
+   W is a combination window, compute the minimum size from the minimum
+   sizes of W's children.  */
 
 static int
-window_min_size_1 (w, width_p)
-     struct window *w;
-     int width_p;
+window_min_size_1 (struct window *w, int width_p, int safe_p)
 {
   struct window *c;
   int size;
 
   if (!NILP (w->hchild))
     {
+      /* W is a horizontal combination.  */
       c = XWINDOW (w->hchild);
       size = 0;
 
       if (width_p)
        {
-         /* The min width of a horizontal combination is
-            the sum of the min widths of its children.  */
+         /* The minimum width of a horizontal combination is the sum of
+            the minimum widths of its children.  */
          while (c)
            {
-             size += window_min_size_1 (c, width_p);
+             size += window_min_size_1 (c, 1, safe_p);
              c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
            }
        }
       else
        {
-         /* The min height a horizontal combination equals
-            the maximum of all min height of its children.  */
+         /* The minimum height of a horizontal combination is the
+            maximum of the minimum heights of its children.  */
          while (c)
            {
-             int min_size = window_min_size_1 (c, width_p);
-             size = max (min_size, size);
+             size = max (window_min_size_1 (c, 0, safe_p), size);
              c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
            }
        }
     }
   else if (!NILP (w->vchild))
     {
+      /* W is a vertical combination.  */
       c = XWINDOW (w->vchild);
       size = 0;
 
       if (width_p)
        {
-         /* The min width of a vertical combination is
-            the maximum of the min widths of its children.  */
+         /* The minimum width of a vertical combination is the maximum
+            of the minimum widths of its children.  */
          while (c)
            {
-             int min_size = window_min_size_1 (c, width_p);
-             size = max (min_size, size);
+             size = max (window_min_size_1 (c, 1, safe_p), size);
              c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
            }
        }
       else
        {
-         /* The min height of a vertical combination equals
-            the sum of the min height of its children.  */
+         /* The minimum height of a vertical combination is the sum of
+            the minimum height of its children.  */
          while (c)
            {
-             size += window_min_size_1 (c, width_p);
+             size += window_min_size_1 (c, 0, safe_p);
              c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
            }
        }
     }
   else
-    size = window_min_size_2 (w, width_p);
+    /* W is a leaf window.  */
+    size = window_min_size_2 (w, width_p, safe_p);
 
   return size;
 }
 
-
 /* Return the minimum size of window W, taking fixed-size windows into
-   account.  WIDTH_P non-zero means return the minimum width,
-   otherwise return the minimum height.  IGNORE_FIXED_P non-zero means
-   ignore if W is fixed-size.  Set *FIXED to 1 if W is fixed-size
-   unless FIXED is null.  */
+   account.  WIDTH_P non-zero means return the minimum width, otherwise
+   return the minimum height.  SAFE_P non-zero means ignore
+   window-min-height|width but just return values that won't crash Emacs
+   and don't hide components like fringes, scrollbars, or modelines.
+   IGNORE_FIXED_P non-zero means ignore if W is fixed-size.  Set *FIXED
+   to 1 if W is fixed-size unless FIXED is null.  */
 
 static int
-window_min_size (w, width_p, ignore_fixed_p, fixed)
-     struct window *w;
-     int width_p, ignore_fixed_p, *fixed;
+window_min_size (struct window *w, int width_p, int safe_p, int ignore_fixed_p, int *fixed)
 {
   int size, fixed_p;
 
@@ -2816,9 +2942,9 @@ window_min_size (w, width_p, ignore_fixed_p, fixed)
     *fixed = fixed_p;
 
   if (fixed_p)
-    size = width_p ? XFASTINT (w->total_cols) : XFASTINT (w->total_lines);
+    size = WINDOW_TOTAL_SIZE (w, width_p);
   else
-    size = window_min_size_1 (w, width_p);
+    size = window_min_size_1 (w, width_p, safe_p);
 
   return size;
 }
@@ -2829,8 +2955,7 @@ window_min_size (w, width_p, ignore_fixed_p, fixed)
    is still too narrow.  */
 
 static int
-adjust_window_margins (w)
-     struct window *w;
+adjust_window_margins (struct window *w)
 {
   int box_cols = (WINDOW_TOTAL_COLS (w)
                  - WINDOW_FRINGE_COLS (w)
@@ -2860,35 +2985,38 @@ adjust_window_margins (w)
   return 1;
 }
 
-/* Calculate new sizes for windows in the list FORWARD when the window size
-   goes from TOTAL to SIZE.  TOTAL must be greater than SIZE.
-   The number of windows in FORWARD is NCHILDREN, and the number that
-   can shrink is SHRINKABLE.
-   The minimum size a window can have is MIN_SIZE.
-   If we are shrinking fixed windows, RESIZE_FIXED_P is non-zero.
-   If we are shrinking columns, WIDTH_P is non-zero, otherwise we are
-   shrinking rows.
+/* Calculate new sizes for windows in the list FORWARD when their
+   compound size goes from TOTAL to SIZE.  TOTAL must be greater than
+   SIZE.  The number of windows in FORWARD is NCHILDREN, and the number
+   that can shrink is SHRINKABLE.  Fixed-size windows may be shrunk if
+   and only if RESIZE_FIXED_P is non-zero.  WIDTH_P non-zero means
+   shrink columns, otherwise shrink lines.
 
-   This function returns an allocated array of new sizes that the caller
-   must free.  The size -1 means the window is fixed and RESIZE_FIXED_P
-   is zero.  Array index 0 refers to the first window in FORWARD, 1 to
-   the second, and so on.
+   SAFE_P zero means windows may be sized down to window-min-height
+   lines (window-min-window columns for WIDTH_P non-zero).  SAFE_P
+   non-zero means windows may be sized down to their minimum safe sizes
+   taking into account the space needed to display modelines, fringes,
+   and scrollbars.
 
-   This function tries to keep windows at least at the minimum size
-   and resize other windows before it resizes any window to zero (i.e.
-   delete that window).
-
-   Windows are resized proportional to their size, so bigger windows
-   shrink more than smaller windows.  */
+   This function returns an allocated array of new sizes that the caller
+   must free.  A size -1 means the window is fixed and RESIZE_FIXED_P is
+   zero.  A size zero means the window shall be deleted.  Array index 0
+   refers to the first window in FORWARD, 1 to the second, and so on.
+
+   This function resizes windows proportionally to their size.  It also
+   tries to preserve smaller windows by resizing larger windows before
+   resizing any window to zero.  If resize_proportionally is non-nil for
+   a specific window, it will attempt to strictly resize that window
+   proportionally, even at the expense of deleting smaller windows.  */
 static int *
-shrink_windows (total, size, nchildren, shrinkable,
-                min_size, resize_fixed_p, forward, width_p)
-     int total, size, nchildren, shrinkable, min_size;
-     int resize_fixed_p, width_p;
+shrink_windows (total, size, nchildren, shrinkable, resize_fixed_p,
+               forward, width_p, safe_p)
+     int total, size, nchildren, shrinkable;
+     int resize_fixed_p, width_p, safe_p;
      Lisp_Object forward;
 {
   int available_resize = 0;
-  int *new_sizes;
+  int *new_sizes, *min_sizes;
   struct window *c;
   Lisp_Object child;
   int smallest = total;
@@ -2897,21 +3025,24 @@ shrink_windows (total, size, nchildren, shrinkable,
   int i;
 
   new_sizes = xmalloc (sizeof (*new_sizes) * nchildren);
+  min_sizes = xmalloc (sizeof (*min_sizes) * nchildren);
 
   for (i = 0, child = forward; !NILP (child); child = c->next, ++i)
     {
       int child_size;
 
       c = XWINDOW (child);
-      child_size = width_p ? XINT (c->total_cols) : XINT (c->total_lines);
+      child_size = WINDOW_TOTAL_SIZE (c, width_p);
 
-      if (! resize_fixed_p && window_fixed_size_p (c, width_p, 0))
+      if (!resize_fixed_p && window_fixed_size_p (c, width_p, 0))
         new_sizes[i] = -1;
       else
         {
           new_sizes[i] = child_size;
-          if (child_size > min_size)
-            available_resize += child_size - min_size;
+          min_sizes[i] = window_min_size_1 (c, width_p, safe_p);
+          if (child_size > min_sizes[i]
+             && NILP (c->resize_proportionally))
+            available_resize += child_size - min_sizes[i];
         }
     }
   /* We might need to shrink some windows to zero.  Find the smallest
@@ -2928,8 +3059,8 @@ shrink_windows (total, size, nchildren, shrinkable,
           {
             /* Resize this window down to zero.  */
             new_sizes[i] = 0;
-            if (smallest > min_size)
-              available_resize -= smallest - min_size;
+            if (smallest > min_sizes[i])
+              available_resize -= smallest - min_sizes[i];
             available_resize += smallest;
             --shrinkable;
             total_removed += smallest;
@@ -2947,11 +3078,12 @@ shrink_windows (total, size, nchildren, shrinkable,
      proportional to its size.  */
   for (i = 0; i < nchildren; ++i)
     {
-      if (new_sizes[i] > min_size)
+      if (new_sizes[i] > min_sizes[i])
         {
-          int to_shrink = total_shrink*new_sizes[i]/total;
-          if (new_sizes[i] - to_shrink < min_size)
-            to_shrink = new_sizes[i] - min_size;
+          int to_shrink = total_shrink * new_sizes[i] / total;
+
+          if (new_sizes[i] - to_shrink < min_sizes[i])
+            to_shrink = new_sizes[i] - min_sizes[i];
           new_sizes[i] -= to_shrink;
           total_removed += to_shrink;
         }
@@ -2972,7 +3104,7 @@ shrink_windows (total, size, nchildren, shrinkable,
           }
 
       for (i = 0; i < nchildren; ++i)
-        if (new_sizes[i] > min_size)
+        if (new_sizes[i] > min_sizes[i])
           {
             --new_sizes[i];
             ++total_removed;
@@ -2982,7 +3114,6 @@ shrink_windows (total, size, nchildren, shrinkable,
             break;
           }
 
-
       /* Special case, only one window left.  */
       if (nonzero_sizes == 1)
         break;
@@ -3002,73 +3133,41 @@ shrink_windows (total, size, nchildren, shrinkable,
         }
     }
 
+  xfree (min_sizes);
+
   return new_sizes;
 }
 
 /* Set WINDOW's height or width to SIZE.  WIDTH_P non-zero means set
-   WINDOW's width.  Resize WINDOW's children, if any, so that they
-   keep their proportionate size relative to WINDOW.
+   WINDOW's width.  Resize WINDOW's children, if any, so that they keep
+   their proportionate size relative to WINDOW.
 
    If FIRST_ONLY is 1, change only the first of WINDOW's children when
    they are in series.  If LAST_ONLY is 1, change only the last of
    WINDOW's children when they are in series.
 
    Propagate WINDOW's top or left edge position to children.  Delete
-   windows that become too small unless NODELETE_P is non-zero.
-
-   If NODELETE_P is 2, that means we do delete windows that are
-   too small, even if they were too small before!  */
+   windows that become too small unless NODELETE_P is 1.  When
+   NODELETE_P equals 2 do not honor settings for window-min-height and
+   window-min-width when resizing windows but use safe defaults instead.
+   This should give better behavior when resizing frames.  */
 
 static void
-size_window (window, size, width_p, nodelete_p, first_only, last_only)
-     Lisp_Object window;
-     int size, width_p, nodelete_p;
-     int first_only, last_only;
+size_window (Lisp_Object window, int size, int width_p, int nodelete_p, int first_only, int last_only)
 {
   struct window *w = XWINDOW (window);
   struct window *c;
   Lisp_Object child, *forward, *sideward;
-  int old_size, min_size, safe_min_size;
+  int old_size = WINDOW_TOTAL_SIZE (w, width_p);
 
-  check_min_window_sizes ();
   size = max (0, size);
 
-  /* If the window has been "too small" at one point,
-     don't delete it for being "too small" in the future.
-     Preserve it as long as that is at all possible.  */
-  if (width_p)
+  /* Delete WINDOW if it's too small.  */
+  if (nodelete_p != 1 && !NILP (w->parent)
+      && size < window_min_size_1 (w, width_p, nodelete_p == 2))
     {
-      old_size = WINDOW_TOTAL_COLS (w);
-      min_size = window_min_width;
-      safe_min_size = window_min_size_2 (w, 1);
-    }
-  else
-    {
-      old_size = XINT (w->total_lines);
-      min_size = window_min_height;
-      safe_min_size = window_min_size_2 (w, 0);
-    }
-
-  if (old_size < min_size && nodelete_p != 2)
-    w->too_small_ok = Qt;
-
-  /* Move the following test here since otherwise the
-     preceding test doesn't make sense.  martin. */
-  if (nodelete_p == 2)
-    nodelete_p = 0;
-
-  /* Maybe delete WINDOW if it's too small.  */
-  if (nodelete_p != 1 && !NILP (w->parent))
-    {
-      if (!MINI_WINDOW_P (w) && !NILP (w->too_small_ok))
-       min_size = width_p ? MIN_SAFE_WINDOW_WIDTH : MIN_SAFE_WINDOW_HEIGHT;
-      if (min_size < safe_min_size)
-       min_size = safe_min_size;
-      if (size < min_size)
-       {
-         delete_window (window);
-         return;
-       }
+      delete_window (window);
+      return;
     }
 
   /* Set redisplay hints.  */
@@ -3118,9 +3217,8 @@ size_window (window, size, width_p, nodelete_p, first_only, last_only)
          last_child = child;
        }
 
-      child_size = XINT (width_p ? c->total_cols : c->total_lines);
-      size_window (last_child,
-                  size - old_size + child_size,
+      child_size = WINDOW_TOTAL_SIZE (c, width_p);
+      size_window (last_child, size - old_size + child_size,
                   width_p, nodelete_p, first_only, last_only);
     }
   else if (!NILP (*forward) && first_only)
@@ -3136,9 +3234,8 @@ size_window (window, size, width_p, nodelete_p, first_only, last_only)
       else
        c->top_line = w->top_line;
 
-      child_size = XINT (width_p ? c->total_cols : c->total_lines);
-      size_window (child,
-                  size - old_size + child_size,
+      child_size = WINDOW_TOTAL_SIZE (c, width_p);
+      size_window (child, size - old_size + child_size,
                   width_p, nodelete_p, first_only, last_only);
     }
   else if (!NILP (*forward))
@@ -3156,7 +3253,7 @@ size_window (window, size, width_p, nodelete_p, first_only, last_only)
          int child_size;
 
          c = XWINDOW (child);
-         child_size = width_p ? XINT (c->total_cols) : XINT (c->total_lines);
+         child_size = WINDOW_TOTAL_SIZE (c, width_p);
          total += child_size;
 
          if (window_fixed_size_p (c, width_p, 0))
@@ -3175,8 +3272,9 @@ size_window (window, size, width_p, nodelete_p, first_only, last_only)
         value of extra takes care of rounding errors.  */
       n = resize_fixed_p ? nchildren : nchildren - nfixed;
       if (size < total && n > 1)
-        new_sizes = shrink_windows (total, size, nchildren, n, min_size,
-                                    resize_fixed_p, *forward, width_p);
+        new_sizes = shrink_windows (total, size, nchildren, n,
+                                    resize_fixed_p, *forward, width_p,
+                                   nodelete_p == 2);
       else
         {
           each = (size - total) / n;
@@ -3191,7 +3289,7 @@ size_window (window, size, width_p, nodelete_p, first_only, last_only)
          int new_size, old_size;
 
          c = XWINDOW (child);
-         old_size = width_p ? XFASTINT (c->total_cols) : XFASTINT (c->total_lines);
+         old_size = WINDOW_TOTAL_SIZE (c, width_p);
          new_size = old_size;
 
          /* The top or left edge position of this child equals the
@@ -3208,7 +3306,7 @@ size_window (window, size, width_p, nodelete_p, first_only, last_only)
              extra = 0;
            }
 
-         /* Set new height.  Note that size_window also propagates
+         /* Set new size.  Note that size_window also propagates
             edge positions to children, so it's not a no-op if we
             didn't change the child's size.  */
          size_window (child, new_size, width_p, 1, first_only, last_only);
@@ -3218,48 +3316,49 @@ size_window (window, size, width_p, nodelete_p, first_only, last_only)
           last_pos += new_size;
        }
 
-      if (new_sizes) xfree (new_sizes);
+      xfree (new_sizes);
 
       /* We should have covered the parent exactly with child windows.  */
       xassert (size == last_pos - first_pos);
 
       /* Now delete any children that became too small.  */
-      if (!nodelete_p)
+      if (nodelete_p != 1)
        for (child = *forward; !NILP (child); child = c->next)
          {
            int child_size;
+
            c = XWINDOW (child);
-           child_size = width_p ? XINT (c->total_cols) : XINT (c->total_lines);
-           size_window (child, child_size, width_p, 2, first_only, last_only);
+           child_size = WINDOW_TOTAL_SIZE (c, width_p);
+           size_window (child, child_size, width_p, nodelete_p,
+                        first_only, last_only);
          }
     }
 }
 
 /* Set WINDOW's height to HEIGHT, and recursively change the height of
-   WINDOW's children.  NODELETE non-zero means don't delete windows
-   that become too small in the process.  (The caller should check
-   later and do so if appropriate.)  */
+   WINDOW's children.  NODELETE zero means windows that have become
+   smaller than window-min-height in the process may be deleted.
+   NODELETE 1 means never delete windows that become too small in the
+   process.  (The caller should check later and do so if appropriate.)
+   NODELETE 2 means delete only windows that have become too small to be
+   displayed correctly.  */
 
 void
-set_window_height (window, height, nodelete)
-     Lisp_Object window;
-     int height;
-     int nodelete;
+set_window_height (Lisp_Object window, int height, int nodelete)
 {
   size_window (window, height, 0, nodelete, 0, 0);
 }
 
-
 /* Set WINDOW's width to WIDTH, and recursively change the width of
-   WINDOW's children.  NODELETE non-zero means don't delete windows
-   that become too small in the process.  (The caller should check
-   later and do so if appropriate.)  */
+   WINDOW's children.  NODELETE zero means windows that have become
+   smaller than window-min-width in the process may be deleted.
+   NODELETE 1 means never delete windows that become too small in the
+   process.  (The caller should check later and do so if appropriate.)
+   NODELETE 2 means delete only windows that have become too small to be
+   displayed correctly.  */
 
 void
-set_window_width (window, width, nodelete)
-     Lisp_Object window;
-     int width;
-     int nodelete;
+set_window_width (Lisp_Object window, int width, int nodelete)
 {
   size_window (window, width, 1, nodelete, 0, 0);
 }
@@ -3267,9 +3366,7 @@ set_window_width (window, width, nodelete)
 /* Change window heights in windows rooted in WINDOW by N lines.  */
 
 void
-change_window_heights (window, n)
-     Lisp_Object window;
-     int n;
+change_window_heights (Lisp_Object window, int n)
 {
   struct window *w = XWINDOW (window);
 
@@ -3296,34 +3393,66 @@ change_window_heights (window, n)
 \f
 int window_select_count;
 
-Lisp_Object
-Fset_window_buffer_unwind (obuf)
-     Lisp_Object obuf;
+EXFUN (Fset_window_fringes, 4);
+EXFUN (Fset_window_scroll_bars, 4);
+
+static void
+run_funs (Lisp_Object funs)
 {
-  Fset_buffer (obuf);
-  return Qnil;
+  for (; CONSP (funs); funs = XCDR (funs))
+    if (!EQ (XCAR (funs), Qt))
+      call0 (XCAR (funs));
 }
 
-EXFUN (Fset_window_fringes, 4);
-EXFUN (Fset_window_scroll_bars, 4);
+static Lisp_Object select_window_norecord (Lisp_Object window);
+static Lisp_Object select_frame_norecord (Lisp_Object frame);
 
 void
 run_window_configuration_change_hook (struct frame *f)
 {
-  if (! NILP (Vwindow_configuration_change_hook)
-      && ! NILP (Vrun_hooks))
+  int count = SPECPDL_INDEX ();
+  Lisp_Object frame, global_wcch
+    = Fdefault_value (Qwindow_configuration_change_hook);
+  XSETFRAME (frame, f);
+
+  if (NILP (Vrun_hooks))
+    return;
+
+  if (SELECTED_FRAME () != f)
     {
-      int count = SPECPDL_INDEX ();
-      if (SELECTED_FRAME () != f)
-       {
-         Lisp_Object frame;
-         XSETFRAME (frame, f);
-         record_unwind_protect (Fselect_frame, Fselected_frame ());
-         Fselect_frame (frame);
-       }
-      call1 (Vrun_hooks, Qwindow_configuration_change_hook);
-      unbind_to (count, Qnil);
+      record_unwind_protect (select_frame_norecord, Fselected_frame ());
+      Fselect_frame (frame, Qt);
     }
+
+  /* Use the right buffer.  Matters when running the local hooks.  */
+  if (current_buffer != XBUFFER (Fwindow_buffer (Qnil)))
+    {
+      record_unwind_protect (Fset_buffer, Fcurrent_buffer ());
+      Fset_buffer (Fwindow_buffer (Qnil));
+    }
+
+  /* Look for buffer-local values.  */
+  {
+    Lisp_Object windows = Fwindow_list (frame, Qlambda, Qnil);
+    for (; CONSP (windows); windows = XCDR (windows))
+      {
+       Lisp_Object window = XCAR (windows);
+       Lisp_Object buffer = Fwindow_buffer (window);
+       if (!NILP (Flocal_variable_p (Qwindow_configuration_change_hook,
+                                     buffer)))
+         {
+           int count = SPECPDL_INDEX ();
+           record_unwind_protect (select_window_norecord, Fselected_window ());
+           select_window_norecord (window);
+           run_funs (Fbuffer_local_value (Qwindow_configuration_change_hook,
+                                          buffer));
+           unbind_to (count, Qnil);
+         }
+      }
+  }
+
+  run_funs (global_wcch);
+  unbind_to (count, Qnil);
 }
 
 /* Make WINDOW display BUFFER as its contents.  RUN_HOOKS_P non-zero
@@ -3333,9 +3462,7 @@ run_window_configuration_change_hook (struct frame *f)
    reset from the buffer's local settings.  */
 
 void
-set_window_buffer (window, buffer, run_hooks_p, keep_margins_p)
-     Lisp_Object window, buffer;
-     int run_hooks_p, keep_margins_p;
+set_window_buffer (Lisp_Object window, Lisp_Object buffer, int run_hooks_p, int keep_margins_p)
 {
   struct window *w = XWINDOW (window);
   struct buffer *b = XBUFFER (buffer);
@@ -3360,7 +3487,7 @@ set_window_buffer (window, buffer, run_hooks_p, keep_margins_p)
   bzero (&w->last_cursor, sizeof w->last_cursor);
   w->window_end_valid = Qnil;
   if (!(keep_margins_p && samebuf))
-    { /* If we're not actually changing the buffer, Don't reset hscroll and
+    { /* If we're not actually changing the buffer, don't reset hscroll and
         vscroll.  This case happens for example when called from
         change_frame_size_1, where we use a dummy call to
         Fset_window_buffer on the frame's selected window (and no other)
@@ -3383,19 +3510,17 @@ set_window_buffer (window, buffer, run_hooks_p, keep_margins_p)
      I doubt it's worth the trouble.  */
   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 must select BUFFER for running the window-scroll-functions.  */
   /* We can't check ! NILP (Vwindow_scroll_functions) here
      because that might itself be a local variable.  */
-  else if (window_initialized)
+  if (window_initialized)
     {
-      record_unwind_protect (Fset_window_buffer_unwind, Fcurrent_buffer ());
+      record_unwind_protect (Fset_buffer, Fcurrent_buffer ());
       Fset_buffer (buffer);
     }
 
+  XMARKER (w->pointm)->insertion_type = !NILP (Vwindow_point_insertion_type);
+
   if (!keep_margins_p)
     {
       /* Set left and right marginal area width etc. from buffer.  */
@@ -3435,36 +3560,42 @@ set_window_buffer (window, buffer, run_hooks_p, keep_margins_p)
 
 
 DEFUN ("set-window-buffer", Fset_window_buffer, Sset_window_buffer, 2, 3, 0,
-       doc: /* Make WINDOW display BUFFER as its contents.
-BUFFER can be a buffer or the name of an existing buffer.
-Optional third arg KEEP-MARGINS non-nil means that WINDOW's current
-display margins, fringe widths, and scroll bar settings are maintained;
-the default is to reset these from BUFFER's local settings or the frame
-defaults.
-
-This function runs the hook `window-scroll-functions'.  */)
-     (window, buffer, keep_margins)
-     register Lisp_Object window, buffer, keep_margins;
-{
-  register Lisp_Object tem;
+       doc: /* Make WINDOW display BUFFER-OR-NAME as its contents.
+WINDOW defaults to the selected window.  BUFFER-OR-NAME must be a buffer
+or the name of an existing buffer.  Optional third argument KEEP-MARGINS
+non-nil means that WINDOW's current display margins, fringe widths, and
+scroll bar settings are preserved; the default is to reset these from
+the local settings for BUFFER-OR-NAME or the frame defaults.  Return nil.
+
+This function throws an error when WINDOW is strongly dedicated to its
+buffer (that is `window-dedicated-p' returns t for WINDOW) and does not
+already display BUFFER-OR-NAME.
+
+This function runs `window-scroll-functions' before running
+`window-configuration-change-hook'.  */)
+     (window, buffer_or_name, keep_margins)
+     register Lisp_Object window, buffer_or_name, keep_margins;
+{
+  register Lisp_Object tem, buffer;
   register struct window *w = decode_window (window);
 
   XSETWINDOW (window, w);
-  buffer = Fget_buffer (buffer);
+  buffer = Fget_buffer (buffer_or_name);
   CHECK_BUFFER (buffer);
-
   if (NILP (XBUFFER (buffer)->name))
     error ("Attempt to display deleted buffer");
 
   tem = w->buffer;
   if (NILP (tem))
     error ("Window is deleted");
-  else if (! EQ (tem, Qt))     /* w->buffer is t when the window
-                                  is first being set up.  */
+  else if (!EQ (tem, Qt))
+    /* w->buffer is t when the window is first being set up.  */
     {
-      if (!NILP (w->dedicated) && !EQ (tem, buffer))
-       error ("Window is dedicated to `%s'",
-              SDATA (XBUFFER (tem)->name));
+      if (!EQ (tem, buffer))
+       if (EQ (w->dedicated, Qt))
+         error ("Window is dedicated to `%s'", SDATA (XBUFFER (tem)->name));
+       else
+         w->dedicated = Qnil;
 
       unshow_buffer (w);
     }
@@ -3473,18 +3604,19 @@ This function runs the hook `window-scroll-functions'.  */)
   return Qnil;
 }
 
-/* Note that selected_window can be nil
-   when this is called from Fset_window_configuration.  */
+/* Note that selected_window can be nil when this is called from
+   Fset_window_configuration.  */
 
 DEFUN ("select-window", Fselect_window, Sselect_window, 1, 2, 0,
        doc: /* Select WINDOW.  Most editing will apply to WINDOW's buffer.
 If WINDOW is not already selected, make WINDOW's buffer current
 and make WINDOW the frame's selected window.  Return WINDOW.
-Optional second arg NORECORD non-nil means
-do not put this buffer at the front of the list of recently selected ones.
+Optional second arg NORECORD non-nil means do not put this buffer
+at the front of the list of recently selected ones and do not
+make this window the most recently selected one.
 
-Note that the main editor command loop
-selects the buffer of the selected window before each command.  */)
+Note that the main editor command loop selects the buffer of the
+selected window before each command.  */)
      (window, norecord)
      register Lisp_Object window, norecord;
 {
@@ -3497,8 +3629,13 @@ selects the buffer of the selected window before each command.  */)
   w = XWINDOW (window);
   w->frozen_window_start_p = 0;
 
-  ++window_select_count;
-  XSETFASTINT (w->use_time, window_select_count);
+  if (NILP (norecord))
+    {
+      ++window_select_count;
+      XSETFASTINT (w->use_time, window_select_count);
+      record_buffer (w->buffer);
+    }
+
   if (EQ (window, selected_window))
     return window;
 
@@ -3510,7 +3647,7 @@ selects the buffer of the selected window before each command.  */)
         so that FRAME_FOCUS_FRAME is moved appropriately as we
         move around in the state where a minibuffer in a separate
         frame is active.  */
-      Fselect_frame (WINDOW_FRAME (w));
+      Fselect_frame (WINDOW_FRAME (w), norecord);
       /* Fselect_frame called us back so we've done all the work already.  */
       eassert (EQ (window, selected_window));
       return window;
@@ -3532,8 +3669,6 @@ selects the buffer of the selected window before each command.  */)
 
   selected_window = window;
 
-  if (NILP (norecord))
-    record_buffer (w->buffer);
   Fset_buffer (w->buffer);
 
   XBUFFER (w->buffer)->last_selected_window = window;
@@ -3558,338 +3693,25 @@ selects the buffer of the selected window before each command.  */)
 }
 
 static Lisp_Object
-select_window_norecord (window)
-     Lisp_Object window;
+select_window_norecord (Lisp_Object window)
 {
-  return Fselect_window (window, Qt);
+  return WINDOW_LIVE_P (window)
+    ? Fselect_window (window, Qt) : selected_window;
 }
-\f
-/* 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;
+select_frame_norecord (Lisp_Object frame)
 {
-  Lisp_Object frame = XWINDOW (window)->frame;
-  FRAME_PTR f = XFRAME (frame);
-
-  FRAME_SAMPLE_VISIBILITY (f);
-
-  if (EQ (frame, selected_frame))
-    ; /* Assume the selected frame is already visible enough.  */
-  else if (minibuf_level > 0
-          && MINI_WINDOW_P (XWINDOW (selected_window))
-          && WINDOW_LIVE_P (minibuf_selected_window)
-          && EQ (frame, WINDOW_FRAME (XWINDOW (minibuf_selected_window))))
-    ; /* Assume the frame from which we invoked the minibuffer is visible.  */
-  else
-    {
-      if (FRAME_ICONIFIED_P (f))
-       Fmake_frame_visible (frame);
-      else if (FRAME_VISIBLE_P (f))
-       Fraise_frame (frame);
-    }
-
-  return window;
-}
-
-DEFUN ("special-display-p", Fspecial_display_p, Sspecial_display_p, 1, 1, 0,
-       doc: /* Returns non-nil if a buffer named BUFFER-NAME gets a special frame.
-If the value is t, `display-buffer' or `pop-to-buffer' would create a
-special frame for that buffer using the default frame parameters.
-
-If the value is a list, it is a list of frame parameters that would be used
-to make a frame for that buffer.
-The variables `special-display-buffer-names'
-and `special-display-regexps' control this.  */)
-     (buffer_name)
-     Lisp_Object buffer_name;
-{
-  Lisp_Object tem;
-
-  CHECK_STRING (buffer_name);
-
-  tem = Fmember (buffer_name, Vspecial_display_buffer_names);
-  if (!NILP (tem))
-    return Qt;
-
-  tem = Fassoc (buffer_name, Vspecial_display_buffer_names);
-  if (!NILP (tem))
-    return XCDR (tem);
-
-  for (tem = Vspecial_display_regexps; CONSP (tem); tem = XCDR (tem))
-    {
-      Lisp_Object car = XCAR (tem);
-      if (STRINGP (car)
-         && fast_string_match (car, buffer_name) >= 0)
-       return Qt;
-      else if (CONSP (car)
-              && STRINGP (XCAR (car))
-              && fast_string_match (XCAR (car), buffer_name) >= 0)
-       return XCDR (car);
-    }
-  return Qnil;
+  return FRAME_LIVE_P (XFRAME (frame))
+    ? Fselect_frame (frame, Qt) : selected_frame;
 }
-
-DEFUN ("same-window-p", Fsame_window_p, Ssame_window_p, 1, 1, 0,
-       doc: /* Returns non-nil if a buffer named BUFFER-NAME would use the same window.
-More precisely, if `display-buffer' or `pop-to-buffer' would display
-that buffer in the selected window rather than (as usual) in some other window.
-See `same-window-buffer-names' and `same-window-regexps'.  */)
-     (buffer_name)
-     Lisp_Object buffer_name;
+\f
+Lisp_Object
+display_buffer (Lisp_Object buffer, Lisp_Object not_this_window_p, Lisp_Object override_frame)
 {
-  Lisp_Object tem;
-
-  CHECK_STRING (buffer_name);
-
-  tem = Fmember (buffer_name, Vsame_window_buffer_names);
-  if (!NILP (tem))
-    return Qt;
-
-  tem = Fassoc (buffer_name, Vsame_window_buffer_names);
-  if (!NILP (tem))
-    return Qt;
-
-  for (tem = Vsame_window_regexps; CONSP (tem); tem = XCDR (tem))
-    {
-      Lisp_Object car = XCAR (tem);
-      if (STRINGP (car)
-         && fast_string_match (car, buffer_name) >= 0)
-       return Qt;
-      else if (CONSP (car)
-              && STRINGP (XCAR (car))
-              && fast_string_match (XCAR (car), buffer_name) >= 0)
-       return Qt;
-    }
-  return Qnil;
+  return call3 (Qdisplay_buffer, buffer, not_this_window_p, override_frame);
 }
 
-/* Use B so the default is (other-buffer).  */
-DEFUN ("display-buffer", Fdisplay_buffer, Sdisplay_buffer, 1, 3,
-       "BDisplay buffer: \nP",
-       doc: /* Make BUFFER appear in some window but don't select it.
-BUFFER must be the name of an existing buffer, or, when called from Lisp,
-a buffer.
-If BUFFER is shown already in some window, just use that one,
-unless the window is the selected window and the optional second
-argument NOT-THIS-WINDOW is non-nil (interactively, with prefix arg).
-If `pop-up-frames' is non-nil, make a new frame if no window shows BUFFER.
-Returns the window displaying BUFFER.
-If `display-buffer-reuse-frames' is non-nil, and another frame is currently
-displaying BUFFER, then simply raise that frame.
-
-The variables `special-display-buffer-names',
-`special-display-regexps', `same-window-buffer-names', and
-`same-window-regexps' customize how certain buffer names are handled.
-The latter two take effect only if NOT-THIS-WINDOW is nil.
-
-If optional argument FRAME is `visible', check all visible frames
-for a window to use.
-If FRAME is 0, check all visible and iconified frames.
-If FRAME is t, check all frames.
-If FRAME is a frame, check only that frame.
-If FRAME is nil, check only the selected frame
- (actually the last nonminibuffer frame),
- unless `pop-up-frames' or `display-buffer-reuse-frames' is non-nil,
- which means search visible and iconified frames.
-
-If a full-width window on a splittable frame is available to display
-the buffer, it may be split, subject to the value of the variable
-`split-height-threshold'.
-
-If `even-window-heights' is non-nil, window heights will be evened out
-if displaying the buffer causes two vertically adjacent windows to be
-displayed.  */)
-     (buffer, not_this_window, frame)
-     Lisp_Object buffer, not_this_window, frame;
-{
-  register Lisp_Object window, tem, swp;
-  struct frame *f;
-
-  swp = Qnil;
-  buffer = Fget_buffer (buffer);
-  CHECK_BUFFER (buffer);
-
-  if (!NILP (Vdisplay_buffer_function))
-    return call2 (Vdisplay_buffer_function, buffer, not_this_window);
-
-  if (NILP (not_this_window)
-      && XBUFFER (XWINDOW (selected_window)->buffer) == XBUFFER (buffer))
-    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))
-    {
-      swp = Fsame_window_p (XBUFFER (buffer)->name);
-      if (!NILP (swp) && !no_switch_window (selected_window))
-       {
-         Fswitch_to_buffer (buffer, Qnil);
-         return display_buffer_1 (selected_window);
-       }
-    }
-
-  /* If the user wants pop-up-frames or display-buffer-reuse-frames,
-     look for a window showing BUFFER on any visible or iconified frame.
-     Otherwise search only the current frame.  */
-  if (! NILP (frame))
-    tem = frame;
-  else if (pop_up_frames
-          || display_buffer_reuse_frames
-          || last_nonminibuf_frame == 0)
-    XSETFASTINT (tem, 0);
-  else
-    XSETFRAME (tem, last_nonminibuf_frame);
-
-  window = Fget_buffer_window (buffer, tem);
-  if (!NILP (window)
-      && (NILP (not_this_window) || !EQ (window, selected_window)))
-    return display_buffer_1 (window);
-
-  /* Certain buffer names get special handling.  */
-  if (!NILP (Vspecial_display_function) && NILP (swp))
-    {
-      tem = Fspecial_display_p (XBUFFER (buffer)->name);
-      if (EQ (tem, Qt))
-       return call1 (Vspecial_display_function, buffer);
-      if (CONSP (tem))
-       return call2 (Vspecial_display_function, buffer, tem);
-    }
-
-  /* If there are no frames open that have more than a minibuffer,
-     we need to create a new frame.  */
-  if (pop_up_frames || last_nonminibuf_frame == 0)
-    {
-      window = Fframe_selected_window (call0 (Vpop_up_frame_function));
-      Fset_window_buffer (window, buffer, Qnil);
-      return display_buffer_1 (window);
-    }
-
-  f = SELECTED_FRAME ();
-  if (pop_up_windows
-      || FRAME_MINIBUF_ONLY_P (f)
-      /* If the current frame is a special display frame,
-        don't try to reuse its windows.  */
-      || !NILP (XWINDOW (FRAME_ROOT_WINDOW (f))->dedicated))
-    {
-      Lisp_Object frames;
-      struct gcpro gcpro1;
-      GCPRO1 (buffer);
-
-      frames = Qnil;
-      if (FRAME_MINIBUF_ONLY_P (f))
-       XSETFRAME (frames, last_nonminibuf_frame);
-
-      /* Note that both Fget_largest_window and Fget_lru_window
-        ignore minibuffers and dedicated windows.
-        This means they can return nil.  */
-
-      /* If the frame we would try to split cannot be split,
-        try other frames.  */
-      if (FRAME_NO_SPLIT_P (NILP (frames) ? f : last_nonminibuf_frame))
-       {
-         /* Try visible frames first.  */
-         window = Fget_largest_window (Qvisible, Qt);
-         /* If that didn't work, try iconified frames.  */
-         if (NILP (window))
-           window = Fget_largest_window (make_number (0), Qt);
-#if 0     /* Don't try windows on other displays.  */
-         if (NILP (window))
-           window = Fget_largest_window (Qt, Qt);
-#endif
-       }
-      else
-       window = Fget_largest_window (frames, Qt);
-
-      /* If the largest window is tall enough, full-width, and either eligible
-        for splitting or the only window, split it.  */
-      if (!NILP (window)
-         && ! FRAME_NO_SPLIT_P (XFRAME (XWINDOW (window)->frame))
-         && WINDOW_FULL_WIDTH_P (XWINDOW (window))
-              && (window_height (window) >= split_height_threshold
-                  || (NILP (XWINDOW (window)->parent)))
-         && (window_height (window)
-             >= (2 * window_min_size_2 (XWINDOW (window), 0))))
-       window = call1 (Vsplit_window_preferred_function, window);
-      else
-       {
-         Lisp_Object upper, other;
-
-         window = Fget_lru_window (frames, Qt);
-         /* If the LRU window is tall enough, and either eligible for
-            splitting and selected or the only window, split it.  */
-         if (!NILP (window)
-             && ! FRAME_NO_SPLIT_P (XFRAME (XWINDOW (window)->frame))
-                  && ((EQ (window, selected_window)
-                       && window_height (window) >= split_height_threshold)
-                      || (NILP (XWINDOW (window)->parent)))
-                  && (window_height (window)
-                      >= (2 * window_min_size_2 (XWINDOW (window), 0))))
-           window = call1 (Vsplit_window_preferred_function, window);
-         else
-           window = Fget_lru_window (frames, Qnil);
-         /* If Fget_lru_window returned nil, try other approaches.  */
-
-         /* Try visible frames first.  */
-         if (NILP (window))
-           window = Fget_buffer_window (buffer, Qvisible);
-         if (NILP (window))
-           window = Fget_largest_window (Qvisible, Qnil);
-         /* If that didn't work, try iconified frames.  */
-         if (NILP (window))
-           window = Fget_buffer_window (buffer, make_number (0));
-         if (NILP (window))
-           window = Fget_largest_window (make_number (0), Qnil);
-
-#if 0     /* Don't try frames on other displays.  */
-         if (NILP (window))
-           window = Fget_buffer_window (buffer, Qt);
-         if (NILP (window))
-           window = Fget_largest_window (Qt, Qnil);
-#endif
-         /* As a last resort, make a new frame.  */
-         if (NILP (window))
-           window = Fframe_selected_window (call0 (Vpop_up_frame_function));
-         /* If window appears above or below another,
-            even out their heights.  */
-         other = upper = Qnil;
-         if (!NILP (XWINDOW (window)->prev))
-           other = upper = XWINDOW (window)->prev;
-         if (!NILP (XWINDOW (window)->next))
-           other = XWINDOW (window)->next, upper = window;
-         if (!NILP (other)
-             && !NILP (Veven_window_heights)
-             /* Check that OTHER and WINDOW are vertically arrayed.  */
-             && !EQ (XWINDOW (other)->top_line, XWINDOW (window)->top_line)
-             && (XFASTINT (XWINDOW (other)->total_lines)
-                 > XFASTINT (XWINDOW (window)->total_lines)))
-           {
-             int total = (XFASTINT (XWINDOW (other)->total_lines)
-                          + XFASTINT (XWINDOW (window)->total_lines));
-             enlarge_window (upper,
-                             total / 2 - XFASTINT (XWINDOW (upper)->total_lines),
-                             0);
-           }
-       }
-      UNGCPRO;
-    }
-  else
-    window = Fget_lru_window (Qnil, Qnil);
-
-  Fset_window_buffer (window, buffer, Qnil);
-  return display_buffer_1 (window);
-}
-
-
 DEFUN ("force-window-update", Fforce_window_update, Sforce_window_update,
        0, 1, 0,
        doc: /* Force all windows to be updated on next redisplay.
@@ -3936,8 +3758,7 @@ displaying that buffer.  */)
 
 
 void
-temp_output_buffer_show (buf)
-     register Lisp_Object buf;
+temp_output_buffer_show (register Lisp_Object buf)
 {
   register struct buffer *old = current_buffer;
   register Lisp_Object window;
@@ -3959,7 +3780,7 @@ temp_output_buffer_show (buf)
     call1 (Vtemp_buffer_show_function, buf);
   else
     {
-      window = Fdisplay_buffer (buf, Qnil, Qnil);
+      window = display_buffer (buf, Qnil, Qnil);
 
       if (!EQ (XWINDOW (window)->frame, selected_frame))
        Fmake_frame_visible (WINDOW_FRAME (XWINDOW (window)));
@@ -3997,8 +3818,7 @@ temp_output_buffer_show (buf)
 }
 \f
 static void
-make_dummy_parent (window)
-     Lisp_Object window;
+make_dummy_parent (Lisp_Object window)
 {
   Lisp_Object new;
   register struct window *o, *p;
@@ -4031,18 +3851,17 @@ make_dummy_parent (window)
 DEFUN ("split-window", Fsplit_window, Ssplit_window, 0, 3, "",
        doc: /* Split WINDOW, putting SIZE lines in the first of the pair.
 WINDOW defaults to selected one and SIZE to half its size.
-If optional third arg HORFLAG is non-nil, split side by side
-and put SIZE columns in the first of the pair.  In that case,
-SIZE includes that window's scroll bar, or the divider column to its right.
+If optional third arg HORIZONTAL is non-nil, split side by side and put
+SIZE columns in the first of the pair.  In that case, SIZE includes that
+window's scroll bar, or the divider column to its right.
 Interactively, all arguments are nil.
-
 Returns the newly created window (which is the lower or rightmost one).
 The upper or leftmost window is the original one, and remains selected
 if it was selected before.
 
-See Info node `(elisp)Splitting Windows' for more details and examples.*/)
-     (window, size, horflag)
-     Lisp_Object window, size, horflag;
+See Info node `(elisp)Splitting Windows' for more details and examples.  */)
+     (window, size, horizontal)
+     Lisp_Object window, size, horizontal;
 {
   register Lisp_Object new;
   register struct window *o, *p;
@@ -4059,7 +3878,7 @@ See Info node `(elisp)Splitting Windows' for more details and examples.*/)
 
   if (NILP (size))
     {
-      if (!NILP (horflag))
+      if (!NILP (horizontal))
        /* Calculate the size of the left-hand window, by dividing
           the usable space in columns by two.
           We round up, since the left-hand window may include
@@ -4076,15 +3895,13 @@ See Info node `(elisp)Splitting Windows' for more details and examples.*/)
 
   if (MINI_WINDOW_P (o))
     error ("Attempt to split minibuffer window");
-  else if (window_fixed_size_p (o, !NILP (horflag), 0))
+  else if (window_fixed_size_p (o, !NILP (horizontal), 0))
     error ("Attempt to split fixed-size window");
 
-  check_min_window_sizes ();
-
-  if (NILP (horflag))
+  if (NILP (horizontal))
     {
-      int window_safe_height = window_min_size_2 (o, 0);
-      
+      int window_safe_height = window_min_size_2 (o, 0, 0);
+
       if (size_int < window_safe_height)
        error ("Window height %d too small (after splitting)", size_int);
       if (size_int + window_safe_height > XFASTINT (o->total_lines))
@@ -4100,8 +3917,8 @@ See Info node `(elisp)Splitting Windows' for more details and examples.*/)
     }
   else
     {
-      int window_safe_width = window_min_size_2 (o, 1);
-      
+      int window_safe_width = window_min_size_2 (o, 1, 0);
+
       if (size_int < window_safe_width)
        error ("Window width %d too small (after splitting)", size_int);
       if (size_int + window_safe_width > XFASTINT (o->total_cols))
@@ -4148,7 +3965,7 @@ See Info node `(elisp)Splitting Windows' for more details and examples.*/)
 
   /* Apportion the available frame space among the two new windows */
 
-  if (!NILP (horflag))
+  if (!NILP (horizontal))
     {
       p->total_lines = o->total_lines;
       p->top_line = o->top_line;
@@ -4175,52 +3992,54 @@ See Info node `(elisp)Splitting Windows' for more details and examples.*/)
 }
 \f
 DEFUN ("enlarge-window", Fenlarge_window, Senlarge_window, 1, 2, "p",
-       doc: /* Make current window ARG lines bigger.
-From program, optional second arg non-nil means grow sideways ARG columns.
-Interactively, if an argument is not given, make the window one line bigger.
-If HORIZONTAL is non-nil, enlarge horizontally instead of vertically.
-This function can delete windows, even the second window, if they get
-too small.  */)
-     (arg, horizontal)
-     Lisp_Object arg, horizontal;
+       doc: /* Make selected window SIZE lines taller.
+Interactively, if no argument is given, make the selected window one
+line taller.  If optional argument HORIZONTAL is non-nil, make selected
+window wider by SIZE columns.  If SIZE is negative, shrink the window by
+-SIZE lines or columns.  Return nil.
+
+This function can delete windows if they get too small.  The size of
+fixed size windows is not altered by this function.  */)
+     (size, horizontal)
+     Lisp_Object size, horizontal;
 {
-  CHECK_NUMBER (arg);
-  enlarge_window (selected_window, XINT (arg), !NILP (horizontal));
+  CHECK_NUMBER (size);
+  enlarge_window (selected_window, XINT (size), !NILP (horizontal));
 
-  if (! NILP (Vwindow_configuration_change_hook))
-    call1 (Vrun_hooks, Qwindow_configuration_change_hook);
+  run_window_configuration_change_hook (SELECTED_FRAME ());
 
   return Qnil;
 }
 
 DEFUN ("shrink-window", Fshrink_window, Sshrink_window, 1, 2, "p",
-       doc: /* Make current window ARG lines smaller.
-From program, optional second arg non-nil means shrink sideways arg columns.
-Interactively, if an argument is not given, make the window one line smaller.
-Only siblings to the right or below are changed.  */)
-     (arg, side)
-     Lisp_Object arg, side;
+       doc: /* Make selected window SIZE lines smaller.
+Interactively, if no argument is given, make the selected window one
+line smaller.  If optional argument HORIZONTAL is non-nil, make the
+window narrower by SIZE columns.  If SIZE is negative, enlarge selected
+window by -SIZE lines or columns.  Return nil.
+
+This function can delete windows if they get too small.  The size of
+fixed size windows is not altered by this function. */)
+     (size, horizontal)
+     Lisp_Object size, horizontal;
 {
-  CHECK_NUMBER (arg);
-  enlarge_window (selected_window, -XINT (arg), !NILP (side));
+  CHECK_NUMBER (size);
+  enlarge_window (selected_window, -XINT (size), !NILP (horizontal));
 
-  if (! NILP (Vwindow_configuration_change_hook))
-    call1 (Vrun_hooks, Qwindow_configuration_change_hook);
+  run_window_configuration_change_hook (SELECTED_FRAME ());
 
   return Qnil;
 }
 
 int
-window_height (window)
-     Lisp_Object window;
+window_height (Lisp_Object window)
 {
   register struct window *p = XWINDOW (window);
   return WINDOW_TOTAL_LINES (p);
 }
 
 int
-window_width (window)
-     Lisp_Object window;
+window_width (Lisp_Object window)
 {
   register struct window *p = XWINDOW (window);
   return WINDOW_TOTAL_COLS (p);
@@ -4234,32 +4053,25 @@ window_width (window)
   *(horiz_flag ? &(XWINDOW (w)->total_cols) : &(XWINDOW (w)->total_lines))
 
 
-/* Enlarge WINDOW by DELTA.
-   HORIZ_FLAG nonzero means enlarge it horizontally;
-   zero means do it vertically.
+/* Enlarge WINDOW by DELTA.  HORIZ_FLAG nonzero means enlarge it
+   horizontally; zero means do it vertically.
 
    Siblings of the selected window are resized to fulfill the size
-   request.  If they become too small in the process, they will be
+   request.  If they become too small in the process, they may be
    deleted.  */
 
 static void
-enlarge_window (window, delta, horiz_flag)
-     Lisp_Object window;
-     int delta, horiz_flag;
+enlarge_window (Lisp_Object window, int delta, int horiz_flag)
 {
   Lisp_Object parent, next, prev;
   struct window *p;
   Lisp_Object *sizep;
   int maximum;
-  int (*sizefun) P_ ((Lisp_Object))
+  int (*sizefun) (Lisp_Object)
     = horiz_flag ? window_width : window_height;
-  void (*setsizefun) P_ ((Lisp_Object, int, int))
+  void (*setsizefun) (Lisp_Object, int, int)
     = (horiz_flag ? set_window_width : set_window_height);
 
-  /* Check values of window_min_width and window_min_height for
-     validity.  */
-  check_min_window_sizes ();
-
   /* Give up if this window cannot be resized.  */
   if (window_fixed_size_p (XWINDOW (window), horiz_flag, 1))
     error ("Window is not resizable");
@@ -4296,11 +4108,11 @@ enlarge_window (window, delta, horiz_flag)
                /* This is a main window followed by a minibuffer.  */
                : !NILP (p->next) ? ((*sizefun) (p->next)
                                     - window_min_size (XWINDOW (p->next),
-                                                       horiz_flag, 0, 0))
+                                                       horiz_flag, 0, 0, 0))
                /* This is a minibuffer following a main window.  */
                : !NILP (p->prev) ? ((*sizefun) (p->prev)
                                     - window_min_size (XWINDOW (p->prev),
-                                                       horiz_flag, 0, 0))
+                                                       horiz_flag, 0, 0, 0))
                /* This is a frame with only one window, a minibuffer-only
                   or a minibufferless frame.  */
                : (delta = 0));
@@ -4312,7 +4124,8 @@ enlarge_window (window, delta, horiz_flag)
       delta = maxdelta;
   }
 
-  if (XINT (*sizep) + delta < window_min_size (XWINDOW (window), horiz_flag, 0, 0))
+  if (XINT (*sizep) + delta < window_min_size (XWINDOW (window),
+                                              horiz_flag, 0, 0, 0))
     {
       delete_window (window);
       return;
@@ -4325,10 +4138,10 @@ enlarge_window (window, delta, horiz_flag)
   maximum = 0;
   for (next = p->next; WINDOWP (next); next = XWINDOW (next)->next)
     maximum += (*sizefun) (next) - window_min_size (XWINDOW (next),
-                                                   horiz_flag, 0, 0);
+                                                   horiz_flag, 0, 0, 0);
   for (prev = p->prev; WINDOWP (prev); prev = XWINDOW (prev)->prev)
     maximum += (*sizefun) (prev) - window_min_size (XWINDOW (prev),
-                                                   horiz_flag, 0, 0);
+                                                   horiz_flag, 0, 0, 0);
 
   /* If we can get it all from them without deleting them, do so.  */
   if (delta <= maximum)
@@ -4349,8 +4162,8 @@ enlarge_window (window, delta, horiz_flag)
          if (! NILP (next))
            {
              int this_one = ((*sizefun) (next)
-                             - window_min_size (XWINDOW (next),
-                                                horiz_flag, 0, &fixed_p));
+                             - window_min_size (XWINDOW (next), horiz_flag,
+                                                0, 0, &fixed_p));
              if (!fixed_p)
                {
                  if (this_one > delta)
@@ -4371,8 +4184,8 @@ enlarge_window (window, delta, horiz_flag)
          if (! NILP (prev))
            {
              int this_one = ((*sizefun) (prev)
-                             - window_min_size (XWINDOW (prev),
-                                                horiz_flag, 0, &fixed_p));
+                             - window_min_size (XWINDOW (prev), horiz_flag,
+                                                0, 0, &fixed_p));
              if (!fixed_p)
                {
                  if (this_one > delta)
@@ -4431,7 +4244,7 @@ enlarge_window (window, delta, horiz_flag)
 
          /* Delete any siblings that come after WINDOW.
             Note that if START is not WINDOW, then WINDOW still
-            Fhas siblings, so WINDOW has not yet replaced its parent.  */
+            has siblings, so WINDOW has not yet replaced its parent.  */
          tem = start;
          while (! EQ (tem, window))
            {
@@ -4468,7 +4281,11 @@ enlarge_window (window, delta, horiz_flag)
 
             The number of children n equals the number of resizable
             children of this window + 1 because we know window itself
-            is resizable (otherwise we would have signalled an error).  */
+            is resizable (otherwise we would have signaled an error).
+
+            This reasoning is not correct when other windows become too
+            small and shrink_windows refuses to delete them.  Below we
+            use resize_proportionally to work around this problem.  */
 
          struct window *w = XWINDOW (window);
          Lisp_Object s;
@@ -4489,12 +4306,17 @@ enlarge_window (window, delta, horiz_flag)
          (*setsizefun) (window, XINT (*sizep) + delta1, 0);
 
          /* Squeeze out delta1 lines or columns from our parent,
-            shriking this window and siblings proportionately.
-            This brings parent back to correct size.
-            Delta1 was calculated so this makes this window the desired size,
-            taking it all out of the siblings.  */
+            shrinking this window and siblings proportionately.  This
+            brings parent back to correct size.  Delta1 was calculated
+            so this makes this window the desired size, taking it all
+            out of the siblings.
+
+            Temporarily set resize_proportionally to Qt to assure that,
+            if necessary, shrink_windows deletes smaller windows rather
+            than shrink this window.  */
+         w->resize_proportionally = Qt;
          (*setsizefun) (parent, opht, 0);
-
+         w->resize_proportionally = Qnil;
        }
     }
 
@@ -4515,22 +4337,13 @@ enlarge_window (window, delta, horiz_flag)
    are not deleted; instead, we signal an error.  */
 
 static void
-adjust_window_trailing_edge (window, delta, horiz_flag)
-     Lisp_Object window;
-     int delta, horiz_flag;
+adjust_window_trailing_edge (Lisp_Object window, int delta, int horiz_flag)
 {
   Lisp_Object parent, child;
   struct window *p;
   Lisp_Object old_config = Fcurrent_window_configuration (Qnil);
   int delcount = window_deletion_count;
 
-  /* Check values of window_min_width and window_min_height for
-     validity.  */
-  check_min_window_sizes ();
-
-  if (NILP (window))
-    window = Fselected_window ();
-
   CHECK_WINDOW (window);
 
   /* Give up if this window cannot be resized.  */
@@ -4585,7 +4398,7 @@ adjust_window_trailing_edge (window, delta, horiz_flag)
 
       /* Don't make this window too small.  */
       if (XINT (CURSIZE (window)) + delta
-         < window_min_size_2 (XWINDOW (window), horiz_flag))
+         < window_min_size_2 (XWINDOW (window), horiz_flag, 0))
        {
          Fset_window_configuration (old_config);
          error ("Cannot adjust window size as specified");
@@ -4664,10 +4477,12 @@ are not deleted; instead, we signal an error.  */)
   Lisp_Object window, delta, horizontal;
 {
   CHECK_NUMBER (delta);
+  if (NILP (window))
+    window = selected_window;
   adjust_window_trailing_edge (window, XINT (delta), !NILP (horizontal));
 
-  if (! NILP (Vwindow_configuration_change_hook))
-    call1 (Vrun_hooks, Qwindow_configuration_change_hook);
+  run_window_configuration_change_hook
+    (XFRAME (WINDOW_FRAME (XWINDOW (window))));
 
   return Qnil;
 }
@@ -4678,7 +4493,7 @@ are not deleted; instead, we signal an error.  */)
                        Resizing Mini-Windows
  ***********************************************************************/
 
-static void shrink_window_lowest_first P_ ((struct window *, int));
+static void shrink_window_lowest_first (struct window *, int);
 
 enum save_restore_action
 {
@@ -4687,16 +4502,14 @@ enum save_restore_action
     RESTORE_ORIG_SIZES
 };
 
-static int save_restore_orig_size P_ ((struct window *,
-                                       enum save_restore_action));
+static int save_restore_orig_size (struct window *,
+                                   enum save_restore_action);
 
 /* Shrink windows rooted in window W to HEIGHT.  Take the space needed
    from lowest windows first.  */
 
 static void
-shrink_window_lowest_first (w, height)
-     struct window *w;
-     int height;
+shrink_window_lowest_first (struct window *w, int height)
 {
   struct window *c;
   Lisp_Object child;
@@ -4736,13 +4549,13 @@ shrink_window_lowest_first (w, height)
       for (child = w->vchild; WINDOWP (child); child = XWINDOW (child)->next)
        last_child = child;
 
-      /* Assign new heights.  We leave only MIN_SAFE_WINDOW_HEIGHT.  */
+      /* Size children down to their safe heights.  */
       for (child = last_child; delta && !NILP (child); child = c->prev)
        {
          int this_one;
 
          c = XWINDOW (child);
-         this_one = XFASTINT (c->total_lines) - MIN_SAFE_WINDOW_HEIGHT;
+         this_one = XFASTINT (c->total_lines) - window_min_size_1 (c, 0, 1);
 
          if (this_one > delta)
            this_one = delta;
@@ -4778,9 +4591,7 @@ shrink_window_lowest_first (w, height)
    stored in orig_top_line and orig_total_lines for all windows.  */
 
 static int
-save_restore_orig_size (w, action)
-     struct window *w;
-     enum save_restore_action action;
+save_restore_orig_size (struct window *w, enum save_restore_action action)
 {
   int success_p = 1;
 
@@ -4835,26 +4646,23 @@ save_restore_orig_size (w, action)
    without deleting other windows.  */
 
 void
-grow_mini_window (w, delta)
-     struct window *w;
-     int delta;
+grow_mini_window (struct window *w, int delta)
 {
   struct frame *f = XFRAME (w->frame);
   struct window *root;
 
   xassert (MINI_WINDOW_P (w));
-  xassert (delta >= 0);
-
-  /* Check values of window_min_width and window_min_height for
-     validity.  */
-  check_min_window_sizes ();
+  /* Commenting out the following assertion goes against the stated interface
+     of the function, but it currently does not seem to do anything useful.
+     See discussion of this issue in the thread for bug#4534.
+     xassert (delta >= 0); */
 
   /* Compute how much we can enlarge the mini-window without deleting
      other windows.  */
   root = XWINDOW (FRAME_ROOT_WINDOW (f));
-  if (delta)
+  if (delta > 0)
     {
-      int min_height = window_min_size (root, 0, 0, 0);
+      int min_height = window_min_size (root, 0, 0, 0, 0);
       if (XFASTINT (root->total_lines) - delta < min_height)
        /* Note that the root window may already be smaller than
           min_height.  */
@@ -4887,8 +4695,7 @@ grow_mini_window (w, delta)
    line.  */
 
 void
-shrink_mini_window (w)
-     struct window *w;
+shrink_mini_window (struct window *w)
 {
   struct frame *f = XFRAME (w->frame);
   struct window *root = XWINDOW (FRAME_ROOT_WINDOW (f));
@@ -4918,8 +4725,7 @@ shrink_mini_window (w)
    the frame are cleared.  */
 
 void
-mark_window_cursors_off (w)
-     struct window *w;
+mark_window_cursors_off (struct window *w)
 {
   while (w)
     {
@@ -4938,8 +4744,7 @@ mark_window_cursors_off (w)
 /* Return number of lines of text (not counting mode lines) in W.  */
 
 int
-window_internal_height (w)
-     struct window *w;
+window_internal_height (struct window *w)
 {
   int ht = XFASTINT (w->total_lines);
 
@@ -4966,8 +4771,7 @@ window_internal_height (w)
    separating W from the sibling to its right.  */
 
 int
-window_box_text_cols (w)
-     struct window *w;
+window_box_text_cols (struct window *w)
 {
   struct frame *f = XFRAME (WINDOW_FRAME (w));
   int width = XINT (w->total_cols);
@@ -5004,11 +4808,7 @@ window_box_text_cols (w)
    respectively.  */
 
 static void
-window_scroll (window, n, whole, noerror)
-     Lisp_Object window;
-     int n;
-     int whole;
-     int noerror;
+window_scroll (Lisp_Object window, int n, int whole, int noerror)
 {
   immediate_quit = 1;
 
@@ -5028,17 +4828,13 @@ window_scroll (window, n, whole, noerror)
    descriptions.  */
 
 static void
-window_scroll_pixel_based (window, n, whole, noerror)
-     Lisp_Object window;
-     int n;
-     int whole;
-     int noerror;
+window_scroll_pixel_based (Lisp_Object window, int n, int whole, int noerror)
 {
   struct it it;
   struct window *w = XWINDOW (window);
   struct text_pos start;
   int this_scroll_margin;
-  /* True if we fiddled the window vscroll field without really scrolling.   */
+  /* True if we fiddled the window vscroll field without really scrolling.  */
   int vscrolled = 0;
   int x, y, rtop, rbot, rowh, vpos;
 
@@ -5138,20 +4934,23 @@ window_scroll_pixel_based (window, n, whole, noerror)
   if (!NILP (Vscroll_preserve_screen_position))
     {
       /* We preserve the goal pixel coordinate across consecutive
-        calls to scroll-up or scroll-down.  This avoids the
+        calls to scroll-up, scroll-down and other commands that
+        have the `scroll-command' property.  This avoids the
         possibility of point becoming "stuck" on a tall line when
         scrolling by one line.  */
       if (window_scroll_pixel_based_preserve_y < 0
-         || (!EQ (current_kboard->Vlast_command, Qscroll_up)
-             && !EQ (current_kboard->Vlast_command, Qscroll_down)))
+         || !SYMBOLP (current_kboard->Vlast_command)
+         || NILP (Fget (current_kboard->Vlast_command, Qscroll_command)))
        {
          start_display (&it, w, start);
          move_it_to (&it, PT, -1, -1, -1, MOVE_TO_POS);
          window_scroll_pixel_based_preserve_y = it.current_y;
+         window_scroll_pixel_based_preserve_x = it.current_x;
        }
     }
   else
-    window_scroll_pixel_based_preserve_y = -1;
+    window_scroll_pixel_based_preserve_y
+      = window_scroll_pixel_based_preserve_x = -1;
 
   /* Move iterator it from start the specified distance forward or
      backward.  The result is the new window start.  */
@@ -5287,10 +5086,11 @@ window_scroll_pixel_based (window, n, whole, noerror)
        {
          /* If we have a header line, take account of it.
             This is necessary because we set it.current_y to 0, above.  */
-         move_it_to (&it, -1, -1,
+         move_it_to (&it, -1,
+                     window_scroll_pixel_based_preserve_x,
                      window_scroll_pixel_based_preserve_y
                      - (WINDOW_WANTS_HEADER_LINE_P (w) ? 1 : 0 ),
-                     -1, MOVE_TO_Y);
+                     -1, MOVE_TO_Y | MOVE_TO_X);
          SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it));
        }
       else
@@ -5348,8 +5148,9 @@ window_scroll_pixel_based (window, n, whole, noerror)
          /* It would be wrong to subtract CURRENT_HEADER_LINE_HEIGHT
             here because we called start_display again and did not
             alter it.current_y this time.  */
-         move_it_to (&it, -1, -1, window_scroll_pixel_based_preserve_y, -1,
-                     MOVE_TO_Y);
+         move_it_to (&it, -1, window_scroll_pixel_based_preserve_x,
+                     window_scroll_pixel_based_preserve_y, -1,
+                     MOVE_TO_Y | MOVE_TO_X);
          SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it));
        }
       else
@@ -5373,11 +5174,7 @@ window_scroll_pixel_based (window, n, whole, noerror)
    See the comment of window_scroll for parameter descriptions.  */
 
 static void
-window_scroll_line_based (window, n, whole, noerror)
-     Lisp_Object window;
-     int n;
-     int whole;
-     int noerror;
+window_scroll_line_based (Lisp_Object window, int n, int whole, int noerror)
 {
   register struct window *w = XWINDOW (window);
   register int opoint = PT, opoint_byte = PT_BYTE;
@@ -5387,8 +5184,7 @@ window_scroll_line_based (window, n, whole, noerror)
   int lose;
   Lisp_Object bolp;
   int startpos;
-  struct position posit;
-  int original_vpos;
+  Lisp_Object original_pos = Qnil;
 
   /* If scrolling screen-fulls, compute the number of lines to
      scroll from the window's height.  */
@@ -5397,11 +5193,24 @@ window_scroll_line_based (window, n, whole, noerror)
 
   startpos = marker_position (w->start);
 
-  posit = *compute_motion (startpos, 0, 0, 0,
-                          PT, ht, 0,
-                          -1, XINT (w->hscroll),
-                          0, w);
-  original_vpos = posit.vpos;
+  if (!NILP (Vscroll_preserve_screen_position))
+    {
+      if (window_scroll_preserve_vpos <= 0
+         || !SYMBOLP (current_kboard->Vlast_command)
+         || NILP (Fget (current_kboard->Vlast_command, Qscroll_command)))
+       {
+         struct position posit
+           = *compute_motion (startpos, 0, 0, 0,
+                              PT, ht, 0,
+                              -1, XINT (w->hscroll),
+                              0, w);
+         window_scroll_preserve_vpos = posit.vpos;
+         window_scroll_preserve_hpos = posit.hpos + XINT (w->hscroll);
+       }
+
+      original_pos = Fcons (make_number (window_scroll_preserve_hpos),
+                           make_number (window_scroll_preserve_vpos));
+    }
 
   XSETFASTINT (tem, PT);
   tem = Fpos_visible_in_window_p (tem, window, Qnil);
@@ -5452,7 +5261,7 @@ window_scroll_line_based (window, n, whole, noerror)
          && (whole || !EQ (Vscroll_preserve_screen_position, Qt)))
        {
          SET_PT_BOTH (pos, pos_byte);
-         Fvertical_motion (make_number (original_vpos), window);
+         Fvertical_motion (original_pos, window);
        }
       /* If we scrolled forward, put point enough lines down
         that it is outside the scroll margin.  */
@@ -5474,7 +5283,7 @@ window_scroll_line_based (window, n, whole, noerror)
          else if (!NILP (Vscroll_preserve_screen_position))
            {
              SET_PT_BOTH (pos, pos_byte);
-             Fvertical_motion (make_number (original_vpos), window);
+             Fvertical_motion (original_pos, window);
            }
          else
            SET_PT (top_margin);
@@ -5499,7 +5308,7 @@ window_scroll_line_based (window, n, whole, noerror)
              if (!NILP (Vscroll_preserve_screen_position))
                {
                  SET_PT_BOTH (pos, pos_byte);
-                 Fvertical_motion (make_number (original_vpos), window);
+                 Fvertical_motion (original_pos, window);
                }
              else
                Fvertical_motion (make_number (-1), window);
@@ -5523,9 +5332,7 @@ window_scroll_line_based (window, n, whole, noerror)
    up.  This is the guts of Fscroll_up and Fscroll_down.  */
 
 static void
-scroll_command (n, direction)
-     Lisp_Object n;
-     int direction;
+scroll_command (Lisp_Object n, int direction)
 {
   int count = SPECPDL_INDEX ();
 
@@ -5555,8 +5362,8 @@ scroll_command (n, direction)
   unbind_to (count, Qnil);
 }
 
-DEFUN ("scroll-up", Fscroll_up, Sscroll_up, 0, 1, "P",
-       doc: /* Scroll text of current window upward ARG lines.
+DEFUN ("scroll-up", Fscroll_up, Sscroll_up, 0, 1, "^P",
+       doc: /* Scroll text of selected window upward ARG lines.
 If ARG is omitted or nil, scroll upward by a near full screen.
 A near full screen is `next-screen-context-lines' less than a full screen.
 Negative ARG means scroll downward.
@@ -5569,8 +5376,8 @@ When calling from a program, supply as argument a number, nil, or `-'.  */)
   return Qnil;
 }
 
-DEFUN ("scroll-down", Fscroll_down, Sscroll_down, 0, 1, "P",
-       doc: /* Scroll text of current window down ARG lines.
+DEFUN ("scroll-down", Fscroll_down, Sscroll_down, 0, 1, "^P",
+       doc: /* Scroll text of selected window down ARG lines.
 If ARG is omitted or nil, scroll down by a near full screen.
 A near full screen is `next-screen-context-lines' less than a full screen.
 Negative ARG means scroll upward.
@@ -5602,7 +5409,7 @@ specifies the window.  This takes precedence over
     {
       window = Fget_buffer_window (Vother_window_scroll_buffer, Qnil);
       if (NILP (window))
-       window = Fdisplay_buffer (Vother_window_scroll_buffer, Qt, Qnil);
+       window = display_buffer (Vother_window_scroll_buffer, Qt, Qnil);
     }
   else
     {
@@ -5675,12 +5482,12 @@ specifies the window to scroll.  This takes precedence over
   return Qnil;
 }
 \f
-DEFUN ("scroll-left", Fscroll_left, Sscroll_left, 0, 2, "P\np",
+DEFUN ("scroll-left", Fscroll_left, Sscroll_left, 0, 2, "^P\np",
        doc: /* Scroll selected window display ARG columns left.
 Default for ARG is window width minus 2.
 Value is the total amount of leftward horizontal scrolling in
 effect after the change.
-If SET_MINIMUM is non-nil, the new scroll amount becomes the
+If SET-MINIMUM is non-nil, the new scroll amount becomes the
 lower bound for automatic scrolling, i.e. automatic scrolling
 will not scroll a window to a column less than the value returned
 by this function.  This happens in an interactive call.  */)
@@ -5705,12 +5512,12 @@ by this function.  This happens in an interactive call.  */)
   return result;
 }
 
-DEFUN ("scroll-right", Fscroll_right, Sscroll_right, 0, 2, "P\np",
+DEFUN ("scroll-right", Fscroll_right, Sscroll_right, 0, 2, "^P\np",
        doc: /* Scroll selected window display ARG columns right.
 Default for ARG is window width minus 2.
 Value is the total amount of leftward horizontal scrolling in
 effect after the change.
-If SET_MINIMUM is non-nil, the new scroll amount becomes the
+If SET-MINIMUM is non-nil, the new scroll amount becomes the
 lower bound for automatic scrolling, i.e. automatic scrolling
 will not scroll a window to a column less than the value returned
 by this function.  This happens in an interactive call.  */)
@@ -5737,7 +5544,7 @@ by this function.  This happens in an interactive call.  */)
 
 DEFUN ("minibuffer-selected-window", Fminibuffer_selected_window, Sminibuffer_selected_window, 0, 0, 0,
        doc: /* Return the window which was selected when entering the minibuffer.
-Returns nil, if current window is not a minibuffer window.  */)
+Returns nil, if selected window is not a minibuffer window.  */)
      ()
 {
   if (minibuf_level > 0
@@ -5752,8 +5559,7 @@ Returns nil, if current window is not a minibuffer window.  */)
    as opposed to its height.  */
 
 static int
-displayed_window_lines (w)
-     struct window *w;
+displayed_window_lines (struct window *w)
 {
   struct it it;
   struct text_pos start;
@@ -5807,14 +5613,17 @@ displayed_window_lines (w)
 
 
 DEFUN ("recenter", Frecenter, Srecenter, 0, 1, "P",
-       doc: /* Center point in window and redisplay frame.
+       doc: /* Center point in selected window and maybe redisplay frame.
 With prefix argument ARG, recenter putting point on screen line ARG
-relative to the current window.  If ARG is negative, it counts up from the
+relative to the selected window.  If ARG is negative, it counts up from the
 bottom of the window.  (ARG should be less than the height of the window.)
 
-If ARG is omitted or nil, erase the entire frame and then redraw with point
-in the center of the current window.  If `auto-resize-tool-bars' is set to
-`grow-only', this resets the tool-bar's height to the minimum height needed.
+If ARG is omitted or nil, then recenter with point on the middle line of
+the selected window; if the variable `recenter-redisplay' is non-nil,
+also erase the entire frame and redraw it (when `auto-resize-tool-bars'
+is set to `grow-only', this resets the tool-bar's height to the minimum
+height needed); if `recenter-redisplay' has the special value `tty',
+then only tty frame are redrawn.
 
 Just C-u as prefix means put point in the center of the window
 and redisplay normally--don't erase and redraw the frame.  */)
@@ -5834,16 +5643,22 @@ and redisplay normally--don't erase and redraw the frame.  */)
 
   if (NILP (arg))
     {
-      int i;
+      if (!NILP (Vrecenter_redisplay)
+         && (!EQ (Vrecenter_redisplay, Qtty)
+             || !NILP (Ftty_type (selected_frame))))
+       {
+         int i;
 
-      /* Invalidate pixel data calculated for all compositions.  */
-      for (i = 0; i < n_compositions; i++)
-       composition_table[i]->font = NULL;
+         /* Invalidate pixel data calculated for all compositions.  */
+         for (i = 0; i < n_compositions; i++)
+           composition_table[i]->font = NULL;
 
-      WINDOW_XFRAME (w)->minimize_tool_bar_window_p = 1;
+         WINDOW_XFRAME (w)->minimize_tool_bar_window_p = 1;
+
+         Fredraw_frame (WINDOW_FRAME (w));
+         SET_FRAME_GARBAGED (WINDOW_XFRAME (w));
+       }
 
-      Fredraw_frame (WINDOW_FRAME (w));
-      SET_FRAME_GARBAGED (WINDOW_XFRAME (w));
       center_p = 1;
     }
   else if (CONSP (arg)) /* Just C-u. */
@@ -5994,8 +5809,9 @@ DEFUN ("window-text-height", Fwindow_text_height, Swindow_text_height,
        0, 1, 0,
        doc: /* Return the height in lines of the text display area of WINDOW.
 WINDOW defaults to the selected window.
-This doesn't include the mode-line (or header-line if any) or any
-partial-height lines in the text display area.  */)
+
+The return value does not include the mode line, any header line, nor
+any partial-height lines in the text display area.  */)
      (window)
      Lisp_Object window;
 {
@@ -6099,9 +5915,6 @@ struct save_window_data
 
     int frame_cols, frame_lines, frame_menu_bar_lines;
     int frame_tool_bar_lines;
-    /* Record the values of window-min-width and window-min-height
-       so that window sizes remain consistent with them.  */
-    int min_width, min_height;
   };
 
 /* This is saved as a Lisp_Vector  */
@@ -6122,7 +5935,7 @@ struct saved_window
   Lisp_Object left_margin_cols, right_margin_cols;
   Lisp_Object left_fringe_width, right_fringe_width, fringes_outside_margins;
   Lisp_Object scroll_bar_width, vertical_scroll_bar_type;
-  Lisp_Object dedicated;
+  Lisp_Object dedicated, resize_proportionally;
 };
 
 #define SAVED_WINDOW_N(swv,n) \
@@ -6278,18 +6091,13 @@ the return value is nil.  Otherwise the value is t.  */)
       /* Problem: Freeing all matrices and later allocating them again
         is a serious redisplay flickering problem.  What we would
         really like to do is to free only those matrices not reused
-        below.   */
+        below.  */
       root_window = XWINDOW (FRAME_ROOT_WINDOW (f));
       leaf_windows
        = (struct window **) alloca (count_windows (root_window)
                                     * sizeof (struct window *));
       n_leaf_windows = get_leaf_windows (root_window, leaf_windows, 0);
 
-      /* 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".
         Restoring the new configuration "undeletes" any that are in it.
@@ -6356,6 +6164,7 @@ the return value is nil.  Otherwise the value is t.  */)
          w->scroll_bar_width = p->scroll_bar_width;
          w->vertical_scroll_bar_type = p->vertical_scroll_bar_type;
          w->dedicated = p->dedicated;
+         w->resize_proportionally = p->resize_proportionally;
          XSETFASTINT (w->last_modified, 0);
          XSETFASTINT (w->last_overlay_modified, 0);
 
@@ -6434,7 +6243,7 @@ the return value is nil.  Otherwise the value is t.  */)
          when the frame's old selected window has been deleted.  */
       if (f != selected_frame && FRAME_WINDOW_P (f))
        do_switch_frame (WINDOW_FRAME (XWINDOW (data->root_window)),
-                        0, 0);
+                        0, 0, Qnil);
 #endif
 
       /* Set the screen height to the value it had before this function.  */
@@ -6477,20 +6286,14 @@ the return value is nil.  Otherwise the value is t.  */)
         Fselect_window above totally superfluous; it still sets f's
         selected window.  */
       if (FRAME_LIVE_P (XFRAME (data->selected_frame)))
-       do_switch_frame (data->selected_frame, 0, 0);
+       do_switch_frame (data->selected_frame, 0, 0, Qnil);
 
-      if (! NILP (Vwindow_configuration_change_hook)
-         && ! NILP (Vrun_hooks))
-       call1 (Vrun_hooks, Qwindow_configuration_change_hook);
+      run_window_configuration_change_hook (f);
     }
 
   if (!NILP (new_current_buffer))
     Fset_buffer (new_current_buffer);
 
-  /* Restore the minimum heights recorded in the configuration.  */
-  window_min_height = data->min_height;
-  window_min_width = data->min_width;
-
   Vminibuf_scroll_window = data->minibuf_scroll_window;
   minibuf_selected_window = data->minibuf_selected_window;
 
@@ -6501,8 +6304,7 @@ the return value is nil.  Otherwise the value is t.  */)
    by setting their buffers to nil.  */
 
 void
-delete_all_subwindows (w)
-     register struct window *w;
+delete_all_subwindows (register struct window *w)
 {
   if (!NILP (w->next))
     delete_all_subwindows (XWINDOW (w->next));
@@ -6528,8 +6330,7 @@ delete_all_subwindows (w)
 }
 \f
 static int
-count_windows (window)
-     register struct window *window;
+count_windows (register struct window *window)
 {
   register int count = 1;
   if (!NILP (window->next))
@@ -6546,10 +6347,7 @@ count_windows (window)
    Value is last index + 1.  */
 
 static int
-get_leaf_windows (w, flat, i)
-     struct window *w;
-     struct window **flat;
-     int i;
+get_leaf_windows (struct window *w, struct window **flat, int i)
 {
   while (w)
     {
@@ -6572,8 +6370,7 @@ get_leaf_windows (w, flat, i)
    can be returned.  */
 
 struct glyph *
-get_phys_cursor_glyph (w)
-     struct window *w;
+get_phys_cursor_glyph (struct window *w)
 {
   struct glyph_row *row;
   struct glyph *glyph;
@@ -6592,10 +6389,7 @@ get_phys_cursor_glyph (w)
 
 
 static int
-save_window_save (window, vector, i)
-     Lisp_Object window;
-     struct Lisp_Vector *vector;
-     int i;
+save_window_save (Lisp_Object window, struct Lisp_Vector *vector, int i)
 {
   register struct saved_window *p;
   register struct window *w;
@@ -6626,6 +6420,7 @@ save_window_save (window, vector, i)
       p->scroll_bar_width = w->scroll_bar_width;
       p->vertical_scroll_bar_type = w->vertical_scroll_bar_type;
       p->dedicated = w->dedicated;
+      p->resize_proportionally = w->resize_proportionally;
       if (!NILP (w->buffer))
        {
          /* Save w's value of point in the window configuration.
@@ -6713,8 +6508,6 @@ redirection (see `redirect-frame-focus').  */)
   data->minibuf_selected_window = minibuf_level > 0 ? minibuf_selected_window : Qnil;
   data->root_window = FRAME_ROOT_WINDOW (f);
   data->focus_frame = FRAME_FOCUS_FRAME (f);
-  data->min_height = window_min_height;
-  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++)
@@ -6754,8 +6547,7 @@ usage: (save-window-excursion BODY...)  */)
  ***********************************************************************/
 
 static Lisp_Object
-window_tree (w)
-     struct window *w;
+window_tree (struct window *w)
 {
   Lisp_Object tail = Qnil;
   Lisp_Object result = Qnil;
@@ -7122,12 +6914,9 @@ If PIXELS-P is non-nil, the return value is VSCROLL.  */)
    additional argument USER_DATA.  Stops when FN returns 0.  */
 
 void
-foreach_window (f, fn, user_data)
-     struct frame *f;
-     int (* fn) P_ ((struct window *, void *));
-     void *user_data;
+foreach_window (struct frame *f, int (*fn) (struct window *, void *), void *user_data)
 {
-  /* Fdelete_frame may set FRAME_ROOT_WINDOW (f) to Qnil.  */
+  /* delete_frame may set FRAME_ROOT_WINDOW (f) to Qnil.  */
   if (WINDOWP (FRAME_ROOT_WINDOW (f)))
     foreach_window_1 (XWINDOW (FRAME_ROOT_WINDOW (f)), fn, user_data);
 }
@@ -7139,10 +6928,7 @@ foreach_window (f, fn, user_data)
    Stop when FN returns 0.  Value is 0 if stopped by FN.  */
 
 static int
-foreach_window_1 (w, fn, user_data)
-     struct window *w;
-     int (* fn) P_ ((struct window *, void *));
-     void *user_data;
+foreach_window_1 (struct window *w, int (*fn) (struct window *, void *), void *user_data)
 {
   int cont;
 
@@ -7167,9 +6953,7 @@ foreach_window_1 (w, fn, user_data)
    the window start.  */
 
 static int
-freeze_window_start (w, freeze_p)
-     struct window *w;
-     void *freeze_p;
+freeze_window_start (struct window *w, void *freeze_p)
 {
   if (MINI_WINDOW_P (w)
       || (WINDOWP (selected_window) /* Can be nil in corner cases.  */
@@ -7189,9 +6973,7 @@ freeze_window_start (w, freeze_p)
    means freeze the window start.  */
 
 void
-freeze_window_starts (f, freeze_p)
-     struct frame *f;
-     int freeze_p;
+freeze_window_starts (struct frame *f, int freeze_p)
 {
   foreach_window (f, freeze_window_start, (void *) (freeze_p ? f : 0));
 }
@@ -7202,12 +6984,10 @@ freeze_window_starts (f, freeze_p)
  ***********************************************************************/
 
 /* Return 1 if window configurations C1 and C2
-   describe the same state of affairs.  This is used by Fequal.   */
+   describe the same state of affairs.  This is used by Fequal.  */
 
 int
-compare_window_configurations (c1, c2, ignore_positions)
-     Lisp_Object c1, c2;
-     int ignore_positions;
+compare_window_configurations (Lisp_Object c1, Lisp_Object c2, int ignore_positions)
 {
   register struct save_window_data *d1, *d2;
   struct Lisp_Vector *sw1, *sw2;
@@ -7247,10 +7027,6 @@ compare_window_configurations (c1, c2, ignore_positions)
      if everything else compares equal.  */
   if (! EQ (d1->focus_frame, d2->focus_frame))
     return 0;
-  if (d1->min_width != d2->min_width)
-    return 0;
-  if (d1->min_height != d2->min_height)
-    return 0;
 
   /* Verify that the two confis have the same number of windows.  */
   if (sw1->size != sw2->size)
@@ -7337,7 +7113,7 @@ and scrolling positions.  */)
 }
 \f
 void
-init_window_once ()
+init_window_once (void)
 {
   struct frame *f = make_initial_frame ();
   XSETFRAME (selected_frame, f);
@@ -7350,38 +7126,47 @@ init_window_once ()
 }
 
 void
-init_window ()
+init_window (void)
 {
   Vwindow_list = Qnil;
 }
 
 void
-syms_of_window ()
+syms_of_window (void)
 {
-  Qscroll_up = intern ("scroll-up");
+  Qscroll_up = intern_c_string ("scroll-up");
   staticpro (&Qscroll_up);
 
-  Qscroll_down = intern ("scroll-down");
+  Qscroll_down = intern_c_string ("scroll-down");
   staticpro (&Qscroll_down);
 
-  Qwindow_size_fixed = intern ("window-size-fixed");
+  Qscroll_command = intern_c_string ("scroll-command");
+  staticpro (&Qscroll_command);
+
+  Fput (Qscroll_up, Qscroll_command, Qt);
+  Fput (Qscroll_down, Qscroll_command, Qt);
+
+  Qwindow_size_fixed = intern_c_string ("window-size-fixed");
   staticpro (&Qwindow_size_fixed);
   Fset (Qwindow_size_fixed, Qnil);
 
   staticpro (&Qwindow_configuration_change_hook);
   Qwindow_configuration_change_hook
-    = intern ("window-configuration-change-hook");
+    = intern_c_string ("window-configuration-change-hook");
 
-  Qwindowp = intern ("windowp");
+  Qwindowp = intern_c_string ("windowp");
   staticpro (&Qwindowp);
 
-  Qwindow_configuration_p = intern ("window-configuration-p");
+  Qwindow_configuration_p = intern_c_string ("window-configuration-p");
   staticpro (&Qwindow_configuration_p);
 
-  Qwindow_live_p = intern ("window-live-p");
+  Qwindow_live_p = intern_c_string ("window-live-p");
   staticpro (&Qwindow_live_p);
 
-  Qtemp_buffer_show_hook = intern ("temp-buffer-show-hook");
+  Qdisplay_buffer = intern_c_string ("display-buffer");
+  staticpro (&Qdisplay_buffer);
+
+  Qtemp_buffer_show_hook = intern_c_string ("temp-buffer-show-hook");
   staticpro (&Qtemp_buffer_show_hook);
 
   staticpro (&Vwindow_list);
@@ -7389,7 +7174,10 @@ syms_of_window ()
   minibuf_selected_window = Qnil;
   staticpro (&minibuf_selected_window);
 
+  window_scroll_pixel_based_preserve_x = -1;
   window_scroll_pixel_based_preserve_y = -1;
+  window_scroll_preserve_hpos = -1;
+  window_scroll_preserve_vpos = -1;
 
   DEFVAR_LISP ("temp-buffer-show-function", &Vtemp_buffer_show_function,
               doc: /* Non-nil means call as function to display a help buffer.
@@ -7399,21 +7187,6 @@ If this function is used, then it must do the entire job of showing
 the buffer; `temp-buffer-show-hook' is not run unless this function runs it.  */);
   Vtemp_buffer_show_function = Qnil;
 
-  DEFVAR_LISP ("display-buffer-function", &Vdisplay_buffer_function,
-              doc: /* If non-nil, function to call to handle `display-buffer'.
-It will receive two args, the buffer and a flag which if non-nil means
-that the currently selected window is not acceptable.
-It should choose or create a window, display the specified buffer in it,
-and return the window.
-Commands such as `switch-to-buffer-other-window' and `find-file-other-window'
-work using this function.  */);
-  Vdisplay_buffer_function = Qnil;
-
-  DEFVAR_LISP ("even-window-heights", &Veven_window_heights,
-              doc: /* *If non-nil, `display-buffer' should even the window heights.
-If nil, `display-buffer' will leave the window configuration alone.  */);
-  Veven_window_heights = Qt;
-
   DEFVAR_LISP ("minibuffer-scroll-window", &Vminibuf_scroll_window,
               doc: /* Non-nil means it is the window that C-M-v in minibuffer should scroll.  */);
   Vminibuf_scroll_window = Qnil;
@@ -7428,171 +7201,64 @@ is displayed in the `mode-line' face.  */);
               doc: /* If non-nil, this is a buffer and \\[scroll-other-window] should scroll its window.  */);
   Vother_window_scroll_buffer = Qnil;
 
-  DEFVAR_BOOL ("pop-up-frames", &pop_up_frames,
-              doc: /* *Non-nil means `display-buffer' should make a separate frame.  */);
-  pop_up_frames = 0;
-
   DEFVAR_BOOL ("auto-window-vscroll", &auto_window_vscroll_p,
               doc: /* *Non-nil means to automatically adjust `window-vscroll' to view tall lines.  */);
   auto_window_vscroll_p = 1;
 
-  DEFVAR_BOOL ("display-buffer-reuse-frames", &display_buffer_reuse_frames,
-              doc: /* *Non-nil means `display-buffer' should reuse frames.
-If the buffer in question is already displayed in a frame, raise that frame.  */);
-  display_buffer_reuse_frames = 0;
-
-  DEFVAR_LISP ("pop-up-frame-function", &Vpop_up_frame_function,
-              doc: /* Function to call to handle automatic new frame creation.
-It is called with no arguments and should return a newly created frame.
-
-A typical value might be `(lambda () (new-frame pop-up-frame-alist))'
-where `pop-up-frame-alist' would hold the default frame parameters.  */);
-  Vpop_up_frame_function = Qnil;
-
-  DEFVAR_LISP ("special-display-buffer-names", &Vspecial_display_buffer_names,
-              doc: /* *List of buffer names that should have their own special frames.
-Displaying a buffer with `display-buffer' or `pop-to-buffer',
-if its name is in this list, makes a special frame for it
-using `special-display-function'.  See also `special-display-regexps'.
-
-An element of the list can be a list instead of just a string.
-There are two ways to use a list as an element:
-  (BUFFER FRAME-PARAMETERS...)   (BUFFER FUNCTION OTHER-ARGS...)
-In the first case, the FRAME-PARAMETERS are pairs of the form
-\(PARAMETER . VALUE); these parameter values are used to create the frame.
-In the second case, FUNCTION is called with BUFFER as the first argument,
-followed by the OTHER-ARGS--it can display BUFFER in any way it likes.
-All this is done by the function found in `special-display-function'.
-
-If the specified frame parameters include (same-buffer . t), the
-buffer is displayed in the currently selected window.  Otherwise, if
-they include (same-frame . t), the buffer is displayed in a new window
-in the currently selected frame.
-
-If this variable appears \"not to work\", because you add a name to it
-but that buffer still appears in the selected window, look at the
-values of `same-window-buffer-names' and `same-window-regexps'.
-Those variables take precedence over this one.  */);
-  Vspecial_display_buffer_names = Qnil;
-
-  DEFVAR_LISP ("special-display-regexps", &Vspecial_display_regexps,
-              doc: /* *List of regexps saying which buffers should have their own special frames.
-When displaying a buffer with `display-buffer' or `pop-to-buffer',
-if any regexp in this list matches the buffer name, it makes a
-special frame for the buffer by calling `special-display-function'.
-
-An element of the list can be a list instead of just a string.
-There are two ways to use a list as an element:
-  (REGEXP FRAME-PARAMETERS...)   (REGEXP FUNCTION OTHER-ARGS...)
-In the first case, the FRAME-PARAMETERS are pairs of the form
-\(PARAMETER . VALUE); these parameter values are used to create the frame.
-In the second case, FUNCTION is called with BUFFER as the first argument,
-followed by the OTHER-ARGS--it can display the buffer in any way it likes.
-All this is done by the function found in `special-display-function'.
-
-If the specified frame parameters include (same-buffer . t), the
-buffer is displayed in the currently selected window.  Otherwise, if
-they include (same-frame . t), the buffer is displayed in a new window
-in the currently selected frame.
-
-If this variable appears \"not to work\", because you add a regexp to it
-but the matching buffers still appear in the selected window, look at the
-values of `same-window-buffer-names' and `same-window-regexps'.
-Those variables take precedence over this one.  */);
-  Vspecial_display_regexps = Qnil;
-
-  DEFVAR_LISP ("special-display-function", &Vspecial_display_function,
-              doc: /* Function to call to make a new frame for a special buffer.
-It is called with two arguments, the buffer and optional buffer specific
-data, and should return a window displaying that buffer.
-The default value normally makes a separate frame for the buffer,
-  using `special-display-frame-alist' to specify the frame parameters.
-But if the buffer specific data includes (same-buffer . t) then the
-  buffer is displayed in the current selected window.
-Otherwise if it includes (same-frame . t) then the buffer is displayed in
-  a new window in the currently selected frame.
-
-A buffer is special if it is listed in `special-display-buffer-names'
-or matches a regexp in `special-display-regexps'.  */);
-  Vspecial_display_function = Qnil;
-
-  DEFVAR_LISP ("same-window-buffer-names", &Vsame_window_buffer_names,
-              doc: /* *List of buffer names that should appear in the selected window.
-Displaying one of these buffers using `display-buffer' or `pop-to-buffer'
-switches to it in the selected window, rather than making it appear
-in some other window.
-
-An element of the list can be a cons cell instead of just a string.
-Then the car must be a string, which specifies the buffer name.
-This is for compatibility with `special-display-buffer-names';
-the cdr of the cons cell is ignored.
-
-See also `same-window-regexps'.  */);
-  Vsame_window_buffer_names = Qnil;
-
-  DEFVAR_LISP ("same-window-regexps", &Vsame_window_regexps,
-              doc: /* *List of regexps saying which buffers should appear in the selected window.
-If a buffer name matches one of these regexps, then displaying it
-using `display-buffer' or `pop-to-buffer' switches to it
-in the selected window, rather than making it appear in some other window.
-
-An element of the list can be a cons cell instead of just a string.
-Then the car must be a string, which specifies the buffer name.
-This is for compatibility with `special-display-buffer-names';
-the cdr of the cons cell is ignored.
-
-See also `same-window-buffer-names'.  */);
-  Vsame_window_regexps = Qnil;
-
-  DEFVAR_BOOL ("pop-up-windows", &pop_up_windows,
-              doc: /* *Non-nil means display-buffer should make new windows.  */);
-  pop_up_windows = 1;
-
   DEFVAR_INT ("next-screen-context-lines", &next_screen_context_lines,
              doc: /* *Number of lines of continuity when scrolling by screenfuls.  */);
   next_screen_context_lines = 2;
 
-  DEFVAR_INT ("split-height-threshold", &split_height_threshold,
-             doc: /* *A window must be at least this tall to be eligible for splitting
-by `display-buffer'.  The value is in line units.
-If there is only one window, it is split regardless of this value.  */);
-  split_height_threshold = 500;
-
-  DEFVAR_LISP ("split-window-preferred-function",
-              &Vsplit_window_preferred_function,
-              doc: /* Function to use to split a window.
-This is used by `display-buffer' to allow the user to choose whether
-to split windows horizontally or vertically or some mix of the two.
-It is called with a window as single argument and should split it in two
-and return the new window.  */);
-  Vsplit_window_preferred_function = intern ("split-window");
-
   DEFVAR_INT ("window-min-height", &window_min_height,
-             doc: /* *Delete any window less than this tall (including its mode line).
-The value is in line units. */);
+             doc: /* Allow deleting windows less than this tall.
+The value is measured in line units.  If a window wants a modeline it
+is counted as one line.
+
+Emacs honors settings of this variable when enlarging or shrinking
+windows vertically.  A value less than 1 is invalid.  */);
   window_min_height = 4;
 
   DEFVAR_INT ("window-min-width", &window_min_width,
-             doc: /* *Delete any window less than this wide (measured in characters).  */);
+             doc: /* Allow deleting windows less than this wide.
+The value is measured in characters and includes any fringes or
+the scrollbar.
+
+Emacs honors settings of this variable when enlarging or shrinking
+windows horizontally.  A value less than 2 is invalid.  */);
   window_min_width = 10;
 
   DEFVAR_LISP ("scroll-preserve-screen-position",
               &Vscroll_preserve_screen_position,
-              doc: /* *Controls if scroll commands move point to keep its screen line unchanged.
+              doc: /* *Controls if scroll commands move point to keep its screen position unchanged.
 A value of nil means point does not keep its screen position except
 at the scroll margin or window boundary respectively.
 A value of t means point keeps its screen position if the scroll
 command moved it vertically out of the window, e.g. when scrolling
 by full screens.
-Any other value means point always keeps its screen position.  */);
+Any other value means point always keeps its screen position.
+Scroll commands should have the `scroll-command' property
+on their symbols to be controlled by this variable.  */);
   Vscroll_preserve_screen_position = Qnil;
 
+  DEFVAR_LISP ("window-point-insertion-type", &Vwindow_point_insertion_type,
+              doc: /* Type of marker to use for `window-point'.  */);
+  Vwindow_point_insertion_type = Qnil;
+
   DEFVAR_LISP ("window-configuration-change-hook",
               &Vwindow_configuration_change_hook,
               doc: /* Functions to call when window configuration changes.
-The selected frame is the one whose configuration has changed.  */);
+The buffer-local part is run once per window, with the relevant window
+selected; while the global part is run only once for the modified frame,
+with the relevant frame selected.  */);
   Vwindow_configuration_change_hook = Qnil;
 
+  DEFVAR_LISP ("recenter-redisplay", &Vrecenter_redisplay,
+              doc: /* If non-nil, then the `recenter' command with a nil argument
+will redraw the entire frame; the special value `tty' causes the
+frame to be redrawn only if it is a tty frame.  */);
+  Vrecenter_redisplay = Qtty;
+
+
   defsubr (&Sselected_window);
   defsubr (&Sminibuffer_window);
   defsubr (&Swindow_minibuffer_p);
@@ -7610,8 +7276,10 @@ The selected frame is the one whose configuration has changed.  */);
   defsubr (&Sset_window_redisplay_end_trigger);
   defsubr (&Swindow_edges);
   defsubr (&Swindow_pixel_edges);
+  defsubr (&Swindow_absolute_pixel_edges);
   defsubr (&Swindow_inside_edges);
   defsubr (&Swindow_inside_pixel_edges);
+  defsubr (&Swindow_inside_absolute_pixel_edges);
   defsubr (&Scoordinates_in_window_p);
   defsubr (&Swindow_at);
   defsubr (&Swindow_point);
@@ -7635,9 +7303,6 @@ The selected frame is the one whose configuration has changed.  */);
   defsubr (&Sdelete_window);
   defsubr (&Sset_window_buffer);
   defsubr (&Sselect_window);
-  defsubr (&Sspecial_display_p);
-  defsubr (&Ssame_window_p);
-  defsubr (&Sdisplay_buffer);
   defsubr (&Sforce_window_update);
   defsubr (&Ssplit_window);
   defsubr (&Senlarge_window);
@@ -7669,10 +7334,14 @@ The selected frame is the one whose configuration has changed.  */);
   defsubr (&Sset_window_vscroll);
   defsubr (&Scompare_window_configurations);
   defsubr (&Swindow_list);
+  defsubr (&Swindow_parameters);
+  defsubr (&Swindow_parameter);
+  defsubr (&Sset_window_parameter);
+
 }
 
 void
-keys_of_window ()
+keys_of_window (void)
 {
   initial_define_key (control_x_map, '1', "delete-other-windows");
   initial_define_key (control_x_map, '2', "split-window");
@@ -7682,12 +7351,9 @@ keys_of_window ()
   initial_define_key (control_x_map, '<', "scroll-left");
   initial_define_key (control_x_map, '>', "scroll-right");
 
-  initial_define_key (global_map, Ctl ('V'), "scroll-up");
+  initial_define_key (global_map, Ctl ('V'), "scroll-up-command");
   initial_define_key (meta_map, Ctl ('V'), "scroll-other-window");
-  initial_define_key (meta_map, 'v', "scroll-down");
-
-  initial_define_key (global_map, Ctl('L'), "recenter");
-  initial_define_key (meta_map, 'r', "move-to-window-line");
+  initial_define_key (meta_map, 'v', "scroll-down-command");
 }
 
 /* arch-tag: 90a9c576-0590-48f1-a5f1-6c96a0452d9f