]> code.delx.au - gnu-emacs/blobdiff - src/window.c
Use bool for boolean in textprop.c, undo.c
[gnu-emacs] / src / window.c
index aafa4a16df1a9e7eca25160a7b8e86de530eb235..0fcf82d43f4a93e62e54ae9d6bd72b1c95f68772 100644 (file)
@@ -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"
@@ -44,41 +45,19 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 #include "msdos.h"
 #endif
 
-Lisp_Object Qwindowp, Qwindow_live_p;
-static Lisp_Object Qwindow_valid_p;
-static Lisp_Object Qwindow_configuration_p;
-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_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 *);
-static int get_leaf_windows (struct window *, struct window **, int);
-static void window_scroll (Lisp_Object, EMACS_INT, bool, int);
-static void window_scroll_pixel_based (Lisp_Object, int, bool, int);
-static void window_scroll_line_based (Lisp_Object, int, bool, int);
-static int add_window_to_list (struct window *, void *);
-static Lisp_Object next_window (Lisp_Object, Lisp_Object,
-                                Lisp_Object, int);
-static void decode_next_window_args (Lisp_Object *, Lisp_Object *,
-                                     Lisp_Object *);
+static ptrdiff_t count_windows (struct window *);
+static ptrdiff_t get_leaf_windows (struct window *, struct window **,
+                                  ptrdiff_t);
+static void window_scroll_pixel_based (Lisp_Object, int, bool, bool);
+static void window_scroll_line_based (Lisp_Object, int, bool, bool);
 static void foreach_window (struct frame *,
-                                int (* fn) (struct window *, void *),
+                           bool (* fn) (struct window *, void *),
                             void *);
-static int foreach_window_1 (struct window *,
-                             int (* fn) (struct window *, void *),
-                             void *);
-static Lisp_Object window_list_1 (Lisp_Object, Lisp_Object, Lisp_Object);
-static int window_resize_check (struct window *, bool);
+static bool foreach_window_1 (struct window *,
+                             bool (* fn) (struct window *, void *),
+                             void *);
+static bool window_resize_check (struct window *, bool);
 static void window_resize_apply (struct window *, bool);
-static void window_resize_apply_total (struct window *, bool);
-static Lisp_Object select_window (Lisp_Object, Lisp_Object, int);
 static void select_window_1 (Lisp_Object, bool);
 
 static struct window *set_window_fringes (struct window *, Lisp_Object,
@@ -86,7 +65,8 @@ 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
@@ -113,17 +93,8 @@ Lisp_Object minibuf_window;
    shown as the selected window when the minibuffer is selected.  */
 Lisp_Object minibuf_selected_window;
 
-/* Hook run at end of temp_output_buffer_show.  */
-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;
+static EMACS_INT sequence_number;
 
 /* Used by the function window_scroll_pixel_based.  */
 static int window_scroll_pixel_based_preserve_x;
@@ -145,66 +116,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)
 {
@@ -218,7 +208,7 @@ wset_combination (struct window *w, bool horflag, Lisp_Object val)
     w->horizontal = horflag;
 }
 
-/* Nonzero if leaf window W doesn't reflect the actual state
+/* True if leaf window W doesn't reflect the actual state
    of displayed buffer due to its text or overlays change.  */
 
 bool
@@ -281,7 +271,7 @@ adjust_window_count (struct window *w, int arg)
       b->window_count += arg;
       eassert (b->window_count >= 0);
       /* These should be recalculated by redisplay code.  */
-      w->window_end_valid = 0;
+      w->window_end_valid = false;
       w->base_line_pos = 0;
     }
 }
@@ -462,17 +452,18 @@ selected windows appears and to which many commands apply.  */)
   return selected_window;
 }
 
-int window_select_count;
+EMACS_INT window_select_count;
 
-/* If select_window is called with inhibit_point_swap non-zero it will
+/* If select_window is called with inhibit_point_swap true it will
    not store point of the old selected window's buffer back into that
    window's pointm slot.  This is needed by Fset_window_configuration to
    avoid that the display routine is called with selected_window set to
    Qnil causing a subsequent crash.  */
 static Lisp_Object
-select_window (Lisp_Object window, Lisp_Object norecord, int inhibit_point_swap)
+select_window (Lisp_Object window, Lisp_Object norecord,
+              bool inhibit_point_swap)
 {
-  register struct window *w;
+  struct window *w;
   struct frame *sf;
 
   CHECK_LIVE_WINDOW (window);
@@ -579,9 +570,9 @@ 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)
+  (Lisp_Object window, Lisp_Object norecord)
 {
-  return select_window (window, norecord, 0);
+  return select_window (window, norecord, false);
 }
 \f
 DEFUN ("window-buffer", Fwindow_buffer, Swindow_buffer, 0, 1, 0,
@@ -905,6 +896,9 @@ window_body_height (struct window *w, bool pixelwise)
 {
   int height = (w->pixel_height
                - WINDOW_HEADER_LINE_HEIGHT (w)
+               - (WINDOW_HAS_HORIZONTAL_SCROLL_BAR (w)
+                  ? WINDOW_SCROLL_BAR_AREA_HEIGHT (w)
+                  : 0)
                - WINDOW_MODE_LINE_HEIGHT (w)
                - WINDOW_BOTTOM_DIVIDER_WIDTH (w));
 
@@ -929,11 +923,10 @@ window_body_width (struct window *w, bool pixelwise)
               - 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))
+                 : (/* A vertical bar is either 1 or 0.  */
+                    !FRAME_WINDOW_P (f)
+                    && !WINDOW_RIGHTMOST_P (w)
+                    && !WINDOW_RIGHT_DIVIDER_WIDTH (w)))
                - WINDOW_MARGINS_WIDTH (w)
                - (FRAME_WINDOW_P (f)
                   ? WINDOW_FRINGES_WIDTH (w)
@@ -960,7 +953,7 @@ visible, that line is not counted.  */)
   (Lisp_Object window, Lisp_Object pixelwise)
 {
   return make_number (window_body_height (decode_live_window (window),
-                                         NILP (pixelwise) ? 0 : 1));
+                                         !NILP (pixelwise)));
 }
 
 DEFUN ("window-body-width", Fwindow_body_width, Swindow_body_width, 0, 2, 0,
@@ -980,7 +973,7 @@ continuation glyph.  */)
   (Lisp_Object window, Lisp_Object pixelwise)
 {
   return make_number (window_body_width (decode_live_window (window),
-                                        NILP (pixelwise) ? 0 : 1));
+                                        !NILP (pixelwise)));
 }
 
 DEFUN ("window-mode-line-height", Fwindow_mode_line_height,
@@ -1028,6 +1021,15 @@ WINDOW must be a live window and defaults to the selected one.  */)
   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.  */)
@@ -1052,9 +1054,11 @@ set_window_hscroll (struct window *w, EMACS_INT hscroll)
 
   /* Prevent redisplay shortcuts when changing the hscroll.  */
   if (w->hscroll != new_hscroll)
-    XBUFFER (w->contents)->prevent_redisplay_optimizations_p = 1;
+    XBUFFER (w->contents)->prevent_redisplay_optimizations_p = true;
 
   w->hscroll = new_hscroll;
+  w->suspend_auto_hscroll = true;
+
   return make_number (new_hscroll);
 }
 
@@ -1204,12 +1208,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)));
 }
@@ -1323,6 +1331,17 @@ coordinates_in_window (register struct window *w, int x, int y)
           && 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
@@ -1366,7 +1385,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);
@@ -1530,10 +1549,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;
 
@@ -1553,7 +1575,7 @@ If they are in the windows's left or right marginal areas, `left-margin'\n\
    Check if window W contains coordinates *CW->x and *CW->y.  If it
    does, return W in *CW->window, as Lisp_Object, and return in
    *CW->part the part of the window under coordinates *X,*Y.  Return
-   zero from this function to stop iterating over windows.  */
+   false from this function to stop iterating over windows.  */
 
 struct check_window_data
 {
@@ -1562,22 +1584,19 @@ struct check_window_data
   enum window_part *part;
 };
 
-static int
+static bool
 check_window_containing (struct window *w, void *user_data)
 {
   struct check_window_data *cw = user_data;
-  enum window_part found;
-  int continue_p = 1;
-
-  found = coordinates_in_window (w, cw->x, cw->y);
-  if (found != ON_NOTHING)
+  enum window_part found = coordinates_in_window (w, cw->x, cw->y);
+  if (found == ON_NOTHING)
+    return true;
+  else
     {
       *cw->part = found;
       XSETWINDOW (*cw->window, w);
-      continue_p = 0;
+      return false;
     }
-
-  return continue_p;
 }
 
 
@@ -1588,7 +1607,7 @@ check_window_containing (struct window *w, void *user_data)
    set *PART to the id of that element.
 
    If there is no window under X, Y return nil and leave *PART
-   unmodified.  TOOL_BAR_P non-zero means detect tool-bar windows.
+   unmodified.  TOOL_BAR_P means detect tool-bar windows.
 
    This function was previously implemented with a loop cycling over
    windows with Fnext_window, and starting with the frame's selected
@@ -1650,7 +1669,7 @@ column 0.  */)
                                   + FRAME_INTERNAL_BORDER_WIDTH (f)),
                                  (FRAME_PIXEL_Y_FROM_CANON_Y (f, y)
                                   + FRAME_INTERNAL_BORDER_WIDTH (f)),
-                                 0, 0);
+                                 0, false);
 }
 
 DEFUN ("window-point", Fwindow_point, Swindow_point, 0, 1, 0,
@@ -1674,6 +1693,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.
@@ -1749,7 +1776,7 @@ if it isn't already recorded.  */)
       if (it.current_y < it.last_visible_y)
        move_it_past_eol (&it);
       value = make_number (IT_CHARPOS (it));
-      bidi_unshelve_cache (itdata, 0);
+      bidi_unshelve_cache (itdata, false);
 
       if (old_buffer)
        set_buffer_internal (old_buffer);
@@ -1807,12 +1834,12 @@ overriding motion of point in order to display at this exact start.  */)
 
   set_marker_restricted (w->start, pos, w->contents);
   /* This is not right, but much easier than doing what is right.  */
-  w->start_at_line_beg = 0;
+  w->start_at_line_beg = false;
   if (NILP (noforce))
-    w->force_start = 1;
-  w->update_mode_line = 1;
+    w->force_start = true;
+  w->update_mode_line = true;
   /* Bug#15957.  */
-  w->window_end_valid = 0;
+  w->window_end_valid = false;
   wset_redisplay (w);
 
   return pos;
