(gdb-location-alist): Rename from
[bpt/emacs.git] / src / window.c
index 8d56b33..5e6f923 100644 (file)
@@ -1,7 +1,7 @@
 /* Window creation, deletion and examination for GNU Emacs.
    Does not include redisplay.
-   Copyright (C) 1985,86,87,93,94,95,96,97,1998,2000, 2001, 2002, 2003
-   Free Software Foundation, Inc.
+   Copyright (C) 1985, 1986, 1987, 1993, 1994, 1995, 1996, 1997, 1998, 2000,
+     2001, 2002, 2003, 2004, 2005  Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -79,10 +79,6 @@ static int foreach_window_1 P_ ((struct window *,
                                 void *));
 static Lisp_Object window_list_1 P_ ((Lisp_Object, Lisp_Object, Lisp_Object));
 
-/* The value of `window-size-fixed'.  */
-
-int window_size_fixed;
-
 /* This is the window in which the terminal's cursor should
    be left when nothing is being done with it.  This must
    always be a leaf window, and its buffer is selected by
@@ -124,6 +120,11 @@ Lisp_Object Vother_window_scroll_buffer;
 
 Lisp_Object Vtemp_buffer_show_function;
 
+/* Non-zero means line and page scrolling on tall lines (with images)
+   does partial scrolling by modifying window-vscroll.  */
+
+int auto_window_vscroll_p;
+
 /* Non-zero means to use mode-line-inactive face in all windows but the
    selected-window and the minibuffer-scroll-window when the
    minibuffer is active.  */
@@ -204,7 +205,7 @@ static int window_initialized;
 Lisp_Object Qwindow_configuration_change_hook;
 Lisp_Object Vwindow_configuration_change_hook;
 
-/* Nonzero means scroll commands try to put point
+/* Non-nil means scroll commands try to put point
    at the same screen height as previously.  */
 
 Lisp_Object Vscroll_preserve_screen_position;
@@ -241,7 +242,8 @@ make_window ()
   register struct window *p;
 
   p = allocate_window ();
-  XSETFASTINT (p->sequence_number, ++sequence_number);
+  ++sequence_number;
+  XSETFASTINT (p->sequence_number, sequence_number);
   XSETFASTINT (p->left_col, 0);
   XSETFASTINT (p->top_line, 0);
   XSETFASTINT (p->total_lines, 0);
@@ -260,6 +262,7 @@ make_window ()
   bzero (&p->last_cursor, sizeof (p->last_cursor));
   bzero (&p->phys_cursor, sizeof (p->phys_cursor));
   p->desired_matrix = p->current_matrix = 0;
+  p->nrows_scale_factor = p->ncols_scale_factor = 1;
   p->phys_cursor_type = -1;
   p->phys_cursor_width = -1;
   p->must_be_updated_p = 0;
@@ -305,7 +308,8 @@ used by that frame.  */)
 }
 
 DEFUN ("window-minibuffer-p", Fwindow_minibuffer_p, Swindow_minibuffer_p, 0, 1, 0,
-       doc: /* Returns non-nil if WINDOW is a minibuffer window.  */)
+       doc: /* Returns non-nil if WINDOW is a minibuffer window.
+WINDOW defaults to the selected window.  */)
      (window)
      Lisp_Object window;
 {
@@ -316,11 +320,18 @@ DEFUN ("window-minibuffer-p", Fwindow_minibuffer_p, Swindow_minibuffer_p, 0, 1,
 
 DEFUN ("pos-visible-in-window-p", Fpos_visible_in_window_p,
        Spos_visible_in_window_p, 0, 3, 0,
-       doc: /* Return t if position POS is currently on the frame in WINDOW.
+       doc: /* Return non-nil if position POS is currently on the frame in WINDOW.
 Return nil if that position is scrolled vertically out of view.
 If a character is only partially visible, nil is returned, unless the
 optional argument PARTIALLY is non-nil.
-POS defaults to point in WINDOW; WINDOW defaults to the selected window.  */)
+If POS is only out of view because of horizontal scrolling, return non-nil.
+POS defaults to point in WINDOW; WINDOW defaults to the selected window.
+
+If POS is visible, return t if PARTIALLY is nil; if PARTIALLY is non-nil,
+return value is a list (X Y PARTIAL) where X and Y are the pixel coordinates
+relative to the top left corner of the window. PARTIAL is nil if the character
+after POS is fully visible; otherwise it is a cons (RTOP . RBOT) where RTOP
+and RBOT are the number of pixels invisible at the top and bottom of the row.  */)
      (pos, window, partially)
      Lisp_Object pos, window, partially;
 {
@@ -328,8 +339,9 @@ POS defaults to point in WINDOW; WINDOW defaults to the selected window.  */)
   register int posint;
   register struct buffer *buf;
   struct text_pos top;
-  Lisp_Object in_window;
-  int fully_p;
+  Lisp_Object in_window = Qnil;
+  int rtop, rbot, fully_p = 1;
+  int x, y;
 
   w = decode_window (window);
   buf = XBUFFER (w->buffer);
@@ -345,38 +357,23 @@ POS defaults to point in WINDOW; WINDOW defaults to the selected window.  */)
   else
     posint = XMARKER (w->pointm)->charpos;
 
-  /* If position is above window start, it's not visible.  */
-  if (posint < CHARPOS (top))
-    in_window = Qnil;
-  else if (XFASTINT (w->last_modified) >= BUF_MODIFF (buf)
-          && XFASTINT (w->last_overlay_modified) >= BUF_OVERLAY_MODIFF (buf)
-          && posint < BUF_Z (buf) - XFASTINT (w->window_end_pos))
-    {
-      /* If frame is up-to-date, and POSINT is < window end pos, use
-        that info.  This doesn't work for POSINT == end pos, because
-        the window end pos is actually the position _after_ the last
-        char in the window.  */
-      if (NILP (partially))
-       {
-         pos_visible_p (w, posint, &fully_p, NILP (partially));
-         in_window = fully_p ? Qt : Qnil;
-       }
-      else
-       in_window = Qt;
-    }
-  else if (posint > BUF_ZV (buf))
-    in_window = Qnil;
-  else if (CHARPOS (top) < BUF_BEGV (buf) || CHARPOS (top) > BUF_ZV (buf))
-    /* If window start is out of range, do something reasonable.  */
-    in_window = Qnil;
-  else
-    {
-      if (pos_visible_p (w, posint, &fully_p, NILP (partially)))
-       in_window = !NILP (partially) || fully_p ? Qt : Qnil;
-      else
-       in_window = Qnil;
-    }
-
+  /* If position is above window start or outside buffer boundaries,
+     or if window start is out of range, position is not visible.  */
+  if (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, NILP (partially))
+      && (fully_p = !rtop && !rbot, (!NILP (partially) || fully_p)))
+    in_window = Qt;
+
+  if (!NILP (in_window) && !NILP (partially))
+    in_window = Fcons (make_number (x),
+                      Fcons (make_number (y),
+                             Fcons ((fully_p ? Qnil
+                                    : Fcons (make_number (rtop),
+                                             make_number (rbot))),
+                                    Qnil)));
   return in_window;
 }
 
