]> code.delx.au - gnu-emacs/blobdiff - src/window.c
Add documentation for horizontal scroll bars and fix some minor issues.
[gnu-emacs] / src / window.c
index e2770410bce5c4efd1c709c0a30b18e169ff32f0..0b0f2140a5821e757668c5b739cb0489a46f6225 100644 (file)
@@ -1,6 +1,6 @@
 /* Window creation, deletion and examination for GNU Emacs.
    Does not include redisplay.
-   Copyright (C) 1985-1987, 1993-1998, 2000-2013 Free Software
+   Copyright (C) 1985-1987, 1993-1998, 2000-2014 Free Software
    Foundation, Inc.
 
 This file is part of GNU Emacs.
@@ -27,6 +27,7 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 #include "buffer.h"
 #include "keyboard.h"
 #include "keymap.h"
+#include "menu.h"
 #include "frame.h"
 #include "window.h"
 #include "commands.h"
@@ -51,9 +52,12 @@ static Lisp_Object Qrecord_window_buffer;
 static Lisp_Object Qwindow_deletable_p, Qdelete_window, Qdisplay_buffer;
 static Lisp_Object Qreplace_buffer_in_windows, Qget_mru_window;
 static Lisp_Object Qwindow_resize_root_window, Qwindow_resize_root_window_vertically;
+static Lisp_Object Qwindow_sanitize_window_sizes;
 static Lisp_Object Qwindow_pixel_to_total;
 static Lisp_Object Qscroll_up, Qscroll_down, Qscroll_command;
 static Lisp_Object Qsafe, Qabove, Qbelow, Qwindow_size, Qclone_of;
+static Lisp_Object Qfloor, Qceiling;
+static Lisp_Object Qwindow_point_insertion_type;
 
 static int displayed_window_lines (struct window *);
 static int count_windows (struct window *);
@@ -84,7 +88,7 @@ static struct window *set_window_fringes (struct window *, Lisp_Object,
 static struct window *set_window_margins (struct window *, Lisp_Object,
                                          Lisp_Object);
 static struct window *set_window_scroll_bars (struct window *, Lisp_Object,
-                                             Lisp_Object, Lisp_Object);
+                                             Lisp_Object, Lisp_Object, Lisp_Object);
 static void apply_window_adjustment (struct window *);
 
 /* This is the window in which the terminal's cursor should
@@ -117,13 +121,10 @@ static Lisp_Object Qtemp_buffer_show_hook;
 /* Incremented for each window created.  */
 static int sequence_number;
 
-/* Nonzero after init_window_once has finished.  */
-static int window_initialized;
-
 /* Hook to run when window config changes.  */
 static Lisp_Object Qwindow_configuration_change_hook;
 
-/* Used by the function window_scroll_pixel_based */
+/* Used by the function window_scroll_pixel_based */
 static int window_scroll_pixel_based_preserve_x;
 static int window_scroll_pixel_based_preserve_y;
 
@@ -143,66 +144,85 @@ wset_combination_limit (struct window *w, Lisp_Object val)
 {
   w->combination_limit = val;
 }
+
 static void
 wset_dedicated (struct window *w, Lisp_Object val)
 {
   w->dedicated = val;
 }
+
 static void
 wset_display_table (struct window *w, Lisp_Object val)
 {
   w->display_table = val;
 }
+
 static void
 wset_new_normal (struct window *w, Lisp_Object val)
 {
   w->new_normal = val;
 }
+
 static void
 wset_new_total (struct window *w, Lisp_Object val)
 {
   w->new_total = val;
 }
+
 static void
 wset_normal_cols (struct window *w, Lisp_Object val)
 {
   w->normal_cols = val;
 }
+
 static void
 wset_normal_lines (struct window *w, Lisp_Object val)
 {
   w->normal_lines = val;
 }
+
 static void
 wset_parent (struct window *w, Lisp_Object val)
 {
   w->parent = val;
 }
+
 static void
 wset_pointm (struct window *w, Lisp_Object val)
 {
   w->pointm = val;
 }
+
+static void
+wset_old_pointm (struct window *w, Lisp_Object val)
+{
+  w->old_pointm = val;
+}
+
 static void
 wset_start (struct window *w, Lisp_Object val)
 {
   w->start = val;
 }
+
 static void
 wset_temslot (struct window *w, Lisp_Object val)
 {
   w->temslot = val;
 }
+
 static void
 wset_vertical_scroll_bar_type (struct window *w, Lisp_Object val)
 {
   w->vertical_scroll_bar_type = val;
 }
+
 static void
 wset_window_parameters (struct window *w, Lisp_Object val)
 {
   w->window_parameters = val;
 }