@@ -1840,12 +1867,13 @@ POS, ROWH is the visible height of that row, and VPOS is the row number
 \(zero-based).  */)
   (Lisp_Object pos, Lisp_Object window, Lisp_Object partially)
 {
-  register struct window *w;
-  register EMACS_INT posint;
-  register struct buffer *buf;
+  struct window *w;
+  EMACS_INT posint;
+  struct buffer *buf;
   struct text_pos top;
   Lisp_Object in_window = Qnil;
-  int rtop, rbot, rowh, vpos, fully_p = 1;
+  int rtop, rbot, rowh, vpos;
+  bool fully_p = true;
   int x, y;
 
   w = decode_live_window (window);
@@ -1870,9 +1898,12 @@ POS, ROWH is the visible height of that row, and VPOS is the row number
        || (posint >= CHARPOS (top) && posint <= BUF_ZV (buf)))
       && CHARPOS (top) >= BUF_BEGV (buf)
       && CHARPOS (top) <= BUF_ZV (buf)
-      && pos_visible_p (w, posint, &x, &y, &rtop, &rbot, &rowh, &vpos)
-      && (fully_p = !rtop && !rbot, (!NILP (partially) || fully_p)))
-    in_window = Qt;
+      && pos_visible_p (w, posint, &x, &y, &rtop, &rbot, &rowh, &vpos))
+    {
+      fully_p = !rtop && !rbot;
+      if (!NILP (partially) || fully_p)
+       in_window = Qt;
+    }
 
   if (!NILP (in_window) && !NILP (partially))
     {
@@ -2177,7 +2208,7 @@ unshow_buffer (register struct window *w)
 
   eassert (b == XMARKER (w->pointm)->buffer);
 
-#if 0
+#if false
   if (w == XWINDOW (selected_window)
       || ! EQ (buf, XWINDOW (selected_window)->contents))
     /* Do this except when the selected window's buffer
@@ -2216,14 +2247,14 @@ unshow_buffer (register struct window *w)
     bset_last_selected_window (b, Qnil);
 }
 
-/* Put NEW into the window structure in place of OLD.  SETFLAG zero
+/* Put NEW into the window structure in place of OLD.  SETFLAG false
    means change window structure only.  Otherwise store geometry and
    other settings as well.  */
 static void
-replace_window (Lisp_Object old, Lisp_Object new, int setflag)
+replace_window (Lisp_Object old, Lisp_Object new, bool setflag)
 {
-  register Lisp_Object tem;
-  register struct window *o = XWINDOW (old), *n = XWINDOW (new);
+  Lisp_Object tem;
+  struct window *o = XWINDOW (old), *n = XWINDOW (new);
 
   /* If OLD is its frame's root window, then NEW is the new
      root window for that frame.  */
@@ -2253,11 +2284,11 @@ replace_window (Lisp_Object old, Lisp_Object new, int setflag)
       n->phys_cursor_type = NO_CURSOR;
       n->phys_cursor_width = -1;
 #endif
-      n->must_be_updated_p = 0;
-      n->pseudo_window_p = 0;
+      n->must_be_updated_p = false;
+      n->pseudo_window_p = false;
       n->window_end_vpos = 0;
       n->window_end_pos = 0;
-      n->window_end_valid = 0;
+      n->window_end_valid = false;
     }
 
   tem = o->next;
@@ -2342,7 +2373,7 @@ recombine_windows (Lisp_Object window)
            }
 
          /* WINDOW can be deleted now.  */
-         wset_combination (w, 0, Qnil);
+         wset_combination (w, false, Qnil);
        }
     }
 }
@@ -2363,14 +2394,14 @@ delete_deletable_window (Lisp_Object window)
    pointer.  This is a callback function for foreach_window, used in
    the window_list function.  */
 
-static int
+static bool
 add_window_to_list (struct window *w, void *user_data)
 {
   Lisp_Object *list = user_data;
   Lisp_Object window;
   XSETWINDOW (window, w);
   *list = Fcons (window, *list);
-  return 1;
+  return true;
 }
 
 
@@ -2388,16 +2419,14 @@ window_list (void)
       Vwindow_list = Qnil;
       FOR_EACH_FRAME (tail, frame)
        {
-         Lisp_Object args[2];
+         Lisp_Object arglist = Qnil;
 
          /* We are visiting windows in canonical order, and add
             new windows at the front of args[1], which means we
             have to reverse this list at the end.  */
-         args[1] = Qnil;
-         foreach_window (XFRAME (frame), add_window_to_list, &args[1]);
-         args[0] = Vwindow_list;
-         args[1] = Fnreverse (args[1]);
-         Vwindow_list = Fnconc (2, args);
+         foreach_window (XFRAME (frame), add_window_to_list, &arglist);
+         arglist = Fnreverse (arglist);
+         Vwindow_list = CALLN (Fnconc, Vwindow_list, arglist);
        }
     }
 
@@ -2405,7 +2434,7 @@ window_list (void)
 }
 
 
-/* Value is non-zero if WINDOW satisfies the constraints given by
+/* Value is true if WINDOW satisfies the constraints given by
    OWINDOW, MINIBUF and ALL_FRAMES.
 
    MINIBUF     t means WINDOW may be minibuffer windows.
@@ -2427,20 +2456,20 @@ candidate_window_p (Lisp_Object window, Lisp_Object owindow,
 {
   struct window *w = XWINDOW (window);
   struct frame *f = XFRAME (w->frame);
-  bool candidate_p = 1;
+  bool candidate_p = true;
 
   if (!BUFFERP (w->contents))
-    candidate_p = 0;
+    candidate_p = false;
   else if (MINI_WINDOW_P (w)
            && (EQ (minibuf, Qlambda)
               || (WINDOWP (minibuf) && !EQ (minibuf, window))))
     {
       /* If MINIBUF is `lambda' don't consider any mini-windows.
          If it is a window, consider only that one.  */
-      candidate_p = 0;
+      candidate_p = false;
     }
   else if (EQ (all_frames, Qt))
-    candidate_p = 1;
+    candidate_p = true;
   else if (NILP (all_frames))
     {
       eassert (WINDOWP (owindow));
@@ -2520,12 +2549,13 @@ decode_next_window_args (Lisp_Object *window, Lisp_Object *minibuf, Lisp_Object
 
 
 /* Return the next or previous window of WINDOW in cyclic ordering
-   of windows.  NEXT_P non-zero means return the next window.  See the
+   of windows.  NEXT_P means return the next window.  See the
    documentation string of next-window for the meaning of MINIBUF and
    ALL_FRAMES.  */
 
 static Lisp_Object
-next_window (Lisp_Object window, Lisp_Object minibuf, Lisp_Object all_frames, int next_p)
+next_window (Lisp_Object window, Lisp_Object minibuf, Lisp_Object all_frames,
+            bool next_p)
 {
   decode_next_window_args (&window, &minibuf, &all_frames);
 
@@ -2623,7 +2653,7 @@ windows, eventually ending up back at the window you started with.
 `previous-window' traverses the same cycle, in the reverse order.  */)
   (Lisp_Object window, Lisp_Object minibuf, Lisp_Object all_frames)
 {
-  return next_window (window, minibuf, all_frames, 1);
+  return next_window (window, minibuf, all_frames, true);
 }
 
 
@@ -2663,7 +2693,7 @@ started with.  `next-window' traverses the same cycle, in the
 reverse order.  */)
   (Lisp_Object window, Lisp_Object minibuf, Lisp_Object all_frames)
 {
-  return next_window (window, minibuf, all_frames, 0);
+  return next_window (window, minibuf, all_frames, false);
 }
 
 
@@ -2761,7 +2791,7 @@ be listed first but no error is signaled.  */)
                 Qnil, look at just the selected frame;
                Qvisible, look at visible frames;
                a frame, just look at windows on that frame.
-   If MINI is non-zero, perform the operation on minibuffer windows too.  */
+   If MINI, perform the operation on minibuffer windows too.  */
 
 enum window_loop
 {
@@ -2773,10 +2803,11 @@ enum window_loop
 };
 
 static Lisp_Object
-window_loop (enum window_loop type, Lisp_Object obj, int mini, Lisp_Object frames)
+window_loop (enum window_loop type, Lisp_Object obj, bool mini,
+            Lisp_Object frames)
 {
   Lisp_Object window, windows, best_window, frame_arg;
-  int frame_best_window_flag = 0;
+  bool frame_best_window_flag = false;
   struct frame *f;
   struct gcpro gcpro1;
 
@@ -2836,7 +2867,7 @@ window_loop (enum window_loop type, Lisp_Object obj, int mini, Lisp_Object frame
            if (EQ (w->contents, obj)
                /* Don't find any minibuffer window except the one that
                   is currently in use.  */
-               && (MINI_WINDOW_P (w) ? EQ (window, minibuf_window) : 1))
+               && (!MINI_WINDOW_P (w) || EQ (window, minibuf_window)))
              {
                if (EQ (window, selected_window))
                  /* Preferably return the selected window.  */
@@ -2847,7 +2878,7 @@ window_loop (enum window_loop type, Lisp_Object obj, int mini, Lisp_Object frame
                     choose another one if we have one already).  */
                  {
                    best_window = window;
-                   frame_best_window_flag = 1;
+                   frame_best_window_flag = true;
                  }
                else if (NILP (best_window))
                  best_window = window;
@@ -2864,7 +2895,7 @@ window_loop (enum window_loop type, Lisp_Object obj, int mini, Lisp_Object frame
                /* Make WINDOW show the buffer returned by
                   other_buffer_safely, don't run any hooks.  */
                set_window_buffer
-                 (window, other_buffer_safely (w->contents), 0, 0);
+                 (window, other_buffer_safely (w->contents), false, false);
                /* If WINDOW is the selected window, make its buffer
                   current.  But do so only if the window shows the
                   current buffer (Bug#6454).  */
@@ -2877,9 +2908,9 @@ window_loop (enum window_loop type, Lisp_Object obj, int mini, Lisp_Object frame
          case REDISPLAY_BUFFER_WINDOWS:
            if (EQ (w->contents, obj))
              {
-               mark_window_display_accurate (window, 0);
-               w->update_mode_line = 1;
-               XBUFFER (obj)->prevent_redisplay_optimizations_p = 1;
+               mark_window_display_accurate (window, false);
+               w->update_mode_line = true;
+               XBUFFER (obj)->prevent_redisplay_optimizations_p = true;
                update_mode_lines = 27;
                best_window = window;
              }
@@ -2916,7 +2947,7 @@ extern void check_all_windows (void) EXTERNALLY_VISIBLE;
 void
 check_all_windows (void)
 {
-  window_loop (CHECK_ALL_WINDOWS, Qnil, 1, Qt);
+  window_loop (CHECK_ALL_WINDOWS, Qnil, true, Qt);
 }
 
 DEFUN ("get-buffer-window", Fget_buffer_window, Sget_buffer_window, 0, 2, 0,
@@ -2947,22 +2978,39 @@ selected frame and no others.  */)
     buffer = Fget_buffer (buffer_or_name);
 
   if (BUFFERP (buffer))
-    return window_loop (GET_BUFFER_WINDOW, buffer, 1, all_frames);
+    return window_loop (GET_BUFFER_WINDOW, buffer, true, all_frames);
   else
     return Qnil;
 }
 
+
 static Lisp_Object
 resize_root_window (Lisp_Object window, Lisp_Object delta, Lisp_Object horizontal, Lisp_Object ignore, Lisp_Object pixelwise)
 {
   return call5 (Qwindow_resize_root_window, window, delta, horizontal, ignore, pixelwise);
 }
 
+/* Placeholder used by temacs -nw before window.el is loaded.  */
+DEFUN ("window--sanitize-window-sizes", Fwindow__sanitize_window_sizes,
+       Swindow__sanitize_window_sizes, 2, 2, 0,
+       doc: /* */
+       attributes: const)
+     (Lisp_Object frame, Lisp_Object horizontal)
+{
+  return Qnil;
+}
+
+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);
 }
 
 
@@ -2987,7 +3035,7 @@ window-start value is reasonable when this function is called.  */)
   struct frame *f;
   Lisp_Object sibling, pwindow, swindow IF_LINT (= Qnil), delta;
   ptrdiff_t startpos IF_LINT (= 0), startbyte IF_LINT (= 0);
-  int top IF_LINT (= 0), new_top, resize_failed;
+  int top IF_LINT (= 0), new_top;
 
   w = decode_valid_window (window);
   XSETWINDOW (window, w);
@@ -3044,7 +3092,7 @@ window-start value is reasonable when this function is called.  */)
         parents and comparing each one with WINDOW.  If it isn't we
         need a new selected window for this frame.  */
       swindow = FRAME_SELECTED_WINDOW (f);
