]> code.delx.au - gnu-emacs/blobdiff - src/window.c
Improve indexing in Emacs manual (Bug#20105)
[gnu-emacs] / src / window.c
index 1e3d70fd88d81e26372baf5245350da840e94ef0..aafa4a16df1a9e7eca25160a7b8e86de530eb235 100644 (file)
@@ -1,6 +1,6 @@
 /* Window creation, deletion and examination for GNU Emacs.
    Does not include redisplay.
-   Copyright (C) 1985-1987, 1993-1998, 2000-2013 Free Software
+   Copyright (C) 1985-1987, 1993-1998, 2000-2015 Free Software
    Foundation, Inc.
 
 This file is part of GNU Emacs.
@@ -54,6 +54,8 @@ static Lisp_Object Qwindow_resize_root_window, Qwindow_resize_root_window_vertic
 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 *);
@@ -123,7 +125,7 @@ static int window_initialized;
 /* Hook to run when window config changes.  */
 static Lisp_Object Qwindow_configuration_change_hook;
 
-/* Used by the function window_scroll_pixel_based */
+/* Used by the function window_scroll_pixel_based */
 static int window_scroll_pixel_based_preserve_x;
 static int window_scroll_pixel_based_preserve_y;
 
@@ -309,7 +311,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;
@@ -558,7 +560,7 @@ select_window_1 (Lisp_Object window, bool inhibit_point_swap)
 DEFUN ("select-window", Fselect_window, Sselect_window, 1, 2, 0,
        doc: /* Select WINDOW which must be a live window.
 Also make WINDOW's frame the selected frame and WINDOW that frame's
-selected window.  In addition, make WINDOW's buffer current and set that
+selected window.  In addition, make WINDOW's buffer current and set its
 buffer's value of `point' to the value of WINDOW's `window-point'.
 Return WINDOW.
 
@@ -566,8 +568,17 @@ Optional second arg NORECORD non-nil means do not put this buffer at the
 front of the buffer list and do not make this window the most recently
 selected one.
 
-Note that the main editor command loop sets the current buffer to the
-buffer of the selected window before each command.  */)
+Run `buffer-list-update-hook' unless NORECORD is non-nil.  Note that
+applications and internal routines often select a window temporarily for
+various purposes; mostly, to simplify coding.  As a rule, such
+selections should be not recorded and therefore will not pollute
+`buffer-list-update-hook'.  Selections that "really count" are those
+causing a visible change in the next redisplay of WINDOW's frame and
+should be always recorded.  So if you think of running a function each
+time a window gets selected put it on `buffer-list-update-hook'.
+
+Also note that the main editor command loop sets the current buffer to
+the buffer of the selected window before each command.  */)
   (register Lisp_Object window, Lisp_Object norecord)
 {
   return select_window (window, norecord, 0);
@@ -682,7 +693,7 @@ selected one.  */)
 }
 \f
 DEFUN ("window-pixel-width", Fwindow_pixel_width, Swindow_pixel_width, 0, 1, 0,
-       doc: /* Return the pixel width of window WINDOW.
+       doc: /* Return the width of window WINDOW in pixels.
 WINDOW must be a valid window and defaults to the selected one.
 
 The return value includes the fringes and margins of WINDOW as well as
@@ -695,50 +706,98 @@ spanned by its children.  */)
 }
 
 DEFUN ("window-pixel-height", Fwindow_pixel_height, Swindow_pixel_height, 0, 1, 0,
-       doc: /* Return the pixel height of window WINDOW.
+       doc: /* Return the height of window WINDOW in pixels.
 WINDOW must be a valid window and defaults to the selected one.
 
-The return value includes the mode line and header line, if any.  If
-WINDOW is an internal window, its pixel height is the height of the
-screen areas spanned by its children.  */)
+The return value includes the mode line and header line and the bottom
+divider, if any.  If WINDOW is an internal window, its pixel height is
+the height of the screen areas spanned by its children.  */)
   (Lisp_Object window)
 {
   return make_number (decode_valid_window (window)->pixel_height);
 }
 
-DEFUN ("window-total-height", Fwindow_total_height, Swindow_total_height, 0, 1, 0,
-       doc: /* Return the total height, in lines, of window WINDOW.
+DEFUN ("window-total-height", Fwindow_total_height, Swindow_total_height, 0, 2, 0,
+       doc: /* Return the height of window WINDOW in lines.
 WINDOW must be a valid window and defaults to the selected one.
 
-The return value includes the mode line and header line, if any.
-If WINDOW is an internal window, the total height is the height
-of the screen areas spanned by its children.
+The return value includes the heights of WINDOW's mode and header line
+and its bottom divider, if any.  If WINDOW is an internal window, the
+total height is the height of the screen areas spanned by its children.
 
-On a graphical display, this total height is reported as an
-integer multiple of the default character height.  */)
-  (Lisp_Object window)
+If WINDOW's pixel height is not an integral multiple of its frame's
+character height, the number of lines occupied by WINDOW is rounded
+internally.  This is done in a way such that, if WINDOW is a parent
+window, the sum of the total heights of all its children internally
+equals the total height of WINDOW.
+
+If the optional argument ROUND is `ceiling', return the smallest integer
+larger than WINDOW's pixel height divided by the character height of
+WINDOW's frame.  ROUND `floor' means to return the largest integer
+smaller than WINDOW's pixel height divided by the character height of
+WINDOW's frame.  Any other value of ROUND means to return the internal
+total height of WINDOW.  */)
+  (Lisp_Object window, Lisp_Object round)
 {
-  return make_number (decode_valid_window (window)->total_lines);
+  struct window *w = decode_valid_window (window);
+
+  if (! EQ (round, Qfloor) && ! EQ (round, Qceiling))
+    return make_number (w->total_lines);
+  else
+    {
+      int unit = FRAME_LINE_HEIGHT (WINDOW_XFRAME (w));
+
+      return make_number (EQ (round, Qceiling)
+                         ? ((w->pixel_height + unit - 1) /unit)
+                         : (w->pixel_height / unit));
+    }
 }
 