+
 static void
 wset_combination (struct window *w, bool horflag, Lisp_Object val)
 {
@@ -309,7 +329,7 @@ DEFUN ("windowp", Fwindowp, Swindowp, 1, 1, 0,
 DEFUN ("window-valid-p", Fwindow_valid_p, Swindow_valid_p, 1, 1, 0,
        doc: /* Return t if OBJECT is a valid window and nil otherwise.
 A valid window is either a window that displays a buffer or an internal
-window.  Deleted windows are not live.  */)
+window.  Windows that have been deleted are not valid.  */)
   (Lisp_Object object)
 {
   return WINDOW_VALID_P (object) ? Qt : Qnil;
@@ -487,11 +507,14 @@ select_window (Lisp_Object window, Lisp_Object norecord, int inhibit_point_swap)
     goto record_and_return;
 
   if (NILP (norecord))
-    /* Mark the window for redisplay since the selected-window has a different
-       mode-line.  */
-    wset_redisplay (XWINDOW (selected_window));
+    { /* Mark the window for redisplay since the selected-window has
+        a different mode-line.  */
+      wset_redisplay (XWINDOW (selected_window));
+      wset_redisplay (w);
+    }
   else
     redisplay_other_windows ();
+
   sf = SELECTED_FRAME ();
   if (XFRAME (WINDOW_FRAME (w)) != sf)
     {
@@ -510,8 +533,6 @@ select_window (Lisp_Object window, Lisp_Object norecord, int inhibit_point_swap)
 
   select_window_1 (window, inhibit_point_swap);
   bset_last_selected_window (XBUFFER (w->contents), window);
-  if (NILP (norecord))
-    wset_redisplay (w);
 
  record_and_return:
   /* record_buffer can run QUIT, so make sure it is run only after we have
@@ -557,7 +578,7 @@ select_window_1 (Lisp_Object window, bool inhibit_point_swap)
 DEFUN ("select-window", Fselect_window, Sselect_window, 1, 2, 0,
        doc: /* Select WINDOW which must be a live window.
 Also make WINDOW's frame the selected frame and WINDOW that frame's
-selected window.  In addition, make WINDOW's buffer current and set that
+selected window.  In addition, make WINDOW's buffer current and set its
 buffer's value of `point' to the value of WINDOW's `window-point'.
 Return WINDOW.
 
@@ -565,8 +586,17 @@ Optional second arg NORECORD non-nil means do not put this buffer at the
 front of the buffer list and do not make this window the most recently
 selected one.
 
-Note that the main editor command loop sets the current buffer to the
-buffer of the selected window before each command.  */)
+Run `buffer-list-update-hook' unless NORECORD is non-nil.  Note that
+applications and internal routines often select a window temporarily for
+various purposes; mostly, to simplify coding.  As a rule, such
+selections should be not recorded and therefore will not pollute
+`buffer-list-update-hook'.  Selections that "really count" are those
+causing a visible change in the next redisplay of WINDOW's frame and
+should be always recorded.  So if you think of running a function each
+time a window gets selected put it on `buffer-list-update-hook'.
+
+Also note that the main editor command loop sets the current buffer to
+the buffer of the selected window before each command.  */)
   (register Lisp_Object window, Lisp_Object norecord)
 {
   return select_window (window, norecord, 0);
@@ -681,7 +711,7 @@ selected one.  */)
 }
 \f
 DEFUN ("window-pixel-width", Fwindow_pixel_width, Swindow_pixel_width, 0, 1, 0,
-       doc: /* Return the pixel width of window WINDOW.
+       doc: /* Return the width of window WINDOW in pixels.
 WINDOW must be a valid window and defaults to the selected one.
 
 The return value includes the fringes and margins of WINDOW as well as
@@ -694,50 +724,98 @@ spanned by its children.  */)
 }
 
 DEFUN ("window-pixel-height", Fwindow_pixel_height, Swindow_pixel_height, 0, 1, 0,
-       doc: /* Return the pixel height of window WINDOW.
+       doc: /* Return the height of window WINDOW in pixels.
 WINDOW must be a valid window and defaults to the selected one.
 
-The return value includes the mode line and header line, if any.  If
-WINDOW is an internal window, its pixel height is the height of the
-screen areas spanned by its children.  */)
+The return value includes the mode line and header line and the bottom
+divider, if any.  If WINDOW is an internal window, its pixel height is
+the height of the screen areas spanned by its children.  */)
   (Lisp_Object window)
 {
   return make_number (decode_valid_window (window)->pixel_height);
 }
 
-DEFUN ("window-total-height", Fwindow_total_height, Swindow_total_height, 0, 1, 0,
-       doc: /* Return the total height, in lines, of window WINDOW.
+DEFUN ("window-total-height", Fwindow_total_height, Swindow_total_height, 0, 2, 0,
+       doc: /* Return the height of window WINDOW in lines.
 WINDOW must be a valid window and defaults to the selected one.
 
-The return value includes the mode line and header line, if any.
-If WINDOW is an internal window, the total height is the height
-of the screen areas spanned by its children.
+The return value includes the heights of WINDOW's mode and header line
+and its bottom divider, if any.  If WINDOW is an internal window, the
+total height is the height of the screen areas spanned by its children.
 
-On a graphical display, this total height is reported as an
-integer multiple of the default character height.  */)
-  (Lisp_Object window)
+If WINDOW's pixel height is not an integral multiple of its frame's
+character height, the number of lines occupied by WINDOW is rounded
+internally.  This is done in a way such that, if WINDOW is a parent
+window, the sum of the total heights of all its children internally
+equals the total height of WINDOW.
+
+If the optional argument ROUND is `ceiling', return the smallest integer
+larger than WINDOW's pixel height divided by the character height of
+WINDOW's frame.  ROUND `floor' means to return the largest integer
+smaller than WINDOW's pixel height divided by the character height of
+WINDOW's frame.  Any other value of ROUND means to return the internal
+total height of WINDOW.  */)
+  (Lisp_Object window, Lisp_Object round)
 {
-  return make_number (decode_valid_window (window)->total_lines);
+  struct window *w = decode_valid_window (window);
+
+  if (! EQ (round, Qfloor) && ! EQ (round, Qceiling))
+    return make_number (w->total_lines);
+  else
+    {
+      int unit = FRAME_LINE_HEIGHT (WINDOW_XFRAME (w));
+
+      return make_number (EQ (round, Qceiling)
+                         ? ((w->pixel_height + unit - 1) /unit)
+                         : (w->pixel_height / unit));
+    }
 }
 
-DEFUN ("window-total-width", Fwindow_total_width, Swindow_total_width, 0, 1, 0,
-       doc: /* Return the total width, in columns, of window WINDOW.
+DEFUN ("window-total-width", Fwindow_total_width, Swindow_total_width, 0, 2, 0,
+       doc: /* Return the total width of window WINDOW in columns.
 WINDOW must be a valid window and defaults to the selected one.
 
-The return value includes any vertical dividers or scroll bars
-belonging to WINDOW.  If WINDOW is an internal window, the total width
-is the width of the screen areas spanned by its children.
-
-On a graphical display, this total width is reported as an
-integer multiple of the default character width.  */)
-  (Lisp_Object window)
+The return value includes the widths of WINDOW's fringes, margins,
+scroll bars and its right divider, if any.  If WINDOW is an internal
+window, the total width is the width of the screen areas spanned by its
+children.
+
+If WINDOW's pixel width is not an integral multiple of its frame's
+character width, the number of lines occupied by WINDOW is rounded
+internally.  This is done in a way such that, if WINDOW is a parent
+window, the sum of the total widths of all its children internally
+equals the total width of WINDOW.
+
+If the optional argument ROUND is `ceiling', return the smallest integer
+larger than WINDOW's pixel width divided by the character width of
+WINDOW's frame.  ROUND `floor' means to return the largest integer
+smaller than WINDOW's pixel width divided by the character width of
+WINDOW's frame.  Any other value of ROUND means to return the internal
+total width of WINDOW.  */)
+  (Lisp_Object window, Lisp_Object round)
 {
-  return make_number (decode_valid_window (window)->total_cols);
+  struct window *w = decode_valid_window (window);
+
+  if (! EQ (round, Qfloor) && ! EQ (round, Qceiling))
+    return make_number (w->total_cols);
+  else
+    {
+      int unit = FRAME_COLUMN_WIDTH (WINDOW_XFRAME (w));
+
+      return make_number (EQ (round, Qceiling)
+                         ? ((w->pixel_width + unit - 1) /unit)
+                         : (w->pixel_width / unit));
+    }
 }
 
 DEFUN ("window-new-total", Fwindow_new_total, Swindow_new_total, 0, 1, 0,
        doc: /* Return the new total size of window WINDOW.
-WINDOW must be a valid window and defaults to the selected one.  */)
+WINDOW must be a valid window and defaults to the selected one.
+
+The new total size of WINDOW is the value set by the last call of
+`set-window-new-total' for WINDOW.  If it is valid, it will be shortly
+installed as WINDOW's total height (see `window-total-height') or total
+width (see `window-total-width').  */)
   (Lisp_Object window)
 {
   return decode_valid_window (window)->new_total;
@@ -746,7 +824,25 @@ WINDOW must be a valid window and defaults to the selected one.  */)
 DEFUN ("window-normal-size", Fwindow_normal_size, Swindow_normal_size, 0, 2, 0,
        doc: /* Return the normal height of window WINDOW.
 WINDOW must be a valid window and defaults to the selected one.
-If HORIZONTAL is non-nil, return the normal width of WINDOW.  */)
+If HORIZONTAL is non-nil, return the normal width of WINDOW.
+
+The normal height of a frame's root window or a window that is
+horizontally combined (a window that has a left or right sibling) is
+1.0.  The normal height of a window that is vertically combined (has a
+sibling above or below) is the fraction of the window's height with
+respect to its parent.  The sum of the normal heights of all windows in a
+vertical combination equals 1.0.
+
+Similarly, the normal width of a frame's root window or a window that is
+vertically combined equals 1.0.  The normal width of a window that is
+horizontally combined is the fraction of the window's width with respect
+to its parent.  The sum of the normal widths of all windows in a
+horizontal combination equals 1.0.
+
+The normal sizes of windows are used to restore the proportional sizes
+of windows after they have been shrunk to their minimum sizes; for
+example when a frame is temporarily made very small and afterwards gets
+re-enlarged to its previous size.  */)
   (Lisp_Object window, Lisp_Object horizontal)
 {
   struct window *w = decode_valid_window (window);
@@ -756,7 +852,11 @@ If HORIZONTAL is non-nil, return the normal width of WINDOW.  */)
 
 DEFUN ("window-new-normal", Fwindow_new_normal, Swindow_new_normal, 0, 1, 0,
        doc: /* Return new normal size of window WINDOW.
-WINDOW must be a valid window and defaults to the selected one.  */)
+WINDOW must be a valid window and defaults to the selected one.
+
+The new normal size of WINDOW is the value set by the last call of
+`set-window-new-normal' for WINDOW.  If valid, it will be shortly
+installed as WINDOW's normal size (see `window-normal-size').  */)
   (Lisp_Object window)
 {
   return decode_valid_window (window)->new_normal;
@@ -764,7 +864,12 @@ WINDOW must be a valid window and defaults to the selected one.  */)
 
 DEFUN ("window-new-pixel", Fwindow_new_pixel, Swindow_new_pixel, 0, 1, 0,
        doc: /* Return new pixel size of window WINDOW.
-WINDOW must be a valid window and defaults to the selected one.  */)
+WINDOW must be a valid window and defaults to the selected one.
+
+The new pixel size of WINDOW is the value set by the last call of
+`set-window-new-pixel' for WINDOW.  If it is valid, it will be shortly
+installed as WINDOW's pixel height (see `window-pixel-height') or pixel
+width (see `window-pixel-width').  */)
   (Lisp_Object window)
 {
   return decode_valid_window (window)->new_pixel;
@@ -810,62 +915,69 @@ WINDOW must be a valid window and defaults to the selected one.  */)
   return make_number (decode_valid_window (window)->top_line);
 }
 
-/* Return the number of lines of W's body.  Don't count any mode or
-   header line of W.  */
-
+/* Return the number of lines/pixels of W's body.  Don't count any mode
+   or header line or horizontal divider of W.  Rounds down to nearest
+   integer when not working pixelwise. */
 static int
 window_body_height (struct window *w, bool pixelwise)
 {
-  int pixels = (w->pixel_height
-               - WINDOW_BOTTOM_DIVIDER_WIDTH (w)
+  int height = (w->pixel_height
                - WINDOW_HEADER_LINE_HEIGHT (w)
-               - WINDOW_MODE_LINE_HEIGHT (w));
-  int unit = FRAME_LINE_HEIGHT (WINDOW_XFRAME (w));
-
-  return pixelwise ? pixels : ((pixels + unit - 1) / unit);
-}
-
-/* Return the number of columns of W's body.  Don't count columns
-   occupied by the scroll bar or the vertical bar separating W from its
-   right sibling.  On window-systems don't count fringes or display
-   margins either.  */
+               - (WINDOW_HAS_HORIZONTAL_SCROLL_BAR (w)
+                  ? WINDOW_SCROLL_BAR_AREA_HEIGHT (w)
+                  : 0)
+               - WINDOW_MODE_LINE_HEIGHT (w)
+               - WINDOW_BOTTOM_DIVIDER_WIDTH (w));
+
+  /* Don't return a negative value.  */
+  return max (pixelwise
+             ? height
+             : height / FRAME_LINE_HEIGHT (WINDOW_XFRAME (w)),
+             0);
+}
+
+/* Return the number of columns/pixels of W's body.  Don't count columns
+   occupied by the scroll bar or the divider/vertical bar separating W
+   from its right sibling or margins.  On window-systems don't count
+   fringes either.  Round down to nearest integer when not working
+   pixelwise.  */
 int
 window_body_width (struct window *w, bool pixelwise)
 {
   struct frame *f = XFRAME (WINDOW_FRAME (w));
 
-  int pixels = (w->pixel_width
-               - WINDOW_RIGHT_DIVIDER_WIDTH (w)
-               - (WINDOW_HAS_VERTICAL_SCROLL_BAR (w)
-                  ? WINDOW_SCROLL_BAR_AREA_WIDTH (w)
-                  : ((!FRAME_WINDOW_P (f)
-                      && !WINDOW_RIGHTMOST_P (w)
-                      && !WINDOW_RIGHT_DIVIDER_WIDTH (w)
-                      && !WINDOW_FULL_WIDTH_P (w))
-                     /* According to Eli this is either 1 or 0.  */
-                     ? 1 : 0))
+  int width = (w->pixel_width
+              - WINDOW_RIGHT_DIVIDER_WIDTH (w)
+              - (WINDOW_HAS_VERTICAL_SCROLL_BAR (w)
+                 ? WINDOW_SCROLL_BAR_AREA_WIDTH (w)
+                 : ((!FRAME_WINDOW_P (f)
+                     && !WINDOW_RIGHTMOST_P (w)
+                     && !WINDOW_RIGHT_DIVIDER_WIDTH (w))
+                    /* A vertical bar is either 1 or 0.  */
+                    ? 1 : 0))
                - WINDOW_MARGINS_WIDTH (w)
                - (FRAME_WINDOW_P (f)
                   ? WINDOW_FRINGES_WIDTH (w)
                   : 0));
-  int unit = FRAME_COLUMN_WIDTH (WINDOW_XFRAME (w));
 
-  return pixelwise ? pixels : ((pixels + unit - 1) / unit);
+  /* Don't return a negative value.  */
+  return max (pixelwise
+             ? width
+             : width / FRAME_COLUMN_WIDTH (WINDOW_XFRAME (w)),
+             0);
 }
 
 DEFUN ("window-body-height", Fwindow_body_height, Swindow_body_height, 0, 2, 0,
-       doc: /* Return the height, in lines, of WINDOW's text area.
-WINDOW must be a live window and defaults to the selected one.
-
-Optional argument PIXELWISE non-nil means return the height in pixels.
-
-The returned height does not include the mode line or header line.  On a
-graphical display, the height is expressed as an integer multiple of the
-default character height if PIXELWISE is nil.
-
-If PIXELWISE is nil and a line at the bottom of the text area is only
-partially visible, that counts as a whole line; to exclude
-partially-visible lines, use `window-text-height'.  */)
+       doc: /* Return the height of WINDOW's text area.
+WINDOW must be a live window and defaults to the selected one.  Optional
+argument PIXELWISE non-nil means return the height of WINDOW's text area
+in pixels.  The return value does not include the mode line or header
+line or any horizontal divider.
+
+If PIXELWISE is nil, return the largest integer smaller than WINDOW's
+pixel height divided by the character height of WINDOW's frame.  This
+means that if a line at the bottom of the text area is only partially
+visible, that line is not counted.  */)
   (Lisp_Object window, Lisp_Object pixelwise)
 {
   return make_number (window_body_height (decode_live_window (window),
@@ -873,19 +985,16 @@ partially-visible lines, use `window-text-height'.  */)
 }
 
 DEFUN ("window-body-width", Fwindow_body_width, Swindow_body_width, 0, 2, 0,
-       doc: /* Return the width, in columns, of WINDOW's text area.
-WINDOW must be a live window and defaults to the selected one.
-
-Optional argument PIXELWISE non-nil means return the width in pixels.
-
-The return value does not include any vertical dividers, fringe or
-marginal areas, or scroll bars.  On a graphical display, the width is
-expressed as an integer multiple of the default character width if
-PIXELWISE is nil.
-
-If PIXELWISE is nil and a column at the right of the text area is only
-partially visible, that counts as a whole column; to exclude
-partially-visible columns, use `window-text-width'.  */)
+       doc: /* Return the width of WINDOW's text area.
+WINDOW must be a live window and defaults to the selected one.  Optional
+argument PIXELWISE non-nil means return the width in pixels.  The return
+value does not include any vertical dividers, fringes or marginal areas,
+or scroll bars.
+
+If PIXELWISE is nil, return the largest integer smaller than WINDOW's
+pixel width divided by the character width of WINDOW's frame.  This
+means that if a column at the right of the text area is only partially
+visible, that column is not counted.  */)
   (Lisp_Object window, Lisp_Object pixelwise)
 {
   return make_number (window_body_width (decode_live_window (window),
@@ -894,7 +1003,7 @@ partially-visible columns, use `window-text-width'.  */)
 
 DEFUN ("window-mode-line-height", Fwindow_mode_line_height,
        Swindow_mode_line_height, 0, 1, 0,
-       doc: /* Return the height in pixel of WINDOW's mode-line.
+       doc: /* Return the height in pixels of WINDOW's mode-line.
 WINDOW must be a live window and defaults to the selected one.  */)
   (Lisp_Object window)
 {
@@ -903,7 +1012,7 @@ WINDOW must be a live window and defaults to the selected one.  */)
 
 DEFUN ("window-header-line-height", Fwindow_header_line_height,
        Swindow_header_line_height, 0, 1, 0,
-       doc: /* Return the height in pixel of WINDOW's header-line.
+       doc: /* Return the height in pixels of WINDOW's header-line.
 WINDOW must be a live window and defaults to the selected one.  */)
   (Lisp_Object window)
 {
@@ -912,7 +1021,7 @@ WINDOW must be a live window and defaults to the selected one.  */)
 
 DEFUN ("window-right-divider-width", Fwindow_right_divider_width,
        Swindow_right_divider_width, 0, 1, 0,
-       doc: /* Return the width of WINDOW's right divider.
+       doc: /* Return the width in pixels of WINDOW's right divider.
 WINDOW must be a live window and defaults to the selected one.  */)
   (Lisp_Object window)
 {
@@ -921,13 +1030,31 @@ WINDOW must be a live window and defaults to the selected one.  */)
 
 DEFUN ("window-bottom-divider-width", Fwindow_bottom_divider_width,
        Swindow_bottom_divider_width, 0, 1, 0,
-       doc: /* Return the width of WINDOW's bottom divider.
+       doc: /* Return the width in pixels of WINDOW's bottom divider.
 WINDOW must be a live window and defaults to the selected one.  */)
   (Lisp_Object window)
 {
   return (make_number (WINDOW_BOTTOM_DIVIDER_WIDTH (decode_live_window (window))));
 }
 
+DEFUN ("window-scroll-bar-width", Fwindow_scroll_bar_width,
+       Swindow_scroll_bar_width, 0, 1, 0,
+       doc: /* Return the width in pixels of WINDOW's vertical scrollbar.
+WINDOW must be a live window and defaults to the selected one.  */)
+  (Lisp_Object window)
+{
+  return (make_number (WINDOW_SCROLL_BAR_AREA_WIDTH (decode_live_window (window))));
+}
+
+DEFUN ("window-scroll-bar-height", Fwindow_scroll_bar_height,
+       Swindow_scroll_bar_height, 0, 1, 0,
+       doc: /* Return the height in pixels of WINDOW's horizontal scrollbar.
+WINDOW must be a live window and defaults to the selected one.  */)
+  (Lisp_Object window)
+{
+  return (make_number (WINDOW_SCROLL_BAR_AREA_HEIGHT (decode_live_window (window))));
+}
+
 DEFUN ("window-hscroll", Fwindow_hscroll, Swindow_hscroll, 0, 1, 0,
        doc: /* Return the number of columns by which WINDOW is scrolled from left margin.
 WINDOW must be a live window and defaults to the selected one.  */)
@@ -955,6 +1082,8 @@ set_window_hscroll (struct window *w, EMACS_INT hscroll)
     XBUFFER (w->contents)->prevent_redisplay_optimizations_p = 1;
 
   w->hscroll = new_hscroll;
+  w->suspend_auto_hscroll = 1;
+
   return make_number (new_hscroll);
 }
 
@@ -1104,12 +1233,16 @@ display margins, fringes, header line, and/or mode line.  */)
 
   return list4i ((WINDOW_BOX_LEFT_EDGE_COL (w)
                  + WINDOW_LEFT_MARGIN_COLS (w)
-                 + WINDOW_LEFT_FRINGE_COLS (w)),
+                 + ((WINDOW_LEFT_FRINGE_WIDTH (w)
+                     + WINDOW_FRAME_COLUMN_WIDTH (w) - 1)
+                    / WINDOW_FRAME_COLUMN_WIDTH (w))),
                 (WINDOW_TOP_EDGE_LINE (w)
                  + WINDOW_HEADER_LINE_LINES (w)),
                 (WINDOW_BOX_RIGHT_EDGE_COL (w)
                  - WINDOW_RIGHT_MARGIN_COLS (w)
-                 - WINDOW_RIGHT_FRINGE_COLS (w)),
+                 - ((WINDOW_RIGHT_FRINGE_WIDTH (w)
+                     + WINDOW_FRAME_COLUMN_WIDTH (w) - 1)
+                    / WINDOW_FRAME_COLUMN_WIDTH (w))),
                 (WINDOW_BOTTOM_EDGE_LINE (w)
                  - WINDOW_MODE_LINE_LINES (w)));
 }
@@ -1211,18 +1344,29 @@ coordinates_in_window (register struct window *w, int x, int y)
   if (y < top_y || y >= bottom_y || x < left_x || x >= right_x)
     return ON_NOTHING;
 
-  /* On vertical window divider (which prevails horizontal
-     dividers)?  */
-  if (!WINDOW_RIGHTMOST_P (w)
-      && WINDOW_RIGHT_DIVIDER_WIDTH (w)
-      && x >= right_x - WINDOW_RIGHT_DIVIDER_WIDTH (w)
-      && x <= right_x)
-    return ON_RIGHT_DIVIDER;
-  /* On the horizontal window divider?  */
-  else if (WINDOW_BOTTOM_DIVIDER_WIDTH (w)
-          && y >= (bottom_y - WINDOW_BOTTOM_DIVIDER_WIDTH (w))
-          && y <= bottom_y)
+  /* On the horizontal window divider (which prevails the vertical
+     divider)?  */
+  if (WINDOW_BOTTOM_DIVIDER_WIDTH (w) > 0
+      && y >= (bottom_y - WINDOW_BOTTOM_DIVIDER_WIDTH (w))
+      && y <= bottom_y)
     return ON_BOTTOM_DIVIDER;
+  /* On vertical window divider?  */
+  else if (!WINDOW_RIGHTMOST_P (w)
+          && WINDOW_RIGHT_DIVIDER_WIDTH (w) > 0
+          && x >= right_x - WINDOW_RIGHT_DIVIDER_WIDTH (w)
+          && x <= right_x)
+    return ON_RIGHT_DIVIDER;
+  /* On the horizontal scroll bar?  (Including the empty space at its
+     right!)  */
+  else if ((WINDOW_HAS_HORIZONTAL_SCROLL_BAR (w)
+           && y >= (bottom_y
+                    - WINDOW_SCROLL_BAR_AREA_HEIGHT (w)
+                    - CURRENT_MODE_LINE_HEIGHT (w)
+                    - WINDOW_BOTTOM_DIVIDER_WIDTH (w))
+           && y <= (bottom_y
+                    - CURRENT_MODE_LINE_HEIGHT (w)
+                    - WINDOW_BOTTOM_DIVIDER_WIDTH (w))))
+    return ON_HORIZONTAL_SCROLL_BAR;
   /* On the mode or header line?   */
   else if ((WINDOW_WANTS_MODELINE_P (w)
            && y >= (bottom_y
@@ -1239,12 +1383,13 @@ coordinates_in_window (register struct window *w, int x, int y)
         resize windows horizontally in case we're using toolkit scroll
         bars.  Note: If scrollbars are on the left, the window that
         must be eventually resized is that on the left of WINDOW.  */
-      if ((WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w)
-          && !WINDOW_LEFTMOST_P (w)
-          && eabs (x - left_x) < grabbable_width)
-         || (!WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w)
-             && !WINDOW_RIGHTMOST_P (w)
-             && eabs (x - right_x) < grabbable_width))
+      if ((WINDOW_RIGHT_DIVIDER_WIDTH (w) == 0)
+         && ((WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w)
+              && !WINDOW_LEFTMOST_P (w)
+              && eabs (x - left_x) < grabbable_width)
+             || (!WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w)
+                 && !WINDOW_RIGHTMOST_P (w)
+                 && eabs (x - right_x) < grabbable_width)))
        return ON_VERTICAL_BORDER;
       else
        return part;
@@ -1265,7 +1410,7 @@ coordinates_in_window (register struct window *w, int x, int y)
 
   /* Outside any interesting column?  */
   if (x < left_x || x > right_x)
-    return ON_SCROLL_BAR;
+    return ON_VERTICAL_SCROLL_BAR;
 
   lmargin_width = window_box_width (w, LEFT_MARGIN_AREA);
   rmargin_width = window_box_width (w, RIGHT_MARGIN_AREA);
@@ -1276,6 +1421,7 @@ coordinates_in_window (register struct window *w, int x, int y)
   if (FRAME_WINDOW_P (f))
     {
       if (!w->pseudo_window_p
+         && WINDOW_RIGHT_DIVIDER_WIDTH (w) == 0
          && !WINDOW_HAS_VERTICAL_SCROLL_BAR (w)
          && !WINDOW_RIGHTMOST_P (w)
          && (eabs (x - right_x) < grabbable_width))
@@ -1284,6 +1430,7 @@ coordinates_in_window (register struct window *w, int x, int y)
   /* Need to say "x > right_x" rather than >=, since on character
      terminals, the vertical line's x coordinate is right_x.  */
   else if (!w->pseudo_window_p
+          && WINDOW_RIGHT_DIVIDER_WIDTH (w) == 0
           && !WINDOW_RIGHTMOST_P (w)
           /* Why check ux if we are not the rightmost window?  Also
              shouldn't a pseudo window always be rightmost?  */
@@ -1297,8 +1444,8 @@ coordinates_in_window (register struct window *w, int x, int y)
              ? (x >= left_x + WINDOW_LEFT_FRINGE_WIDTH (w))
              : (x < left_x + lmargin_width)))
        return ON_LEFT_MARGIN;
-
-      return ON_LEFT_FRINGE;
+      else
+       return ON_LEFT_FRINGE;
     }
 
   if (x >= text_right)
@@ -1308,8 +1455,8 @@ coordinates_in_window (register struct window *w, int x, int y)
              ? (x < right_x - WINDOW_RIGHT_FRINGE_WIDTH (w))
              : (x >= right_x - rmargin_width)))
        return ON_RIGHT_MARGIN;
-
-      return ON_RIGHT_FRINGE;
+      else
+       return ON_RIGHT_FRINGE;
     }
 
   /* Everything special ruled out - must be on text area */
@@ -1328,6 +1475,8 @@ window_relative_x_coord (struct window *w, enum window_part part, int x)
     case ON_TEXT:
       return x - window_box_left (w, TEXT_AREA);
 
+    case ON_HEADER_LINE:
+    case ON_MODE_LINE:
     case ON_LEFT_FRINGE:
       return x - left_x;
 
@@ -1364,8 +1513,10 @@ measured in characters from the upper-left corner of the frame.
 frame.
 If COORDINATES are in the text portion of WINDOW,
    the coordinates relative to the window are returned.
+If they are in the bottom divider of WINDOW, `bottom-divider' is returned.
+If they are in the right divider of WINDOW, `right-divider' is returned.
 If they are in the mode line of WINDOW, `mode-line' is returned.
-If they are in the top mode line of WINDOW, `header-line' is returned.
+If they are in the header line of WINDOW, `header-line' is returned.
 If they are in the left fringe of WINDOW, `left-fringe' is returned.
 If they are in the right fringe of WINDOW, `right-fringe' is returned.
 If they are on the border between WINDOW and its right sibling,
@@ -1423,10 +1574,13 @@ If they are in the windows's left or right marginal areas, `left-margin'\n\
     case ON_RIGHT_MARGIN:
       return Qright_margin;
 
-    case ON_SCROLL_BAR:
+    case ON_VERTICAL_SCROLL_BAR:
       /* Historically we are supposed to return nil in this case.  */
       return Qnil;
 
+    case ON_HORIZONTAL_SCROLL_BAR:
+      return Qnil;
+
     case ON_RIGHT_DIVIDER:
       return Qright_divider;
 
@@ -1567,6 +1721,14 @@ correct to return the top-level value of `point', outside of any
     return Fmarker_position (w->pointm);
 }
 
+DEFUN ("window-old-point", Fwindow_old_point, Swindow_old_point, 0, 1, 0,
+       doc: /* Return old value of point in WINDOW.
+WINDOW must be a live window and defaults to the selected one.  */)
+  (Lisp_Object window)
+{
+  return Fmarker_position (decode_live_window (window)->old_pointm);
+}
+
 DEFUN ("window-start", Fwindow_start, Swindow_start, 0, 1, 0,
        doc: /* Return position at which display currently starts in WINDOW.
 WINDOW must be a live window and defaults to the selected one.
@@ -1683,7 +1845,7 @@ Return POS.  */)
       set_marker_restricted (w->pointm, pos, w->contents);
       /* We have to make sure that redisplay updates the window to show
         the new value of point.  */
-      windows_or_buffers_changed = 25;
+      wset_redisplay (w);
     }
 
   return pos;
@@ -1706,8 +1868,7 @@ overriding motion of point in order to display at this exact start.  */)
   w->update_mode_line = 1;
   /* Bug#15957.  */
   w->window_end_valid = 0;
-  if (w != XWINDOW (selected_window))
-    wset_redisplay (w);
+  wset_redisplay (w);
 
   return pos;
 }
@@ -2846,6 +3007,7 @@ selected frame and no others.  */)
     return Qnil;
 }
 
+
 static Lisp_Object
 resize_root_window (Lisp_Object window, Lisp_Object delta, Lisp_Object horizontal, Lisp_Object ignore, Lisp_Object pixelwise)
 {
@@ -2853,10 +3015,17 @@ resize_root_window (Lisp_Object window, Lisp_Object delta, Lisp_Object horizonta
 }
 
 
+Lisp_Object
+sanitize_window_sizes (Lisp_Object frame, Lisp_Object horizontal)
+{
+  return call2 (Qwindow_sanitize_window_sizes, frame, horizontal);
+}
+
+
 static Lisp_Object
 window_pixel_to_total (Lisp_Object frame, Lisp_Object horizontal)
 {
-  return call2(Qwindow_pixel_to_total, frame, horizontal);
+  return call2 (Qwindow_pixel_to_total, frame, horizontal);
 }
 
 
@@ -2979,7 +3148,7 @@ window-start value is reasonable when this function is called.  */)
     }
   free_window_matrices (r);
 
-  windows_or_buffers_changed = 27;
+  fset_redisplay (f);
   Vwindow_list = Qnil;
   FRAME_WINDOW_SIZES_CHANGED (f) = 1;
   resize_failed = 0;
@@ -3135,88 +3304,6 @@ replace_buffer_in_windows_safely (Lisp_Object buffer)
        window_loop (REPLACE_BUFFER_IN_WINDOWS_SAFELY, buffer, 1, frame);
     }
 }
-
-/* If *HEIGHT or *WIDTH are too small a size for FRAME, set them to the
-   minimum allowable size.  PIXELWISE means interpret these as pixel
-   sizes.  */
-
-void
-check_frame_size (struct frame *frame, int *width, int *height, bool pixelwise)
-{
-  /* For height, we have to see:
-     how many windows the frame has at minimum (one or two),
-     and whether it has a menu bar or other special stuff at the top.  */
-  if (pixelwise)
-    {
-      int min_height = MIN_SAFE_WINDOW_HEIGHT * FRAME_LINE_HEIGHT (frame);
-      int min_width = MIN_SAFE_WINDOW_WIDTH * FRAME_COLUMN_WIDTH (frame);
-
-      if (!FRAME_MINIBUF_ONLY_P (frame) && FRAME_HAS_MINIBUF_P (frame))
-       min_height = 2 * min_height;
-
-      min_height += FRAME_TOP_MARGIN_HEIGHT (frame);
-
-      if (*height < min_height)
-       *height = min_height;
-      if (*width < min_width)
-       *width = min_width;
-    }
-  else
-    {
-      int min_height
-       = ((FRAME_MINIBUF_ONLY_P (frame) || ! FRAME_HAS_MINIBUF_P (frame))
-          ? MIN_SAFE_WINDOW_HEIGHT
-          : 2 * MIN_SAFE_WINDOW_HEIGHT);
-
-      if (FRAME_TOP_MARGIN (frame) > 0)
-       min_height += FRAME_TOP_MARGIN (frame);
-
-      if (*height < min_height)
-       *height = min_height;
-      if (*width  < MIN_SAFE_WINDOW_WIDTH)
-       *width = MIN_SAFE_WINDOW_WIDTH;
-    }
-}
-
-/* Adjust the margins of window W if text area is too small.
-   Return 1 if window width is ok after adjustment; 0 if window
-   is still too narrow.  */
-
-static int
-adjust_window_margins (struct window *w)
-{
-  int box_width = (WINDOW_PIXEL_WIDTH (w)
-                  - WINDOW_FRINGES_WIDTH (w)
-                  - WINDOW_SCROLL_BAR_AREA_WIDTH (w));
-  int margin_width = WINDOW_MARGINS_WIDTH (w);
-
-  if (box_width - margin_width >= MIN_SAFE_WINDOW_PIXEL_WIDTH (w))
-    return 1;
-
-  if (margin_width < 0 || box_width < MIN_SAFE_WINDOW_PIXEL_WIDTH (w))
-    return 0;
-  else
-    /* Window's text area is too narrow, but reducing the window
-       margins will fix that.  */
-    {
-      int unit = WINDOW_FRAME_COLUMN_WIDTH (w);
-
-      margin_width = box_width - MIN_SAFE_WINDOW_PIXEL_WIDTH (w);
-
-      if (WINDOW_RIGHT_MARGIN_WIDTH (w) > 0)
-       {
-         if (WINDOW_LEFT_MARGIN_WIDTH (w) > 0)
-           w->left_margin_cols = w->right_margin_cols =
-             margin_width / (2 * unit);
-         else
-           w->right_margin_cols = margin_width / unit;
-       }
-      else
-       w->left_margin_cols = margin_width / unit;
-
-      return 1;
-    }
-}
 \f
 /* The following three routines are needed for running a window's
    configuration change hook.  */
@@ -3250,7 +3337,7 @@ run_window_configuration_change_hook (struct frame *f)
     = Fdefault_value (Qwindow_configuration_change_hook);
   XSETFRAME (frame, f);
 
-  if (NILP (Vrun_hooks) || !NILP (inhibit_lisp_code))
+  if (NILP (Vrun_hooks) || !(f->official))
     return;
 
   /* Use the right buffer.  Matters when running the local hooks.  */
@@ -3345,17 +3432,21 @@ set_window_buffer (Lisp_Object window, Lisp_Object buffer,
   w->last_cursor_vpos = 0;
 
   if (!(keep_margins_p && samebuf))
-    { /* If we're not actually changing the buffer, don't reset hscroll and
-        vscroll.  This case happens for example when called from
+    { /* 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)
-        just in order to run window-configuration-change-hook.
-        Resetting hscroll and vscroll here is problematic for things like
-        image-mode and doc-view-mode since it resets the image's position
-        whenever we resize the frame.  */
-      w->hscroll = w->min_hscroll = 0;
+        Fset_window_buffer on the frame's selected window (and no
+        other) just in order to run window-configuration-change-hook
+        (no longer true since change_frame_size_1 directly calls
+        run_window_configuration_change_hook).  Resetting hscroll and
+        vscroll here is problematic for things like image-mode and
+        doc-view-mode since it resets the image's position whenever we
+        resize the frame.  */
+      w->hscroll = w->min_hscroll = w->hscroll_whole = 0;
+      w->suspend_auto_hscroll = 0;
       w->vscroll = 0;
       set_marker_both (w->pointm, buffer, BUF_PT (b), BUF_PT_BYTE (b));
+      set_marker_both (w->old_pointm, buffer, BUF_PT (b), BUF_PT_BYTE (b));
       set_marker_restricted (w->start,
                             make_number (b->last_window_start),
                             buffer);
@@ -3364,18 +3455,16 @@ set_window_buffer (Lisp_Object window, Lisp_Object buffer,
     }
   /* Maybe we could move this into the `if' but it's not obviously safe and
      I doubt it's worth the trouble.  */
-  windows_or_buffers_changed = 28;
+  wset_redisplay (w);
+  w->update_mode_line = true;
 
-  /* 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.  */
-  if (window_initialized)
-    {
-      record_unwind_current_buffer ();
-      Fset_buffer (buffer);
-    }
+  /* We must select BUFFER to run the window-scroll-functions and to look up
+     the buffer-local value of Vwindow_point_insertion_type.  */
+  record_unwind_current_buffer ();
+  Fset_buffer (buffer);
 
   XMARKER (w->pointm)->insertion_type = !NILP (Vwindow_point_insertion_type);
+  XMARKER (w->old_pointm)->insertion_type = !NILP (Vwindow_point_insertion_type);
 
   if (!keep_margins_p)
     {
@@ -3384,7 +3473,9 @@ set_window_buffer (Lisp_Object window, Lisp_Object buffer,
                          BVAR (b, right_fringe_width),
                          BVAR (b, fringes_outside_margins));
       set_window_scroll_bars (w, BVAR (b, scroll_bar_width),
-                             BVAR (b, vertical_scroll_bar_type), Qnil);
+                             BVAR (b, vertical_scroll_bar_type),
+                             BVAR (b, scroll_bar_height),
+                             BVAR (b, horizontal_scroll_bar_type));
       set_window_margins (w, BVAR (b, left_margin_cols),
                          BVAR (b, right_margin_cols));
       apply_window_adjustment (w);
@@ -3530,10 +3621,11 @@ temp_output_buffer_show (register Lisp_Object buf)
        Fmake_frame_visible (WINDOW_FRAME (XWINDOW (window)));
       Vminibuf_scroll_window = window;
       w = XWINDOW (window);
-      w->hscroll = 0;
-      w->min_hscroll = 0;
+      w->hscroll = w->min_hscroll = w->hscroll_whole = 0;
+      w->suspend_auto_hscroll = 0;
       set_marker_restricted_both (w->start, buf, BEG, BEG);
       set_marker_restricted_both (w->pointm, buf, BEG, BEG);
+      set_marker_restricted_both (w->old_pointm, buf, BEG, BEG);
 
       /* Run temp-buffer-show-hook, with the chosen window selected
         and its buffer current.  */
@@ -3585,6 +3677,7 @@ make_parent_window (Lisp_Object window, bool horflag)
   /* ...but now P becomes an internal window.  */
   wset_start (p, Qnil);
   wset_pointm (p, Qnil);
+  wset_old_pointm (p, Qnil);
   wset_buffer (p, Qnil);
   wset_combination (p, horflag, window);
   wset_combination_limit (p, Qnil);
@@ -3608,7 +3701,9 @@ make_window (void)
   wset_new_pixel (w, make_number (0));
   wset_start (w, Fmake_marker ());
   wset_pointm (w, Fmake_marker ());
+  wset_old_pointm (w, Fmake_marker ());
   wset_vertical_scroll_bar_type (w, Qt);
+  wset_horizontal_scroll_bar_type (w, Qt);
   /* These Lisp fields are marked specially so they're not set to nil by
      allocate_window.  */
   wset_prev_buffers (w, Qnil);
@@ -3625,8 +3720,8 @@ make_window (void)
 #endif
   w->sequence_number = ++sequence_number;
   w->scroll_bar_width = -1;
+  w->scroll_bar_height = -1;
   w->column_number_displayed = -1;
-
   /* Reset window_list.  */
   Vwindow_list = Qnil;
   /* Return window.  */
@@ -3642,14 +3737,18 @@ Return SIZE.
 Optional argument ADD non-nil means add SIZE to the new pixel size of
 WINDOW and return the sum.
 
+The new pixel size of WINDOW, if valid, will be shortly installed as
+WINDOW's pixel height (see `window-pixel-height') or pixel width (see
+`window-pixel-width').
+
 Note: This function does not operate on any child windows of WINDOW.  */)
   (Lisp_Object window, Lisp_Object size, Lisp_Object add)
 {
   struct window *w = decode_valid_window (window);
-  EMACS_INT size_max = (min (INT_MAX, MOST_POSITIVE_FIXNUM)
-                       - (NILP (add) ? 0 : XINT (w->new_pixel)));
+  EMACS_INT size_min = NILP (add) ? 0 : - XINT (w->new_pixel);
+  EMACS_INT size_max = size_min + min (INT_MAX, MOST_POSITIVE_FIXNUM);
 
-  CHECK_RANGED_INTEGER (size, 0, size_max);
+  CHECK_RANGED_INTEGER (size, size_min, size_max);
   if (NILP (add))
     wset_new_pixel (w, size);
   else
@@ -3666,6 +3765,10 @@ Return SIZE.
 Optional argument ADD non-nil means add SIZE to the new total size of
 WINDOW and return the sum.
 
+The new total size of WINDOW, if valid, will be shortly installed as
+WINDOW's total height (see `window-total-height') or total width (see
+`window-total-width').
+
 Note: This function does not operate on any child windows of WINDOW.  */)
      (Lisp_Object window, Lisp_Object size, Lisp_Object add)
 {
@@ -3685,6 +3788,9 @@ DEFUN ("set-window-new-normal", Fset_window_new_normal, Sset_window_new_normal,
 WINDOW must be a valid window and defaults to the selected one.
 Return SIZE.
 
+The new normal size of WINDOW, if valid, will be shortly installed as
+WINDOW's normal size (see `window-normal-size').
+
 Note: This function does not operate on any child windows of WINDOW.  */)
      (Lisp_Object window, Lisp_Object size)
 {
@@ -3727,18 +3833,20 @@ window_resize_check (struct window *w, bool horflag)
        /* The sum of the heights of the child windows of W must equal
           W's height.  */
        {
-         int sum_of_pixels = 0;
+         int remaining_pixels = XINT (w->new_pixel);
 
          while (c)
            {
              if (!window_resize_check (c, horflag))
                return 0;
 
-             sum_of_pixels = sum_of_pixels + XINT (c->new_pixel);
+             remaining_pixels -= XINT (c->new_pixel);
+             if (remaining_pixels < 0)
+               return 0;
              c = NILP (c->next) ? 0 : XWINDOW (c->next);
            }
 
-         return (sum_of_pixels == XINT (w->new_pixel));
+         return remaining_pixels == 0;
        }
     }
   else if (WINDOW_HORIZONTAL_COMBINATION_P (w))
@@ -3749,18 +3857,20 @@ window_resize_check (struct window *w, bool horflag)
        /* The sum of the widths of the child windows of W must equal W's
           width.  */
        {
-         int sum_of_pixels = 0;
+         int remaining_pixels = XINT (w->new_pixel);
 
          while (c)
            {
              if (!window_resize_check (c, horflag))
                return 0;
 
-             sum_of_pixels = sum_of_pixels + XINT (c->new_pixel);
+             remaining_pixels -= XINT (c->new_pixel);
+             if (remaining_pixels < 0)
+               return 0;
              c = NILP (c->next) ? 0 : XWINDOW (c->next);
            }
 
-         return (sum_of_pixels == XINT (w->new_pixel));
+         return remaining_pixels == 0;
        }
       else
        /* All child windows of W must have the same height as W.  */
@@ -3787,7 +3897,7 @@ window_resize_check (struct window *w, bool horflag)
 }
 
 
-/* Set w->pixel_height (w->pixel_height if HORIZONTAL is non-zero) to
+/* Set w->pixel_height (w->pixel_width if HORFLAG is non-zero) to
    w->new_pixel for window W and recursively all child windows of W.
    Also calculate and assign the new vertical (horizontal) pixel start
    positions of each of these windows.
@@ -3877,7 +3987,7 @@ window_resize_apply (struct window *w, bool horflag)
 }
 
 
-/* Set w->total_lines (w->total_cols if HORIZONTAL is non-zero) to
+/* Set w->total_lines (w->total_cols if HORFLAG is non-zero) to
    w->new_total for window W and recursively all child windows of W.
    Also calculate and assign the new vertical (horizontal) start
    positions of each of these windows.  */
@@ -3945,9 +4055,14 @@ If FRAME is omitted or nil, it defaults to the selected frame.
 Optional argument HORIZONTAL omitted or nil means apply requested
 height values.  HORIZONTAL non-nil means apply requested width values.
 
-This function checks whether the requested values sum up to a valid
-window layout, recursively assigns the new sizes of all child windows
-and calculates and assigns the new start positions of these windows.
+The requested size values are those set by `set-window-new-pixel' and
+`set-window-new-normal'.  This function checks whether the requested
+values sum up to a valid window layout, recursively assigns the new
+sizes of all child windows and calculates and assigns the new start
+positions of these windows.
+
+Return t if the requested values have been applied correctly, nil
+otherwise.
 
 Note: This function does not check any of `window-fixed-size-p',
 `window-min-height' or `window-min-width'.  All these checks have to
@@ -3966,7 +4081,7 @@ be applied on the Elisp level.  */)
   block_input ();
   window_resize_apply (r, horflag);
 
-  windows_or_buffers_changed = 30;
+  fset_redisplay (f);
   FRAME_WINDOW_SIZES_CHANGED (f) = 1;
 
   adjust_frame_glyphs (f);
@@ -3996,6 +4111,20 @@ values.  */)
   r->left_col = 0;
   r->top_line = FRAME_TOP_MARGIN (f);
   window_resize_apply_total (r, !NILP (horizontal));
+  /* Handle the mini window.  */
+  if (FRAME_HAS_MINIBUF_P (f) && !FRAME_MINIBUF_ONLY_P (f))
+    {
+      struct window *m = XWINDOW (f->minibuffer_window);
+
+      if (NILP (horizontal))
+       {
+         m->top_line = r->top_line + r->total_lines;
+         m->total_lines = XFASTINT (m->new_total);
+       }
+      else
+       m->total_cols = XFASTINT (m->new_total);
+    }
+
   unblock_input ();
 
   return Qt;
@@ -4019,40 +4148,45 @@ resize_frame_windows (struct frame *f, int size, bool horflag, bool pixelwise)
   /* old_size is the old size of the frame's root window.  */
   int old_size = horflag ? r->total_cols : r->total_lines;
   int old_pixel_size = horflag ? r->pixel_width : r->pixel_height;
+  int old_pixel_top = r->pixel_top;
   /* new_size is the new size of the frame's root window.  */
   int new_size, new_pixel_size;
+  int unit = horflag ? FRAME_COLUMN_WIDTH (f) : FRAME_LINE_HEIGHT (f);
 
+  /* Don't let the size drop below one unit.  This is more comforting
+     when we are called from x_set_tool_bar_lines since the latter may
+     have implicitly given us a zero or negative height.  */
   if (pixelwise)
     {
-      new_pixel_size
-       = (horflag
-          ? size
-          : (size
-             - FRAME_TOP_MARGIN_HEIGHT (f)
-             - ((FRAME_HAS_MINIBUF_P (f) && !FRAME_MINIBUF_ONLY_P (f))
-                ? FRAME_LINE_HEIGHT (f) : 0)));
-      new_size = new_pixel_size / (horflag
-                                  ? FRAME_COLUMN_WIDTH (f)
-                                  : FRAME_LINE_HEIGHT (f));
+      /* Note: This does not include the size for internal borders
+        since these are not part of the frame's text area.  */
+      new_pixel_size = max (horflag
+                           ? size
+                           : (size
+                              - ((FRAME_HAS_MINIBUF_P (f)
+                                  && !FRAME_MINIBUF_ONLY_P (f))
+                                 ? FRAME_LINE_HEIGHT (f) : 0)),
+                           unit);
+      new_size = new_pixel_size / unit;
     }
   else
     {
-      new_size= (horflag
-                ? size
-                : (size
-                   - FRAME_TOP_MARGIN (f)
-                   - ((FRAME_HAS_MINIBUF_P (f) && !FRAME_MINIBUF_ONLY_P (f))
-                      ? 1 : 0)));
-      new_pixel_size = new_size * (horflag
-                                  ? FRAME_COLUMN_WIDTH (f)
-                                  : FRAME_LINE_HEIGHT (f));
+      new_size = max (horflag
+                     ? size
+                     : (size
+                        - ((FRAME_HAS_MINIBUF_P (f)
+                            && !FRAME_MINIBUF_ONLY_P (f))
+                           ? 1 : 0)),
+                     1);
+      new_pixel_size = new_size * unit;
     }
 
   r->top_line = FRAME_TOP_MARGIN (f);
   r->pixel_top = FRAME_TOP_MARGIN_HEIGHT (f);
 
-  if (new_pixel_size == old_pixel_size)
-    return;
+  if (new_pixel_size == old_pixel_size
+      && r->pixel_top == old_pixel_top)
+    ;
   else if (WINDOW_LEAF_P (r))
     /* For a leaf root window just set the size.  */
     if (horflag)
@@ -4093,6 +4227,7 @@ resize_frame_windows (struct frame *f, int size, bool horflag, bool pixelwise)
            {
              window_resize_apply (r, horflag);
              window_pixel_to_total (r->frame, horflag ? Qt : Qnil);
+#if 0 /* Let's try without safe sizes and/or killing other windows.  */
            }
          else
            {
@@ -4122,6 +4257,7 @@ resize_frame_windows (struct frame *f, int size, bool horflag, bool pixelwise)
                      XWINDOW (root)->pixel_height = new_pixel_size;
                    }
                }