-      while (1)
+      while (true)
        {
          pwindow = swindow;
          while (!NILP (pwindow) && !EQ (window, pwindow))
@@ -3076,7 +3124,7 @@ window-start value is reasonable when this function is called.  */)
       /* We are going to free the glyph matrices of WINDOW, and with
         that we might lose any information about glyph rows that have
         some of their glyphs highlighted in mouse face.  (These rows
-        are marked with a non-zero mouse_face_p flag.)  If WINDOW
+        are marked with a mouse_face_p flag.)  If WINDOW
         indeed has some glyphs highlighted in mouse face, signal to
         frame's up-to-date hook that mouse highlight was overwritten,
         so that it will arrange for redisplaying the highlight.  */
@@ -3087,8 +3135,8 @@ window-start value is reasonable when this function is called.  */)
 
   fset_redisplay (f);
   Vwindow_list = Qnil;
-  FRAME_WINDOW_SIZES_CHANGED (f) = 1;
-  resize_failed = 0;
+  FRAME_WINDOW_SIZES_CHANGED (f) = true;
+  bool resize_failed = false;
 
   if (!WINDOW_LEAF_P (w))
     {
@@ -3097,21 +3145,21 @@ window-start value is reasonable when this function is called.  */)
       w->pixel_top = r->pixel_top;
       w->top_line = r->top_line;
       resize_root_window (window, delta, Qnil, Qnil, Qt);
-      if (window_resize_check (w, 0))
+      if (window_resize_check (w, false))
        {
-         window_resize_apply (w, 0);
+         window_resize_apply (w, false);
          window_pixel_to_total (w->frame, Qnil);
        }
       else
        {
          resize_root_window (window, delta, Qnil, Qt, Qt);
-         if (window_resize_check (w, 0))
+         if (window_resize_check (w, false))
            {
-             window_resize_apply (w, 0);
+             window_resize_apply (w, false);
              window_pixel_to_total (w->frame, Qnil);
            }
          else
-           resize_failed = 1;
+           resize_failed = true;
        }
 
       /* Resize child windows horizontally.  */
@@ -3121,21 +3169,21 @@ window-start value is reasonable when this function is called.  */)
          w->pixel_left = r->pixel_left;
          XSETINT (delta, r->pixel_width - w->pixel_width);
          resize_root_window (window, delta, Qt, Qnil, Qt);
-         if (window_resize_check (w, 1))
+         if (window_resize_check (w, true))
            {
-             window_resize_apply (w, 1);
+             window_resize_apply (w, true);
              window_pixel_to_total (w->frame, Qt);
            }
          else
            {
              resize_root_window (window, delta, Qt, Qt, Qt);
-             if (window_resize_check (w, 1))
+             if (window_resize_check (w, true))
                {
-                 window_resize_apply (w, 1);
+                 window_resize_apply (w, true);
                  window_pixel_to_total (w->frame, Qt);
                }
              else
-               resize_failed = 1;
+               resize_failed = true;
            }
        }
 
@@ -3171,10 +3219,10 @@ window-start value is reasonable when this function is called.  */)
   if (WINDOWP (r->contents))
     {
       delete_all_child_windows (r->contents);
-      wset_combination (r, 0, Qnil);
+      wset_combination (r, false, Qnil);
     }
 
-  replace_window (root, window, 1);
+  replace_window (root, window, true);
 
   /* This must become SWINDOW anyway .......  */
   if (BUFFERP (w->contents) && !resize_failed)
@@ -3198,12 +3246,12 @@ window-start value is reasonable when this function is called.  */)
          pos = *vmotion (startpos, startbyte, -top, w);
 
          set_marker_both (w->start, w->contents, pos.bufpos, pos.bytepos);
-         w->window_end_valid = 0;
+         w->window_end_valid = false;
          w->start_at_line_beg = (pos.bytepos == BEGV_BYTE
                                    || FETCH_BYTE (pos.bytepos - 1) == '\n');
          /* We need to do this, so that the window-scroll-functions
             get called.  */
-         w->optional_new_start = 1;
+         w->optional_new_start = true;
 
          set_buffer_internal (obuf);
        }
@@ -3238,90 +3286,7 @@ replace_buffer_in_windows_safely (Lisp_Object buffer)
         considers frames on the current keyboard.  So loop manually over
         frames, and handle each one.  */
       FOR_EACH_FRAME (tail, frame)
-       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);
-      min_height += FRAME_INTERNAL_BORDER_WIDTH (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;
+       window_loop (REPLACE_BUFFER_IN_WINDOWS_SAFELY, buffer, true, frame);
     }
 }
 \f
@@ -3357,7 +3322,9 @@ 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->can_x_set_window_size)
+      || !(f->after_make_frame))
     return;
 
   /* Use the right buffer.  Matters when running the local hooks.  */
@@ -3419,9 +3386,9 @@ If WINDOW is omitted or nil, it defaults to the selected window.  */)
   return Qnil;
 }
 
-/* Make WINDOW display BUFFER.  RUN_HOOKS_P non-zero means it's allowed
+/* Make WINDOW display BUFFER.  RUN_HOOKS_P means it's allowed
    to run hooks.  See make_frame for a case where it's not allowed.
-   KEEP_MARGINS_P non-zero means that the current margins, fringes, and
+   KEEP_MARGINS_P means that the current margins, fringes, and
    scroll-bar settings of the window are not reset from the buffer's
    local settings.  */
 
@@ -3452,38 +3419,39 @@ 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 = false;
       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);
-      w->start_at_line_beg = 0;
-      w->force_start = 0;
+      w->start_at_line_beg = false;
+      w->force_start = false;
     }
   /* Maybe we could move this into the `if' but it's not obviously safe and
      I doubt it's worth the trouble.  */
   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)
     {
@@ -3492,7 +3460,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);
@@ -3559,7 +3529,7 @@ This function runs `window-scroll-functions' before running
       unshow_buffer (w);
     }
 
-  set_window_buffer (window, buffer, 1, !NILP (keep_margins));
+  set_window_buffer (window, buffer, true, !NILP (keep_margins));
 
   return Qnil;
 }
@@ -3588,10 +3558,10 @@ displaying that buffer.  */)
   if (WINDOWP (object))
     {
       struct window *w = XWINDOW (object);
-      mark_window_display_accurate (object, 0);
-      w->update_mode_line = 1;
+      mark_window_display_accurate (object, false);
+      w->update_mode_line = true;
       if (BUFFERP (w->contents))
-       XBUFFER (w->contents)->prevent_redisplay_optimizations_p = 1;
+       XBUFFER (w->contents)->prevent_redisplay_optimizations_p = true;
       update_mode_lines = 29;
       return Qt;
     }
@@ -3603,7 +3573,7 @@ displaying that buffer.  */)
     {
       /* If buffer is live and shown in at least one window, find
         all windows showing this buffer and force update of them.  */
-      object = window_loop (REDISPLAY_BUFFER_WINDOWS, object, 0, Qvisible);
+      object = window_loop (REDISPLAY_BUFFER_WINDOWS, object, false, Qvisible);
       return NILP (object) ? Qnil : Qt;
     }
 
@@ -3638,10 +3608,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 = false;
       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.  */
@@ -3659,14 +3630,23 @@ temp_output_buffer_show (register Lisp_Object buf)
         record_unwind_protect (select_window_norecord, prev_window);
         Fselect_window (window, Qt);
         Fset_buffer (w->contents);
-        Frun_hooks (1, &Qtemp_buffer_show_hook);
+        run_hook (Qtemp_buffer_show_hook);
         unbind_to (count, Qnil);
       }
     }
 }
-\f
+
+/* Allocate basically initialized window.  */
+
+static struct window *
+allocate_window (void)
+{
+  return ALLOCATE_ZEROED_PSEUDOVECTOR
+    (struct window, current_matrix, PVEC_WINDOW);
+}
+
 /* Make new window, have it replace WINDOW in window-tree, and make
-   WINDOW its only vertical child (HORFLAG means make WINDOW its only
+   WINDOW its only vertical child (HORFLAG means make WINDOW its only
    horizontal child).   */
 static void
 make_parent_window (Lisp_Object window, bool horflag)
@@ -3685,7 +3665,7 @@ make_parent_window (Lisp_Object window, bool horflag)
 
   p->sequence_number = ++sequence_number;
 
-  replace_window (window, parent, 1);
+  replace_window (window, parent, true);
 
   wset_next (o, Qnil);
   wset_prev (o, Qnil);
@@ -3693,6 +3673,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);
@@ -3716,7 +3697,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);
@@ -3733,8 +3716,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.  */
@@ -3811,14 +3794,14 @@ Note: This function does not operate on any child windows of WINDOW.  */)
   return size;
 }
 
-/* Return 1 if setting w->pixel_height (w->pixel_width if HORFLAG is
-   non-zero) to w->new_pixel would result in correct heights (widths)
+/* Return true if setting w->pixel_height (w->pixel_width if HORFLAG)
+   to w->new_pixel would result in correct heights (widths)
    for window W and recursively all child windows of W.
 
    Note: This function does not check any of `window-fixed-size-p',
    `window-min-height' or `window-min-width'.  It does check that window
    sizes do not drop below one line (two columns). */