@@ -404,7 +401,8 @@ decode_any_window (window)
 }
 
 DEFUN ("window-buffer", Fwindow_buffer, Swindow_buffer, 0, 1, 0,
-       doc: /* Return the buffer that WINDOW is displaying.  */)
+       doc: /* Return the buffer that WINDOW is displaying.
+WINDOW defaults to the selected window.  */)
      (window)
      Lisp_Object window;
 {
@@ -440,7 +438,7 @@ DEFUN ("window-hscroll", Fwindow_hscroll, Swindow_hscroll, 0, 1, 0,
 
 DEFUN ("set-window-hscroll", Fset_window_hscroll, Sset_window_hscroll, 2, 2, 0,
        doc: /* Set number of columns WINDOW is scrolled from left margin to NCOL.
-NCOL should be zero or positive.
+Return NCOL.  NCOL should be zero or positive.
 
 Note that if `automatic-hscrolling' is non-nil, you cannot scroll the
 window so that the location of point becomes invisible.  */)
@@ -554,7 +552,7 @@ display margins, fringes, header line, and/or mode line.  */)
 }
 
 DEFUN ("window-inside-pixel-edges", Fwindow_inside_pixel_edges, Swindow_inside_pixel_edges, 0, 1, 0,
-       doc: /* Return a list of the edge coordinates of WINDOW.
+       doc: /* Return a list of the edge pixel coordinates of WINDOW.
 \(LEFT TOP RIGHT BOTTOM), all relative to 0, 0 at top left corner of frame.
 RIGHT is one more than the rightmost x position used by text in WINDOW,
 and BOTTOM is one more than the bottommost y position used by text in WINDOW.
@@ -586,6 +584,8 @@ display margins, fringes, header line, and/or mode line.  */)
    if it is on the window's modeline, return ON_MODE_LINE;
    if it is on the border between the window and its right sibling,
       return ON_VERTICAL_BORDER.
+   if it is on a scroll bar,
+      return ON_SCROLL_BAR.
    if it is on the window's top line, return ON_HEADER_LINE;
    if it is in left or right fringe of the window,
       return ON_LEFT_FRINGE or ON_RIGHT_FRINGE, and convert *X and *Y
@@ -612,9 +612,6 @@ coordinates_in_window (w, x, y)
   int grabbable_width = ux;
   int lmargin_width, rmargin_width, text_left, text_right;
 
-  if (*x < x0 || *x >= x1)
-    return ON_NOTHING;
-
   /* In what's below, we subtract 1 when computing right_x because we
      want the rightmost pixel, which is given by left_pixel+width-1.  */
   if (w->pseudo_window_p)
@@ -664,6 +661,9 @@ coordinates_in_window (w, x, y)
            return ON_VERTICAL_BORDER;
        }
 
+      if (*x < x0 || *x >= x1)
+       return ON_NOTHING;
+
       /* Convert X and Y to window relative coordinates.
         Mode line starts at left edge of window.  */
       *x -= x0;
@@ -678,9 +678,12 @@ coordinates_in_window (w, x, y)
       goto header_vertical_border_check;
     }
 
+  if (*x < x0 || *x >= x1)
+    return ON_NOTHING;
+
   /* Outside any interesting column?  */
   if (*x < left_x || *x > right_x)
-    return ON_NOTHING;
+    return ON_SCROLL_BAR;
 
   lmargin_width = window_box_width (w, LEFT_MARGIN_AREA);
   rmargin_width = window_box_width (w, RIGHT_MARGIN_AREA);
@@ -790,8 +793,8 @@ If they are in the windows's left or right marginal areas, `left-margin'\n\
   ly = Fcdr (coordinates);
   CHECK_NUMBER_OR_FLOAT (lx);
   CHECK_NUMBER_OR_FLOAT (ly);
-  x = FRAME_PIXEL_X_FROM_CANON_X (f, lx);
-  y = FRAME_PIXEL_Y_FROM_CANON_Y (f, ly);
+  x = FRAME_PIXEL_X_FROM_CANON_X (f, lx) + FRAME_INTERNAL_BORDER_WIDTH (f);
+  y = FRAME_PIXEL_Y_FROM_CANON_Y (f, ly) + FRAME_INTERNAL_BORDER_WIDTH (f);
 
   switch (coordinates_in_window (w, &x, &y))
     {
@@ -825,6 +828,10 @@ 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:
+      /* Historically we are supposed to return nil in this case.  */
+      return Qnil;
+
     default:
       abort ();
     }
@@ -945,8 +952,10 @@ column 0.  */)
   CHECK_NUMBER_OR_FLOAT (y);
 
   return window_from_coordinates (f,
-                                 FRAME_PIXEL_X_FROM_CANON_X (f, x),
-                                 FRAME_PIXEL_Y_FROM_CANON_Y (f, y),
+                                 (FRAME_PIXEL_X_FROM_CANON_X (f, x)
+                                  + FRAME_INTERNAL_BORDER_WIDTH (f)),
+                                 (FRAME_PIXEL_Y_FROM_CANON_Y (f, y)
+                                  + FRAME_INTERNAL_BORDER_WIDTH (f)),
                                  0, 0, 0, 0);
 }
 