+#endif /* 0 */
            }
        }
     }
@@ -4144,7 +4280,7 @@ resize_frame_windows (struct frame *f, int size, bool horflag, bool pixelwise)
        }
     }
 
-  windows_or_buffers_changed = 31;
+  fset_redisplay (f);
 }
 
 
@@ -4246,7 +4382,7 @@ set correctly.  See the code of `split-window' for how this is done.  */)
        error ("Sum of sizes of old and new window don't fit");
     }
 
-  /* This is our point of no return. */
+  /* This is our point of no return.  */
   if (combination_limit)
     {
       /* Save the old value of o->normal_cols/lines.  It gets corrupted
@@ -4271,7 +4407,7 @@ set correctly.  See the code of `split-window' for how this is done.  */)
   else
     p = XWINDOW (o->parent);
 
-  windows_or_buffers_changed = 32;
+  fset_redisplay (f);
   FRAME_WINDOW_SIZES_CHANGED (f) = 1;
   new = make_window ();
   n = XWINDOW (new);
@@ -4307,7 +4443,9 @@ set correctly.  See the code of `split-window' for how this is done.  */)
   n->right_fringe_width = r->right_fringe_width;
   n->fringes_outside_margins = r->fringes_outside_margins;
   n->scroll_bar_width = r->scroll_bar_width;
+  n->scroll_bar_height = r->scroll_bar_height;
   wset_vertical_scroll_bar_type (n, r->vertical_scroll_bar_type);
+  wset_horizontal_scroll_bar_type (n, r->horizontal_scroll_bar_type);
 
   /* Directly assign orthogonal coordinates and sizes.  */
   if (horflag)
@@ -4435,7 +4573,7 @@ Signal an error when WINDOW is the only window on its frame.  */)
            hlinfo->mouse_face_window = Qnil;
        }
 
-      windows_or_buffers_changed = 33;
+      fset_redisplay (f);
       Vwindow_list = Qnil;
       FRAME_WINDOW_SIZES_CHANGED (f) = 1;
 
@@ -4451,6 +4589,7 @@ Signal an error when WINDOW is the only window on its frame.  */)
        {
          unshow_buffer (w);
          unchain_marker (XMARKER (w->pointm));
+         unchain_marker (XMARKER (w->old_pointm));
          unchain_marker (XMARKER (w->start));
          wset_buffer (w, Qnil);
        }
@@ -4572,8 +4711,10 @@ grow_mini_window (struct window *w, int delta, bool pixelwise)
          /* Grow the mini-window.  */
          w->pixel_top = r->pixel_top + r->pixel_height;
          w->top_line = r->top_line + r->total_lines;
-         w->pixel_height += pixel_height;
-         w->total_lines += line_height;
+         /* Make sure the mini-window has always at least one line.  */
+         w->pixel_height = max (w->pixel_height + pixel_height,
+                                FRAME_LINE_HEIGHT (f));
+         w->total_lines = max (w->total_lines + line_height, 1);
 
          /* Enforce full redisplay of the frame.  */
          /* FIXME: Shouldn't window--resize-root-window-vertically do it?  */
@@ -4653,12 +4794,12 @@ DEFUN ("resize-mini-window-internal", Fresize_mini_window_internal, Sresize_mini
       block_input ();
       window_resize_apply (r, 0);
 
-      w->total_lines = XFASTINT (w->new_total);
-      w->top_line = r->top_line + r->total_lines;
       w->pixel_height = XFASTINT (w->new_pixel);
+      w->total_lines = w->pixel_height / FRAME_LINE_HEIGHT (f);
       w->pixel_top = r->pixel_top + r->pixel_height;
+      w->top_line = r->top_line + r->total_lines;
 
-      windows_or_buffers_changed = 36;
+      fset_redisplay (f);
       FRAME_WINDOW_SIZES_CHANGED (f) = 1;
       adjust_frame_glyphs (f);
       unblock_input ();
@@ -4710,6 +4851,7 @@ window_internal_height (struct window *w)
 
   return ht;
 }
+
 \f
 /************************************************************************
                           Window Scrolling
@@ -4728,6 +4870,8 @@ window_scroll (Lisp_Object window, EMACS_INT n, bool whole, int noerror)
   immediate_quit = 1;
   n = clip_to_bounds (INT_MIN, n, INT_MAX);
 
+  wset_redisplay (XWINDOW (window));
+
   /* If we must, use the pixel-based version which is much slower than
      the line-based one but can handle varying line heights.  */
   if (FRAME_WINDOW_P (XFRAME (XWINDOW (window)->frame)))
@@ -4758,6 +4902,8 @@ window_scroll_pixel_based (Lisp_Object window, int n, bool whole, int noerror)
   void *itdata = NULL;
   int window_total_lines;
   int frame_line_height = default_line_pixel_height (w);
+  bool adjust_old_pointm = !NILP (Fequal (Fwindow_point (window),
+                                         Fwindow_old_point (window)));
 
   SET_TEXT_POS_FROM_MARKER (start, w->start);
   /* Scrolling a minibuffer window via scroll bar when the echo area
@@ -4769,7 +4915,7 @@ window_scroll_pixel_based (Lisp_Object window, int n, bool whole, int noerror)
   /* If PT is not visible in WINDOW, move back one half of
      the screen.  Allow PT to be partially visible, otherwise
      something like (scroll-down 1) with PT in the line before
-     the partially visible one would recenter. */
+     the partially visible one would recenter.  */
 
   if (!pos_visible_p (w, PT, &x, &y, &rtop, &rbot, &rowh, &vpos))
     {
@@ -4798,7 +4944,7 @@ window_scroll_pixel_based (Lisp_Object window, int n, bool whole, int noerror)
     }
   else if (auto_window_vscroll_p)
     {
-      if (rtop || rbot)                /* partially visible */
+      if (rtop || rbot)                /* Partially visible.  */
        {
          int px;
          int dy = frame_line_height;
@@ -4886,6 +5032,7 @@ window_scroll_pixel_based (Lisp_Object window, int n, bool whole, int noerror)
     {
       ptrdiff_t start_pos = IT_CHARPOS (it);
       int dy = frame_line_height;
+
       dy = max ((window_box_height (w)
                 - next_screen_context_lines * dy),
                dy) * n;
@@ -5062,6 +5209,32 @@ window_scroll_pixel_based (Lisp_Object window, int n, bool whole, int noerror)
       charpos = IT_CHARPOS (it);
       bytepos = IT_BYTEPOS (it);
 
+      /* If PT is in the screen line at the last fully visible line,
+        move_it_to will stop at X = 0 in that line, because the
+        required Y coordinate is reached there.  See if we can get to
+        PT without descending lower in Y, and if we can, it means we
+        reached PT before the scroll margin.  */
+      if (charpos != PT)
+       {
+         struct it it2;
+         void *it_data;
+
+         it2 = it;
+         it_data = bidi_shelve_cache ();
+         move_it_to (&it, PT, -1, -1, -1, MOVE_TO_POS);
+         if (IT_CHARPOS (it) == PT && it.current_y == it2.current_y)
+           {
+             charpos = IT_CHARPOS (it);
+             bytepos = IT_BYTEPOS (it);
+             bidi_unshelve_cache (it_data, 1);
+           }
+         else
+           {
+             it = it2;
+             bidi_unshelve_cache (it_data, 0);
+           }
+       }
+
       /* See if point is on a partially visible line at the end.  */
       if (it.what == IT_EOB)
        partial_p = it.current_y + it.ascent + it.descent > it.last_visible_y;
@@ -5103,6 +5276,13 @@ window_scroll_pixel_based (Lisp_Object window, int n, bool whole, int noerror)
        }
     }
   bidi_unshelve_cache (itdata, 0);
+
+  if (adjust_old_pointm)
+    Fset_marker (w->old_pointm,
+                ((w == XWINDOW (selected_window))
+                 ? make_number (BUF_PT (XBUFFER (w->contents)))
+                 : Fmarker_position (w->pointm)),
+                w->contents);
 }
 
 
@@ -5127,6 +5307,8 @@ window_scroll_line_based (Lisp_Object window, int n, bool whole, int noerror)
   ptrdiff_t startpos = marker_position (w->start);
   ptrdiff_t startbyte = marker_byte_position (w->start);
   Lisp_Object original_pos = Qnil;
+  bool adjust_old_pointm = !NILP (Fequal (Fwindow_point (window),
+                                         Fwindow_old_point (window)));
 
   /* If scrolling screen-fulls, compute the number of lines to
      scroll from the window's height.  */
@@ -5142,6 +5324,7 @@ window_scroll_line_based (Lisp_Object window, int n, bool whole, int noerror)
          struct position posit
            = *compute_motion (startpos, startbyte, 0, 0, 0,
                               PT, ht, 0, -1, w->hscroll, 0, w);
+
          window_scroll_preserve_vpos = posit.vpos;
          window_scroll_preserve_hpos = posit.hpos + w->hscroll;
        }
@@ -5257,6 +5440,13 @@ window_scroll_line_based (Lisp_Object window, int n, bool whole, int noerror)
       else
        xsignal0 (Qend_of_buffer);
     }
+
+  if (adjust_old_pointm)
+    Fset_marker (w->old_pointm,
+                ((w == XWINDOW (selected_window))
+                 ? make_number (BUF_PT (XBUFFER (w->contents)))
+                 : Fmarker_position (w->pointm)),
+                w->contents);
 }
 
 
@@ -5279,9 +5469,6 @@ scroll_command (Lisp_Object n, int direction)
     {
       record_unwind_protect (save_excursion_restore, save_excursion_save ());
       Fset_buffer (XWINDOW (selected_window)->contents);
-
-      /* Make redisplay consider other windows than just selected_window.  */
-      windows_or_buffers_changed = 37;
     }
 
   if (NILP (n))
@@ -5337,8 +5524,10 @@ specifies the window.  This takes precedence over
   if (MINI_WINDOW_P (XWINDOW (selected_window))
       && !NILP (Vminibuf_scroll_window))
     window = Vminibuf_scroll_window;
-  /* If buffer is specified, scroll that buffer.  */
-  else if (!NILP (Vother_window_scroll_buffer))
+  /* If buffer is specified and live, scroll that buffer.  */
+  else if (!NILP (Vother_window_scroll_buffer)
+          && BUFFERP (Vother_window_scroll_buffer)
+          && BUFFER_LIVE_P (XBUFFER (Vother_window_scroll_buffer)))
     {
       window = Fget_buffer_window (Vother_window_scroll_buffer, Qnil);
       if (NILP (window))
@@ -5391,10 +5580,10 @@ specifies the window to scroll.  This takes precedence over
 
   /* Don't screw up if window_scroll gets an error.  */
   record_unwind_protect (save_excursion_restore, save_excursion_save ());
-  windows_or_buffers_changed = 38;
 
   Fset_buffer (w->contents);
   SET_PT_BOTH (marker_position (w->pointm), marker_byte_position (w->pointm));
+  SET_PT_BOTH (marker_position (w->old_pointm), marker_byte_position (w->old_pointm));
 
   if (NILP (arg))
     window_scroll (window, 1, 1, 1);
@@ -5409,6 +5598,7 @@ specifies the window to scroll.  This takes precedence over
     }
 
   set_marker_both (w->pointm, Qnil, PT, PT_BYTE);
+  set_marker_both (w->old_pointm, Qnil, PT, PT_BYTE);
   unbind_to (count, Qnil);
 
   return Qnil;
@@ -5434,6 +5624,8 @@ by this function.  This happens in an interactive call.  */)
   if (!NILP (set_minimum))
     w->min_hscroll = w->hscroll;
 
+  w->suspend_auto_hscroll = 1;
+
   return result;
 }
 
@@ -5457,6 +5649,8 @@ by this function.  This happens in an interactive call.  */)
   if (!NILP (set_minimum))
     w->min_hscroll = w->hscroll;
 
+  w->suspend_auto_hscroll = 1;
+
   return result;
 }
 
@@ -5547,14 +5741,16 @@ and redisplay normally--don't erase and redraw the frame.  */)
 {
   struct window *w = XWINDOW (selected_window);
   struct buffer *buf = XBUFFER (w->contents);
-  struct buffer *obuf = current_buffer;
   bool center_p = 0;
   ptrdiff_t charpos, bytepos;
   EMACS_INT iarg IF_LINT (= 0);
   int this_scroll_margin;
 
+  if (buf != current_buffer)
+    error ("`recenter'ing a window that does not display current-buffer.");
+
   /* If redisplay is suppressed due to an error, try again.  */