-static int
+static bool
 window_resize_check (struct window *w, bool horflag)
 {
   struct frame *f = XFRAME (w->frame);
@@ -3835,12 +3818,12 @@ window_resize_check (struct window *w, bool horflag)
            {
              if (XINT (c->new_pixel) != XINT (w->new_pixel)
                  || !window_resize_check (c, horflag))
-               return 0;
+               return false;
 
              c = NILP (c->next) ? 0 : XWINDOW (c->next);
            }
 
-         return 1;
+         return true;
        }
       else
        /* The sum of the heights of the child windows of W must equal
@@ -3851,11 +3834,11 @@ window_resize_check (struct window *w, bool horflag)
          while (c)
            {
              if (!window_resize_check (c, horflag))
-               return 0;
+               return false;
 
              remaining_pixels -= XINT (c->new_pixel);
              if (remaining_pixels < 0)
-               return 0;
+               return false;
              c = NILP (c->next) ? 0 : XWINDOW (c->next);
            }
 
@@ -3875,11 +3858,11 @@ window_resize_check (struct window *w, bool horflag)
          while (c)
            {
              if (!window_resize_check (c, horflag))
-               return 0;
+               return false;
 
              remaining_pixels -= XINT (c->new_pixel);
              if (remaining_pixels < 0)
-               return 0;
+               return false;
              c = NILP (c->next) ? 0 : XWINDOW (c->next);
            }
 
@@ -3892,12 +3875,12 @@ window_resize_check (struct window *w, bool horflag)
            {
              if (XINT (c->new_pixel) != XINT (w->new_pixel)
                  || !window_resize_check (c, horflag))
-               return 0;
+               return false;
 
              c = NILP (c->next) ? 0 : XWINDOW (c->next);
            }
 
-         return 1;
+         return true;
        }
     }
   else
@@ -3910,7 +3893,7 @@ window_resize_check (struct window *w, bool horflag)
 }
 
 
-/* Set w->pixel_height (w->pixel_width if HORFLAG is non-zero) to
+/* Set w->pixel_height (w->pixel_width if HORFLAG) 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.
@@ -3995,15 +3978,12 @@ window_resize_apply (struct window *w, bool horflag)
        }
     }
   else
-    {
-      adjust_window_margins (w);
-      /* Bug#15957.  */
-      w->window_end_valid = 0;
-    }
+    /* Bug#15957.  */
+    w->window_end_valid = false;
 }
 
 
-/* Set w->total_lines (w->total_cols if HORFLAG is non-zero) to
+/* Set w->total_lines (w->total_cols if HORFLAG) 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.  */
@@ -4098,7 +4078,7 @@ be applied on the Elisp level.  */)
   window_resize_apply (r, horflag);
 
   fset_redisplay (f);
-  FRAME_WINDOW_SIZES_CHANGED (f) = 1;
+  FRAME_WINDOW_SIZES_CHANGED (f) = true;
 
   adjust_frame_glyphs (f);
   unblock_input ();
@@ -4148,12 +4128,8 @@ values.  */)
 
 
 /* Resize frame F's windows when number of lines of F is set to SIZE.
-   HORFLAG 1 means resize windows when number of columns of F is set to
-   SIZE.  PIXELWISE 1 means to interpret SIZE as pixels.
-
-   This function can delete all windows but the selected one in order to
-   satisfy the request.  The result will be meaningful if and only if
-   F's windows have meaningful sizes when you call this.  */
+   HORFLAG means resize windows when number of columns of F is set to
+   SIZE.  PIXELWISE means to interpret SIZE as pixels.  */
 void
 resize_frame_windows (struct frame *f, int size, bool horflag, bool pixelwise)
 {
@@ -4164,6 +4140,7 @@ 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);
@@ -4178,7 +4155,6 @@ resize_frame_windows (struct frame *f, int size, bool horflag, bool pixelwise)
       new_pixel_size = max (horflag
                            ? size
                            : (size
-                              - FRAME_TOP_MARGIN_HEIGHT (f)
                               - ((FRAME_HAS_MINIBUF_P (f)
                                   && !FRAME_MINIBUF_ONLY_P (f))
                                  ? FRAME_LINE_HEIGHT (f) : 0)),
@@ -4187,13 +4163,9 @@ resize_frame_windows (struct frame *f, int size, bool horflag, bool pixelwise)
     }
   else
     {
-      new_size = max (horflag
-                     ? size
-                     : (size
-                        - FRAME_TOP_MARGIN (f)
-                        - ((FRAME_HAS_MINIBUF_P (f)
-                            && !FRAME_MINIBUF_ONLY_P (f))
-                           ? 1 : 0)),
+      new_size = max (size - (!horflag
+                             && FRAME_HAS_MINIBUF_P (f)
+                             && !FRAME_MINIBUF_ONLY_P (f)),
                      1);
       new_pixel_size = new_size * unit;
     }
@@ -4201,7 +4173,8 @@ resize_frame_windows (struct frame *f, int size, bool horflag, bool pixelwise)
   r->top_line = FRAME_TOP_MARGIN (f);
   r->pixel_top = FRAME_TOP_MARGIN_HEIGHT (f);
 
-  if (new_pixel_size == old_pixel_size)
+  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.  */
@@ -4243,6 +4216,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 false /* Let's try without safe sizes and/or killing other windows.  */
            }
          else
            {
@@ -4255,7 +4229,6 @@ 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 killing other windows.  */
              else
                {
                  /* We lost.  Delete all windows but the frame's
@@ -4273,7 +4246,7 @@ resize_frame_windows (struct frame *f, int size, bool horflag, bool pixelwise)
                      XWINDOW (root)->pixel_height = new_pixel_size;
                    }
                }
-#endif /* 0 */
+#endif /* false */
            }
        }
     }
@@ -4303,7 +4276,7 @@ resize_frame_windows (struct frame *f, int size, bool horflag, bool pixelwise)
 DEFUN ("split-window-internal", Fsplit_window_internal, Ssplit_window_internal, 4, 4, 0,
        doc: /* Split window OLD.
 Second argument PIXEL-SIZE specifies the number of pixels of the
-new window.  In any case TOTAL-SIZE must be a positive integer.
+new window.  It must be a positive integer.
 
 Third argument SIDE nil (or `below') specifies that the new window shall
 be located below WINDOW.  SIDE `above' means the new window shall be
@@ -4330,14 +4303,12 @@ set correctly.  See the code of `split-window' for how this is done.  */)
      provided OLD is a leaf window, or to the frame's selected window.
      NEW (*n) is the new window created with some parameters taken from
      REFERENCE (*r).  */
-  register Lisp_Object new, frame, reference;
-  register struct window *o, *p, *n, *r, *c;
+  Lisp_Object new, frame, reference;
+  struct window *o, *p, *n, *r, *c;
   struct frame *f;
   bool horflag
-    /* HORFLAG is 1 when we split side-by-side, 0 otherwise.  */
+    /* HORFLAG is true when we split side-by-side, false otherwise.  */
     = EQ (side, Qt) || EQ (side, Qleft) || EQ (side, Qright);
-  int combination_limit = 0, sum = 0;
-  int total_size;
 
   CHECK_WINDOW (old);
   o = XWINDOW (old);
@@ -4345,20 +4316,20 @@ set correctly.  See the code of `split-window' for how this is done.  */)
   f = XFRAME (frame);
 
   CHECK_NUMBER (pixel_size);
-  total_size
+  EMACS_INT total_size
     = XINT (pixel_size) / (horflag
                           ? FRAME_COLUMN_WIDTH (f)
                           : FRAME_LINE_HEIGHT (f));
 
-  /* Set combination_limit to 1 if we have to make a new parent window.
+  /* Set combination_limit if we have to make a new parent window.
      We do that if either `window-combination-limit' is t, or OLD has no
      parent, or OLD is ortho-combined.  */
-  combination_limit =
-    EQ (Vwindow_combination_limit, Qt)
-    || NILP (o->parent)
-    || (horflag
-       ? WINDOW_VERTICAL_COMBINATION_P (XWINDOW (o->parent))
-       : WINDOW_HORIZONTAL_COMBINATION_P (XWINDOW (o->parent)));
+  bool combination_limit
+    = (EQ (Vwindow_combination_limit, Qt)
+       || NILP (o->parent)
+       || (horflag
+          ? WINDOW_VERTICAL_COMBINATION_P (XWINDOW (o->parent))
+          : WINDOW_HORIZONTAL_COMBINATION_P (XWINDOW (o->parent))));
 
   /* We need a live reference window to initialize some parameters.  */
   if (WINDOW_LIVE_P (old))
@@ -4424,7 +4395,7 @@ set correctly.  See the code of `split-window' for how this is done.  */)
     p = XWINDOW (o->parent);
 
   fset_redisplay (f);
-  FRAME_WINDOW_SIZES_CHANGED (f) = 1;
+  FRAME_WINDOW_SIZES_CHANGED (f) = true;
   new = make_window ();
   n = XWINDOW (new);
   wset_frame (n, frame);
@@ -4449,7 +4420,7 @@ set correctly.  See the code of `split-window' for how this is done.  */)
       wset_next (o, new);
     }
 
-  n->window_end_valid = 0;
+  n->window_end_valid = false;
   n->last_cursor_vpos = 0;
 
   /* Get special geometry settings from reference window.  */
@@ -4459,7 +4430,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)
@@ -4480,6 +4453,7 @@ set correctly.  See the code of `split-window' for how this is done.  */)
   /* Iso-coordinates and sizes are assigned by window_resize_apply,
      get them ready here.  */
   wset_new_pixel (n, pixel_size);
+  EMACS_INT sum = 0;
   c = XWINDOW (p->contents);
   while (c)
     {
@@ -4498,7 +4472,7 @@ set correctly.  See the code of `split-window' for how this is done.  */)
   adjust_frame_glyphs (f);
   /* Set buffer of NEW to buffer of reference window.  Don't run
      any hooks.  */
