]> code.delx.au - gnu-emacs/blobdiff - src/window.c
Update copyright year to 2015
[gnu-emacs] / src / window.c
index e3554ea032e9bfc14b409d0bb1d630473223d38e..938f1a3268f830191edaa8307ffa45ac720ebba4 100644 (file)
@@ -1,6 +1,6 @@
 /* Window creation, deletion and examination for GNU Emacs.
    Does not include redisplay.
-   Copyright (C) 1985-1987, 1993-1998, 2000-2014 Free Software
+   Copyright (C) 1985-1987, 1993-1998, 2000-2015 Free Software
    Foundation, Inc.
 
 This file is part of GNU Emacs.
@@ -329,7 +329,7 @@ DEFUN ("windowp", Fwindowp, Swindowp, 1, 1, 0,
 DEFUN ("window-valid-p", Fwindow_valid_p, Swindow_valid_p, 1, 1, 0,
        doc: /* Return t if OBJECT is a valid window and nil otherwise.
 A valid window is either a window that displays a buffer or an internal
-window.  Deleted windows are not live.  */)
+window.  Windows that have been deleted are not valid.  */)
   (Lisp_Object object)
 {
   return WINDOW_VALID_P (object) ? Qt : Qnil;
@@ -810,7 +810,12 @@ total width of WINDOW.  */)
 
 DEFUN ("window-new-total", Fwindow_new_total, Swindow_new_total, 0, 1, 0,
        doc: /* Return the new total size of window WINDOW.
-WINDOW must be a valid window and defaults to the selected one.  */)
+WINDOW must be a valid window and defaults to the selected one.
+
+The new total size of WINDOW is the value set by the last call of
+`set-window-new-total' for WINDOW.  If it is valid, it will be shortly
+installed as WINDOW's total height (see `window-total-height') or total
+width (see `window-total-width').  */)
   (Lisp_Object window)
 {
   return decode_valid_window (window)->new_total;
@@ -819,7 +824,25 @@ WINDOW must be a valid window and defaults to the selected one.  */)
 DEFUN ("window-normal-size", Fwindow_normal_size, Swindow_normal_size, 0, 2, 0,
        doc: /* Return the normal height of window WINDOW.
 WINDOW must be a valid window and defaults to the selected one.
-If HORIZONTAL is non-nil, return the normal width of WINDOW.  */)
+If HORIZONTAL is non-nil, return the normal width of WINDOW.
+
+The normal height of a frame's root window or a window that is
+horizontally combined (a window that has a left or right sibling) is
+1.0.  The normal height of a window that is vertically combined (has a
+sibling above or below) is the fraction of the window's height with
+respect to its parent.  The sum of the normal heights of all windows in a
+vertical combination equals 1.0.
+
+Similarly, the normal width of a frame's root window or a window that is
+vertically combined equals 1.0.  The normal width of a window that is
+horizontally combined is the fraction of the window's width with respect
+to its parent.  The sum of the normal widths of all windows in a
+horizontal combination equals 1.0.
+
+The normal sizes of windows are used to restore the proportional sizes
+of windows after they have been shrunk to their minimum sizes; for
+example when a frame is temporarily made very small and afterwards gets
+re-enlarged to its previous size.  */)
   (Lisp_Object window, Lisp_Object horizontal)
 {
   struct window *w = decode_valid_window (window);
@@ -829,7 +852,11 @@ If HORIZONTAL is non-nil, return the normal width of WINDOW.  */)
 
 DEFUN ("window-new-normal", Fwindow_new_normal, Swindow_new_normal, 0, 1, 0,
        doc: /* Return new normal size of window WINDOW.
-WINDOW must be a valid window and defaults to the selected one.  */)
+WINDOW must be a valid window and defaults to the selected one.
+
+The new normal size of WINDOW is the value set by the last call of
+`set-window-new-normal' for WINDOW.  If valid, it will be shortly
+installed as WINDOW's normal size (see `window-normal-size').  */)
   (Lisp_Object window)
 {
   return decode_valid_window (window)->new_normal;
@@ -837,7 +864,12 @@ WINDOW must be a valid window and defaults to the selected one.  */)
 
 DEFUN ("window-new-pixel", Fwindow_new_pixel, Swindow_new_pixel, 0, 1, 0,
        doc: /* Return new pixel size of window WINDOW.
-WINDOW must be a valid window and defaults to the selected one.  */)
+WINDOW must be a valid window and defaults to the selected one.
+
+The new pixel size of WINDOW is the value set by the last call of
+`set-window-new-pixel' for WINDOW.  If it is valid, it will be shortly
+installed as WINDOW's pixel height (see `window-pixel-height') or pixel
+width (see `window-pixel-width').  */)
   (Lisp_Object window)
 {
   return decode_valid_window (window)->new_pixel;
@@ -3305,7 +3337,9 @@ run_window_configuration_change_hook (struct frame *f)
     = Fdefault_value (Qwindow_configuration_change_hook);
   XSETFRAME (frame, f);
 
-  if (NILP (Vrun_hooks) || !(f->official))
+  if (NILP (Vrun_hooks)
+      || !(f->can_x_set_window_size)
+      || !(f->can_run_window_configuration_change_hook))
     return;
 
   /* Use the right buffer.  Matters when running the local hooks.  */
@@ -3705,6 +3739,10 @@ Return SIZE.
 Optional argument ADD non-nil means add SIZE to the new pixel size of
 WINDOW and return the sum.
 
+The new pixel size of WINDOW, if valid, will be shortly installed as
+WINDOW's pixel height (see `window-pixel-height') or pixel width (see
+`window-pixel-width').
+
 Note: This function does not operate on any child windows of WINDOW.  */)
   (Lisp_Object window, Lisp_Object size, Lisp_Object add)
 {
@@ -3729,6 +3767,10 @@ Return SIZE.
 Optional argument ADD non-nil means add SIZE to the new total size of
 WINDOW and return the sum.
 
+The new total size of WINDOW, if valid, will be shortly installed as
+WINDOW's total height (see `window-total-height') or total width (see
+`window-total-width').
+
 Note: This function does not operate on any child windows of WINDOW.  */)
      (Lisp_Object window, Lisp_Object size, Lisp_Object add)
 {
@@ -3748,6 +3790,9 @@ DEFUN ("set-window-new-normal", Fset_window_new_normal, Sset_window_new_normal,
 WINDOW must be a valid window and defaults to the selected one.
 Return SIZE.
 
+The new normal size of WINDOW, if valid, will be shortly installed as
+WINDOW's normal size (see `window-normal-size').
+
 Note: This function does not operate on any child windows of WINDOW.  */)
      (Lisp_Object window, Lisp_Object size)
 {
@@ -4012,9 +4057,14 @@ If FRAME is omitted or nil, it defaults to the selected frame.
 Optional argument HORIZONTAL omitted or nil means apply requested
 height values.  HORIZONTAL non-nil means apply requested width values.
 
-This function checks whether the requested values sum up to a valid
-window layout, recursively assigns the new sizes of all child windows
-and calculates and assigns the new start positions of these windows.
+The requested size values are those set by `set-window-new-pixel' and
+`set-window-new-normal'.  This function checks whether the requested
+values sum up to a valid window layout, recursively assigns the new
+sizes of all child windows and calculates and assigns the new start
+positions of these windows.
+
+Return t if the requested values have been applied correctly, nil
+otherwise.
 
 Note: This function does not check any of `window-fixed-size-p',
 `window-min-height' or `window-min-width'.  All these checks have to
@@ -4085,11 +4135,7 @@ 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.  */
+   SIZE.  PIXELWISE 1 means to interpret SIZE as pixels.  */
 void
 resize_frame_windows (struct frame *f, int size, bool horflag, bool pixelwise)
 {
@@ -4115,7 +4161,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)),
@@ -4127,7 +4172,6 @@ resize_frame_windows (struct frame *f, int size, bool horflag, bool pixelwise)
       new_size = max (horflag
                      ? size
                      : (size
-/**                     - FRAME_TOP_MARGIN (f) **/
                         - ((FRAME_HAS_MINIBUF_P (f)
                             && !FRAME_MINIBUF_ONLY_P (f))
                            ? 1 : 0)),
@@ -4748,10 +4792,10 @@ DEFUN ("resize-mini-window-internal", Fresize_mini_window_internal, Sresize_mini
       block_input ();
       window_resize_apply (r, 0);
 
-      w->total_lines = XFASTINT (w->new_total);
-      w->top_line = r->top_line + r->total_lines;
       w->pixel_height = XFASTINT (w->new_pixel);
+      w->total_lines = w->pixel_height / FRAME_LINE_HEIGHT (f);
       w->pixel_top = r->pixel_top + r->pixel_height;
+      w->top_line = r->top_line + r->total_lines;
 
       fset_redisplay (f);
       FRAME_WINDOW_SIZES_CHANGED (f) = 1;
@@ -4821,11 +4865,16 @@ window_internal_height (struct window *w)
 static void
 window_scroll (Lisp_Object window, EMACS_INT n, bool whole, int noerror)
 {
+  ptrdiff_t count = SPECPDL_INDEX ();
+
   immediate_quit = 1;
   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)))