-  obuf->display_error_modiff = 0;
+  buf->display_error_modiff = 0;
 
   if (NILP (arg))
     {
@@ -5576,7 +5772,7 @@ and redisplay normally--don't erase and redraw the frame.  */)
 
       center_p = 1;
     }
-  else if (CONSP (arg)) /* Just C-u. */
+  else if (CONSP (arg)) /* Just C-u.  */
     center_p = 1;
   else
     {
@@ -5585,12 +5781,10 @@ and redisplay normally--don't erase and redraw the frame.  */)
       iarg = XINT (arg);
     }
 
-  set_buffer_internal (buf);
-
   /* Do this after making BUF current
      in case scroll_margin is buffer-local.  */
-  this_scroll_margin =
-    max (0, min (scroll_margin, w->total_lines / 4));
+  this_scroll_margin
+    max (0, min (scroll_margin, w->total_lines / 4));
 
   /* Handle centering on a graphical frame specially.  Such frames can
      have variable-height lines and centering point on the basis of
@@ -5638,7 +5832,7 @@ and redisplay normally--don't erase and redraw the frame.  */)
            h -= it.current_y;
          else
            {
-             /* Last line has no newline */
+             /* Last line has no newline */
              h -= line_bottom_y (&it);
              it.vpos++;
            }