-  set_window_buffer (new, r->contents, 0, 1);
+  set_window_buffer (new, r->contents, false, true);
   unblock_input ();
 
   /* Maybe we should run the scroll functions in Elisp (which already
@@ -4515,12 +4489,12 @@ DEFUN ("delete-window-internal", Fdelete_window_internal, Sdelete_window_interna
        doc: /* Remove WINDOW from its frame.
 WINDOW defaults to the selected window.  Return nil.
 Signal an error when WINDOW is the only window on its frame.  */)
-     (register Lisp_Object window)
+     (Lisp_Object window)
 {
-  register Lisp_Object parent, sibling, frame, root;
+  Lisp_Object parent, sibling, frame, root;
   struct window *w, *p, *s, *r;
   struct frame *f;
-  bool horflag, before_sibling = 0;
+  bool horflag, before_sibling = false;
 
   w = decode_any_window (window);
   XSETWINDOW (window, w);
@@ -4550,9 +4524,9 @@ Signal an error when WINDOW is the only window on its frame.  */)
   if (NILP (w->prev))
     /* Get SIBLING below (on the right of) WINDOW.  */
     {
-      /* before_sibling means WINDOW is the first child of its
+      /* before_sibling means WINDOW is the first child of its
         parent and thus before the sibling.  */
-      before_sibling = 1;
+      before_sibling = true;
       sibling = w->next;
       s = XWINDOW (sibling);
       wset_prev (s, Qnil);
@@ -4589,7 +4563,7 @@ Signal an error when WINDOW is the only window on its frame.  */)
 
       fset_redisplay (f);
       Vwindow_list = Qnil;
-      FRAME_WINDOW_SIZES_CHANGED (f) = 1;
+      FRAME_WINDOW_SIZES_CHANGED (f) = true;
 
       wset_next (w, Qnil);  /* Don't delete w->next too.  */
       free_window_matrices (w);
@@ -4597,12 +4571,13 @@ Signal an error when WINDOW is the only window on its frame.  */)
       if (WINDOWP (w->contents))
        {
          delete_all_child_windows (w->contents);
-         wset_combination (w, 0, Qnil);
+         wset_combination (w, false, Qnil);
        }
       else
        {
          unshow_buffer (w);
          unchain_marker (XMARKER (w->pointm));
+         unchain_marker (XMARKER (w->old_pointm));
          unchain_marker (XMARKER (w->start));
          wset_buffer (w, Qnil);
        }
@@ -4612,13 +4587,13 @@ Signal an error when WINDOW is the only window on its frame.  */)
             PARENT.  */
        {
          /* Put SIBLING into PARENT's place.  */
-         replace_window (parent, sibling, 0);
+         replace_window (parent, sibling, false);
          /* Have SIBLING inherit the following three slot values from
             PARENT (the combination_limit slot is not inherited).  */
          wset_normal_cols (s, p->normal_cols);
          wset_normal_lines (s, p->normal_lines);
          /* Mark PARENT as deleted.  */
-         wset_combination (p, 0, Qnil);
+         wset_combination (p, false, Qnil);
          /* Try to merge SIBLING into its new parent.  */
          recombine_windows (sibling);
        }
@@ -4703,10 +4678,10 @@ grow_mini_window (struct window *w, int delta, bool pixelwise)
       r = XWINDOW (root);
       height = call3 (Qwindow_resize_root_window_vertically,
                      root, make_number (- delta), pixelwise ? Qt : Qnil);
-      if (INTEGERP (height) && window_resize_check (r, 0))
+      if (INTEGERP (height) && window_resize_check (r, false))
        {
          block_input ();
-         window_resize_apply (r, 0);
+         window_resize_apply (r, false);
 
          if (pixelwise)
            {
@@ -4758,10 +4733,10 @@ shrink_mini_window (struct window *w, bool pixelwise)
       delta = call3 (Qwindow_resize_root_window_vertically,
                     root, make_number (height - unit),
                     pixelwise ? Qt : Qnil);
-      if (INTEGERP (delta) && window_resize_check (r, 0))
+      if (INTEGERP (delta) && window_resize_check (r, false))
        {
          block_input ();
-         window_resize_apply (r, 0);
+         window_resize_apply (r, false);
 
          /* Shrink the mini-window.  */
          w->top_line = r->top_line + r->total_lines;
@@ -4800,12 +4775,12 @@ DEFUN ("resize-mini-window-internal", Fresize_mini_window_internal, Sresize_mini
 
   r = XWINDOW (FRAME_ROOT_WINDOW (f));
   height = r->pixel_height + w->pixel_height;
-  if (window_resize_check (r, 0)
+  if (window_resize_check (r, false)
       && XINT (w->new_pixel) > 0
       && height == XINT (r->new_pixel) + XINT (w->new_pixel))
     {
       block_input ();
-      window_resize_apply (r, 0);
+      window_resize_apply (r, false);
 
       w->pixel_height = XFASTINT (w->new_pixel);
       w->total_lines = w->pixel_height / FRAME_LINE_HEIGHT (f);
@@ -4813,7 +4788,7 @@ DEFUN ("resize-mini-window-internal", Fresize_mini_window_internal, Sresize_mini
       w->top_line = r->top_line + r->total_lines;
 
       fset_redisplay (f);
-      FRAME_WINDOW_SIZES_CHANGED (f) = 1;
+      FRAME_WINDOW_SIZES_CHANGED (f) = true;
       adjust_frame_glyphs (f);
       unblock_input ();
       return Qt;
@@ -4835,7 +4810,7 @@ mark_window_cursors_off (struct window *w)
       if (WINDOWP (w->contents))
        mark_window_cursors_off (XWINDOW (w->contents));
       else
-       w->phys_cursor_on_p = 0;
+       w->phys_cursor_on_p = false;
 
       w = NILP (w->next) ? 0 : XWINDOW (w->next);
     }
@@ -4864,26 +4839,32 @@ window_internal_height (struct window *w)
 
   return ht;
 }
+
 \f
 /************************************************************************
                           Window Scrolling
  ***********************************************************************/
 
-/* Scroll contents of window WINDOW up.  If WHOLE is non-zero, scroll
+/* Scroll contents of window WINDOW up.  If WHOLE, scroll
    N screen-fulls, which is defined as the height of the window minus
    next_screen_context_lines.  If WHOLE is zero, scroll up N lines
-   instead.  Negative values of N mean scroll down.  NOERROR non-zero
+   instead.  Negative values of N mean scroll down.  NOERROR
    means don't signal an error if we try to move over BEGV or ZV,
    respectively.  */
 
 static void
-window_scroll (Lisp_Object window, EMACS_INT n, bool whole, int noerror)
+window_scroll (Lisp_Object window, EMACS_INT n, bool whole, bool noerror)
 {
-  immediate_quit = 1;
+  ptrdiff_t count = SPECPDL_INDEX ();
+
+  immediate_quit = true;
   n = clip_to_bounds (INT_MIN, n, INT_MAX);
 
   wset_redisplay (XWINDOW (window));
 
+  if (whole && Vfast_but_imprecise_scrolling)
+    specbind (Qfontification_functions, Qnil);
+
   /* 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)))
@@ -4891,9 +4872,11 @@ window_scroll (Lisp_Object window, EMACS_INT n, bool whole, int noerror)
   else
     window_scroll_line_based (window, n, whole, noerror);
 
+  unbind_to (count, Qnil);
+
   /* Bug#15957.  */
-  XWINDOW (window)->window_end_valid = 0;
-  immediate_quit = 0;
+  XWINDOW (window)->window_end_valid = false;
+  immediate_quit = false;
 }
 
 
@@ -4902,18 +4885,20 @@ window_scroll (Lisp_Object window, EMACS_INT n, bool whole, int noerror)
    descriptions.  */
 
 static void
-window_scroll_pixel_based (Lisp_Object window, int n, bool whole, int noerror)
+window_scroll_pixel_based (Lisp_Object window, int n, bool whole, bool noerror)
 {
   struct it it;
   struct window *w = XWINDOW (window);
   struct text_pos start;
   int this_scroll_margin;
   /* True if we fiddled the window vscroll field without really scrolling.  */
-  int vscrolled = 0;
+  bool vscrolled = false;
   int x, y, rtop, rbot, rowh, vpos;
   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
@@ -4925,7 +4910,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))
     {
@@ -4950,11 +4935,11 @@ window_scroll_pixel_based (Lisp_Object window, int n, bool whole, int noerror)
        }
 
       start = it.current.pos;
-      bidi_unshelve_cache (itdata, 0);
+      bidi_unshelve_cache (itdata, false);
     }
   else if (auto_window_vscroll_p)
     {
-      if (rtop || rbot)                /* partially visible */
+      if (rtop || rbot)                /* Partially visible.  */
        {
          int px;
          int dy = frame_line_height;
@@ -5003,11 +4988,11 @@ window_scroll_pixel_based (Lisp_Object window, int n, bool whole, int noerror)
                    spos = min (XINT (Fline_end_position (Qnil)) + 1, ZV);
                  set_marker_restricted (w->start, make_number (spos),
                                         w->contents);
-                 w->start_at_line_beg = 1;
-                 w->update_mode_line = 1;
+                 w->start_at_line_beg = true;
+                 w->update_mode_line = true;
                  /* Set force_start so that redisplay_window will run the
                     window-scroll-functions.  */
-                 w->force_start = 1;
+                 w->force_start = true;
                  return;
                }
            }
@@ -5101,7 +5086,7 @@ window_scroll_pixel_based (Lisp_Object window, int n, bool whole, int noerror)
            }
          else
            {
-             bidi_unshelve_cache (itdata, 0);
+             bidi_unshelve_cache (itdata, false);
              if (noerror)
                return;
              else if (n < 0)   /* could happen with empty buffers */
@@ -5118,7 +5103,7 @@ window_scroll_pixel_based (Lisp_Object window, int n, bool whole, int noerror)
            w->vscroll = 0;
          else
            {
-             bidi_unshelve_cache (itdata, 0);
+             bidi_unshelve_cache (itdata, false);
              if (noerror)
                return;
              else
@@ -5128,10 +5113,10 @@ window_scroll_pixel_based (Lisp_Object window, int n, bool whole, int noerror)
 
       /* If control gets here, then we vscrolled.  */
 
-      XBUFFER (w->contents)->prevent_redisplay_optimizations_p = 1;
+      XBUFFER (w->contents)->prevent_redisplay_optimizations_p = true;
 
       /* Don't try to change the window start below.  */
-      vscrolled = 1;
+      vscrolled = true;
     }
 
   if (! vscrolled)
@@ -5152,10 +5137,10 @@ window_scroll_pixel_based (Lisp_Object window, int n, bool whole, int noerror)
                                  IT_BYTEPOS (it));
       bytepos = marker_byte_position (w->start);
       w->start_at_line_beg = (pos == BEGV || FETCH_BYTE (bytepos - 1) == '\n');
-      w->update_mode_line = 1;
+      w->update_mode_line = true;
       /* Set force_start so that redisplay_window will run the
         window-scroll-functions.  */
-      w->force_start = 1;
+      w->force_start = true;
     }
 
   /* The rest of this function uses current_y in a nonstandard way,
@@ -5188,8 +5173,8 @@ window_scroll_pixel_based (Lisp_Object window, int n, bool whole, int noerror)
             This is necessary because we set it.current_y to 0, above.  */
          move_it_to (&it, -1,
                      window_scroll_pixel_based_preserve_x,
-                     window_scroll_pixel_based_preserve_y
-                     - (WINDOW_WANTS_HEADER_LINE_P (w) ? 1 : 0 ),
+                     (window_scroll_pixel_based_preserve_y
+                      - WINDOW_WANTS_HEADER_LINE_P (w)),
                      -1, MOVE_TO_Y | MOVE_TO_X);
          SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it));
        }