-DEFUN ("window-total-width", Fwindow_total_width, Swindow_total_width, 0, 1, 0,
-       doc: /* Return the total width, in columns, of window WINDOW.
+DEFUN ("window-total-width", Fwindow_total_width, Swindow_total_width, 0, 2, 0,
+       doc: /* Return the total width of window WINDOW in columns.
 WINDOW must be a valid window and defaults to the selected one.
 
-The return value includes any vertical dividers or scroll bars
-belonging to WINDOW.  If WINDOW is an internal window, the total width
-is the width of the screen areas spanned by its children.
-
-On a graphical display, this total width is reported as an
-integer multiple of the default character width.  */)
-  (Lisp_Object window)
+The return value includes the widths of WINDOW's fringes, margins,
+scroll bars and its right divider, if any.  If WINDOW is an internal
+window, the total width is the width of the screen areas spanned by its
+children.
+
+If WINDOW's pixel width is not an integral multiple of its frame's
+character width, the number of lines occupied by WINDOW is rounded
+internally.  This is done in a way such that, if WINDOW is a parent
+window, the sum of the total widths of all its children internally
+equals the total width of WINDOW.
+
+If the optional argument ROUND is `ceiling', return the smallest integer
+larger than WINDOW's pixel width divided by the character width of
+WINDOW's frame.  ROUND `floor' means to return the largest integer
+smaller than WINDOW's pixel width divided by the character width of
+WINDOW's frame.  Any other value of ROUND means to return the internal
+total width of WINDOW.  */)
+  (Lisp_Object window, Lisp_Object round)
 {
-  return make_number (decode_valid_window (window)->total_cols);
+  struct window *w = decode_valid_window (window);
+
+  if (! EQ (round, Qfloor) && ! EQ (round, Qceiling))
+    return make_number (w->total_cols);
+  else
+    {
+      int unit = FRAME_COLUMN_WIDTH (WINDOW_XFRAME (w));
+
+      return make_number (EQ (round, Qceiling)
+                         ? ((w->pixel_width + unit - 1) /unit)
+                         : (w->pixel_width / unit));
+    }
 }
 
 DEFUN ("window-new-total", Fwindow_new_total, Swindow_new_total, 0, 1, 0,
        doc: /* Return the new total size of window WINDOW.
-WINDOW must be a valid window and defaults to the selected one.  */)
+WINDOW must be a valid window and defaults to the selected one.
+
+The new total size of WINDOW is the value set by the last call of
+`set-window-new-total' for WINDOW.  If it is valid, it will be shortly
+installed as WINDOW's total height (see `window-total-height') or total
+width (see `window-total-width').  */)
   (Lisp_Object window)
 {
   return decode_valid_window (window)->new_total;
@@ -747,7 +806,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);
@@ -757,7 +834,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;
@@ -765,7 +846,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;
@@ -811,62 +897,66 @@ WINDOW must be a valid window and defaults to the selected one.  */)
   return make_number (decode_valid_window (window)->top_line);
 }
 
-/* Return the number of lines of W's body.  Don't count any mode or
-   header line of W.  */
-
+/* Return the number of lines/pixels of W's body.  Don't count any mode
+   or header line or horizontal divider of W.  Rounds down to nearest
+   integer when not working pixelwise. */
 static int
 window_body_height (struct window *w, bool pixelwise)
 {
-  int pixels = (w->pixel_height
-               - WINDOW_BOTTOM_DIVIDER_WIDTH (w)
+  int height = (w->pixel_height
                - WINDOW_HEADER_LINE_HEIGHT (w)
-               - WINDOW_MODE_LINE_HEIGHT (w));
-  int unit = FRAME_LINE_HEIGHT (WINDOW_XFRAME (w));
+               - WINDOW_MODE_LINE_HEIGHT (w)
+               - WINDOW_BOTTOM_DIVIDER_WIDTH (w));
 
-  return pixelwise ? pixels : ((pixels + unit - 1) / unit);
+  /* Don't return a negative value.  */
+  return max (pixelwise
+             ? height
+             : height / FRAME_LINE_HEIGHT (WINDOW_XFRAME (w)),
+             0);
 }
 
-/* Return the number of columns of W's body.  Don't count columns
-   occupied by the scroll bar or the vertical bar separating W from its
-   right sibling.  On window-systems don't count fringes or display
-   margins either.  */
+/* Return the number of columns/pixels of W's body.  Don't count columns
+   occupied by the scroll bar or the divider/vertical bar separating W
+   from its right sibling or margins.  On window-systems don't count
+   fringes either.  Round down to nearest integer when not working
+   pixelwise.  */
 int
 window_body_width (struct window *w, bool pixelwise)
 {
   struct frame *f = XFRAME (WINDOW_FRAME (w));
 
-  int pixels = (w->pixel_width
-               - WINDOW_RIGHT_DIVIDER_WIDTH (w)
-               - (WINDOW_HAS_VERTICAL_SCROLL_BAR (w)
-                  ? WINDOW_SCROLL_BAR_AREA_WIDTH (w)
-                  : ((!FRAME_WINDOW_P (f)
-                      && !WINDOW_RIGHTMOST_P (w)
-                      && !WINDOW_RIGHT_DIVIDER_WIDTH (w)
-                      && !WINDOW_FULL_WIDTH_P (w))
-                     /* According to Eli this is either 1 or 0.  */
-                     ? 1 : 0))
+  int width = (w->pixel_width
+              - WINDOW_RIGHT_DIVIDER_WIDTH (w)
+              - (WINDOW_HAS_VERTICAL_SCROLL_BAR (w)
+                 ? WINDOW_SCROLL_BAR_AREA_WIDTH (w)
+                 : ((!FRAME_WINDOW_P (f)
+                     && !WINDOW_RIGHTMOST_P (w)
+                     && !WINDOW_RIGHT_DIVIDER_WIDTH (w))
+                    /* A vertical bar is either 1 or 0.  */
+                    ? 1 : 0))
                - WINDOW_MARGINS_WIDTH (w)
                - (FRAME_WINDOW_P (f)
                   ? WINDOW_FRINGES_WIDTH (w)
                   : 0));
-  int unit = FRAME_COLUMN_WIDTH (WINDOW_XFRAME (w));
 
-  return pixelwise ? pixels : ((pixels + unit - 1) / unit);
+  /* Don't return a negative value.  */
+  return max (pixelwise
+             ? width
+             : width / FRAME_COLUMN_WIDTH (WINDOW_XFRAME (w)),
+             0);
 }
 
 DEFUN ("window-body-height", Fwindow_body_height, Swindow_body_height, 0, 2, 0,
-       doc: /* Return the height, in lines, of WINDOW's text area.
-WINDOW must be a live window and defaults to the selected one.
-
-Optional argument PIXELWISE non-nil means return the height in pixels.
-
-The returned height does not include the mode line or header line.  On a
-graphical display, the height is expressed as an integer multiple of the
-default character height if PIXELWISE is nil.
-
-If PIXELWISE is nil and a line at the bottom of the text area is only
-partially visible, that counts as a whole line; to exclude
-partially-visible lines, use `window-text-height'.  */)
+       doc: /* Return the height of WINDOW's text area.
+WINDOW must be a live window and defaults to the selected one.  Optional
+argument PIXELWISE non-nil means return the height of WINDOW's text area
+in pixels.  The return value does not include the mode line or header
+line or any horizontal divider.
+
+If PIXELWISE is nil, return the largest integer smaller than WINDOW's
+pixel height divided by the character height of WINDOW's frame.  This
+means that if a line at the bottom of the text area is only partially
+visible, that line is not counted.  */)
   (Lisp_Object window, Lisp_Object pixelwise)
 {
   return make_number (window_body_height (decode_live_window (window),
@@ -874,19 +964,19 @@ partially-visible lines, use `window-text-height'.  */)
 }
 
 DEFUN ("window-body-width", Fwindow_body_width, Swindow_body_width, 0, 2, 0,
-       doc: /* Return the width, in columns, of WINDOW's text area.
-WINDOW must be a live window and defaults to the selected one.
-
-Optional argument PIXELWISE non-nil means return the width in pixels.
-
-The return value does not include any vertical dividers, fringe or
-marginal areas, or scroll bars.  On a graphical display, the width is
-expressed as an integer multiple of the default character width if
-PIXELWISE is nil.
-
-If PIXELWISE is nil and a column at the right of the text area is only
-partially visible, that counts as a whole column; to exclude
-partially-visible columns, use `window-text-width'.  */)
+       doc: /* Return the width of WINDOW's text area.
+WINDOW must be a live window and defaults to the selected one.  Optional
+argument PIXELWISE non-nil means return the width in pixels.  The return
+value does not include any vertical dividers, fringes or marginal areas,
+or scroll bars.
+
+If PIXELWISE is nil, return the largest integer smaller than WINDOW's
+pixel width divided by the character width of WINDOW's frame.  This
+means that if a column at the right of the text area is only partially
+visible, that column is not counted.
+
+Note that the returned value includes the column reserved for the
+continuation glyph.  */)
   (Lisp_Object window, Lisp_Object pixelwise)
 {
   return make_number (window_body_width (decode_live_window (window),
@@ -895,7 +985,7 @@ partially-visible columns, use `window-text-width'.  */)
 
 DEFUN ("window-mode-line-height", Fwindow_mode_line_height,
        Swindow_mode_line_height, 0, 1, 0,
-       doc: /* Return the height in pixel of WINDOW's mode-line.
+       doc: /* Return the height in pixels of WINDOW's mode-line.
 WINDOW must be a live window and defaults to the selected one.  */)
   (Lisp_Object window)
 {
@@ -904,7 +994,7 @@ WINDOW must be a live window and defaults to the selected one.  */)
 
 DEFUN ("window-header-line-height", Fwindow_header_line_height,
        Swindow_header_line_height, 0, 1, 0,
-       doc: /* Return the height in pixel of WINDOW's header-line.
+       doc: /* Return the height in pixels of WINDOW's header-line.
 WINDOW must be a live window and defaults to the selected one.  */)
   (Lisp_Object window)
 {
@@ -913,7 +1003,7 @@ WINDOW must be a live window and defaults to the selected one.  */)
 
 DEFUN ("window-right-divider-width", Fwindow_right_divider_width,
        Swindow_right_divider_width, 0, 1, 0,
-       doc: /* Return the width of WINDOW's right divider.
+       doc: /* Return the width in pixels of WINDOW's right divider.
 WINDOW must be a live window and defaults to the selected one.  */)
   (Lisp_Object window)
 {
@@ -922,13 +1012,22 @@ WINDOW must be a live window and defaults to the selected one.  */)
 
 DEFUN ("window-bottom-divider-width", Fwindow_bottom_divider_width,
        Swindow_bottom_divider_width, 0, 1, 0,
-       doc: /* Return the width of WINDOW's bottom divider.
+       doc: /* Return the width in pixels of WINDOW's bottom divider.
 WINDOW must be a live window and defaults to the selected one.  */)
   (Lisp_Object window)
 {
   return (make_number (WINDOW_BOTTOM_DIVIDER_WIDTH (decode_live_window (window))));
 }
 
+DEFUN ("window-scroll-bar-width", Fwindow_scroll_bar_width,
+       Swindow_scroll_bar_width, 0, 1, 0,
+       doc: /* Return the width in pixels of WINDOW's vertical scrollbar.
+WINDOW must be a live window and defaults to the selected one.  */)
+  (Lisp_Object window)
+{
+  return (make_number (WINDOW_SCROLL_BAR_AREA_WIDTH (decode_live_window (window))));
+}
+
 DEFUN ("window-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.  */)
@@ -1212,18 +1311,18 @@ coordinates_in_window (register struct window *w, int x, int y)
   if (y < top_y || y >= bottom_y || x < left_x || x >= right_x)
     return ON_NOTHING;
 
-  /* On vertical window divider (which prevails horizontal
-     dividers)?  */
-  if (!WINDOW_RIGHTMOST_P (w)
-      && WINDOW_RIGHT_DIVIDER_WIDTH (w)
-      && x >= right_x - WINDOW_RIGHT_DIVIDER_WIDTH (w)
-      && x <= right_x)
-    return ON_RIGHT_DIVIDER;
-  /* On the horizontal window divider?  */
-  else if (WINDOW_BOTTOM_DIVIDER_WIDTH (w)
-          && y >= (bottom_y - WINDOW_BOTTOM_DIVIDER_WIDTH (w))
-          && y <= bottom_y)
+  /* On the horizontal window divider (which prevails the vertical
+     divider)?  */
+  if (WINDOW_BOTTOM_DIVIDER_WIDTH (w) > 0
+      && y >= (bottom_y - WINDOW_BOTTOM_DIVIDER_WIDTH (w))
+      && y <= bottom_y)
     return ON_BOTTOM_DIVIDER;
+  /* On vertical window divider?  */
+  else if (!WINDOW_RIGHTMOST_P (w)
+          && WINDOW_RIGHT_DIVIDER_WIDTH (w) > 0
+          && x >= right_x - WINDOW_RIGHT_DIVIDER_WIDTH (w)
+          && x <= right_x)
+    return ON_RIGHT_DIVIDER;
   /* On the mode or header line?   */
   else if ((WINDOW_WANTS_MODELINE_P (w)
            && y >= (bottom_y
@@ -1240,12 +1339,13 @@ coordinates_in_window (register struct window *w, int x, int y)
         resize windows horizontally in case we're using toolkit scroll
         bars.  Note: If scrollbars are on the left, the window that
         must be eventually resized is that on the left of WINDOW.  */
-      if ((WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w)
-          && !WINDOW_LEFTMOST_P (w)
-          && eabs (x - left_x) < grabbable_width)
-         || (!WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w)
-             && !WINDOW_RIGHTMOST_P (w)
-             && eabs (x - right_x) < grabbable_width))
+      if ((WINDOW_RIGHT_DIVIDER_WIDTH (w) == 0)
+         && ((WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w)
+              && !WINDOW_LEFTMOST_P (w)
+              && eabs (x - left_x) < grabbable_width)
+             || (!WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w)
+                 && !WINDOW_RIGHTMOST_P (w)
+                 && eabs (x - right_x) < grabbable_width)))
        return ON_VERTICAL_BORDER;
       else
        return part;
@@ -1277,6 +1377,7 @@ coordinates_in_window (register struct window *w, int x, int y)
   if (FRAME_WINDOW_P (f))
     {
       if (!w->pseudo_window_p
+         && WINDOW_RIGHT_DIVIDER_WIDTH (w) == 0
          && !WINDOW_HAS_VERTICAL_SCROLL_BAR (w)
          && !WINDOW_RIGHTMOST_P (w)
          && (eabs (x - right_x) < grabbable_width))
@@ -1285,6 +1386,7 @@ coordinates_in_window (register struct window *w, int x, int y)
   /* Need to say "x > right_x" rather than >=, since on character
      terminals, the vertical line's x coordinate is right_x.  */
   else if (!w->pseudo_window_p
+          && WINDOW_RIGHT_DIVIDER_WIDTH (w) == 0
           && !WINDOW_RIGHTMOST_P (w)
           /* Why check ux if we are not the rightmost window?  Also
              shouldn't a pseudo window always be rightmost?  */
@@ -1298,8 +1400,8 @@ coordinates_in_window (register struct window *w, int x, int y)
              ? (x >= left_x + WINDOW_LEFT_FRINGE_WIDTH (w))
              : (x < left_x + lmargin_width)))
        return ON_LEFT_MARGIN;
-
-      return ON_LEFT_FRINGE;
+      else
+       return ON_LEFT_FRINGE;
     }
 
   if (x >= text_right)
@@ -1309,8 +1411,8 @@ coordinates_in_window (register struct window *w, int x, int y)
              ? (x < right_x - WINDOW_RIGHT_FRINGE_WIDTH (w))
              : (x >= right_x - rmargin_width)))
        return ON_RIGHT_MARGIN;
-
-      return ON_RIGHT_FRINGE;
+      else
+       return ON_RIGHT_FRINGE;
     }
 
   /* Everything special ruled out - must be on text area */
@@ -1329,6 +1431,8 @@ window_relative_x_coord (struct window *w, enum window_part part, int x)
     case ON_TEXT:
       return x - window_box_left (w, TEXT_AREA);
 
+    case ON_HEADER_LINE:
+    case ON_MODE_LINE:
     case ON_LEFT_FRINGE:
       return x - left_x;
 
@@ -1365,8 +1469,10 @@ measured in characters from the upper-left corner of the frame.
 frame.
 If COORDINATES are in the text portion of WINDOW,
    the coordinates relative to the window are returned.
+If they are in the bottom divider of WINDOW, `bottom-divider' is returned.
+If they are in the right divider of WINDOW, `right-divider' is returned.
 If they are in the mode line of WINDOW, `mode-line' is returned.
-If they are in the top mode line of WINDOW, `header-line' is returned.
+If they are in the header line of WINDOW, `header-line' is returned.
 If they are in the left fringe of WINDOW, `left-fringe' is returned.
 If they are in the right fringe of WINDOW, `right-fringe' is returned.
 If they are on the border between WINDOW and its right sibling,
@@ -3155,6 +3261,7 @@ check_frame_size (struct frame *frame, int *width, int *height, bool pixelwise)
        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;
@@ -3643,6 +3750,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)
 {
@@ -3667,6 +3778,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)
 {
@@ -3686,6 +3801,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)
 {
@@ -3792,7 +3910,7 @@ window_resize_check (struct window *w, bool horflag)
 }
 
 
-/* Set w->pixel_height (w->pixel_height if HORIZONTAL is non-zero) to
+/* Set w->pixel_height (w->pixel_width if HORFLAG is non-zero) to
    w->new_pixel for window W and recursively all child windows of W.
    Also calculate and assign the new vertical (horizontal) pixel start
    positions of each of these windows.
@@ -3877,12 +3995,15 @@ window_resize_apply (struct window *w, bool horflag)
        }
     }
   else
-    /* Bug#15957.  */
-    w->window_end_valid = 0;
+    {
+      adjust_window_margins (w);
+      /* Bug#15957.  */
+      w->window_end_valid = 0;
+    }
 }
 
 
-/* Set w->total_lines (w->total_cols if HORIZONTAL is non-zero) to
+/* Set w->total_lines (w->total_cols if HORFLAG is non-zero) to
    w->new_total for window W and recursively all child windows of W.
    Also calculate and assign the new vertical (horizontal) start
    positions of each of these windows.  */
@@ -3950,9 +4071,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
@@ -4047,6 +4173,8 @@ resize_frame_windows (struct frame *f, int size, bool horflag, bool pixelwise)
      have implicitly given us a zero or negative height.  */
   if (pixelwise)
     {
+      /* Note: This does not include the size for internal borders
+        since these are not part of the frame's text area.  */
       new_pixel_size = max (horflag
                            ? size
                            : (size
@@ -4582,24 +4710,24 @@ grow_mini_window (struct window *w, int delta, bool pixelwise)
 
          if (pixelwise)
            {
-             pixel_height = max (min (-XINT (height), INT_MAX - w->pixel_height),
-                                 FRAME_LINE_HEIGHT (f));
+             pixel_height = min (-XINT (height), INT_MAX - w->pixel_height);
              line_height = pixel_height / FRAME_LINE_HEIGHT (f);
            }
          else
            {
-             line_height = max (min (-XINT (height),
-                                     ((INT_MAX - w->pixel_height)
-                                      / FRAME_LINE_HEIGHT (f))),
-                                1);
+             line_height = min (-XINT (height),
+                                ((INT_MAX - w->pixel_height)
+                                 / FRAME_LINE_HEIGHT (f)));
              pixel_height = line_height * FRAME_LINE_HEIGHT (f);
            }
 
          /* Grow the mini-window.  */
          w->pixel_top = r->pixel_top + r->pixel_height;
          w->top_line = r->top_line + r->total_lines;
-         w->pixel_height += pixel_height;
-         w->total_lines += line_height;
+         /* Make sure the mini-window has always at least one line.  */
+         w->pixel_height = max (w->pixel_height + pixel_height,
+                                FRAME_LINE_HEIGHT (f));
+         w->total_lines = max (w->total_lines + line_height, 1);
 
          /* Enforce full redisplay of the frame.  */
          /* FIXME: Shouldn't window--resize-root-window-vertically do it?  */
@@ -4679,10 +4807,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;
@@ -4812,8 +4940,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);
@@ -4830,9 +4958,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;
 
@@ -4914,8 +5047,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
@@ -5090,6 +5227,32 @@ window_scroll_pixel_based (Lisp_Object window, int n, bool whole, int noerror)
       charpos = IT_CHARPOS (it);
       bytepos = IT_BYTEPOS (it);
 
+      /* If PT is in the screen line at the last fully visible line,
+        move_it_to will stop at X = 0 in that line, because the
+        required Y coordinate is reached there.  See if we can get to
+        PT without descending lower in Y, and if we can, it means we
+        reached PT before the scroll margin.  */
+      if (charpos != PT)
+       {
+         struct it it2;
+         void *it_data;
+
+         it2 = it;
+         it_data = bidi_shelve_cache ();
+         move_it_to (&it, PT, -1, -1, -1, MOVE_TO_POS);
+         if (IT_CHARPOS (it) == PT && it.current_y == it2.current_y)
+           {
+             charpos = IT_CHARPOS (it);
+             bytepos = IT_BYTEPOS (it);
+             bidi_unshelve_cache (it_data, 1);
+           }
+         else
+           {
+             it = it2;
+             bidi_unshelve_cache (it_data, 0);
+           }
+       }
+
       /* See if point is on a partially visible line at the end.  */
       if (it.what == IT_EOB)
        partial_p = it.current_y + it.ascent + it.descent > it.last_visible_y;
@@ -5362,8 +5525,10 @@ specifies the window.  This takes precedence over
   if (MINI_WINDOW_P (XWINDOW (selected_window))
       && !NILP (Vminibuf_scroll_window))
     window = Vminibuf_scroll_window;
-  /* If buffer is specified, scroll that buffer.  */
-  else if (!NILP (Vother_window_scroll_buffer))
+  /* If buffer is specified and live, scroll that buffer.  */
+  else if (!NILP (Vother_window_scroll_buffer)
+          && BUFFERP (Vother_window_scroll_buffer)
+          && BUFFER_LIVE_P (XBUFFER (Vother_window_scroll_buffer)))
     {
       window = Fget_buffer_window (Vother_window_scroll_buffer, Qnil);
       if (NILP (window))
@@ -5744,6 +5909,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);
+
   set_buffer_internal (obuf);
   return Qnil;
 }
@@ -6540,7 +6707,8 @@ save_window_save (Lisp_Object window, struct Lisp_Vector *vector, int i)
          else
            p->pointm = Fcopy_marker (w->pointm, Qnil);
          XMARKER (p->pointm)->insertion_type
-           = !NILP (Vwindow_point_insertion_type);
+           = !NILP (buffer_local_value_1 /* 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;
@@ -6631,6 +6799,7 @@ apply_window_adjustment (struct window *w)
   adjust_window_margins (w);
   clear_glyph_matrix (w->current_matrix);
   w->window_end_valid = 0;
+  windows_or_buffers_changed = 30;
   wset_redisplay (w);
   adjust_frame_glyphs (XFRAME (WINDOW_FRAME (w)));
 }
@@ -6834,9 +7003,7 @@ value.  */)
 {
   struct window *w = decode_live_window (window);
 
-  return list4 (make_number ((WINDOW_CONFIG_SCROLL_BAR_WIDTH (w)
-                             ? WINDOW_CONFIG_SCROLL_BAR_WIDTH (w)
-                             : WINDOW_SCROLL_BAR_AREA_WIDTH (w))),
+  return list4 (make_number (WINDOW_SCROLL_BAR_AREA_WIDTH (w)),
                make_number (WINDOW_SCROLL_BAR_COLS (w)),
                w->vertical_scroll_bar_type, Qnil);
 }
@@ -7099,6 +7266,8 @@ syms_of_window (void)
   DEFSYM (Qabove, "above");
   DEFSYM (Qbelow, "below");
   DEFSYM (Qclone_of, "clone-of");
+  DEFSYM (Qfloor, "floor");
+  DEFSYM (Qceiling, "ceiling");
 
   staticpro (&Vwindow_list);
 
@@ -7129,7 +7298,7 @@ is displayed in the `mode-line' face.  */);
   mode_line_in_non_selected_windows = 1;
 
   DEFVAR_LISP ("other-window-scroll-buffer", Vother_window_scroll_buffer,
-              doc: /* If non-nil, this is a buffer and \\[scroll-other-window] should scroll its window.  */);
+              doc: /* If this is a live buffer, \\[scroll-other-window] should scroll its window.  */);
   Vother_window_scroll_buffer = Qnil;
 
   DEFVAR_BOOL ("auto-window-vscroll", auto_window_vscroll_p,
@@ -7156,6 +7325,7 @@ on their symbols to be controlled by this variable.  */);
   DEFVAR_LISP ("window-point-insertion-type", Vwindow_point_insertion_type,
               doc: /* Type of marker to use for `window-point'.  */);
   Vwindow_point_insertion_type = Qnil;
+  DEFSYM (Qwindow_point_insertion_type, "window_point_insertion_type");
 
   DEFVAR_LISP ("window-configuration-change-hook",
               Vwindow_configuration_change_hook,
@@ -7248,11 +7418,10 @@ respectively are not installed by `window-state-put'.  */);
   Vwindow_persistent_parameters = list1 (Fcons (Qclone_of, Qt));
 
   DEFVAR_BOOL ("window-resize-pixelwise", window_resize_pixelwise,
-              doc: /*  Non-nil means resizing windows works pixelwise.
-Functions currently affected by this option are `split-window',
-`maximize-window', `minimize-window', `fit-window-to-buffer' and
-`fit-frame-to-buffer' and all functions symmetrically resizing a
-parent window.
+              doc: /*  Non-nil means resize windows pixelwise.
+This currently affects the functions: `split-window', `maximize-window',
+`minimize-window', `fit-window-to-buffer' and `fit-frame-to-buffer', and
+all functions that symmetrically resize a parent window.
 
 Note that when a frame's pixel size is not a multiple of the
 frame's character size, at least one window may get resized
@@ -7311,6 +7480,7 @@ pixelwise even if this option is nil.  */);
   defsubr (&Swindow_header_line_height);
   defsubr (&Swindow_right_divider_width);
   defsubr (&Swindow_bottom_divider_width);
+  defsubr (&Swindow_scroll_bar_width);
   defsubr (&Swindow_inside_edges);
   defsubr (&Swindow_inside_pixel_edges);
   defsubr (&Swindow_inside_absolute_pixel_edges);