@@ -5717,42 +5911,55 @@ and redisplay normally--don't erase and redraw the frame.  */)
 
   w->optional_new_start = 1;
 
-  w->start_at_line_beg = (bytepos == BEGV_BYTE ||
-                         FETCH_BYTE (bytepos - 1) == '\n');
+  w->start_at_line_beg = (bytepos == BEGV_BYTE
+                         || FETCH_BYTE (bytepos - 1) == '\n');
+
+  wset_redisplay (w);
 
-  set_buffer_internal (obuf);
   return Qnil;
 }
 
 DEFUN ("window-text-width", Fwindow_text_width, Swindow_text_width,
-       0, 1, 0,
+       0, 2, 0,
        doc: /* Return the width in columns of the text display area of WINDOW.
 WINDOW must be a live window and defaults to the selected one.
 
 The returned width does not include dividers, scrollbars, margins,
 fringes, nor any partial-width columns at the right of the text
-area.  */)
-  (Lisp_Object window)
+area.
+
+Optional argument PIXELWISE non-nil, means to return the width in
+pixels.  */)
+  (Lisp_Object window, Lisp_Object pixelwise)
 {
   struct window *w = decode_live_window (window);
 
-  return make_number (window_box_width (w, TEXT_AREA)
-                     / FRAME_COLUMN_WIDTH (WINDOW_XFRAME (w)));
+  if (NILP (pixelwise))
+    return make_number (window_box_width (w, TEXT_AREA)
+                       / FRAME_COLUMN_WIDTH (WINDOW_XFRAME (w)));
+  else
+    return make_number (window_box_width (w, TEXT_AREA));
 }
 
 DEFUN ("window-text-height", Fwindow_text_height, Swindow_text_height,
-       0, 1, 0,
+       0, 2, 0,
        doc: /* Return the height in lines of the text display area of WINDOW.
 WINDOW must be a live window and defaults to the selected one.
 
 The returned height does not include dividers, the mode line, any header
-line, nor any partial-height lines at the bottom of the text area.  */)
-  (Lisp_Object window)
+line, nor any partial-height lines at the bottom of the text area.
+
+Optional argument PIXELWISE non-nil, means to return the height in
+pixels.  */)
+  (Lisp_Object window, Lisp_Object pixelwise)
 {
   struct window *w = decode_live_window (window);
 
-  return make_number (window_box_height (w)
-                     / FRAME_LINE_HEIGHT (WINDOW_XFRAME (w)));
+  if (NILP (pixelwise))
+    return make_number (window_box_height (w)
+                       / FRAME_LINE_HEIGHT (WINDOW_XFRAME (w)));
+  else
+    return make_number (window_box_height (w));
 }
 \f
 DEFUN ("move-to-window-line", Fmove_to_window_line, Smove_to_window_line,
@@ -5857,22 +6064,23 @@ struct save_window_data
     int frame_menu_bar_height, frame_tool_bar_height;
   };
 