@@ -5208,7 +5193,7 @@ window_scroll_pixel_based (Lisp_Object window, int n, bool whole, int noerror)
   else if (n < 0)
     {
       ptrdiff_t charpos, bytepos;
-      int partial_p;
+      bool partial_p;
 
       /* Save our position, for the
         window_scroll_pixel_based_preserve_y case.  */
@@ -5244,12 +5229,12 @@ window_scroll_pixel_based (Lisp_Object window, int n, bool whole, int noerror)
            {
              charpos = IT_CHARPOS (it);
              bytepos = IT_BYTEPOS (it);
-             bidi_unshelve_cache (it_data, 1);
+             bidi_unshelve_cache (it_data, true);
            }
          else
            {
              it = it2;
-             bidi_unshelve_cache (it_data, 0);
+             bidi_unshelve_cache (it_data, false);
            }
        }
 
@@ -5293,7 +5278,14 @@ window_scroll_pixel_based (Lisp_Object window, int n, bool whole, int noerror)
            SET_PT_BOTH (charpos, bytepos);
        }
     }
-  bidi_unshelve_cache (itdata, 0);
+  bidi_unshelve_cache (itdata, false);
+
+  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);
 }
 
 
@@ -5301,9 +5293,9 @@ window_scroll_pixel_based (Lisp_Object window, int n, bool whole, int noerror)
    See the comment of window_scroll for parameter descriptions.  */
 
 static void
-window_scroll_line_based (Lisp_Object window, int n, bool whole, int noerror)
+window_scroll_line_based (Lisp_Object window, int n, bool whole, bool noerror)
 {
-  register struct window *w = XWINDOW (window);
+  struct window *w = XWINDOW (window);
   /* Fvertical_motion enters redisplay, which can trigger
      fontification, which in turn can modify buffer text (e.g., if the
      fontification functions replace escape sequences with faces, as
@@ -5318,6 +5310,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.  */
@@ -5331,8 +5325,9 @@ window_scroll_line_based (Lisp_Object window, int n, bool whole, int noerror)
          || NILP (Fget (KVAR (current_kboard, Vlast_command), Qscroll_command)))
        {
          struct position posit
-           = *compute_motion (startpos, startbyte, 0, 0, 0,
+           = *compute_motion (startpos, startbyte, 0, 0, false,
                               PT, ht, 0, -1, w->hscroll, 0, w);
+
          window_scroll_preserve_vpos = posit.vpos;
          window_scroll_preserve_hpos = posit.hpos + w->hscroll;
        }
@@ -5346,14 +5341,14 @@ window_scroll_line_based (Lisp_Object window, int n, bool whole, int noerror)
 
   if (NILP (tem))
     {
-      Fvertical_motion (make_number (- (ht / 2)), window);
+      Fvertical_motion (make_number (- (ht / 2)), window, Qnil);
       startpos = PT;
       startbyte = PT_BYTE;
     }
 
   SET_PT_BOTH (startpos, startbyte);
   lose = n < 0 && PT == BEGV;
-  Fvertical_motion (make_number (n), window);
+  Fvertical_motion (make_number (n), window, Qnil);
   pos = PT;
   pos_byte = PT_BYTE;
   bolp = Fbolp ();
@@ -5376,16 +5371,16 @@ window_scroll_line_based (Lisp_Object window, int n, bool whole, int noerror)
 
       set_marker_restricted_both (w->start, w->contents, pos, pos_byte);
       w->start_at_line_beg = !NILP (bolp);
-      w->update_mode_line = 1;
+      w->update_mode_line = true;
       /* Set force_start so that redisplay_window will run
         the window-scroll-functions.  */
-      w->force_start = 1;
+      w->force_start = true;
 
       if (!NILP (Vscroll_preserve_screen_position)
          && (whole || !EQ (Vscroll_preserve_screen_position, Qt)))
        {
          SET_PT_BOTH (pos, pos_byte);
-         Fvertical_motion (original_pos, window);
+         Fvertical_motion (original_pos, window, Qnil);
        }
       /* If we scrolled forward, put point enough lines down
         that it is outside the scroll margin.  */
@@ -5396,7 +5391,7 @@ window_scroll_line_based (Lisp_Object window, int n, bool whole, int noerror)
          if (this_scroll_margin > 0)
            {
              SET_PT_BOTH (pos, pos_byte);
-             Fvertical_motion (make_number (this_scroll_margin), window);
+             Fvertical_motion (make_number (this_scroll_margin), window, Qnil);
              top_margin = PT;
            }
          else
@@ -5408,7 +5403,7 @@ window_scroll_line_based (Lisp_Object window, int n, bool whole, int noerror)
          else if (!NILP (Vscroll_preserve_screen_position))
            {
              SET_PT_BOTH (pos, pos_byte);
-             Fvertical_motion (original_pos, window);
+             Fvertical_motion (original_pos, window, Qnil);
            }
          else
            SET_PT (top_margin);
@@ -5420,7 +5415,8 @@ window_scroll_line_based (Lisp_Object window, int n, bool whole, int noerror)
          /* If we scrolled backward, put point near the end of the window
             but not within the scroll margin.  */
          SET_PT_BOTH (pos, pos_byte);
-         tem = Fvertical_motion (make_number (ht - this_scroll_margin), window);
+         tem = Fvertical_motion (make_number (ht - this_scroll_margin), window,
+                                 Qnil);
          if (XFASTINT (tem) == ht - this_scroll_margin)
            bottom_margin = PT;
          else
@@ -5434,10 +5430,10 @@ window_scroll_line_based (Lisp_Object window, int n, bool whole, int noerror)
              if (!NILP (Vscroll_preserve_screen_position))
                {
                  SET_PT_BOTH (pos, pos_byte);
-                 Fvertical_motion (original_pos, window);
+                 Fvertical_motion (original_pos, window, Qnil);
                }
              else
-               Fvertical_motion (make_number (-1), window);
+               Fvertical_motion (make_number (-1), window, Qnil);
            }
        }
     }
@@ -5448,6 +5444,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);
 }
 
 
@@ -5473,13 +5476,13 @@ scroll_command (Lisp_Object n, int direction)
     }
 
   if (NILP (n))
-    window_scroll (selected_window, direction, 1, 0);
+    window_scroll (selected_window, direction, true, false);
   else if (EQ (n, Qminus))
-    window_scroll (selected_window, -direction, 1, 0);
+    window_scroll (selected_window, -direction, true, false);
   else
     {
       n = Fprefix_numeric_value (n);
-      window_scroll (selected_window, XINT (n) * direction, 0, 0);
+      window_scroll (selected_window, XINT (n) * direction, false, false);
     }
 
   unbind_to (count, Qnil);
@@ -5584,20 +5587,22 @@ specifies the window to scroll.  This takes precedence over
 
   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);
+    window_scroll (window, 1, true, true);
   else if (EQ (arg, Qminus))
-    window_scroll (window, -1, 1, 1);
+    window_scroll (window, -1, true, true);
   else
     {
       if (CONSP (arg))
        arg = XCAR (arg);
       CHECK_NUMBER (arg);
-      window_scroll (window, XINT (arg), 0, 1);
+      window_scroll (window, XINT (arg), false, true);
     }
 
   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;
@@ -5623,6 +5628,8 @@ by this function.  This happens in an interactive call.  */)
   if (!NILP (set_minimum))
     w->min_hscroll = w->hscroll;
 
+  w->suspend_auto_hscroll = true;
+
   return result;
 }
 
@@ -5646,6 +5653,8 @@ by this function.  This happens in an interactive call.  */)
   if (!NILP (set_minimum))
     w->min_hscroll = w->hscroll;
 
+  w->suspend_auto_hscroll = true;
+
   return result;
 }
 
@@ -5692,7 +5701,7 @@ displayed_window_lines (struct window *w)
   start_display (&it, w, start);
   move_it_vertically (&it, height);
   bottom_y = line_bottom_y (&it);
-  bidi_unshelve_cache (itdata, 0);
+  bidi_unshelve_cache (itdata, false);
 
   /* rms: On a non-window display,
      the value of it.vpos at the bottom of the screen
@@ -5736,14 +5745,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;
+  bool center_p = false;
   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))
     {
@@ -5763,10 +5774,10 @@ and redisplay normally--don't erase and redraw the frame.  */)
          SET_FRAME_GARBAGED (WINDOW_XFRAME (w));
        }
 
-      center_p = 1;
+      center_p = true;
     }