@@ -996,6 +1005,8 @@ DEFUN ("window-end", Fwindow_end, Swindow_end, 0, 2, 0,
 This is updated by redisplay, when it runs to completion.
 Simply changing the buffer text or setting `window-start'
 does not update this value.
+Return nil if there is no recorded value.  \(This can happen if the
+last redisplay of WINDOW was preempted, and did not finish.)
 If UPDATE is non-nil, compute the up-to-date position
 if it isn't already recorded.  */)
      (window, update)
@@ -1061,7 +1072,8 @@ if it isn't already recorded.  */)
 }
 
 DEFUN ("set-window-point", Fset_window_point, Sset_window_point, 2, 2, 0,
-       doc: /* Make point value in WINDOW be at position POS in WINDOW's buffer.  */)
+       doc: /* Make point value in WINDOW be at position POS in WINDOW's buffer.
+Return POS.  */)
      (window, pos)
      Lisp_Object window, pos;
 {
@@ -1084,6 +1096,7 @@ DEFUN ("set-window-point", Fset_window_point, Sset_window_point, 2, 2, 0,
 
 DEFUN ("set-window-start", Fset_window_start, Sset_window_start, 2, 3, 0,
        doc: /* Make display in WINDOW start at position POS in WINDOW's buffer.
+Return POS.
 Optional third arg NOFORCE non-nil inhibits next redisplay
 from overriding motion of point in order to display at this exact start.  */)
      (window, pos, noforce)
@@ -1602,7 +1615,7 @@ decode_next_window_args (window, minibuf, all_frames)
                   : Qnil);
   else if (EQ (*all_frames, Qvisible))
     ;
-  else if (XFASTINT (*all_frames) == 0)
+  else if (EQ (*all_frames, make_number (0)))
     ;
   else if (FRAMEP (*all_frames))
     ;
@@ -1758,8 +1771,8 @@ DEFUN ("other-window", Fother_window, Sother_window, 1, 2, "p",
        doc: /* Select the ARG'th different window on this frame.
 All windows on current frame are arranged in a cyclic order.
 This command selects the window ARG steps away in that order.
-A negative ARG moves in the opposite order.  If the optional second
-argument ALL_FRAMES is non-nil, cycle through all frames.  */)
+A negative ARG moves in the opposite order.  The optional second
+argument ALL_FRAMES has the same meaning as in `next-window', which see.  */)
      (arg, all_frames)
      Lisp_Object arg, all_frames;
 {
@@ -1809,7 +1822,7 @@ static Lisp_Object
 window_list_1 (window, minibuf, all_frames)
      Lisp_Object window, minibuf, all_frames;
 {
-  Lisp_Object tail, list;
+  Lisp_Object tail, list, rest;
 
   decode_next_window_args (&window, &minibuf, &all_frames);
   list = Qnil;
@@ -1818,7 +1831,17 @@ window_list_1 (window, minibuf, all_frames)
     if (candidate_window_p (XCAR (tail), window, minibuf, all_frames))
       list = Fcons (XCAR (tail), list);
 
-  return Fnreverse (list);
+  /* Rotate the list to start with WINDOW.  */
+  list = Fnreverse (list);
+  rest = Fmemq (window, list);
+  if (!NILP (rest) && !EQ (rest, list))
+    {
+      for (tail = list; !EQ (XCDR (tail), rest); tail = XCDR (tail))
+       ;
+      XSETCDR (tail, Qnil);
+      list = nconc2 (rest, list);
+    }
+  return list;
 }
 
 
@@ -1866,7 +1889,7 @@ window_loop (type, obj, mini, frames)
 
   if (f)
     frame_arg = Qlambda;
-  else if (XFASTINT (frames) == 0)
+  else if (EQ (frames, make_number (0)))
     frame_arg = frames;
   else if (EQ (frames, Qvisible))
     frame_arg = frames;
@@ -2043,6 +2066,9 @@ window_loop (type, obj, mini, frames)
            if (EQ (w->buffer, obj))
              {
                mark_window_display_accurate (window, 0);
+               w->update_mode_line = Qt;
+               XBUFFER (obj)->prevent_redisplay_optimizations_p = 1;
+               ++update_mode_lines;
                best_window = window;
              }
            break;
@@ -2073,6 +2099,10 @@ check_all_windows ()
 
 DEFUN ("get-lru-window", Fget_lru_window, Sget_lru_window, 0, 1, 0,
        doc: /* Return the window least recently selected or used for display.
+Return a full-width window if possible.
+A minibuffer window is never a candidate.
+A dedicated window is never a candidate, so if all windows are dedicated,
+the value is nil.
 If optional argument FRAME is `visible', search all visible frames.
 If FRAME is 0, search all visible and iconified frames.
 If FRAME is t, search all frames.
@@ -2092,6 +2122,9 @@ If FRAME is a frame, search only that frame.  */)
 
 DEFUN ("get-largest-window", Fget_largest_window, Sget_largest_window, 0, 1, 0,
        doc: /* Return the largest window in area.
+A minibuffer window is never a candidate.
+A dedicated window is never a candidate, so if all windows are dedicated,
+the value is nil.
 If optional argument FRAME is `visible', search all visible frames.
 If FRAME is 0, search all visible and iconified frames.
 If FRAME is t, search all frames.
@@ -2106,6 +2139,7 @@ If FRAME is a frame, search only that frame.  */)
 
 DEFUN ("get-buffer-window", Fget_buffer_window, Sget_buffer_window, 1, 2, 0,
        doc: /* Return a window currently displaying BUFFER, or nil if none.
+BUFFER can be a buffer or a buffer name.
 If optional argument FRAME is `visible', search all visible frames.
 If optional argument FRAME is 0, search all visible and iconified frames.
 If FRAME is t, search all frames.
@@ -2188,6 +2222,7 @@ value is reasonable when this function is called.  */)
 DEFUN ("delete-windows-on", Fdelete_windows_on, Sdelete_windows_on,
        1, 2, "bDelete windows on (buffer): ",
        doc: /* Delete all windows showing BUFFER.
+BUFFER must be a buffer or the name of an existing buffer.
 Optional second argument FRAME controls which frames are affected.
 If optional argument FRAME is `visible', search all visible frames.
 If FRAME is 0, search all visible and iconified frames.
@@ -2217,7 +2252,8 @@ If FRAME is a frame, search only that frame.  */)
 DEFUN ("replace-buffer-in-windows", Freplace_buffer_in_windows,
        Sreplace_buffer_in_windows,
        1, 1, "bReplace buffer in windows: ",
-       doc: /* Replace BUFFER with some other buffer in all windows showing it.  */)
+       doc: /* Replace BUFFER with some other buffer in all windows showing it.
+BUFFER may be a buffer or the name of an existing buffer.  */)
      (buffer)
      Lisp_Object buffer;
 {
@@ -2630,6 +2666,9 @@ shrink_windows (total, size, nchildren, shrinkable,
             --shrinkable;
             total_removed += smallest;
 
+            /* We don't know what the smallest is now.  */
+            smallest = total;
+
             /* Out of for, just remove one window at the time and
                check again if we have enough space.  */
             break;
@@ -2654,6 +2693,16 @@ shrink_windows (total, size, nchildren, shrinkable,
      that are left and still can be shrunk.  */
   while (total_shrink > total_removed)
     {
+      int nonzero_sizes = 0;
+      int nonzero_idx = -1;
+
+      for (i = 0; i < nchildren; ++i)
+        if (new_sizes[i] > 0)
+          {
+            ++nonzero_sizes;
+            nonzero_idx = i;
+          }
+
       for (i = 0; i < nchildren; ++i)
         if (new_sizes[i] > min_size)
           {
@@ -2664,6 +2713,25 @@ shrink_windows (total, size, nchildren, shrinkable,
                check again if we have enough space.  */
             break;
           }
+
+
+      /* Special case, only one window left.  */
+      if (nonzero_sizes == 1)
+        break;
+    }
+
+  /* Any surplus due to rounding, we add to windows that are left.  */
+  while (total_shrink < total_removed)
+    {
+      for (i = 0; i < nchildren; ++i)
+        {
+          if (new_sizes[i] != 0 && total_shrink < total_removed)
+            {
+              ++new_sizes[i];
+              --total_removed;
+              break;
+            }
+        }
     }
 
   return new_sizes;
@@ -2952,6 +3020,9 @@ set_window_buffer (window, buffer, run_hooks_p, keep_margins_p)
   if (EQ (window, selected_window))
     b->last_selected_window = window;
 
+  /* Let redisplay errors through.  */
+  b->display_error_modiff = 0;
+
   /* Update time stamps of buffer display.  */
   if (INTEGERP (b->display_count))
     XSETINT (b->display_count, XINT (b->display_count) + 1);
@@ -3029,11 +3100,13 @@ set_window_buffer (window, buffer, run_hooks_p, keep_margins_p)
 
 DEFUN ("set-window-buffer", Fset_window_buffer, Sset_window_buffer, 2, 3, 0,
        doc: /* Make WINDOW display BUFFER as its contents.
-BUFFER can be a buffer or buffer name.
-Optional third arg KEEP_MARGINS non-nil means that WINDOW's current
+BUFFER can be a buffer or the name of an existing buffer.
+Optional third arg KEEP-MARGINS non-nil means that WINDOW's current
 display margins, fringe widths, and scroll bar settings are maintained;
 the default is to reset these from BUFFER's local settings or the frame
-defaults.  */)
+defaults.
+
+This function runs the hook `window-scroll-functions'.  */)
      (window, buffer, keep_margins)
      register Lisp_Object window, buffer, keep_margins;
 {
@@ -3069,8 +3142,8 @@ defaults.  */)
 
 DEFUN ("select-window", Fselect_window, Sselect_window, 1, 2, 0,
        doc: /* Select WINDOW.  Most editing will apply to WINDOW's buffer.
-If WINDOW is not already selected, also make WINDOW's buffer current.
-Also make WINDOW the frame's selected window.
+If WINDOW is not already selected, make WINDOW's buffer current
+and make WINDOW the frame's selected window.  Return WINDOW.
 Optional second arg NORECORD non-nil means
 do not put this buffer at the front of the list of recently selected ones.
 
@@ -3088,10 +3161,14 @@ selects the buffer of the selected window before each command.  */)
   w = XWINDOW (window);
   w->frozen_window_start_p = 0;
 
-  XSETFASTINT (w->use_time, ++window_select_count);
+  ++window_select_count;
+  XSETFASTINT (w->use_time, window_select_count);
   if (EQ (window, selected_window))
     return window;
 
+  /* Store the current buffer's actual point into the
+     old selected window.  It belongs to that window,
+     and when the window is not selected, must be in the window.  */
   if (!NILP (selected_window))
     {
       ow = XWINDOW (selected_window);
@@ -3185,10 +3262,13 @@ display_buffer_1 (window)
 }
 
 DEFUN ("special-display-p", Fspecial_display_p, Sspecial_display_p, 1, 1, 0,
-       doc: /* Returns non-nil if a buffer named BUFFER-NAME would be created specially.
-The value is actually t if the frame should be called with default frame
-parameters, and a list of frame parameters if they were specified.
-See `special-display-buffer-names', and `special-display-regexps'.  */)
+       doc: /* Returns non-nil if a buffer named BUFFER-NAME gets a special frame.
+If the value is t, a frame would be created for that buffer
+using the default frame parameters.  If the value is a list,
+it is a list of frame parameters that would be used
+to make a frame for that buffer.
+The variables `special-display-buffer-names'
+and `special-display-regexps' control this.  */)
      (buffer_name)
      Lisp_Object buffer_name;
 {
@@ -3254,7 +3334,8 @@ See `same-window-buffer-names' and `same-window-regexps'.  */)
 DEFUN ("display-buffer", Fdisplay_buffer, Sdisplay_buffer, 1, 3,
        "BDisplay buffer: \nP",
        doc: /* Make BUFFER appear in some window but don't select it.
-BUFFER can be a buffer or a buffer name.
+BUFFER must  be the name of an existing buffer, or, when called from Lisp,
+a buffer.
 If BUFFER is shown already in some window, just use that one,
 unless the window is the selected window and the optional second
 argument NOT-THIS-WINDOW is non-nil (interactively, with prefix arg).
@@ -3263,9 +3344,10 @@ Returns the window displaying BUFFER.
 If `display-buffer-reuse-frames' is non-nil, and another frame is currently
 displaying BUFFER, then simply raise that frame.
 
-The variables `special-display-buffer-names', `special-display-regexps',
-`same-window-buffer-names', and `same-window-regexps' customize how certain
-buffer names are handled.
+The variables `special-display-buffer-names',
+`special-display-regexps', `same-window-buffer-names', and
+`same-window-regexps' customize how certain buffer names are handled.
+The latter two take effect only if NOT-THIS-WINDOW is t.
 
 If optional argument FRAME is `visible', search all visible frames.
 If FRAME is 0, search all visible and iconified frames.
@@ -3276,6 +3358,10 @@ If FRAME is nil, search only the selected frame
  unless `pop-up-frames' or `display-buffer-reuse-frames' is non-nil,
  which means search visible and iconified frames.
 
+If a full-width window on a splittable frame is available to display
+the buffer, it may be split, subject to the value of the variable
+`split-height-threshold'.
+
 If `even-window-heights' is non-nil, window heights will be evened out
 if displaying the buffer causes two vertically adjacent windows to be
 displayed.  */)
@@ -3453,7 +3539,7 @@ DEFUN ("force-window-update", Fforce_window_update, Sforce_window_update,
        0, 1, 0,
        doc: /* Force redisplay of all windows.
 If optional arg OBJECT is a window, force redisplay of that window only.
-If OBJECT is a buffer or buffer name, force redisplay of all windows 
+If OBJECT is a buffer or buffer name, force redisplay of all windows
 displaying that buffer.  */)
      (object)
      Lisp_Object object;
@@ -3461,15 +3547,21 @@ displaying that buffer.  */)
   if (NILP (object))
     {
       windows_or_buffers_changed++;
+      update_mode_lines++;
       return Qt;
     }
 
   if (WINDOWP (object))
     {
+      struct window *w = XWINDOW (object);
       mark_window_display_accurate (object, 0);
+      w->update_mode_line = Qt;
+      if (BUFFERP (w->buffer))
+       XBUFFER (w->buffer)->prevent_redisplay_optimizations_p = 1;
+      ++update_mode_lines;
       return Qt;
     }
-    
+
   if (STRINGP (object))
     object = Fget_buffer (object);
   if (BUFFERP (object) && !NILP (XBUFFER (object)->name))
@@ -3534,7 +3626,7 @@ temp_output_buffer_show (buf)
          Lisp_Object prev_window, prev_buffer;
          prev_window = selected_window;
          XSETBUFFER (prev_buffer, old);
-         
+
          /* Select the window that was chosen, for running the hook.
             Note: Both Fselect_window and select_window_norecord may
             set-buffer to the buffer displayed in the window,
@@ -3564,7 +3656,8 @@ make_dummy_parent (window)
       = ((struct Lisp_Vector *)o)->contents[i];
   XSETWINDOW (new, p);
 
-  XSETFASTINT (p->sequence_number, ++sequence_number);
+  ++sequence_number;
+  XSETFASTINT (p->sequence_number, sequence_number);
 
   /* Put new into window structure in place of window */
   replace_window (window, new);
@@ -3585,7 +3678,12 @@ DEFUN ("split-window", Fsplit_window, Ssplit_window, 0, 3, "",
 WINDOW defaults to selected one and SIZE to half its size.
 If optional third arg HORFLAG is non-nil, split side by side
 and put SIZE columns in the first of the pair.  In that case,
-SIZE includes that window's scroll bar, or the divider column to its right.  */)
+SIZE includes that window's scroll bar, or the divider column to its right.
+Interactively, all arguments are nil.
+
+Returns the newly created window (which is the lower or rightmost one).
+The upper or leftmost window is the original one and remains selected.
+See Info node `(elisp)Splitting Windows' for more details and examples.*/)
      (window, size, horflag)
      Lisp_Object window, size, horflag;
 {
@@ -4457,7 +4555,7 @@ window_scroll_pixel_based (window, n, whole, noerror)
         results for variable height lines.  */
       init_iterator (&it, w, PT, PT_BYTE, NULL, DEFAULT_FACE_ID);
       it.current_y = it.last_visible_y;
-      move_it_vertically (&it, - window_box_height (w) / 2);
+      move_it_vertically_backward (&it, window_box_height (w) / 2);
 
       /* The function move_iterator_vertically may move over more than
         the specified y-distance.  If it->w is small, e.g. a
@@ -4467,14 +4565,41 @@ window_scroll_pixel_based (window, n, whole, noerror)
       if (it.current_y <= 0)
        {
          init_iterator (&it, w, PT, PT_BYTE, NULL, DEFAULT_FACE_ID);
-         move_it_vertically (&it, 0);
+         move_it_vertically_backward (&it, 0);
          it.current_y = 0;
        }
 
       start = it.current.pos;
     }
+  else if (auto_window_vscroll_p)
+    {
+      if (tem = XCAR (XCDR (XCDR (tem))), CONSP (tem))
+       {
+         int px;
+         int dy = WINDOW_FRAME_LINE_HEIGHT (w);
+         if (whole)
+           dy = max ((window_box_height (w)
+                      - next_screen_context_lines * dy),
+                     dy);
+         dy *= n;
+
+         if (n < 0 && (px = XINT (XCAR (tem))) > 0)
+           {
+             px = max (0, -w->vscroll - min (px, -dy));
+             Fset_window_vscroll (window, make_number (px), Qt);
+             return;
+           }
+         if (n > 0 && (px = XINT (XCDR (tem))) > 0)
+           {
+             px = max (0, -w->vscroll + min (px, dy));
+             Fset_window_vscroll (window, make_number (px), Qt);
+             return;
+           }
+       }
+      Fset_window_vscroll (window, make_number (0), Qt);
+    }
 
-  /* If scroll_preserve_screen_position is non-zero, we try to set
+  /* If scroll_preserve_screen_position is non-nil, we try to set
      point in the same window line as it is now, so get that line.  */
   if (!NILP (Vscroll_preserve_screen_position))
     {
@@ -4490,18 +4615,34 @@ window_scroll_pixel_based (window, n, whole, noerror)
   start_display (&it, w, start);
   if (whole)
     {
-      int screen_full = (window_box_height (w)
-                        - next_screen_context_lines * FRAME_LINE_HEIGHT (it.f));
-      int dy = n * screen_full;
+      int start_pos = IT_CHARPOS (it);
+      int dy = WINDOW_FRAME_LINE_HEIGHT (w);
+      dy = max ((window_box_height (w)
+                - next_screen_context_lines * dy),
+               dy) * n;
 
       /* Note that move_it_vertically always moves the iterator to the
          start of a line.  So, if the last line doesn't have a newline,
         we would end up at the start of the line ending at ZV.  */
       if (dy <= 0)
-       move_it_vertically_backward (&it, -dy);
+       {
+         move_it_vertically_backward (&it, -dy);
+         /* Ensure we actually does move, e.g. in case we are currently
+            looking at an image that is taller that the window height.  */
+         while (start_pos == IT_CHARPOS (it)
+                && start_pos > BEGV)
+           move_it_by_lines (&it, -1, 1);
+       }
       else if (dy > 0)
-       move_it_to (&it, ZV, -1, it.current_y + dy, -1,
-                   MOVE_TO_POS | MOVE_TO_Y);
+       {
+         move_it_to (&it, ZV, -1, it.current_y + dy, -1,
+                     MOVE_TO_POS | MOVE_TO_Y);
+         /* Ensure we actually does move, e.g. in case we are currently
+            looking at an image that is taller that the window height.  */
+         while (start_pos == IT_CHARPOS (it)
+                && start_pos < ZV)
+           move_it_by_lines (&it, 1, 1);
+       }
     }
   else
     move_it_by_lines (&it, n, 1);
@@ -4576,26 +4717,37 @@ window_scroll_pixel_based (window, n, whole, noerror)
       w->force_start = Qt;
     }
 
+  /* The rest of this function uses current_y in a nonstandard way,
+     not including the height of the header line if any.  */
   it.current_y = it.vpos = 0;
 
-  /* Preserve the screen position if we must.  */
-  if (preserve_y >= 0)
-    {
-      move_it_to (&it, -1, -1, preserve_y, -1, MOVE_TO_Y);
-      SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it));
-    }
-  else
+  /* Move PT out of scroll margins.
+     This code wants current_y to be zero at the window start position
+     even if there is a header line.  */
+  this_scroll_margin = max (0, scroll_margin);
+  this_scroll_margin = min (this_scroll_margin, XFASTINT (w->total_lines) / 4);
+  this_scroll_margin *= FRAME_LINE_HEIGHT (it.f);
+
+  if (n > 0)
     {
-      /* Move PT out of scroll margins.  */
-      this_scroll_margin = max (0, scroll_margin);
-      this_scroll_margin = min (this_scroll_margin, XFASTINT (w->total_lines) / 4);
-      this_scroll_margin *= FRAME_LINE_HEIGHT (it.f);
+      /* We moved the window start towards ZV, so PT may be now
+        in the scroll margin at the top.  */
+      move_it_to (&it, PT, -1, -1, -1, MOVE_TO_POS);
+      if (IT_CHARPOS (it) == PT && it.current_y >= this_scroll_margin)
+       /* We found PT at a legitimate height.  Leave it alone.  */
+       ;
+      else if (preserve_y >= 0)
+       {
+         /* If we have a header line, take account of it.
+            This is necessary because we set it.current_y to 0, above.  */
+         if (WINDOW_WANTS_HEADER_LINE_P (w))
+           preserve_y -= CURRENT_HEADER_LINE_HEIGHT (w);
 
-      if (n > 0)
+         move_it_to (&it, -1, -1, preserve_y, -1, MOVE_TO_Y);
+         SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it));
+       }
+      else
        {
-         /* We moved the window start towards ZV, so PT may be now
-            in the scroll margin at the top.  */
-         move_it_to (&it, PT, -1, -1, -1, MOVE_TO_POS);
          while (it.current_y < this_scroll_margin)
            {
              int prev = it.current_y;
@@ -4605,23 +4757,57 @@ window_scroll_pixel_based (window, n, whole, noerror)
            }
          SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it));
        }
-      else if (n < 0)
+    }
+  else if (n < 0)
+    {
+      int charpos, bytepos;
+      int partial_p;
+
+      /* Save our position, for the preserve_y case.  */
+      charpos = IT_CHARPOS (it);
+      bytepos = IT_BYTEPOS (it);
+
+      /* We moved the window start towards BEGV, so PT may be now
+        in the scroll margin at the bottom.  */
+      move_it_to (&it, PT, -1,
+                 it.last_visible_y - this_scroll_margin - 1, -1,
+                 MOVE_TO_POS | MOVE_TO_Y);
+
+      /* Save our position, in case it's correct.  */
+      charpos = IT_CHARPOS (it);
+      bytepos = IT_BYTEPOS (it);
+
+      /* 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;
+      else
        {
-         int charpos, bytepos;
-
-         /* We moved the window start towards BEGV, so PT may be now
-            in the scroll margin at the bottom.  */
-         move_it_to (&it, PT, -1,
-                     it.last_visible_y - this_scroll_margin - 1, -1,
-                     MOVE_TO_POS | MOVE_TO_Y);
+         move_it_by_lines (&it, 1, 1);
+         partial_p = it.current_y > it.last_visible_y;
+       }
 
-         /* Save our position, in case it's correct.  */
-         charpos = IT_CHARPOS (it);
-         bytepos = IT_BYTEPOS (it);
+      if (charpos == PT && !partial_p)
+       /* We found PT before we found the display margin, so PT is ok.  */
+       ;
+      else if (preserve_y >= 0)
+       {
+         SET_TEXT_POS_FROM_MARKER (start, w->start);
+         start_display (&it, w, start);
+#if 0  /* It's wrong to subtract this here
+         because we called start_display again
+         and did not alter it.current_y this time.  */
+
+         /* If we have a header line, take account of it.  */
+         if (WINDOW_WANTS_HEADER_LINE_P (w))
+           preserve_y -= CURRENT_HEADER_LINE_HEIGHT (w);
+#endif
 
-         /* See if point is on a partially visible line at the end.  */
-         move_it_by_lines (&it, 1, 1);
-         if (it.current_y > it.last_visible_y)
+         move_it_to (&it, -1, -1, preserve_y, -1, MOVE_TO_Y);
+         SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it));
+       }
+      else
+       {
+         if (partial_p)
            /* The last line was only partially visible, so back up two
               lines to make sure we're on a fully visible line.  */
            {
@@ -4666,7 +4852,7 @@ window_scroll_line_based (window, n, whole, noerror)
 
   posit = *compute_motion (startpos, 0, 0, 0,
                           PT, ht, 0,
-                          window_box_text_cols (w), XINT (w->hscroll),
+                          -1, XINT (w->hscroll),
                           0, w);
   original_vpos = posit.vpos;
 
@@ -4822,7 +5008,8 @@ scroll_command (n, direction)
 }
 
 DEFUN ("scroll-up", Fscroll_up, Sscroll_up, 0, 1, "P",
-       doc: /* Scroll text of current window upward ARG lines; or near full screen if no ARG.
+       doc: /* Scroll text of current window upward ARG lines.
+If ARG is omitted or nil, scroll upward by a near full screen.
 A near full screen is `next-screen-context-lines' less than a full screen.
 Negative ARG means scroll downward.
 If ARG is the atom `-', scroll downward by nearly full screen.
@@ -4835,7 +5022,8 @@ When calling from a program, supply as argument a number, nil, or `-'.  */)
 }
 
 DEFUN ("scroll-down", Fscroll_down, Sscroll_down, 0, 1, "P",
-       doc: /* Scroll text of current window down ARG lines; or near full screen if no ARG.
+       doc: /* Scroll text of current window down ARG lines.
+If ARG is omitted or nil, scroll down by a near full screen.
 A near full screen is `next-screen-context-lines' less than a full screen.
 Negative ARG means scroll upward.
 If ARG is the atom `-', scroll upward by nearly full screen.
@@ -4849,10 +5037,11 @@ When calling from a program, supply as argument a number, nil, or `-'.  */)
 \f
 DEFUN ("other-window-for-scrolling", Fother_window_for_scrolling, Sother_window_for_scrolling, 0, 0, 0,
        doc: /* Return the other window for \"other window scroll\" commands.
-If in the minibuffer, `minibuffer-scroll-window' if non-nil
-specifies the window.
 If `other-window-scroll-buffer' is non-nil, a window
-showing that buffer is used.  */)
+showing that buffer is used.
+If in the minibuffer, `minibuffer-scroll-window' if non-nil
+specifies the window.  This takes precedence over
+`other-window-scroll-buffer'.  */)
      ()
 {
   Lisp_Object window;
@@ -4898,10 +5087,11 @@ if the current one is at the bottom.  Negative ARG means scroll downward.
 If ARG is the atom `-', scroll downward by nearly full screen.
 When calling from a program, supply as argument a number, nil, or `-'.
 
-If in the minibuffer, `minibuffer-scroll-window' if non-nil
-specifies the window to scroll.
 If `other-window-scroll-buffer' is non-nil, scroll the window
-showing that buffer, popping the buffer up if necessary.  */)
+showing that buffer, popping the buffer up if necessary.
+If in the minibuffer, `minibuffer-scroll-window' if non-nil
+specifies the window to scroll.  This takes precedence over
+`other-window-scroll-buffer'.  */)
      (arg)
      Lisp_Object arg;
 {
@@ -4937,17 +5127,17 @@ showing that buffer, popping the buffer up if necessary.  */)
   return Qnil;
 }
 \f
-DEFUN ("scroll-left", Fscroll_left, Sscroll_left, 0, 1, "P",
+DEFUN ("scroll-left", Fscroll_left, Sscroll_left, 0, 2, "P\np",
        doc: /* Scroll selected window display ARG columns left.
 Default for ARG is window width minus 2.
 Value is the total amount of leftward horizontal scrolling in
 effect after the change.
-If `automatic-hscrolling' is non-nil, the argument ARG modifies
-lower bound for automatic scrolling, i.e. automatic scrolling
+If SET_MINIMUM is non-nil, the new scroll amount becomes the
+lower bound for automatic scrolling, i.e. automatic scrolling
 will not scroll a window to a column less than the value returned
-by this function.  */)
-     (arg)
-     register Lisp_Object arg;
+by this function.  This happens in an interactive call.  */)
+     (arg, set_minimum)
+     register Lisp_Object arg, set_minimum;
 {
   Lisp_Object result;
   int hscroll;
@@ -4961,23 +5151,23 @@ by this function.  */)
   hscroll = XINT (w->hscroll) + XINT (arg);
   result = Fset_window_hscroll (selected_window, make_number (hscroll));
 
-  if (interactive_p (0))
+  if (!NILP (set_minimum))
     w->min_hscroll = w->hscroll;
 
   return result;
 }
 
-DEFUN ("scroll-right", Fscroll_right, Sscroll_right, 0, 1, "P",
+DEFUN ("scroll-right", Fscroll_right, Sscroll_right, 0, 2, "P\np",
        doc: /* Scroll selected window display ARG columns right.
 Default for ARG is window width minus 2.
 Value is the total amount of leftward horizontal scrolling in
 effect after the change.
-If `automatic-hscrolling' is non-nil, the argument ARG modifies
-lower bound for automatic scrolling, i.e. automatic scrolling
+If SET_MINIMUM is non-nil, the new scroll amount becomes the
+lower bound for automatic scrolling, i.e. automatic scrolling
 will not scroll a window to a column less than the value returned
-by this function.  */)
-     (arg)
-     register Lisp_Object arg;
+by this function.  This happens in an interactive call.  */)
+     (arg, set_minimum)
+     register Lisp_Object arg, set_minimum;
 {
   Lisp_Object result;
   int hscroll;
@@ -4991,7 +5181,7 @@ by this function.  */)
   hscroll = XINT (w->hscroll) - XINT (arg);
   result = Fset_window_hscroll (selected_window, make_number (hscroll));
 
-  if (interactive_p (0))
+  if (!NILP (set_minimum))
     w->min_hscroll = w->hscroll;
 
   return result;
@@ -5124,7 +5314,7 @@ and redisplay normally--don't erase and redraw the frame.  */)
 
          SET_TEXT_POS (pt, PT, PT_BYTE);
          start_display (&it, w, pt);
-         move_it_vertically (&it, - window_box_height (w) / 2);
+         move_it_vertically_backward (&it, window_box_height (w) / 2);
          charpos = IT_CHARPOS (it);
          bytepos = IT_BYTEPOS (it);
        }