-/* This is saved as a Lisp_Vector  */
+/* This is saved as a Lisp_Vector.  */
 struct saved_window
 {
   struct vectorlike_header header;
 
-  Lisp_Object window, buffer, start, pointm, mark;
+  Lisp_Object window, buffer, start, pointm, old_pointm;
   Lisp_Object pixel_left, pixel_top, pixel_height, pixel_width;
   Lisp_Object left_col, top_line, total_cols, total_lines;
   Lisp_Object normal_cols, normal_lines;
-  Lisp_Object hscroll, min_hscroll;
+  Lisp_Object hscroll, min_hscroll, hscroll_whole, suspend_auto_hscroll;
   Lisp_Object parent, prev;
   Lisp_Object start_at_line_beg;
   Lisp_Object display_table;
   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, dedicated;
+  Lisp_Object scroll_bar_height, horizontal_scroll_bar_type;
   Lisp_Object combination_limit, window_parameters;
 };
 
@@ -5916,6 +6124,7 @@ the return value is nil.  Otherwise the value is t.  */)
   Lisp_Object frame;
   struct frame *f;
   ptrdiff_t old_point = -1;
+  USE_SAFE_ALLOCA;
 
   CHECK_WINDOW_CONFIGURATION (configuration);
 
@@ -5980,19 +6189,6 @@ the return value is nil.  Otherwise the value is t.  */)
       ptrdiff_t k;
       int i, n;
 
-      /* If the frame has been resized since this window configuration was
-        made, we change the frame to the size specified in the
-        configuration, restore the configuration, and then resize it
-        back.  We keep track of the prevailing height in these variables.  */
-      int previous_frame_text_height = FRAME_TEXT_HEIGHT (f);
-      int previous_frame_text_width =  FRAME_TEXT_WIDTH  (f);
-      /* int previous_frame_menu_bar_height = FRAME_MENU_BAR_HEIGHT (f); */
-      /* int previous_frame_tool_bar_height = FRAME_TOOL_BAR_HEIGHT (f); */
-      /* int previous_frame_lines = FRAME_LINES (f); */
-      /* int previous_frame_cols =  FRAME_COLS  (f); */
-      int previous_frame_menu_bar_lines = FRAME_MENU_BAR_LINES (f);
-      int previous_frame_tool_bar_lines = FRAME_TOOL_BAR_LINES (f);
-
       /* Don't do this within the main loop below: This may call Lisp
         code and is thus potentially unsafe while input is blocked.  */
       for (k = 0; k < saved_windows->header.size; k++)
@@ -6008,32 +6204,12 @@ the return value is nil.  Otherwise the value is t.  */)
            call1 (Qrecord_window_buffer, window);
        }
 
+      /* Consider frame unofficial, temporarily.  */
+      f->official = false;
       /* The mouse highlighting code could get screwed up
         if it runs during this.  */
       block_input ();
 
-      if (data->frame_text_width != previous_frame_text_width
-         || data->frame_text_height != previous_frame_text_height)
-       change_frame_size (f, data->frame_text_width,
-                          data->frame_text_height, 0, 0, 0, 1);
-
-      if (data->frame_menu_bar_lines != previous_frame_menu_bar_lines)
-       {
-#ifdef HAVE_WINDOW_SYSTEM
-         if (FRAME_WINDOW_P (f))
-           x_set_menu_bar_lines (f, make_number (data->frame_menu_bar_lines),
-                                 make_number (0));
-         else  /* TTY or MSDOS */
-#endif
-           set_menu_bar_lines (f, make_number (data->frame_menu_bar_lines),
-                               make_number (0));
-       }
-#ifdef HAVE_WINDOW_SYSTEM
-      if (data->frame_tool_bar_lines != previous_frame_tool_bar_lines)
-       x_set_tool_bar_lines (f, make_number (data->frame_tool_bar_lines),
-                             make_number (0));
-#endif
-
       /* "Swap out" point from the selected window's buffer
         into the window itself.  (Normally the pointm of the selected
         window holds garbage.)  We do this now, before
@@ -6048,7 +6224,7 @@ the return value is nil.  Otherwise the value is t.  */)
                           BUF_PT_BYTE (XBUFFER (w->contents)));
        }
 
-      windows_or_buffers_changed = 39;
+      fset_redisplay (f);
       FRAME_WINDOW_SIZES_CHANGED (f) = 1;
 
       /* Problem: Freeing all matrices and later allocating them again
@@ -6056,8 +6232,8 @@ the return value is nil.  Otherwise the value is t.  */)
         really like to do is to free only those matrices not reused
         below.  */
       root_window = XWINDOW (FRAME_ROOT_WINDOW (f));
-      leaf_windows = alloca (count_windows (root_window)
-                            * sizeof *leaf_windows);
+      int nwindows = count_windows (root_window);
+      SAFE_NALLOCA (leaf_windows, 1, nwindows);
       n_leaf_windows = get_leaf_windows (root_window, leaf_windows, 0);
 
       /* Kludge Alert!
@@ -6112,7 +6288,9 @@ the return value is nil.  Otherwise the value is t.  */)
          wset_normal_cols (w, p->normal_cols);
          wset_normal_lines (w, p->normal_lines);
          w->hscroll = XFASTINT (p->hscroll);
+         w->suspend_auto_hscroll = !NILP (p->suspend_auto_hscroll);
          w->min_hscroll = XFASTINT (p->min_hscroll);
+         w->hscroll_whole = XFASTINT (p->hscroll_whole);
          wset_display_table (w, p->display_table);
          w->left_margin_cols = XINT (p->left_margin_cols);
          w->right_margin_cols = XINT (p->right_margin_cols);
@@ -6120,7 +6298,9 @@ the return value is nil.  Otherwise the value is t.  */)
          w->right_fringe_width = XINT (p->right_fringe_width);
          w->fringes_outside_margins = !NILP (p->fringes_outside_margins);
          w->scroll_bar_width = XINT (p->scroll_bar_width);