-  else if (CONSP (arg)) /* Just C-u. */
-    center_p = 1;
+  else if (CONSP (arg)) /* Just C-u.  */
+    center_p = true;
   else
     {
       arg = Fprefix_numeric_value (arg);
@@ -5774,17 +5785,14 @@ 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
-     line counts would lead to strange effects.  */
-  if (FRAME_WINDOW_P (XFRAME (w->frame)))
+  /* Don't use redisplay code for initial frames, as the necessary
+     data structures might not be set up yet then.  */
+  if (!FRAME_INITIAL_P (XFRAME (w->frame)))
     {
       if (center_p)
        {
@@ -5797,7 +5805,7 @@ and redisplay normally--don't erase and redraw the frame.  */)
          move_it_vertically_backward (&it, window_box_height (w) / 2);
          charpos = IT_CHARPOS (it);
          bytepos = IT_BYTEPOS (it);
-         bidi_unshelve_cache (itdata, 0);
+         bidi_unshelve_cache (itdata, false);
        }
       else if (iarg < 0)
        {
@@ -5806,9 +5814,11 @@ and redisplay normally--don't erase and redraw the frame.  */)
          ptrdiff_t nlines = min (PTRDIFF_MAX, -iarg);
          int extra_line_spacing;
          int h = window_box_height (w);
+         int ht = window_internal_height (w);
          void *itdata = bidi_shelve_cache ();
 
-         iarg = - max (-iarg, this_scroll_margin);
+         nlines = clip_to_bounds (this_scroll_margin + 1, nlines,
+                                  ht - this_scroll_margin);
 
          SET_TEXT_POS (pt, PT, PT_BYTE);
          start_display (&it, w, pt);
@@ -5827,7 +5837,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++;
            }
@@ -5845,7 +5855,7 @@ and redisplay normally--don't erase and redraw the frame.  */)
            }
          if (h <= 0)
            {
-             bidi_unshelve_cache (itdata, 0);
+             bidi_unshelve_cache (itdata, false);
              return Qnil;
            }
 
@@ -5868,17 +5878,37 @@ and redisplay normally--don't erase and redraw the frame.  */)
          charpos = IT_CHARPOS (it);
          bytepos = IT_BYTEPOS (it);
 
-         bidi_unshelve_cache (itdata, 0);
+         bidi_unshelve_cache (itdata, false);
        }
       else
        {
-         struct position pos;
+         struct it it;
+         struct text_pos pt;
+         ptrdiff_t nlines = min (PTRDIFF_MAX, iarg);
+         int ht = window_internal_height (w);
+         void *itdata = bidi_shelve_cache ();
+
+         nlines = clip_to_bounds (this_scroll_margin, nlines,
+                                  ht - this_scroll_margin - 1);
+
+         SET_TEXT_POS (pt, PT, PT_BYTE);
+         start_display (&it, w, pt);
+
+         /* Move to the beginning of screen line containing PT.  */
+         move_it_by_lines (&it, 0);
 
-         iarg = max (iarg, this_scroll_margin);
+         /* Move back to find the point which is ARG screen lines above PT.  */
+         if (nlines > 0)
+           {
+             it.current_y = 0;
+             it.vpos = 0;
+             move_it_by_lines (&it, -nlines);
+           }
 
-         pos = *vmotion (PT, PT_BYTE, -iarg, w);
-         charpos = pos.bufpos;
-         bytepos = pos.bytepos;
+         charpos = IT_CHARPOS (it);
+         bytepos = IT_BYTEPOS (it);
+
+         bidi_unshelve_cache (itdata, false);
        }
     }
   else
@@ -5902,48 +5932,59 @@ and redisplay normally--don't erase and redraw the frame.  */)
 
   /* Set the new window start.  */
   set_marker_both (w->start, w->contents, charpos, bytepos);
-  w->window_end_valid = 0;
+  w->window_end_valid = false;
 
-  w->optional_new_start = 1;
+  w->optional_new_start = true;
 
-  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,
@@ -5957,7 +5998,7 @@ zero means top of window, negative means relative to bottom of window.  */)
   struct window *w = XWINDOW (selected_window);
   int lines, start;
   Lisp_Object window;
-#if 0
+#if false
   int this_scroll_margin;
 #endif
 
@@ -5971,17 +6012,17 @@ zero means top of window, negative means relative to bottom of window.  */)
   if (start < BEGV || start > ZV)
     {
       int height = window_internal_height (w);
-      Fvertical_motion (make_number (- (height / 2)), window);
+      Fvertical_motion (make_number (- (height / 2)), window, Qnil);
       set_marker_both (w->start, w->contents, PT, PT_BYTE);
       w->start_at_line_beg = !NILP (Fbolp ());
-      w->force_start = 1;
+      w->force_start = true;
     }
   else
     Fgoto_char (w->start);
 
   lines = displayed_window_lines (w);
 
-#if 0
+#if false
   this_scroll_margin = max (0, min (scroll_margin, lines / 4));
 #endif
 
@@ -5994,11 +6035,11 @@ zero means top of window, negative means relative to bottom of window.  */)
       if (iarg < 0)
        iarg = iarg + lines;
 
-#if  /* This code would prevent move-to-window-line from moving point
-         to a place inside the scroll margins (which would cause the
-         next redisplay to scroll).  I wrote this code, but then concluded
-         it is probably better not to install it.  However, it is here
-         inside #if 0 so as not to lose it.  -- rms.  */
+#if false /* This code would prevent move-to-window-line from moving point
+            to a place inside the scroll margins (which would cause the
+            next redisplay to scroll).  I wrote this code, but then concluded
+            it is probably better not to install it.  However, it is here
+            inside #if false so as not to lose it.  -- rms.  */
 
       /* Don't let it get into the margin at either top or bottom.  */
       iarg = max (iarg, this_scroll_margin);
@@ -6012,7 +6053,7 @@ zero means top of window, negative means relative to bottom of window.  */)
   if (w->vscroll)
     XSETINT (arg, XINT (arg) + 1);
 
-  return Fvertical_motion (arg, window);
+  return Fvertical_motion (arg, window, Qnil);
 }
 
 
@@ -6048,22 +6089,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;
 };
 
@@ -6091,13 +6133,6 @@ DEFUN ("window-configuration-frame", Fwindow_configuration_frame, Swindow_config
   return XWINDOW (SAVED_WINDOW_N (saved_windows, 0)->window)->frame;
 }
 
-/* From Chong's unwind_create_frame_1.  */
-static void
-unwind_change_frame (Lisp_Object val)
-{
-  inhibit_lisp_code = val;
-}
-
 DEFUN ("set-window-configuration", Fset_window_configuration,
        Sset_window_configuration, 1, 1, 0,
        doc: /* Set the configuration of windows and buffers as specified by CONFIGURATION.
@@ -6114,6 +6149,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);
 
@@ -6169,27 +6205,12 @@ the return value is nil.  Otherwise the value is t.  */)
     {
       Lisp_Object window;
       Lisp_Object dead_windows = Qnil;
-      register Lisp_Object tem, par, pers;
-      register struct window *w;
-      register struct saved_window *p;
+      Lisp_Object tem, par, pers;
+      struct window *w;
+      struct saved_window *p;
       struct window *root_window;
       struct window **leaf_windows;
-      int n_leaf_windows;
-      ptrdiff_t k;
-      int i, n;
-      ptrdiff_t count = SPECPDL_INDEX ();
-      /* 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);
+      ptrdiff_t i, k, n_leaf_windows;
 
       /* Don't do this within the main loop below: This may call Lisp
         code and is thus potentially unsafe while input is blocked.  */
@@ -6206,36 +6227,12 @@ the return value is nil.  Otherwise the value is t.  */)
            call1 (Qrecord_window_buffer, window);
        }
 
-      /* Don't run lisp in the following segment since the frame is in a
-        completely inconsistent state.  See Bug#16207.  */
-      record_unwind_protect (unwind_change_frame, inhibit_lisp_code);
-      inhibit_lisp_code = Qt;
+      /* Disallow x_set_window_size, temporarily.  */
+      f->can_x_set_window_size = 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
@@ -6251,15 +6248,15 @@ the return value is nil.  Otherwise the value is t.  */)
        }
 
       fset_redisplay (f);
-      FRAME_WINDOW_SIZES_CHANGED (f) = 1;
+      FRAME_WINDOW_SIZES_CHANGED (f) = true;
 
       /* Problem: Freeing all matrices and later allocating them again
         is a serious redisplay flickering problem.  What we would
         really like to do is to free only those matrices not reused
         below.  */
       root_window = XWINDOW (FRAME_ROOT_WINDOW (f));
-      leaf_windows = alloca (count_windows (root_window)
-                            * sizeof *leaf_windows);
+      ptrdiff_t nwindows = count_windows (root_window);
+      SAFE_NALLOCA (leaf_windows, 1, nwindows);
       n_leaf_windows = get_leaf_windows (root_window, leaf_windows, 0);
 
       /* Kludge Alert!
@@ -6314,7 +6311,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);
@@ -6322,7 +6321,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.
@@ -6353,18 +6354,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.  */
            {
@@ -6376,21 +6374,27 @@ 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)));
-             w->start_at_line_beg = 1;
+             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 = true;
            }
          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);
-             w->start_at_line_beg = 1;
+             set_marker_restricted_both (w->old_pointm, w->contents, 0, 0);
+             w->start_at_line_beg = true;
              if (!NILP (w->dedicated))
                /* Record this window as dead.  */
                dead_windows = Fcons (window, dead_windows);
@@ -6414,7 +6418,7 @@ the return value is nil.  Otherwise the value is t.  */)
 
         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);
+      select_window (data->current_window, Qt, true);
       BVAR (XBUFFER (XWINDOW (selected_window)->contents),
            last_selected_window)
        = selected_window;
@@ -6424,42 +6428,18 @@ the return value is nil.  Otherwise the value is t.  */)
              && 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)
-       {
-         if (NILP (leaf_windows[i]->contents))
-           free_window_matrices (leaf_windows[i]);
-         else if (EQ (leaf_windows[i]->contents, new_current_buffer))
-           ++n;
-       }
+      for (i = 0; i < n_leaf_windows; i++)
+       if (NILP (leaf_windows[i]->contents))
+         free_window_matrices (leaf_windows[i]);
+
+      /* Allow x_set_window_size again and apply frame size changes if
+        needed.  */
+      f->can_x_set_window_size = true;
+      adjust_frame_size (f, -1, -1, 1, false, Qset_window_configuration);
 
       adjust_frame_glyphs (f);
       unblock_input ();
-      unbind_to (count, Qnil);
 
       /* Scan dead buffer windows.  */
       for (; CONSP (dead_windows); dead_windows = XCDR (dead_windows))