@@ -5132,29 +5322,62 @@ and redisplay normally--don't erase and redraw the frame.  */)
        {
          struct it it;
          struct text_pos pt;
-         int y0, y1, h, nlines;
+         int nlines = - XINT (arg);
+         int extra_line_spacing;
+         int h = window_box_height (w);
 
          SET_TEXT_POS (pt, PT, PT_BYTE);
          start_display (&it, w, pt);
-         y0 = it.current_y;
+
+         /* Be sure we have the exact height of the full line containing PT.  */
+         move_it_by_lines (&it, 0, 1);
 
          /* The amount of pixels we have to move back is the window
             height minus what's displayed in the line containing PT,
             and the lines below.  */
-         nlines = - XINT (arg) - 1;
+         it.current_y = 0;
+         it.vpos = 0;
          move_it_by_lines (&it, nlines, 1);
 
-         y1 = line_bottom_y (&it);
+         if (it.vpos == nlines)
+           h -= it.current_y;
+         else
+           {
+             /* Last line has no newline */
+             h -= line_bottom_y (&it);
+             it.vpos++;
+           }
+
+         /* Don't reserve space for extra line spacing of last line.  */
+         extra_line_spacing = it.max_extra_line_spacing;
 
          /* If we can't move down NLINES lines because we hit
             the end of the buffer, count in some empty lines.  */
          if (it.vpos < nlines)
-           y1 += (nlines - it.vpos) * FRAME_LINE_HEIGHT (it.f);
-
-         h = window_box_height (w) - (y1 - y0);
+           {
+             nlines -= it.vpos;
+             extra_line_spacing = it.extra_line_spacing;
+             h -= nlines * (FRAME_LINE_HEIGHT (it.f) + extra_line_spacing);
+           }
+         if (h <= 0)
+           return Qnil;
 
+         /* Now find the new top line (starting position) of the window.  */
          start_display (&it, w, pt);
-         move_it_vertically (&it, - h);
+         it.current_y = 0;
+         move_it_vertically_backward (&it, h);
+
+         /* If extra line spacing is present, we may move too far
+            back.  This causes the last line to be only partially
+            visible (which triggers redisplay to recenter that line
+            in the middle), so move forward.
+            But ignore extra line spacing on last line, as it is not
+            considered to be part of the visible height of the line.
+         */
+         h += extra_line_spacing;
+         while (-it.current_y > h)
+           move_it_by_lines (&it, 1, 1);
+
          charpos = IT_CHARPOS (it);
          bytepos = IT_BYTEPOS (it);
        }