+         w->scroll_bar_height = XINT (p->scroll_bar_height);
          wset_vertical_scroll_bar_type (w, p->vertical_scroll_bar_type);
+         wset_horizontal_scroll_bar_type (w, p->horizontal_scroll_bar_type);
          wset_dedicated (w, p->dedicated);
          wset_combination_limit (w, p->combination_limit);
          /* Restore any window parameters that have been saved.
@@ -6151,18 +6331,15 @@ the return value is nil.  Otherwise the value is t.  */)
              wset_buffer (w, p->buffer);
              w->start_at_line_beg = !NILP (p->start_at_line_beg);
              set_marker_restricted (w->start, p->start, w->contents);
-             set_marker_restricted (w->pointm, p->pointm,
-                                    w->contents);
-             Fset_marker (BVAR (XBUFFER (w->contents), mark),
-                          p->mark, w->contents);
-
+             set_marker_restricted (w->pointm, p->pointm, w->contents);
+             set_marker_restricted (w->old_pointm, p->old_pointm, w->contents);
              /* As documented in Fcurrent_window_configuration, don't
                 restore the location of point in the buffer which was
                 current when the window configuration was recorded.  */
              if (!EQ (p->buffer, new_current_buffer)
                  && XBUFFER (p->buffer) == current_buffer)
                Fgoto_char (w->pointm);
-            }
+           }
          else if (BUFFERP (w->contents) && BUFFER_LIVE_P (XBUFFER (w->contents)))
            /* Keep window's old buffer; make sure the markers are real.  */
            {
@@ -6174,20 +6351,26 @@ the return value is nil.  Otherwise the value is t.  */)
                  (w->pointm, w->contents,
                   BUF_PT (XBUFFER (w->contents)),
                   BUF_PT_BYTE (XBUFFER (w->contents)));
+             if (XMARKER (w->old_pointm)->buffer == 0)
+               set_marker_restricted_both
+                 (w->old_pointm, w->contents,
+                  BUF_PT (XBUFFER (w->contents)),
+                  BUF_PT_BYTE (XBUFFER (w->contents)));
              w->start_at_line_beg = 1;
            }
          else if (!NILP (w->start))
            /* Leaf window has no live buffer, get one.  */
            {
              /* Get the buffer via other_buffer_safely in order to
-             avoid showing an unimportant buffer and, if necessary, to
-             recreate *scratch* in the course (part of Juanma's bs-show
-             scenario from March 2011).  */
+                avoid showing an unimportant buffer and, if necessary, to
+                recreate *scratch* in the course (part of Juanma's bs-show
+                scenario from March 2011).  */
              wset_buffer (w, other_buffer_safely (Fcurrent_buffer ()));
              /* This will set the markers to beginning of visible
                 range.  */
              set_marker_restricted_both (w->start, w->contents, 0, 0);
              set_marker_restricted_both (w->pointm, w->contents, 0, 0);
+             set_marker_restricted_both (w->old_pointm, w->contents, 0, 0);
              w->start_at_line_beg = 1;
              if (!NILP (w->dedicated))
                /* Record this window as dead.  */
@@ -6205,35 +6388,23 @@ the return value is nil.  Otherwise the value is t.  */)
                               make_number (old_point),
                               XWINDOW (data->current_window)->contents);
 
+      /* In the following call to `select-window', prevent "swapping out
+        point" in the old selected window using the buffer that has
+        been restored into it.  We already swapped out that point from
+        that window's old buffer.
+
+        Do not record the buffer here.  We do that in a separate call
+        to select_window below.  See also Bug#16207.  */
+      select_window (data->current_window, Qt, 1);
+      BVAR (XBUFFER (XWINDOW (selected_window)->contents),
+           last_selected_window)
+       = selected_window;
+
       if (NILP (data->focus_frame)
          || (FRAMEP (data->focus_frame)
              && FRAME_LIVE_P (XFRAME (data->focus_frame))))
        Fredirect_frame_focus (frame, data->focus_frame);
 
-      /* Set the frame size to the value it had before this function.  */
-      if (previous_frame_text_width != FRAME_TEXT_WIDTH (f)
-         || previous_frame_text_height != FRAME_TEXT_HEIGHT (f))
-       change_frame_size (f, previous_frame_text_width,
-                          previous_frame_text_height, 0, 0, 0, 1);
-
-      if (previous_frame_menu_bar_lines != FRAME_MENU_BAR_LINES (f))
-       {
-#ifdef HAVE_WINDOW_SYSTEM
-         if (FRAME_WINDOW_P (f))
-           x_set_menu_bar_lines (f,
-                                 make_number (previous_frame_menu_bar_lines),
-                                 make_number (0));
-         else  /* TTY or MSDOS */
-#endif
-           set_menu_bar_lines (f, make_number (previous_frame_menu_bar_lines),
-                               make_number (0));
-       }
-#ifdef HAVE_WINDOW_SYSTEM
-      if (previous_frame_tool_bar_lines != FRAME_TOOL_BAR_LINES (f))
-       x_set_tool_bar_lines (f, make_number (previous_frame_tool_bar_lines),
-                             make_number (0));
-#endif
-
       /* Now, free glyph matrices in windows that were not reused.  */
       for (i = n = 0; i < n_leaf_windows; ++i)
        {
@@ -6243,6 +6414,11 @@ the return value is nil.  Otherwise the value is t.  */)
            ++n;
        }
 
+      /* Make frame official again and apply frame size changes if
+        needed.  */
+      f->official = true;
+      adjust_frame_size (f, -1, -1, 1, 0);
+
       adjust_frame_glyphs (f);
       unblock_input ();
 
@@ -6254,19 +6430,9 @@ the return value is nil.  Otherwise the value is t.  */)
            delete_deletable_window (window);
        }
 
-      /* In the following call to `select-window', prevent "swapping out
-        point" in the old selected window using the buffer that has
-        been restored into it.  We already swapped out that point from
-        that window's old buffer.  */
-      /* This `select_window' calls record_buffer which calls Fdelq which
-        invokes QUIT, so we do it here at the end rather than earlier,
-        to minimize the risk of interrupting the Fset_window_configuration
-        in an inconsistent state (e.g. before frame-focus redirection is
-        canceled).  */
-      select_window (data->current_window, Qnil, 1);
-      BVAR (XBUFFER (XWINDOW (selected_window)->contents),
-           last_selected_window)
-       = selected_window;
+      /* Record the selected window's buffer here.  The window should
+        already be the selected one from the call above.  */
+      select_window (data->current_window, Qnil, 0);
 
       /* Fselect_window will have made f the selected frame, so we
         reselect the proper frame here.  Fhandle_switch_frame will change the
@@ -6291,9 +6457,11 @@ the return value is nil.  Otherwise the value is t.  */)
   Vminibuf_scroll_window = data->minibuf_scroll_window;
   minibuf_selected_window = data->minibuf_selected_window;
 
+  SAFE_FREE ();
   return (FRAME_LIVE_P (f) ? Qt : Qnil);
 }
 
+
 void
 restore_window_configuration (Lisp_Object configuration)
 {
@@ -6325,6 +6493,7 @@ delete_all_child_windows (Lisp_Object window)
     {
       unshow_buffer (w);
       unchain_marker (XMARKER (w->pointm));
+      unchain_marker (XMARKER (w->old_pointm));
       unchain_marker (XMARKER (w->start));
       /* Since combination limit makes sense for an internal windows
         only, we use this slot to save the buffer for the sake of
@@ -6431,7 +6600,9 @@ save_window_save (Lisp_Object window, struct Lisp_Vector *vector, int i)
       p->normal_cols = w->normal_cols;
       p->normal_lines = w->normal_lines;
       XSETFASTINT (p->hscroll, w->hscroll);
+      p->suspend_auto_hscroll = w->suspend_auto_hscroll ? Qt : Qnil;
       XSETFASTINT (p->min_hscroll, w->min_hscroll);
+      XSETFASTINT (p->hscroll_whole, w->hscroll_whole);
       p->display_table = w->display_table;
       p->left_margin_cols = make_number (w->left_margin_cols);
       p->right_margin_cols = make_number (w->right_margin_cols);
@@ -6439,7 +6610,9 @@ save_window_save (Lisp_Object window, struct Lisp_Vector *vector, int i)
       p->right_fringe_width = make_number (w->right_fringe_width);
       p->fringes_outside_margins = w->fringes_outside_margins ? Qt : Qnil;
       p->scroll_bar_width = make_number (w->scroll_bar_width);
+      p->scroll_bar_height = make_number (w->scroll_bar_height);
       p->vertical_scroll_bar_type = w->vertical_scroll_bar_type;
+      p->horizontal_scroll_bar_type = w->horizontal_scroll_bar_type;
       p->dedicated = w->dedicated;
       p->combination_limit = w->combination_limit;
       p->window_parameters = Qnil;
@@ -6501,32 +6674,27 @@ save_window_save (Lisp_Object window, struct Lisp_Vector *vector, int i)
                                      BUF_PT_BYTE (XBUFFER (w->contents)));
          else
            p->pointm = Fcopy_marker (w->pointm, Qnil);
+         p->old_pointm = Fcopy_marker (w->old_pointm, Qnil);
          XMARKER (p->pointm)->insertion_type
-           = !NILP (Vwindow_point_insertion_type);
+           = !NILP (buffer_local_value /* Don't signal error if void.  */
+                    (Qwindow_point_insertion_type, w->contents));
+         XMARKER (p->old_pointm)->insertion_type
+           = !NILP (buffer_local_value /* Don't signal error if void.  */
+                    (Qwindow_point_insertion_type, w->contents));
 
          p->start = Fcopy_marker (w->start, Qnil);
          p->start_at_line_beg = w->start_at_line_beg ? Qt : Qnil;
-
-         tem = BVAR (XBUFFER (w->contents), mark);
-         p->mark = Fcopy_marker (tem, Qnil);
        }
       else
        {
          p->pointm = Qnil;
+         p->old_pointm = Qnil;
          p->start = Qnil;
-         p->mark = Qnil;
          p->start_at_line_beg = Qnil;
        }
 
-      if (NILP (w->parent))
-       p->parent = Qnil;
-      else
-       p->parent = XWINDOW (w->parent)->temslot;
-
-      if (NILP (w->prev))
-       p->prev = Qnil;
-      else
-       p->prev = XWINDOW (w->prev)->temslot;
+      p->parent = NILP (w->parent) ? Qnil : XWINDOW (w->parent)->temslot;
+      p->prev = NILP (w->prev) ? Qnil : XWINDOW (w->prev)->temslot;
 
       if (WINDOWP (w->contents))
        i = save_window_save (w->contents, vector, i);