@@ -4833,6 +4882,8 @@ 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;
@@ -4884,8 +4935,8 @@ window_scroll_pixel_based (Lisp_Object window, int n, bool whole, int noerror)
       /* The function move_iterator_vertically may move over more than
         the specified y-distance.  If it->w is small, e.g. a
         mini-buffer window, we may end up in front of the window's
-        display area.  This is the case when Start displaying at the
-        start of the line containing PT in this case.  */
+        display area.  Start displaying at the start of the line
+        containing PT in this case.  */
       if (it.current_y <= 0)
        {
          init_iterator (&it, w, PT, PT_BYTE, NULL, DEFAULT_FACE_ID);
@@ -4902,9 +4953,14 @@ window_scroll_pixel_based (Lisp_Object window, int n, bool whole, int noerror)
        {
          int px;
          int dy = frame_line_height;
+         /* In the below we divide the window box height by the
+            frame's line height to make the result predictable when
+            the window box is not an integral multiple of the line
+            height.  This is important to ensure we get back to the
+            same position when scrolling up, then down.  */
          if (whole)
-           dy = max ((window_box_height (w)
-                      - next_screen_context_lines * dy),
+           dy = max ((window_box_height (w) / dy
+                      - next_screen_context_lines) * dy,
                      dy);
          dy *= n;
 
@@ -4986,9 +5042,12 @@ window_scroll_pixel_based (Lisp_Object window, int n, bool whole, int noerror)
     {
       ptrdiff_t start_pos = IT_CHARPOS (it);
       int dy = frame_line_height;
-
-      dy = max ((window_box_height (w)
-                - next_screen_context_lines * dy),
+      /* In the below we divide the window box height by the frame's
+        line height to make the result predictable when the window
+        box is not an integral multiple of the line height.  This is
+        important to ensure we get back to the same position when
+        scrolling up, then down.  */
+      dy = max ((window_box_height (w) / dy - next_screen_context_lines) * dy,
                dy) * n;
 
       /* Note that move_it_vertically always moves the iterator to the
@@ -5868,6 +5927,8 @@ and redisplay normally--don't erase and redraw the frame.  */)
   w->start_at_line_beg = (bytepos == BEGV_BYTE
                          || FETCH_BYTE (bytepos - 1) == '\n');
 
+  wset_redisplay (w);
+
   return Qnil;
 }
 
@@ -6076,6 +6137,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);
 
@@ -6155,8 +6217,8 @@ the return value is nil.  Otherwise the value is t.  */)
            call1 (Qrecord_window_buffer, window);
        }
 