@@ -5366,7 +5589,20 @@ the return value is nil.  Otherwise the value is t.  */)
       if (XBUFFER (new_current_buffer) == current_buffer)
        old_point = PT;
       else
-       old_point = BUF_PT (XBUFFER (new_current_buffer));
+       /* 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)->buffer, new_current_buffer)
+           /* If current_window = selected_window, its point is in BUF_PT.  */
+           && !EQ (selected_window, data->current_window))
+         old_point = XMARKER (XWINDOW (data->current_window)->pointm)->charpos;
+       else
+         old_point = BUF_PT (XBUFFER (new_current_buffer));
     }
 
   frame = XWINDOW (SAVED_WINDOW_N (saved_windows, 0)->window)->frame;
@@ -5411,8 +5647,9 @@ the return value is nil.  Otherwise the value is t.  */)
 #endif
 #endif
 
-      /* "Swap out" point from the selected window
-        into its buffer.  We do this now, before
+      /* "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)->buffer))
@@ -5562,10 +5799,11 @@ the return value is nil.  Otherwise the value is t.  */)
       FRAME_ROOT_WINDOW (f) = data->root_window;
       /* Prevent "swapping out point" in the old selected window
         using the buffer that has been restored into it.
-        Use the point value from the beginning of this function
-        since unshow_buffer (called from delete_all_subwindows)
-        could have altered it.  */
+        We already swapped out point that from that window's old buffer.  */
       selected_window = Qnil;