@@ -6540,8 +6708,8 @@ DEFUN ("current-window-configuration", Fcurrent_window_configuration,
        doc: /* Return an object representing the current window configuration of FRAME.
 If FRAME is nil or omitted, use the selected frame.
 This describes the number of windows, their sizes and current buffers,
-and for each displayed buffer, where display starts, and the positions of
-point and mark.  An exception is made for point in the current buffer:
+and for each displayed buffer, where display starts, and the position of
+point.  An exception is made for point in the current buffer:
 its value is -not- saved.
 This also records the currently selected frame, and FRAME's focus
 redirection (see `redirect-frame-focus').  The variable
@@ -6590,10 +6758,10 @@ static void
 apply_window_adjustment (struct window *w)
 {
   eassert (w);
-  adjust_window_margins (w);
   clear_glyph_matrix (w->current_matrix);
   w->window_end_valid = 0;
-  windows_or_buffers_changed = 40;
+  windows_or_buffers_changed = 30;
+  wset_redisplay (w);
   adjust_frame_glyphs (XFRAME (WINDOW_FRAME (w)));
 }
 
@@ -6607,8 +6775,8 @@ set_window_margins (struct window *w, Lisp_Object left_width,
                    Lisp_Object right_width)
 {
   int left, right;
+  int unit = WINDOW_FRAME_COLUMN_WIDTH (w);
 
-  /* FIXME: what about margins that are too wide?  */
   left = (NILP (left_width) ? 0
          : (CHECK_NATNUM (left_width), XINT (left_width)));
   right = (NILP (right_width) ? 0
@@ -6616,11 +6784,23 @@ set_window_margins (struct window *w, Lisp_Object left_width,
 
   if (w->left_margin_cols != left || w->right_margin_cols != right)
     {
-      w->left_margin_cols = left;
-      w->right_margin_cols = right;
-      return w;
+      /* Don't change anything if new margins won't fit.  */
+      if ((WINDOW_PIXEL_WIDTH (w)
+          - WINDOW_FRINGES_WIDTH (w)
+          - WINDOW_SCROLL_BAR_AREA_WIDTH (w)
+          - (left + right) * unit)
+         >= MIN_SAFE_WINDOW_PIXEL_WIDTH (w))
+       {
+         w->left_margin_cols = left;
+         w->right_margin_cols = right;
+
+         return w;
+       }
+      else
+       return NULL;
     }
-  return NULL;
+  else
+    return NULL;
 }
 
 DEFUN ("set-window-margins", Fset_window_margins, Sset_window_margins,
@@ -6682,12 +6862,25 @@ set_window_fringes (struct window *w, Lisp_Object left_width,
          || w->right_fringe_width != right
          || w->fringes_outside_margins != outside))
     {
+      if (left > 0 || right > 0)
+       {
+         /* Don't change anything if new fringes don't fit.  */
+         if ((WINDOW_PIXEL_WIDTH (w)
+              - WINDOW_MARGINS_WIDTH (w)
+              - WINDOW_SCROLL_BAR_AREA_WIDTH (w)
+              - max (left, 0) - max (right, 0))
+             < MIN_SAFE_WINDOW_PIXEL_WIDTH (w))
+           return NULL;
+       }
+
       w->left_fringe_width = left;
       w->right_fringe_width = right;
       w->fringes_outside_margins = outside;
+
       return w;
     }
-  return NULL;
+  else
+    return NULL;
 }
 
 DEFUN ("set-window-fringes", Fset_window_fringes, Sset_window_fringes,
@@ -6738,9 +6931,11 @@ Value is a list of the form (LEFT-WIDTH RIGHT-WIDTH OUTSIDE-MARGINS).  */)
 
 static struct window *
 set_window_scroll_bars (struct window *w, Lisp_Object width,
-                       Lisp_Object vertical_type, Lisp_Object horizontal_type)
+                       Lisp_Object vertical_type, Lisp_Object height,
+                       Lisp_Object horizontal_type)
 {
   int iwidth = (NILP (width) ? -1 : (CHECK_NATNUM (width), XINT (width)));
+  bool changed = 0;
 
   if (iwidth == 0)
     vertical_type = Qnil;
@@ -6754,32 +6949,78 @@ set_window_scroll_bars (struct window *w, Lisp_Object width,
   if (w->scroll_bar_width != iwidth
       || !EQ (w->vertical_scroll_bar_type, vertical_type))
     {
-      w->scroll_bar_width = iwidth;
-      wset_vertical_scroll_bar_type (w, vertical_type);
-      return w;
+      /* Don't change anything if new scroll bar won't fit.  */
+      if ((WINDOW_PIXEL_WIDTH (w)
+          - WINDOW_MARGINS_WIDTH (w)
+          - WINDOW_FRINGES_WIDTH (w)
+          - max (iwidth, 0))
+         >= MIN_SAFE_WINDOW_PIXEL_WIDTH (w))
+       {
+         w->scroll_bar_width = iwidth;
+         wset_vertical_scroll_bar_type (w, vertical_type);
+         changed = 1;
+       }
     }
-  return NULL;
+
+#if USE_HORIZONTAL_SCROLL_BARS
+  {
+    int iheight = (NILP (height) ? -1 : (CHECK_NATNUM (height), XINT (height)));
+
+    if (MINI_WINDOW_P (w) || iheight == 0)
+      horizontal_type = Qnil;
+
+    if (!(NILP (horizontal_type)
+         || EQ (horizontal_type, Qbottom)
+         || EQ (horizontal_type, Qt)))
+      error ("Invalid type of horizontal scroll bar");
+
+    if (w->scroll_bar_height != iheight
+       || !EQ (w->horizontal_scroll_bar_type, horizontal_type))
+      {
+       /* Don't change anything if new scroll bar won't fit.  */
+       if ((WINDOW_PIXEL_HEIGHT (w)
+            - WINDOW_HEADER_LINE_HEIGHT (w)
+            - WINDOW_MODE_LINE_HEIGHT (w)
+            - max (iheight, 0))
+           >= MIN_SAFE_WINDOW_PIXEL_HEIGHT (w))
+         {
+           w->scroll_bar_height = iheight;
+           wset_horizontal_scroll_bar_type (w, horizontal_type);
+           changed = 1;
+         }
+      }
+  }
+#else
+  wset_horizontal_scroll_bar_type (w, Qnil);
+#endif
+
+  return changed ? w : NULL;
 }
 
 DEFUN ("set-window-scroll-bars", Fset_window_scroll_bars,
-       Sset_window_scroll_bars, 2, 4, 0,
+       Sset_window_scroll_bars, 1, 5, 0,
        doc: /* Set width and type of scroll bars of window WINDOW.
 WINDOW must be a live window and defaults to the selected one.
 
-Second parameter WIDTH specifies the pixel width for the scroll bar.
+Second parameter WIDTH specifies the pixel width for the vertical scroll
+bar.  If WIDTH is nil, use the scroll-bar width of WINDOW's frame.
 Third parameter VERTICAL-TYPE specifies the type of the vertical scroll
-bar: left, right, or nil.
-If WIDTH is nil, use the frame's scroll-bar width.
-If VERTICAL-TYPE is t, use the frame's scroll-bar type.
-Fourth parameter HORIZONTAL-TYPE is currently unused.
+bar: left, right, or nil.  If VERTICAL-TYPE is t, this means use the
+frame's scroll-bar type.
+
+Fourth parameter HEIGHT specifies the pixel height for the horizontal
+scroll bar.  If HEIGHT is nil, use the scroll-bar height of WINDOW's
+frame.  Fifth parameter HORIZONTAL-TYPE specifies the type of the
+horizontal scroll bar: nil, bottom, or t.  If HORIZONTAL-TYPE is t, this
+means to use the frame's horizontal scroll-bar type.
 
 Return t if scroll bars were actually changed and nil otherwise.  */)
-  (Lisp_Object window, Lisp_Object width,
-   Lisp_Object vertical_type, Lisp_Object horizontal_type)
+  (Lisp_Object window, Lisp_Object width, Lisp_Object vertical_type,
+   Lisp_Object height, Lisp_Object horizontal_type)
 {
   struct window *w
     = set_window_scroll_bars (decode_live_window (window),
-                             width, vertical_type, horizontal_type);
+                             width, vertical_type, height, horizontal_type);
   return w ? (apply_window_adjustment (w), Qt) : Qnil;
 }
 
@@ -6789,21 +7030,25 @@ DEFUN ("window-scroll-bars", Fwindow_scroll_bars, Swindow_scroll_bars,
        doc: /* Get width and type of scroll bars of window WINDOW.
 WINDOW must be a live window and defaults to the selected one.
 
-Value is a list of the form (WIDTH COLS VERTICAL-TYPE HORIZONTAL-TYPE).
-If WIDTH is nil or TYPE is t, the window is using the frame's corresponding
+Value is a list of the form (WIDTH COLUMNS VERTICAL-TYPE HEIGHT LINES
+HORIZONTAL-TYPE).  If WIDTH or HEIGHT is nil or VERTICAL-TYPE or
+HORIZONTAL-TYPE is t, the window is using the frame's corresponding
 value.  */)
   (Lisp_Object window)
 {
   struct window *w = decode_live_window (window);
 
-  return list4 (make_number ((WINDOW_CONFIG_SCROLL_BAR_WIDTH (w)
-                             ? WINDOW_CONFIG_SCROLL_BAR_WIDTH (w)
-                             : WINDOW_SCROLL_BAR_AREA_WIDTH (w))),
-               make_number (WINDOW_SCROLL_BAR_COLS (w)),
-               w->vertical_scroll_bar_type, Qnil);
+  return Fcons (((w->scroll_bar_width >= 0)
+                ? make_number (w->scroll_bar_width)
+                : Qnil),
+               list5 (make_number (WINDOW_SCROLL_BAR_COLS (w)),
+                      w->vertical_scroll_bar_type,
+                      ((w->scroll_bar_height >= 0)
+                       ? make_number (w->scroll_bar_height)
+                       : Qnil),
+                      make_number (WINDOW_SCROLL_BAR_LINES (w)),
+                      w->horizontal_scroll_bar_type));
 }
-
-
 \f
 /***********************************************************************
                           Smooth scrolling
@@ -6986,15 +7231,16 @@ compare_window_configurations (Lisp_Object configuration1,
                  || !EQ (sw1->min_hscroll, sw2->min_hscroll)
                  || !EQ (sw1->start_at_line_beg, sw2->start_at_line_beg)
                  || NILP (Fequal (sw1->start, sw2->start))
-                 || NILP (Fequal (sw1->pointm, sw2->pointm))
-                 || NILP (Fequal (sw1->mark, sw2->mark))))
+                 || NILP (Fequal (sw1->pointm, sw2->pointm))))
          || !EQ (sw1->left_margin_cols, sw2->left_margin_cols)
          || !EQ (sw1->right_margin_cols, sw2->right_margin_cols)
          || !EQ (sw1->left_fringe_width, sw2->left_fringe_width)
          || !EQ (sw1->right_fringe_width, sw2->right_fringe_width)
          || !EQ (sw1->fringes_outside_margins, sw2->fringes_outside_margins)
          || !EQ (sw1->scroll_bar_width, sw2->scroll_bar_width)
-         || !EQ (sw1->vertical_scroll_bar_type, sw2->vertical_scroll_bar_type))
+         || !EQ (sw1->scroll_bar_height, sw2->scroll_bar_height)
+         || !EQ (sw1->vertical_scroll_bar_type, sw2->vertical_scroll_bar_type)
+         || !EQ (sw1->horizontal_scroll_bar_type, sw2->horizontal_scroll_bar_type))
        return 0;
     }
 
@@ -7004,7 +7250,7 @@ compare_window_configurations (Lisp_Object configuration1,
 DEFUN ("compare-window-configurations", Fcompare_window_configurations,
        Scompare_window_configurations, 2, 2, 0,
        doc: /* Compare two window configurations as regards the structure of windows.
-This function ignores details such as the values of point and mark
+This function ignores details such as the values of point
 and scrolling positions.  */)
   (Lisp_Object x, Lisp_Object y)
 {
@@ -7021,8 +7267,6 @@ init_window_once (void)
   Vterminal_frame = selected_frame;
   minibuf_window = f->minibuffer_window;
   selected_window = f->selected_window;
-
-  window_initialized = 1;
 }
 
 void
@@ -7050,6 +7294,7 @@ syms_of_window (void)
   DEFSYM (Qdelete_window, "delete-window");
   DEFSYM (Qwindow_resize_root_window, "window--resize-root-window");
   DEFSYM (Qwindow_resize_root_window_vertically, "window--resize-root-window-vertically");
+  DEFSYM (Qwindow_sanitize_window_sizes, "window--sanitize-window-sizes");
   DEFSYM (Qwindow_pixel_to_total, "window--pixel-to-total");
   DEFSYM (Qsafe, "safe");
   DEFSYM (Qdisplay_buffer, "display-buffer");
@@ -7061,6 +7306,8 @@ syms_of_window (void)
   DEFSYM (Qabove, "above");
   DEFSYM (Qbelow, "below");
   DEFSYM (Qclone_of, "clone-of");
+  DEFSYM (Qfloor, "floor");
+  DEFSYM (Qceiling, "ceiling");
 
   staticpro (&Vwindow_list);
 
@@ -7091,7 +7338,7 @@ is displayed in the `mode-line' face.  */);
   mode_line_in_non_selected_windows = 1;
 
   DEFVAR_LISP ("other-window-scroll-buffer", Vother_window_scroll_buffer,
-              doc: /* If non-nil, this is a buffer and \\[scroll-other-window] should scroll its window.  */);
+              doc: /* If this is a live buffer, \\[scroll-other-window] should scroll its window.  */);
   Vother_window_scroll_buffer = Qnil;
 
   DEFVAR_BOOL ("auto-window-vscroll", auto_window_vscroll_p,
@@ -7118,6 +7365,7 @@ on their symbols to be controlled by this variable.  */);
   DEFVAR_LISP ("window-point-insertion-type", Vwindow_point_insertion_type,
               doc: /* Type of marker to use for `window-point'.  */);
   Vwindow_point_insertion_type = Qnil;
+  DEFSYM (Qwindow_point_insertion_type, "window_point_insertion_type");
 
   DEFVAR_LISP ("window-configuration-change-hook",
               Vwindow_configuration_change_hook,
@@ -7210,11 +7458,10 @@ respectively are not installed by `window-state-put'.  */);
   Vwindow_persistent_parameters = list1 (Fcons (Qclone_of, Qt));
 
   DEFVAR_BOOL ("window-resize-pixelwise", window_resize_pixelwise,
-              doc: /*  Non-nil means resizing windows works pixelwise.
-Functions currently affected by this option are `split-window',
-`maximize-window', `minimize-window', `fit-window-to-buffer' and
-`fit-frame-to-buffer' and all functions symmetrically resizing a
-parent window.
+              doc: /*  Non-nil means resize windows pixelwise.
+This currently affects the functions: `split-window', `maximize-window',
+`minimize-window', `fit-window-to-buffer' and `fit-frame-to-buffer', and
+all functions that symmetrically resize a parent window.
 
 Note that when a frame's pixel size is not a multiple of the
 frame's character size, at least one window may get resized
@@ -7273,12 +7520,15 @@ pixelwise even if this option is nil.  */);
   defsubr (&Swindow_header_line_height);
   defsubr (&Swindow_right_divider_width);
   defsubr (&Swindow_bottom_divider_width);
+  defsubr (&Swindow_scroll_bar_width);
+  defsubr (&Swindow_scroll_bar_height);
   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);
+  defsubr (&Swindow_old_point);
   defsubr (&Swindow_start);
   defsubr (&Swindow_end);
   defsubr (&Sset_window_point);