@@ -6471,7 +6451,7 @@ the return value is nil.  Otherwise the value is t.  */)
 
       /* 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);
+      select_window (data->current_window, Qnil, false);
 
       /* Fselect_window will have made f the selected frame, so we
         reselect the proper frame here.  Fhandle_switch_frame will change the
@@ -6496,9 +6476,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)
 {
@@ -6524,12 +6506,13 @@ delete_all_child_windows (Lisp_Object window)
   if (WINDOWP (w->contents))
     {
       delete_all_child_windows (w->contents);
-      wset_combination (w, 0, Qnil);
+      wset_combination (w, false, Qnil);
     }
   else if (BUFFERP (w->contents))
     {
       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
@@ -6541,10 +6524,10 @@ delete_all_child_windows (Lisp_Object window)
   Vwindow_list = Qnil;
 }
 \f
-static int
-count_windows (register struct window *window)
+static ptrdiff_t
+count_windows (struct window *window)
 {
-  register int count = 1;
+  ptrdiff_t count = 1;
   if (!NILP (window->next))
     count += count_windows (XWINDOW (window->next));
   if (WINDOWP (window->contents))
@@ -6555,8 +6538,8 @@ count_windows (register struct window *window)
 
 /* Fill vector FLAT with leaf windows under W, starting at index I.
    Value is last index + 1.  */
-static int
-get_leaf_windows (struct window *w, struct window **flat, int i)
+static ptrdiff_t
+get_leaf_windows (struct window *w, struct window **flat, ptrdiff_t i)
 {
   while (w)
     {
@@ -6610,12 +6593,12 @@ get_phys_cursor_glyph (struct window *w)
 }
 
 
-static int
-save_window_save (Lisp_Object window, struct Lisp_Vector *vector, int i)
+static ptrdiff_t
+save_window_save (Lisp_Object window, struct Lisp_Vector *vector, ptrdiff_t i)
 {
-  register struct saved_window *p;
-  register struct window *w;
-  register Lisp_Object tem, pers, par;
+  struct saved_window *p;
+  struct window *w;
+  Lisp_Object tem, pers, par;
 
   for (; !NILP (window); window = w->next)
     {
@@ -6636,7 +6619,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);
@@ -6644,7 +6629,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;
@@ -6706,33 +6693,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 (buffer_local_value_1 /* Don't signal error if void.  */
+           = !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);
@@ -6746,8 +6727,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
@@ -6755,10 +6736,9 @@ redirection (see `redirect-frame-focus').  The variable
 saved by this function.  */)
   (Lisp_Object frame)
 {
-  register Lisp_Object tem;
-  register int n_windows;
-  register struct save_window_data *data;
-  register int i;
+  Lisp_Object tem;
+  ptrdiff_t i, n_windows;
+  struct save_window_data *data;
   struct frame *f = decode_live_frame (frame);
 
   n_windows = count_windows (XWINDOW (FRAME_ROOT_WINDOW (f)));
@@ -6796,9 +6776,8 @@ 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;
+  w->window_end_valid = false;
   windows_or_buffers_changed = 30;
   wset_redisplay (w);
   adjust_frame_glyphs (XFRAME (WINDOW_FRAME (w)));
@@ -6809,25 +6788,42 @@ apply_window_adjustment (struct window *w)
                            Marginal Areas
  ***********************************************************************/
 
+static int
+extract_dimension (Lisp_Object dimension)
+{
+  if (NILP (dimension))
+    return -1;
+  CHECK_RANGED_INTEGER (dimension, 0, INT_MAX);
+  return XINT (dimension);
+}
+
 static struct window *
 set_window_margins (struct window *w, Lisp_Object left_width,
                    Lisp_Object right_width)
 {
-  int left, right;
-
-  /* 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
-          : (CHECK_NATNUM (right_width), XINT (right_width)));
+  int unit = WINDOW_FRAME_COLUMN_WIDTH (w);
+  int left = NILP (left_width) ? 0 : extract_dimension (left_width);
+  int right = NILP (right_width) ? 0 : extract_dimension (right_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,
@@ -6876,12 +6872,9 @@ static struct window *
 set_window_fringes (struct window *w, Lisp_Object left_width,
                    Lisp_Object right_width, Lisp_Object outside_margins)
 {
-  int left, right, outside = !NILP (outside_margins);
-
-  left = (NILP (left_width) ? -1
-         : (CHECK_NATNUM (left_width), XINT (left_width)));
-  right = (NILP (right_width) ? -1
-          : (CHECK_NATNUM (right_width), XINT (right_width)));
+  bool outside = !NILP (outside_margins);
+  int left = extract_dimension (left_width);
+  int right = extract_dimension (right_width);
 
   /* Do nothing on a tty or if nothing to actually change.  */
   if (FRAME_WINDOW_P (WINDOW_XFRAME (w))
@@ -6889,12 +6882,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,
@@ -6945,9 +6951,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)));
+  int iwidth = extract_dimension (width);
+  bool changed = false;
 
   if (iwidth == 0)
     vertical_type = Qnil;
@@ -6961,32 +6969,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 = true;
+       }
     }
-  return NULL;
+
+#if USE_HORIZONTAL_SCROLL_BARS
+  {
+    int iheight = extract_dimension (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 = true;
+         }
+      }
+  }
+#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;
 }
 
@@ -6996,19 +7050,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_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
@@ -7069,7 +7129,7 @@ If PIXELS-P is non-nil, the return value is VSCROLL.  */)
            adjust_frame_glyphs (f);
 
          /* Prevent redisplay shortcuts.  */
-         XBUFFER (w->contents)->prevent_redisplay_optimizations_p = 1;
+         XBUFFER (w->contents)->prevent_redisplay_optimizations_p = true;
        }
     }
 
@@ -7082,7 +7142,7 @@ If PIXELS-P is non-nil, the return value is VSCROLL.  */)
    additional argument USER_DATA.  Stops when FN returns 0.  */
 
 static void
-foreach_window (struct frame *f, int (*fn) (struct window *, void *),
+foreach_window (struct frame *f, bool (*fn) (struct window *, void *),
                void *user_data)
 {
   /* delete_frame may set FRAME_ROOT_WINDOW (f) to Qnil.  */
@@ -7094,14 +7154,15 @@ foreach_window (struct frame *f, int (*fn) (struct window *, void *),
 /* Helper function for foreach_window.  Call FN for all leaf windows
    reachable from W.  FN is called with the first argument being a
    pointer to the leaf window, and with additional argument USER_DATA.
-   Stop when FN returns 0.  Value is 0 if stopped by FN.  */
+   Stop when FN returns false.  Value is false if stopped by FN.  */
 
-static int
-foreach_window_1 (struct window *w, int (*fn) (struct window *, void *), void *user_data)
+static bool
+foreach_window_1 (struct window *w, bool (*fn) (struct window *, void *),
+                 void *user_data)
 {
-  int cont;
+  bool cont;
 
-  for (cont = 1; w && cont;)
+  for (cont = true; w && cont;)
     {
       if (WINDOWP (w->contents))
        cont = foreach_window_1 (XWINDOW (w->contents), fn, user_data);
@@ -7118,7 +7179,7 @@ foreach_window_1 (struct window *w, int (*fn) (struct window *, void *), void *u
                            Initialization
  ***********************************************************************/
 
-/* Return 1 if window configurations CONFIGURATION1 and CONFIGURATION2
+/* Return true if window configurations CONFIGURATION1 and CONFIGURATION2
    describe the same state of affairs.  This is used by Fequal.
 
    IGNORE_POSITIONS means ignore non-matching scroll positions
@@ -7157,7 +7218,7 @@ compare_window_configurations (Lisp_Object configuration1,
       || !EQ (d1->focus_frame, d2->focus_frame)
       /* Verify that the two configurations have the same number of windows.  */
       || sws1->header.size != sws2->header.size)
-    return 0;
+    return false;
 
   for (i = 0; i < sws1->header.size; i++)
     {
@@ -7191,29 +7252,30 @@ 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))
-       return 0;
+         || !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 false;
     }
 
-  return 1;
+  return true;
 }
 
 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)
 {
-  if (compare_window_configurations (x, y, 1))
+  if (compare_window_configurations (x, y, true))
     return Qt;
   return Qnil;
 }
@@ -7226,8 +7288,6 @@ init_window_once (void)
   Vterminal_frame = selected_frame;
   minibuf_window = f->minibuffer_window;
   selected_window = f->selected_window;
-
-  window_initialized = 1;
 }
 
 void
@@ -7255,6 +7315,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");
@@ -7295,7 +7356,7 @@ the buffer; `temp-buffer-show-hook' is not run unless this function runs it.  */
               doc: /* Non-nil means to use `mode-line-inactive' face in non-selected windows.
 If the minibuffer is active, the `minibuffer-scroll-window' mode line
 is displayed in the `mode-line' face.  */);
-  mode_line_in_non_selected_windows = 1;
+  mode_line_in_non_selected_windows = true;
 
   DEFVAR_LISP ("other-window-scroll-buffer", Vother_window_scroll_buffer,
               doc: /* If this is a live buffer, \\[scroll-other-window] should scroll its window.  */);
@@ -7303,7 +7364,7 @@ is displayed in the `mode-line' face.  */);
 
   DEFVAR_BOOL ("auto-window-vscroll", auto_window_vscroll_p,
               doc: /* Non-nil means to automatically adjust `window-vscroll' to view tall lines.  */);
-  auto_window_vscroll_p = 1;
+  auto_window_vscroll_p = true;
 
   DEFVAR_INT ("next-screen-context-lines", next_screen_context_lines,
              doc: /* Number of lines of continuity when scrolling by screenfuls.  */);
@@ -7426,7 +7487,18 @@ 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
 pixelwise even if this option is nil.  */);
-  window_resize_pixelwise = 0;
+  window_resize_pixelwise = false;
+
+  DEFVAR_BOOL ("fast-but-imprecise-scrolling",
+               Vfast_but_imprecise_scrolling,
+               doc: /* When non-nil, accelerate scrolling operations.
+This comes into play when scrolling rapidly over previously
+unfontified buffer regions.  Only those portions of the buffer which
+are actually going to be displayed get fontified.
+
+Note that this optimization can cause the portion of the buffer
+displayed after a scrolling operation to be somewhat inaccurate.  */);
+  Vfast_but_imprecise_scrolling = false;
 
   defsubr (&Sselected_window);
   defsubr (&Sminibuffer_window);
@@ -7481,12 +7553,14 @@ pixelwise even if this option is nil.  */);
   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);
@@ -7497,6 +7571,7 @@ pixelwise even if this option is nil.  */);
   defsubr (&Sset_window_display_table);
   defsubr (&Snext_window);
   defsubr (&Sprevious_window);
+  defsubr (&Swindow__sanitize_window_sizes);
   defsubr (&Sget_buffer_window);
   defsubr (&Sdelete_other_windows_internal);
   defsubr (&Sdelete_window_internal);