-      /* Consider frame unofficial, temporarily.  */
-      f->official = false;
+      /* 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 ();
@@ -6183,8 +6245,8 @@ the return value is nil.  Otherwise the value is t.  */)
         really like to do is to free only those matrices not reused
         below.  */
       root_window = XWINDOW (FRAME_ROOT_WINDOW (f));
-      leaf_windows = alloca (count_windows (root_window)
-                            * sizeof *leaf_windows);
+      int nwindows = count_windows (root_window);
+      SAFE_NALLOCA (leaf_windows, 1, nwindows);
       n_leaf_windows = get_leaf_windows (root_window, leaf_windows, 0);
 
       /* Kludge Alert!
@@ -6365,10 +6427,10 @@ the return value is nil.  Otherwise the value is t.  */)
            ++n;
        }
 
-      /* Make frame official again and apply frame size changes if
+      /* Allow x_set_window_size again and apply frame size changes if
         needed.  */
-      f->official = true;
-      adjust_frame_size (f, -1, -1, 1, 0);
+      f->can_x_set_window_size = true;
+      adjust_frame_size (f, -1, -1, 1, 0, Qnil);
 
       adjust_frame_glyphs (f);
       unblock_input ();
@@ -6408,424 +6470,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);
 }
 
 
-#if 0
-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.
-CONFIGURATION must be a value previously returned
-by `current-window-configuration' (which see).
-If CONFIGURATION was made from a frame that is now deleted,
-only frame-independent values can be restored.  In this case,
-the return value is nil.  Otherwise the value is t.  */)
-  (Lisp_Object configuration)
-{
-  register struct save_window_data *data;
-  struct Lisp_Vector *saved_windows;
-  Lisp_Object new_current_buffer;
-  Lisp_Object frame;
-  struct frame *f;
-  ptrdiff_t old_point = -1;
-
-  CHECK_WINDOW_CONFIGURATION (configuration);
-
-  data = (struct save_window_data *) XVECTOR (configuration);
-  saved_windows = XVECTOR (data->saved_windows);
-
-  new_current_buffer = data->current_buffer;
-  if (!BUFFER_LIVE_P (XBUFFER (new_current_buffer)))
-    new_current_buffer = Qnil;
-  else
-    {
-      if (XBUFFER (new_current_buffer) == current_buffer)
-       /* The code further down "preserves point" by saving here PT in
-          old_point and then setting it later back into PT.  When the
-          current-selected-window and the final-selected-window both show
-          the current buffer, this suffers from the problem that the
-          current PT is the window-point of the current-selected-window,
-          while the final PT is the point of the final-selected-window, so
-          this copy from one PT to the other would end up moving the
-          window-point of the final-selected-window to the window-point of
-          the current-selected-window.  So we have to be careful which
-          point of the current-buffer we copy into old_point.  */
-       if (EQ (XWINDOW (data->current_window)->contents, new_current_buffer)
-           && WINDOWP (selected_window)
-           && EQ (XWINDOW (selected_window)->contents, new_current_buffer)
-           && !EQ (selected_window, data->current_window))
-         old_point = marker_position (XWINDOW (data->current_window)->pointm);
-       else
-         old_point = PT;
-      else
-       /* BUF_PT (XBUFFER (new_current_buffer)) gives us the position of
-          point in new_current_buffer as of the last time this buffer was
-          used.  This can be non-deterministic since it can be changed by
-          things like jit-lock by mere temporary selection of some random
-          window that happens to show this buffer.
-          So if possible we want this arbitrary choice of "which point" to
-          be the one from the to-be-selected-window so as to prevent this
-          window's cursor from being copied from another window.  */
-       if (EQ (XWINDOW (data->current_window)->contents, new_current_buffer)
-           /* If current_window = selected_window, its point is in BUF_PT.  */
-           && !EQ (selected_window, data->current_window))
-         old_point = marker_position (XWINDOW (data->current_window)->pointm);
-       else
-         old_point = BUF_PT (XBUFFER (new_current_buffer));
-    }
-
-  frame = XWINDOW (SAVED_WINDOW_N (saved_windows, 0)->window)->frame;
-  f = XFRAME (frame);
-
-  /* If f is a dead frame, don't bother rebuilding its window tree.
-     However, there is other stuff we should still try to do below.  */
-  if (FRAME_LIVE_P (f))
-    {
-      Lisp_Object window;
-      Lisp_Object dead_windows = Qnil;
-      register Lisp_Object tem, par, pers;
-      register struct window *w;
-      register 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);
-
-      /* Don't do this within the main loop below: This may call Lisp
-        code and is thus potentially unsafe while input is blocked.  */
-      for (k = 0; k < saved_windows->header.size; k++)
-       {
-         p = SAVED_WINDOW_N (saved_windows, k);
-         window = p->window;
-         w = XWINDOW (window);
-         if (BUFFERP (w->contents)
-             && !EQ (w->contents, p->buffer)
-             && BUFFER_LIVE_P (XBUFFER (p->buffer)))
-           /* If a window we restore gets another buffer, record the
-              window's old buffer.  */
-           call1 (Qrecord_window_buffer, window);
-       }
-
-      /* Consider frame unofficial, temporarily.  */
-      f->official = false;
-      /* The mouse highlighting code could get screwed up
-        if it runs during this.  */
-      block_input ();
-
-      if (data->frame_text_width != previous_frame_text_width
-         || data->frame_text_height != previous_frame_text_height)
-       /* Make frame size fit the one in data, so window sizes restored
-          from data match those of the frame.  */
-       adjust_frame_size (f, data->frame_text_width,
-                          data->frame_text_height, 5, 0);
-
-      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
-        restoring the window contents, and prevent it from
-        being done later on when we select a new window.  */
-      if (! NILP (XWINDOW (selected_window)->contents))
-       {
-         w = XWINDOW (selected_window);
-         set_marker_both (w->pointm,
-                          w->contents,
-                          BUF_PT (XBUFFER (w->contents)),
-                          BUF_PT_BYTE (XBUFFER (w->contents)));
-       }
-
-      fset_redisplay (f);
-      FRAME_WINDOW_SIZES_CHANGED (f) = 1;
-
-      /* 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);
-      n_leaf_windows = get_leaf_windows (root_window, leaf_windows, 0);
-
-      /* Kludge Alert!
-        Mark all windows now on frame as "deleted".
-        Restoring the new configuration "undeletes" any that are in it.
-
-        Save their current buffers in their height fields, since we may
-        need it later, if a buffer saved in the configuration is now
-        dead.  */
-      delete_all_child_windows (FRAME_ROOT_WINDOW (f));
-
-      for (k = 0; k < saved_windows->header.size; k++)
-       {
-         p = SAVED_WINDOW_N (saved_windows, k);
-         window = p->window;
-         w = XWINDOW (window);
-         wset_next (w, Qnil);
-
-         if (!NILP (p->parent))
-           wset_parent
-             (w, SAVED_WINDOW_N (saved_windows, XFASTINT (p->parent))->window);
-         else
-           wset_parent (w, Qnil);
-
-         if (!NILP (p->prev))
-           {
-             wset_prev
-               (w, SAVED_WINDOW_N (saved_windows, XFASTINT (p->prev))->window);
-             wset_next (XWINDOW (w->prev), p->window);
-           }
-         else
-           {
-             wset_prev (w, Qnil);
-             if (!NILP (w->parent))
-               wset_combination (XWINDOW (w->parent),
-                                 (XINT (p->total_cols)
-                                  != XWINDOW (w->parent)->total_cols),
-                                 p->window);
-           }
-
-         /* If we squirreled away the buffer, restore it now.  */
-         if (BUFFERP (w->combination_limit))
-           wset_buffer (w, w->combination_limit);
-         w->pixel_left = XFASTINT (p->pixel_left);
-         w->pixel_top = XFASTINT (p->pixel_top);
-         w->pixel_width = XFASTINT (p->pixel_width);
-         w->pixel_height = XFASTINT (p->pixel_height);
-         w->left_col = XFASTINT (p->left_col);
-         w->top_line = XFASTINT (p->top_line);
-         w->total_cols = XFASTINT (p->total_cols);
-         w->total_lines = XFASTINT (p->total_lines);
-         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);
-         w->left_fringe_width = XINT (p->left_fringe_width);
-         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.
-            Parameters that have not been saved are left alone.  */
-         for (tem = p->window_parameters; CONSP (tem); tem = XCDR (tem))
-           {
-             pers = XCAR (tem);
-             if (CONSP (pers))
-               {
-                 if (NILP (XCDR (pers)))
-                   {
-                     par = Fassq (XCAR (pers), w->window_parameters);
-                     if (CONSP (par) && !NILP (XCDR (par)))
-                       /* Reset a parameter to nil if and only if it
-                          has a non-nil association.  Don't make new
-                          associations.  */
-                       Fsetcdr (par, Qnil);
-                   }
-                 else
-                   /* Always restore a non-nil value.  */
-                   Fset_window_parameter (window, XCAR (pers), XCDR (pers));
-               }
-           }
-
-         if (BUFFERP (p->buffer) && BUFFER_LIVE_P (XBUFFER (p->buffer)))
-           /* If saved buffer is alive, install it.  */
-           {
-             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);
-             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.  */
-           {
-             /* Set window markers at start of visible range.  */
-             if (XMARKER (w->start)->buffer == 0)
-               set_marker_restricted_both (w->start, w->contents, 0, 0);
-             if (XMARKER (w->pointm)->buffer == 0)
-               set_marker_restricted_both
-                 (w->pointm, w->contents,
-                  BUF_PT (XBUFFER (w->contents)),
-                  BUF_PT_BYTE (XBUFFER (w->contents)));
-             if (XMARKER (w->old_pointm)->buffer == 0)
-               set_marker_restricted_both
-                 (w->old_pointm, w->contents,
-                  BUF_PT (XBUFFER (w->contents)),
-                  BUF_PT_BYTE (XBUFFER (w->contents)));
-             w->start_at_line_beg = 1;
-           }
-         else if (!NILP (w->start))
-           /* Leaf window has no live buffer, get one.  */
-           {
-             /* Get the buffer via other_buffer_safely in order to
-                avoid showing an unimportant buffer and, if necessary, to
-                recreate *scratch* in the course (part of Juanma's bs-show
-                scenario from March 2011).  */
-             wset_buffer (w, other_buffer_safely (Fcurrent_buffer ()));
-             /* This will set the markers to beginning of visible
-                range.  */
-             set_marker_restricted_both (w->start, w->contents, 0, 0);
-             set_marker_restricted_both (w->pointm, w->contents, 0, 0);
-             set_marker_restricted_both (w->old_pointm, w->contents, 0, 0);
-             w->start_at_line_beg = 1;
-             if (!NILP (w->dedicated))
-               /* Record this window as dead.  */
-               dead_windows = Fcons (window, dead_windows);
-             /* Make sure window is no more dedicated.  */
-             wset_dedicated (w, Qnil);
-           }
-       }
-
-      fset_root_window (f, data->root_window);
-      /* Arrange *not* to restore point in the buffer that was
-        current when the window configuration was saved.  */
-      if (EQ (XWINDOW (data->current_window)->contents, new_current_buffer))
-       set_marker_restricted (XWINDOW (data->current_window)->pointm,
-                              make_number (old_point),
-                              XWINDOW (data->current_window)->contents);
-
-      /* In the following call to `select-window', prevent "swapping out
-        point" in the old selected window using the buffer that has
-        been restored into it.  We already swapped out that point from
-        that window's old buffer.
-
-        Do not record the buffer here.  We do that in a separate call
-        to select_window below.  See also Bug#16207.  */
-      select_window (data->current_window, Qt, 1);
-      BVAR (XBUFFER (XWINDOW (selected_window)->contents),
-           last_selected_window)
-       = selected_window;
-
-      if (NILP (data->focus_frame)
-         || (FRAMEP (data->focus_frame)
-             && FRAME_LIVE_P (XFRAME (data->focus_frame))))
-       Fredirect_frame_focus (frame, data->focus_frame);
-
-      /* Set the frame size to the value it had before this function.  */
-      if (previous_frame_text_width != FRAME_TEXT_WIDTH (f)
-         || previous_frame_text_height != FRAME_TEXT_HEIGHT (f))
-       adjust_frame_size (f, previous_frame_text_width,
-                          previous_frame_text_height, 5, 0);
-
-      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;
-       }
-
-      /* Make frame official again and apply frame size changes if
-        needed.  */
-      f->official = true;
-      adjust_frame_size (f, -1, -1, 1, 0);
-
-      adjust_frame_glyphs (f);
-      unblock_input ();
-
-      /* Scan dead buffer windows.  */
-      for (; CONSP (dead_windows); dead_windows = XCDR (dead_windows))
-       {
-         window = XCAR (dead_windows);
-         if (WINDOW_LIVE_P (window) && !EQ (window, FRAME_ROOT_WINDOW (f)))
-           delete_deletable_window (window);
-       }
-
-      /* Record the selected window's buffer here.  The window should
-        already be the selected one from the call above.  */
-      select_window (data->current_window, Qnil, 0);
-
-      /* Fselect_window will have made f the selected frame, so we
-        reselect the proper frame here.  Fhandle_switch_frame will change the
-        selected window too, but that doesn't make the call to
-        Fselect_window above totally superfluous; it still sets f's
-        selected window.  */
-      if (FRAME_LIVE_P (XFRAME (data->selected_frame)))
-       do_switch_frame (data->selected_frame, 0, 0, Qnil);
-
-      run_window_configuration_change_hook (f);
-    }
-
-  if (!NILP (new_current_buffer))
-    {
-      Fset_buffer (new_current_buffer);
-      /* If the new current buffer doesn't appear in the selected
-        window, go to its old point (see bug#12208).  */
-      if (!EQ (XWINDOW (data->current_window)->contents, new_current_buffer))
-       Fgoto_char (make_number (old_point));
-    }
-
-  Vminibuf_scroll_window = data->minibuf_scroll_window;
-  minibuf_selected_window = data->minibuf_selected_window;
-
-  return (FRAME_LIVE_P (f) ? Qt : Qnil);
-}
-#endif
-
 void
 restore_window_configuration (Lisp_Object configuration)
 {
@@ -7299,7 +6948,6 @@ set_window_scroll_bars (struct window *w, Lisp_Object width,
                        Lisp_Object horizontal_type)
 {
   int iwidth = (NILP (width) ? -1 : (CHECK_NATNUM (width), XINT (width)));
-  int iheight = (NILP (height) ? -1 : (CHECK_NATNUM (height), XINT (height)));
   bool changed = 0;
 
   if (iwidth == 0)
@@ -7327,29 +6975,37 @@ set_window_scroll_bars (struct window *w, Lisp_Object width,
        }
     }
 
-  if (MINI_WINDOW_P (w) || iheight == 0)
-    horizontal_type = Qnil;
+#if USE_HORIZONTAL_SCROLL_BARS
+  {
+    int iheight = (NILP (height) ? -1 : (CHECK_NATNUM (height), XINT (height)));
 
-  if (!(NILP (horizontal_type)
-       || EQ (horizontal_type, Qbottom)
-       || EQ (horizontal_type, Qt)))
-    error ("Invalid type of horizontal scroll bar");
+    if (MINI_WINDOW_P (w) || iheight == 0)
+      horizontal_type = Qnil;
 
-  if (w->scroll_bar_height != iheight
-      || !EQ (w->horizontal_scroll_bar_type, horizontal_type))
-    {
-      /* Don't change anything if new scroll bar won't fit.  */
-      if ((WINDOW_PIXEL_HEIGHT (w)
-          - WINDOW_HEADER_LINE_HEIGHT (w)
-          - WINDOW_MODE_LINE_HEIGHT (w)
-          - max (iheight, 0))
-         >= MIN_SAFE_WINDOW_PIXEL_HEIGHT (w))
-       {
-         w->scroll_bar_height = iheight;
-         wset_horizontal_scroll_bar_type (w, horizontal_type);
-         changed = 1;
-       }
-    }
+    if (!(NILP (horizontal_type)
+         || EQ (horizontal_type, Qbottom)
+         || EQ (horizontal_type, Qt)))
+      error ("Invalid type of horizontal scroll bar");
+
+    if (w->scroll_bar_height != iheight
+       || !EQ (w->horizontal_scroll_bar_type, horizontal_type))
+      {
+       /* Don't change anything if new scroll bar won't fit.  */
+       if ((WINDOW_PIXEL_HEIGHT (w)
+            - WINDOW_HEADER_LINE_HEIGHT (w)
+            - WINDOW_MODE_LINE_HEIGHT (w)
+            - max (iheight, 0))
+           >= MIN_SAFE_WINDOW_PIXEL_HEIGHT (w))
+         {
+           w->scroll_bar_height = iheight;
+           wset_horizontal_scroll_bar_type (w, horizontal_type);
+           changed = 1;
+         }
+      }
+  }
+#else
+  wset_horizontal_scroll_bar_type (w, Qnil);
+#endif
 
   return changed ? w : NULL;
 }
@@ -7359,16 +7015,17 @@ DEFUN ("set-window-scroll-bars", Fset_window_scroll_bars,
        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.
+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 scroll bar.
-Fifth parameter HORIZONTAL-TYPE specifies the type of the vertical
-scroll bar: nil, bottom, or t.  If HEIGHT is nil, use the frame's
-scroll-bar height.  If HORIZONTAL-TYPE is t, 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,
@@ -7386,17 +7043,22 @@ 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 HEIGHT LINES
-HORIZONTAL-TYPE).  If WIDTH or HEIGHT is nil or TYPE is t, the window is
-using the frame's corresponding value.  */)
+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 Fcons (make_number (WINDOW_SCROLL_BAR_AREA_WIDTH (w)),
+  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,
-                      make_number (WINDOW_SCROLL_BAR_AREA_HEIGHT (w)),
+                      ((w->scroll_bar_height >= 0)
+                       ? make_number (w->scroll_bar_height)
+                       : Qnil),
                       make_number (WINDOW_SCROLL_BAR_LINES (w)),
                       w->horizontal_scroll_bar_type));
 }
@@ -7686,7 +7348,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.  */);
@@ -7694,7 +7356,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.  */);
@@ -7817,7 +7479,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);