+
+      /* Arrange *not* to restore point in the buffer that was
+        current when the window configuration was saved.  */
       if (EQ (XWINDOW (data->current_window)->buffer, new_current_buffer))
        set_marker_restricted (XWINDOW (data->current_window)->pointm,
                               make_number (old_point),
@@ -5756,7 +5994,7 @@ save_window_save (window, vector, i)
       p = SAVED_WINDOW_N (vector, i);
       w = XWINDOW (window);
 
-      XSETFASTINT (w->temslot, i++);
+      XSETFASTINT (w->temslot, i); i++;
       p->window = window;
       p->buffer = w->buffer;
       p->left_col = w->left_col;
@@ -5877,7 +6115,8 @@ redirection (see `redirect-frame-focus').  */)
 
 DEFUN ("save-window-excursion", Fsave_window_excursion, Ssave_window_excursion,
        0, UNEVALLED, 0,
-       doc: /* Execute body, preserving window sizes and contents.
+       doc: /* Execute BODY, preserving window sizes and contents.
+Return the value of the last form in BODY.
 Restore which buffer appears in which window, where display starts,
 and the value of point and mark for each window.
 Also restore the choice of selected window.
@@ -5986,9 +6225,9 @@ display marginal areas and the text area.  */)
   struct window *w = decode_window (window);
 
   if (!NILP (left))
-    CHECK_NUMBER (left);
+    CHECK_NATNUM (left);
   if (!NILP (right))
-    CHECK_NUMBER (right);
+    CHECK_NATNUM (right);
 
   if (!EQ (w->left_fringe_width, left)
       || !EQ (w->right_fringe_width, right)
@@ -6015,9 +6254,7 @@ DEFUN ("window-fringes", Fwindow_fringes, Swindow_fringes,
        0, 1, 0,
        doc: /* Get width of fringes of window WINDOW.
 If WINDOW is omitted or nil, use the currently selected window.
-Value is a list of the form (LEFT-WIDTH RIGHT-WIDTH OUTSIDE-MARGINS).
-If a window specific fringe width is not set, its width will be returned
-as nil.  */)
+Value is a list of the form (LEFT-WIDTH RIGHT-WIDTH OUTSIDE-MARGINS).  */)
      (window)
      Lisp_Object window;
 {
@@ -6050,13 +6287,15 @@ If TYPE is t, use the frame's scroll-bar type.  */)
   struct window *w = decode_window (window);
 
   if (!NILP (width))
-    CHECK_NUMBER (width);
+    {
+      CHECK_NATNUM (width);
 
-  if (XINT (width) == 0)
-    vertical_type = Qnil;
+      if (XINT (width) == 0)
+       vertical_type = Qnil;
+    }
 
   if (!(EQ (vertical_type, Qnil)
-       || EQ (vertical_type, Qleft) 
+       || EQ (vertical_type, Qleft)
        || EQ (vertical_type, Qright)
        || EQ (vertical_type, Qt)))
     error ("Invalid type of vertical scroll bar");
@@ -6105,12 +6344,13 @@ value.  */)
                           Smooth scrolling
  ***********************************************************************/
 
-DEFUN ("window-vscroll", Fwindow_vscroll, Swindow_vscroll, 0, 1, 0,
+DEFUN ("window-vscroll", Fwindow_vscroll, Swindow_vscroll, 0, 2, 0,
        doc: /* Return the amount by which WINDOW is scrolled vertically.
 Use the selected window if WINDOW is nil or omitted.
-Value is a multiple of the canonical character height of WINDOW.  */)
-     (window)
-     Lisp_Object window;
+Normally, value is a multiple of the canonical character height of WINDOW;
+optional second arg PIXELS_P means value is measured in pixels.  */)
+  (window, pixels_p)
+     Lisp_Object window, pixels_p;
 {
   Lisp_Object result;
   struct frame *f;
@@ -6124,7 +6364,9 @@ Value is a multiple of the canonical character height of WINDOW.  */)
   f = XFRAME (w->frame);
 
   if (FRAME_WINDOW_P (f))
-    result = FRAME_CANON_Y_FROM_PIXEL_Y (f, -w->vscroll);
+    result = (NILP (pixels_p)
+             ? FRAME_CANON_Y_FROM_PIXEL_Y (f, -w->vscroll)
+             : make_number (-w->vscroll));
   else
     result = make_number (0);
   return result;
@@ -6132,12 +6374,17 @@ Value is a multiple of the canonical character height of WINDOW.  */)
 
 
 DEFUN ("set-window-vscroll", Fset_window_vscroll, Sset_window_vscroll,
-       2, 2, 0,
+       2, 3, 0,
        doc: /* Set amount by which WINDOW should be scrolled vertically to VSCROLL.
-WINDOW nil means use the selected window.  VSCROLL is a non-negative
-multiple of the canonical character height of WINDOW.  */)
-     (window, vscroll)
-     Lisp_Object window, vscroll;
+WINDOW nil means use the selected window.  Normally, VSCROLL is a
+non-negative multiple of the canonical character height of WINDOW;
+optional third arg PIXELS_P non-nil means that VSCROLL is in pixels.
+If PIXELS-P is nil, VSCROLL may have to be rounded so that it
+corresponds to an integral number of pixels.  The return value is the
+result of this rounding.
+If PIXELS-P is non-nil, the return value is VSCROLL.  */)
+  (window, vscroll, pixels_p)
+     Lisp_Object window, vscroll, pixels_p;
 {
   struct window *w;
   struct frame *f;
@@ -6155,19 +6402,24 @@ multiple of the canonical character height of WINDOW.  */)
     {
       int old_dy = w->vscroll;
 
-      w->vscroll = - FRAME_LINE_HEIGHT (f) * XFLOATINT (vscroll);
+      w->vscroll = - (NILP (pixels_p)
+                     ? FRAME_LINE_HEIGHT (f) * XFLOATINT (vscroll)
+                     : XFLOATINT (vscroll));
       w->vscroll = min (w->vscroll, 0);
 
-      /* Adjust glyph matrix of the frame if the virtual display
-        area becomes larger than before.  */
-      if (w->vscroll < 0 && w->vscroll < old_dy)
-       adjust_glyphs (f);
+      if (w->vscroll != old_dy)
+       {
+         /* Adjust glyph matrix of the frame if the virtual display
+            area becomes larger than before.  */
+         if (w->vscroll < 0 && w->vscroll < old_dy)
+           adjust_glyphs (f);
 
-      /* Prevent redisplay shortcuts.  */
-      XBUFFER (w->buffer)->prevent_redisplay_optimizations_p = 1;
+         /* Prevent redisplay shortcuts.  */
+         XBUFFER (w->buffer)->prevent_redisplay_optimizations_p = 1;
+       }
     }
 
-  return Fwindow_vscroll (window);
+  return Fwindow_vscroll (window, pixels_p);
 }
 
 \f
@@ -6413,6 +6665,7 @@ syms_of_window ()
 {
   Qwindow_size_fixed = intern ("window-size-fixed");
   staticpro (&Qwindow_size_fixed);
+  Fset (Qwindow_size_fixed, Qnil);
 
   staticpro (&Qwindow_configuration_change_hook);
   Qwindow_configuration_change_hook
@@ -6446,7 +6699,9 @@ the buffer; `temp-buffer-show-hook' is not run unless this function runs it.  */
   DEFVAR_LISP ("display-buffer-function", &Vdisplay_buffer_function,
               doc: /* If non-nil, function to call to handle `display-buffer'.
 It will receive two args, the buffer and a flag which if non-nil means
- that the currently selected window is not acceptable.
+that the currently selected window is not acceptable.
+It should choose or create a window, display the specified buffer in it,
+and return the window.
 Commands such as `switch-to-buffer-other-window' and `find-file-other-window'
 work using this function.  */);
   Vdisplay_buffer_function = Qnil;
@@ -6474,6 +6729,10 @@ is displayed in the `mode-line' face.  */);
               doc: /* *Non-nil means `display-buffer' should make a separate frame.  */);
   pop_up_frames = 0;
 
+  DEFVAR_BOOL ("auto-window-vscroll", &auto_window_vscroll_p,
+              doc: /* *Non-nil means to automatically adjust `window-vscroll' to view tall lines.  */);
+  auto_window_vscroll_p = 1;
+
   DEFVAR_BOOL ("display-buffer-reuse-frames", &display_buffer_reuse_frames,
               doc: /* *Non-nil means `display-buffer' should reuse frames.
 If the buffer in question is already displayed in a frame, raise that frame.  */);
@@ -6495,9 +6754,10 @@ using `special-display-function'.  See also `special-display-regexps'.
 An element of the list can be a list instead of just a string.
 There are two ways to use a list as an element:
   (BUFFER FRAME-PARAMETERS...)   (BUFFER FUNCTION OTHER-ARGS...)
-In the first case, FRAME-PARAMETERS are used to create the frame.
-In the latter case, FUNCTION is called with BUFFER as the first argument,
-followed by OTHER-ARGS--it can display BUFFER in any way it likes.
+In the first case, the FRAME-PARAMETERS are pairs of the form
+\(PARAMETER . VALUE); these parameter values are used to create the frame.
+In the second case, FUNCTION is called with BUFFER as the first argument,
+followed by the OTHER-ARGS--it can display BUFFER in any way it likes.
 All this is done by the function found in `special-display-function'.
 
 If the specified frame parameters include (same-buffer . t), the
@@ -6520,9 +6780,10 @@ using `special-display-function'.
 An element of the list can be a list instead of just a string.
 There are two ways to use a list as an element:
   (REGEXP FRAME-PARAMETERS...)   (REGEXP FUNCTION OTHER-ARGS...)
-In the first case, FRAME-PARAMETERS are used to create the frame.
-In the latter case, FUNCTION is called with the buffer as first argument,
-followed by OTHER-ARGS--it can display the buffer in any way it likes.
+In the first case, the FRAME-PARAMETERS are pairs of the form
+\(PARAMETER . VALUE); these parameter values are used to create the frame.
+In the second case, FUNCTION is called with BUFFER as the first argument,
+followed by the OTHER-ARGS--it can display the buffer in any way it likes.
 All this is done by the function found in `special-display-function'.
 
 If the specified frame parameters include (same-buffer . t), the
@@ -6588,7 +6849,7 @@ See also `same-window-buffer-names'.  */);
   next_screen_context_lines = 2;
 
   DEFVAR_INT ("split-height-threshold", &split_height_threshold,
-             doc: /* *display-buffer would prefer to split the largest window if this large.
+             doc: /* *A window must be at least this tall to be eligible for splitting by `display-buffer'.
 If there is only one window, it is split regardless of this value.  */);
   split_height_threshold = 500;
 
@@ -6602,7 +6863,9 @@ If there is only one window, it is split regardless of this value.  */);
 
   DEFVAR_LISP ("scroll-preserve-screen-position",
               &Vscroll_preserve_screen_position,
-              doc: /* *Non-nil means scroll commands move point to keep its screen line unchanged.  */);
+              doc: /* *Non-nil means scroll commands move point to keep its screen line unchanged.
+This is only when it is impossible to keep point fixed and still
+scroll as specified.  */);
   Vscroll_preserve_screen_position = Qnil;
 
   DEFVAR_LISP ("window-configuration-change-hook",
@@ -6611,14 +6874,6 @@ If there is only one window, it is split regardless of this value.  */);
 The selected frame is the one whose configuration has changed.  */);
   Vwindow_configuration_change_hook = Qnil;
 
-  DEFVAR_BOOL ("window-size-fixed", &window_size_fixed,
-              doc: /* Non-nil in a buffer means windows displaying the buffer are fixed-size.
-Emacs won't change the size of any window displaying that buffer,
-unless you explicitly change the size, or Emacs has no other choice.
-This variable automatically becomes buffer-local when set.  */);
-  Fmake_variable_buffer_local (Qwindow_size_fixed);
-  window_size_fixed = 0;
-
   defsubr (&Sselected_window);
   defsubr (&Sminibuffer_window);
   defsubr (&Swindow_minibuffer_p);