]> code.delx.au - gnu-emacs/blobdiff - src/window.c
(Fwindow_tree): Remove unused var alist.
[gnu-emacs] / src / window.c
index 93495afb1a532f1e18a5d3b3f8825f7e0509da12..96cafc5820e4400400a024e7b05a9ee4bbfbec85 100644 (file)
@@ -1,7 +1,7 @@
 /* Window creation, deletion and examination for GNU Emacs.
    Does not include redisplay.
-   Copyright (C) 1985,86,87, 1993,94,95,96,97,98, 2000,01,02,03,04
-   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.
 
@@ -17,8 +17,8 @@ GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
 along with GNU Emacs; see the file COPYING.  If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA.  */
+the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA.  */
 
 #include <config.h>
 #include "lisp.h"
@@ -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
@@ -277,7 +273,6 @@ make_window ()
   XSETWINDOW (val, p);
   XSETFASTINT (p->last_point, 0);
   p->frozen_window_start_p = 0;
-  p->height_fixed_p = 0;
   p->last_cursor_off_p = p->cursor_off_p = 0;
   p->left_margin_cols = Qnil;
   p->right_margin_cols = Qnil;
@@ -286,7 +281,6 @@ make_window ()
   p->fringes_outside_margins = Qnil;
   p->scroll_bar_width = Qnil;
   p->vertical_scroll_bar_type = Qt;
-  p->overlay_arrow_bitmap = 0;
 
   Vwindow_list = Qnil;
   return val;
@@ -549,7 +543,7 @@ display margins, fringes, header line, and/or mode line.  */)
                             + WINDOW_LEFT_FRINGE_COLS (w)),
                make_number (WINDOW_TOP_EDGE_LINE (w)
                             + WINDOW_HEADER_LINE_LINES (w)),
-               make_number (WINDOW_RIGHT_EDGE_COL (w)
+               make_number (WINDOW_BOX_RIGHT_EDGE_COL (w)
                             - WINDOW_RIGHT_MARGIN_COLS (w)
                             - WINDOW_RIGHT_FRINGE_COLS (w)),
                make_number (WINDOW_BOTTOM_EDGE_LINE (w)
@@ -573,7 +567,7 @@ display margins, fringes, header line, and/or mode line.  */)
                             + WINDOW_LEFT_FRINGE_WIDTH (w)),
                make_number (WINDOW_TOP_EDGE_Y (w)
                             + WINDOW_HEADER_LINE_HEIGHT (w)),
-               make_number (WINDOW_RIGHT_EDGE_X (w)
+               make_number (WINDOW_BOX_RIGHT_EDGE_X (w)
                             - WINDOW_RIGHT_MARGIN_WIDTH (w)
                             - WINDOW_RIGHT_FRINGE_WIDTH (w)),
                make_number (WINDOW_BOTTOM_EDGE_Y (w)
@@ -688,7 +682,10 @@ coordinates_in_window (w, x, y)
 
   /* Outside any interesting column?  */
   if (*x < left_x || *x > right_x)
-    return ON_SCROLL_BAR;
+    {
+      *y -= top_y;
+      return ON_SCROLL_BAR;
+    }
 
   lmargin_width = window_box_width (w, LEFT_MARGIN_AREA);
   rmargin_width = window_box_width (w, RIGHT_MARGIN_AREA);
@@ -745,9 +742,9 @@ coordinates_in_window (w, x, y)
              ? (*x < right_x - WINDOW_RIGHT_FRINGE_WIDTH (w))
              : (*x >= right_x - rmargin_width)))
        {
-         *x -= right_x;
-         if (!WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w))
-           *x -= WINDOW_RIGHT_FRINGE_WIDTH (w);
+         *x -= right_x - rmargin_width;
+         if (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w))
+           *x += WINDOW_RIGHT_FRINGE_WIDTH (w);
          *y -= top_y;
          return ON_RIGHT_MARGIN;
        }
@@ -759,7 +756,7 @@ coordinates_in_window (w, x, y)
     }
 
   /* Everything special ruled out - must be on text area */
-  *x -= left_x + WINDOW_LEFT_FRINGE_WIDTH (w);
+  *x -= text_left;
   *y -= top_y;
   return ON_TEXT;
 }
@@ -1035,7 +1032,8 @@ if it isn't already recorded.  */)
 
   if (! NILP (update)
       && ! (! NILP (w->window_end_valid)
-           && XFASTINT (w->last_modified) >= MODIFF))
+           && XFASTINT (w->last_modified) >= MODIFF)
+      && !noninteractive)
     {
       struct text_pos startp;
       struct it it;
@@ -1457,8 +1455,10 @@ delete_window (window)
   tem = par->hchild;
   if (NILP (tem))
     tem = par->vchild;
-  if (NILP (XWINDOW (tem)->next))
+  if (NILP (XWINDOW (tem)->next)) {
     replace_window (parent, tem);
+    par = XWINDOW (tem);
+  }
 
   /* Since we may be deleting combination windows, we must make sure that
      not only p but all its children have been marked as deleted.  */
@@ -1470,6 +1470,51 @@ delete_window (window)
   /* Mark this window as deleted.  */
   p->buffer = p->hchild = p->vchild = Qnil;
 
+  if (! NILP (par->parent))
+    par = XWINDOW (par->parent);
+
+  /* Check if we have a v/hchild with a v/hchild.  In that case remove
+     one of them.  */
+
+  if (! NILP (par->vchild) && ! NILP (XWINDOW (par->vchild)->vchild))
+    {
+      p = XWINDOW (par->vchild);
+      par->vchild = p->vchild;
+      tem = p->vchild;
+    }
+  else if (! NILP (par->hchild) && ! NILP (XWINDOW (par->hchild)->hchild))
+    {
+      p = XWINDOW (par->hchild);
+      par->hchild = p->hchild;
+      tem = p->hchild;
+    }
+  else
+    p = 0;
+
+  if (p)
+    {
+      while (! NILP (tem)) {
+        XWINDOW (tem)->parent = p->parent;
+        if (NILP (XWINDOW (tem)->next))
+          break;
+        tem = XWINDOW (tem)->next;
+      }
+      if (! NILP (tem)) {
+        /* The next of the v/hchild we are removing is now the next of the
+           last child for the v/hchild:
+           Before v/hchild -> v/hchild -> next1 -> next2
+                    |
+                     -> next3
+           After:  v/hchild -> next1 -> next2 -> next3
+        */
+        XWINDOW (tem)->next = p->next;
+        if (! NILP (p->next))
+          XWINDOW (p->next)->prev = tem;
+      }
+      p->next = p->prev = p->vchild = p->hchild = p->buffer = Qnil;
+    }
+
+
   /* Adjust glyph matrices. */
   adjust_glyphs (f);
   UNBLOCK_INPUT;
@@ -2396,27 +2441,22 @@ window_fixed_size_p (w, width_p, check_siblings_p)
     }
   else if (BUFFERP (w->buffer))
     {
-      if (w->height_fixed_p && !width_p)
-       fixed_p = 1;
-      else
-       {
-         struct buffer *old = current_buffer;
-         Lisp_Object val;
+      struct buffer *old = current_buffer;
+      Lisp_Object val;
 
-         current_buffer = XBUFFER (w->buffer);
-         val = find_symbol_value (Qwindow_size_fixed);
-         current_buffer = old;
+      current_buffer = XBUFFER (w->buffer);
+      val = find_symbol_value (Qwindow_size_fixed);
+      current_buffer = old;
 
-         fixed_p = 0;
-         if (!EQ (val, Qunbound))
-           {
-             fixed_p = !NILP (val);
+      fixed_p = 0;
+      if (!EQ (val, Qunbound))
+       {
+         fixed_p = !NILP (val);
 
-             if (fixed_p
-                 && ((EQ (val, Qheight) && width_p)
-                     || (EQ (val, Qwidth) && !width_p)))
-               fixed_p = 0;
-           }
+         if (fixed_p
+             && ((EQ (val, Qheight) && width_p)
+                 || (EQ (val, Qwidth) && !width_p)))
+           fixed_p = 0;
        }
 
       /* Can't tell if this one is resizable without looking at
@@ -3171,6 +3211,9 @@ selects the buffer of the selected window before each command.  */)
   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);
@@ -3189,7 +3232,7 @@ selects the buffer of the selected window before each command.  */)
         so that FRAME_FOCUS_FRAME is moved appropriately as we
         move around in the state where a minibuffer in a separate
         frame is active.  */
-      Fselect_frame (WINDOW_FRAME (w), Qnil);
+      Fselect_frame (WINDOW_FRAME (w));
     }
   else
     sf->selected_window = window;
@@ -3265,9 +3308,10 @@ 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 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
+If the value is t, `display-buffer' or `pop-to-buffer' would create a
+special frame 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.  */)
@@ -3301,7 +3345,9 @@ and `special-display-regexps' control this.  */)
 }
 
 DEFUN ("same-window-p", Fsame_window_p, Ssame_window_p, 1, 1, 0,
-       doc: /* Returns non-nil if a new buffer named BUFFER-NAME would use the same window.
+       doc: /* Returns non-nil if a buffer named BUFFER-NAME would use the same window.
+More precisely, if `display-buffer' or `pop-to-buffer' would display
+that buffer in the selected window rather than (as usual) in some other window.
 See `same-window-buffer-names' and `same-window-regexps'.  */)
      (buffer_name)
      Lisp_Object buffer_name;
@@ -4132,7 +4178,7 @@ enlarge_window (window, delta, widthflag, preserve_before)
 
             The number of children n equals the number of resizable
             children of this window + 1 because we know window itself
-            is resizable (otherwise we would have signalled an error.  */
+            is resizable (otherwise we would have signalled an error).  */
 
          struct window *w = XWINDOW (window);
          Lisp_Object s;
@@ -4735,7 +4781,9 @@ window_scroll_pixel_based (window, n, whole, noerror)
       /* 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)
+      if (IT_CHARPOS (it) == PT && it.current_y >= this_scroll_margin
+          && (NILP (Vscroll_preserve_screen_position)
+             || EQ (Vscroll_preserve_screen_position, Qt)))
        /* We found PT at a legitimate height.  Leave it alone.  */
        ;
       else if (preserve_y >= 0)
@@ -4772,7 +4820,9 @@ window_scroll_pixel_based (window, n, whole, noerror)
       /* 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,
+                 (it.last_visible_y - CURRENT_HEADER_LINE_HEIGHT (w)
+                  - this_scroll_margin - 1),
+                 -1,
                  MOVE_TO_POS | MOVE_TO_Y);
 
       /* Save our position, in case it's correct.  */
@@ -4788,7 +4838,9 @@ window_scroll_pixel_based (window, n, whole, noerror)
          partial_p = it.current_y > it.last_visible_y;
        }
 
-      if (charpos == PT && !partial_p)
+      if (charpos == PT && !partial_p
+          && (NILP (Vscroll_preserve_screen_position)
+             || EQ (Vscroll_preserve_screen_position, Qt)))
        /* We found PT before we found the display margin, so PT is ok.  */
        ;
       else if (preserve_y >= 0)
@@ -4903,7 +4955,8 @@ window_scroll_line_based (window, n, whole, noerror)
         the window-scroll-functions.  */
       w->force_start = Qt;
 
-      if (whole && !NILP (Vscroll_preserve_screen_position))
+      if (!NILP (Vscroll_preserve_screen_position)
+         && (whole || !EQ (Vscroll_preserve_screen_position, Qt)))
        {
          SET_PT_BOTH (pos, pos_byte);
          Fvertical_motion (make_number (original_vpos), window);
@@ -5278,6 +5331,8 @@ and redisplay normally--don't erase and redraw the frame.  */)
   struct buffer *obuf = current_buffer;
   int center_p = 0;
   int charpos, bytepos;
+  int iarg;
+  int this_scroll_margin;
 
   /* If redisplay is suppressed due to an error, try again.  */
   obuf->display_error_modiff = 0;
@@ -5300,10 +5355,17 @@ and redisplay normally--don't erase and redraw the frame.  */)
     {
       arg = Fprefix_numeric_value (arg);
       CHECK_NUMBER (arg);
+      iarg = XINT (arg);
     }
 
   set_buffer_internal (buf);
 
+  /* Do this after making BUF current
+     in case scroll_margin is buffer-local.  */
+  this_scroll_margin = max (0, scroll_margin);
+  this_scroll_margin = min (this_scroll_margin,
+                           XFASTINT (w->total_lines) / 4);
+
   /* Handle centering on a graphical frame specially.  Such frames can
      have variable-height lines and centering point on the basis of
      line counts would lead to strange effects.  */
@@ -5320,14 +5382,16 @@ and redisplay normally--don't erase and redraw the frame.  */)
          charpos = IT_CHARPOS (it);
          bytepos = IT_BYTEPOS (it);
        }
-      else if (XINT (arg) < 0)
+      else if (iarg < 0)
        {
          struct it it;
          struct text_pos pt;
-         int nlines = - XINT (arg);
+         int nlines = -iarg;
          int extra_line_spacing;
          int h = window_box_height (w);
 
+         iarg = - max (-iarg, this_scroll_margin);
+
          SET_TEXT_POS (pt, PT, PT_BYTE);
          start_display (&it, w, pt);
 
@@ -5386,7 +5450,10 @@ and redisplay normally--don't erase and redraw the frame.  */)
       else
        {
          struct position pos;
-         pos = *vmotion (PT, - XINT (arg), w);
+
+         iarg = max (iarg, this_scroll_margin);
+
+         pos = *vmotion (PT, -iarg, w);
          charpos = pos.bufpos;
          bytepos = pos.bytepos;
        }
@@ -5397,11 +5464,15 @@ and redisplay normally--don't erase and redraw the frame.  */)
       int ht = window_internal_height (w);
 
       if (center_p)
-       arg = make_number (ht / 2);
-      else if (XINT (arg) < 0)
-       arg = make_number (XINT (arg) + ht);
+       iarg = ht / 2;
+      else if (iarg < 0)
+       iarg += ht;
 
-      pos = *vmotion (PT, - XINT (arg), w);
+      /* Don't let it get into the margin at either top or bottom.  */
+      iarg = max (iarg, this_scroll_margin);
+      iarg = min (iarg, ht - this_scroll_margin - 1);
+
+      pos = *vmotion (PT, - iarg, w);
       charpos = pos.bufpos;
       bytepos = pos.bytepos;
     }
@@ -5450,6 +5521,9 @@ zero means top of window, negative means relative to bottom of window.  */)
   struct window *w = XWINDOW (selected_window);
   int lines, start;
   Lisp_Object window;
+#if 0
+  int this_scroll_margin;
+#endif
 
   window = selected_window;
   start = marker_position (w->start);
@@ -5465,13 +5539,33 @@ zero means top of window, negative means relative to bottom of window.  */)
     Fgoto_char (w->start);
 
   lines = displayed_window_lines (w);
+
+#if 0
+  this_scroll_margin = max (0, scroll_margin);
+  this_scroll_margin = min (this_scroll_margin, lines / 4);
+#endif
+
   if (NILP (arg))
     XSETFASTINT (arg, lines / 2);
   else
     {
-      arg = Fprefix_numeric_value (arg);
-      if (XINT (arg) < 0)
-       XSETINT (arg, XINT (arg) + lines);
+      int iarg = XINT (Fprefix_numeric_value (arg));
+
+      if (iarg < 0)
+       iarg = iarg + lines;
+
+#if 0  /* This code would prevent move-to-window-line from moving point
+         to a place inside the scroll margins (which would cause the
+         next redisplay to scroll).  I wrote this code, but then concluded
+         it is probably better not to install it.  However, it is here
+         inside #if 0 so as not to lose it.  -- rms.  */
+
+      /* Don't let it get into the margin at either top or bottom.  */
+      iarg = max (iarg, this_scroll_margin);
+      iarg = min (iarg, lines - this_scroll_margin - 1);
+#endif
+
+      arg = make_number (iarg);
     }
 
   /* Skip past a partially visible first line.  */
@@ -5528,8 +5622,6 @@ struct saved_window
   Lisp_Object scroll_bar_width, vertical_scroll_bar_type;
 };
 
-#define SAVED_WINDOW_VECTOR_SIZE 24 /* Arg to Fmake_vector */
-
 #define SAVED_WINDOW_N(swv,n) \
   ((struct saved_window *) (XVECTOR ((swv)->contents[(n)])))
 
@@ -5591,7 +5683,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;
@@ -5636,8 +5741,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))
@@ -5787,10 +5893,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),
@@ -6094,7 +6201,7 @@ redirection (see `redirect-frame-focus').  */)
   data->saved_windows = tem;
   for (i = 0; i < n_windows; i++)
     XVECTOR (tem)->contents[i]
-      = Fmake_vector (make_number (SAVED_WINDOW_VECTOR_SIZE), Qnil);
+      = Fmake_vector (make_number (VECSIZE (struct saved_window)), Qnil);
   save_window_save (FRAME_ROOT_WINDOW (f), XVECTOR (tem), 0);
   XSETWINDOW_CONFIGURATION (tem, data);
   return (tem);
@@ -6122,6 +6229,84 @@ usage: (save-window-excursion BODY ...)  */)
   return unbind_to (count, val);
 }
 
+
+\f
+/***********************************************************************
+                           Window Split Tree
+ ***********************************************************************/
+
+static Lisp_Object
+window_tree (w)
+     struct window *w;
+{
+  Lisp_Object tail = Qnil;
+  Lisp_Object result = Qnil;
+
+  while (w)
+    {
+      Lisp_Object wn;
+
+      XSETWINDOW (wn, w);
+      if (!NILP (w->hchild))
+       wn = Fcons (Qnil, Fcons (Fwindow_edges (wn),
+                                window_tree (XWINDOW (w->hchild))));
+      else if (!NILP (w->vchild))
+       wn = Fcons (Qt, Fcons (Fwindow_edges (wn),
+                              window_tree (XWINDOW (w->vchild))));
+
+      if (NILP (result))
+       {
+         result = tail = Fcons (wn, Qnil);
+       }
+      else
+       {
+         XSETCDR (tail, Fcons (wn, Qnil));
+         tail = XCDR (tail);
+       }
+
+      w = NILP (w->next) ? 0 : XWINDOW (w->next);
+    }
+
+  return result;
+}
+
+
+
+DEFUN ("window-tree", Fwindow_tree, Swindow_tree,
+       0, 1, 0,
+       doc: /* Return the window tree for frame FRAME.
+
+The return value is a list of the form (ROOT MINI), where ROOT
+represents the window tree of the frame's root window, and MINI
+is the frame's minibuffer window.
+
+If the root window is not split, ROOT is the root window itself.
+Otherwise, ROOT is a list (DIR EDGES W1 W2 ...) where DIR is nil for a
+horizontal split, and t for a vertical split, EDGES gives the combined
+size and position of the subwindows in the split, and the rest of the
+elements are the subwindows in the split.  Each of the subwindows may
+again be a window or a list representing a window split, and so on.
+EDGES is a list \(LEFT TOP RIGHT BOTTOM) as returned by `window-edges'.
+
+If FRAME is nil or omitted, return information on the currently
+selected frame.  */)
+     (frame)
+     Lisp_Object frame;
+{
+  FRAME_PTR f;
+
+  if (NILP (frame))
+    frame = selected_frame;
+
+  CHECK_FRAME (frame);
+  f = XFRAME (frame);
+
+  if (!FRAME_LIVE_P (f))
+    return Qnil;
+
+  return window_tree (XWINDOW (FRAME_ROOT_WINDOW (f)));
+}
+
 \f
 /***********************************************************************
                            Marginal Areas
@@ -6135,33 +6320,33 @@ Second arg LEFT-WIDTH specifies the number of character cells to
 reserve for the left marginal area.  Optional third arg RIGHT-WIDTH
 does the same for the right marginal area.  A nil width parameter
 means no margin.  */)
-     (window, left, right)
-     Lisp_Object window, left, right;
+     (window, left_width, right_width)
+     Lisp_Object window, left_width, right_width;
 {
   struct window *w = decode_window (window);
 
   /* Translate negative or zero widths to nil.
      Margins that are too wide have to be checked elsewhere.  */
 
-  if (!NILP (left))
+  if (!NILP (left_width))
     {
-      CHECK_NUMBER (left);
-      if (XINT (left) <= 0)
-       left = Qnil;
+      CHECK_NUMBER (left_width);
+      if (XINT (left_width) <= 0)
+       left_width = Qnil;
     }
 
-  if (!NILP (right))
+  if (!NILP (right_width))
     {
-      CHECK_NUMBER (right);
-      if (XINT (right) <= 0)
-       right = Qnil;
+      CHECK_NUMBER (right_width);
+      if (XINT (right_width) <= 0)
+       right_width = Qnil;
     }
 
-  if (!EQ (w->left_margin_cols, left)
-      || !EQ (w->right_margin_cols, right))
+  if (!EQ (w->left_margin_cols, left_width)
+      || !EQ (w->right_margin_cols, right_width))
     {
-      w->left_margin_cols = left;
-      w->right_margin_cols = right;
+      w->left_margin_cols = left_width;
+      w->right_margin_cols = right_width;
 
       adjust_window_margins (w);
 
@@ -6206,22 +6391,22 @@ the command `set-fringe-style'.
 If optional fourth arg OUTSIDE-MARGINS is non-nil, draw the fringes
 outside of the display margins.  By default, fringes are drawn between
 display marginal areas and the text area.  */)
-     (window, left, right, outside_margins)
-     Lisp_Object window, left, right, outside_margins;
+     (window, left_width, right_width, outside_margins)
+     Lisp_Object window, left_width, right_width, outside_margins;
 {
   struct window *w = decode_window (window);
 
-  if (!NILP (left))
-    CHECK_NATNUM (left);
-  if (!NILP (right))
-    CHECK_NATNUM (right);
+  if (!NILP (left_width))
+    CHECK_NATNUM (left_width);
+  if (!NILP (right_width))
+    CHECK_NATNUM (right_width);
 
-  if (!EQ (w->left_fringe_width, left)
-      || !EQ (w->right_fringe_width, right)
+  if (!EQ (w->left_fringe_width, left_width)
+      || !EQ (w->right_fringe_width, right_width)
       || !EQ (w->fringes_outside_margins, outside_margins))
     {
-      w->left_fringe_width = left;
-      w->right_fringe_width = right;
+      w->left_fringe_width = left_width;
+      w->right_fringe_width = right_width;
       w->fringes_outside_margins = outside_margins;
 
       adjust_window_margins (w);
@@ -6652,6 +6837,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
@@ -6734,7 +6920,8 @@ where `pop-up-frame-alist' would hold the default frame parameters.  */);
 
   DEFVAR_LISP ("special-display-buffer-names", &Vspecial_display_buffer_names,
               doc: /* *List of buffer names that should have their own special frames.
-Displaying a buffer whose name is in this list makes a special frame for it
+Displaying a buffer with `display-buffer' or `pop-to-buffer',
+if its name is in this list, makes a special frame for it
 using `special-display-function'.  See also `special-display-regexps'.
 
 An element of the list can be a list instead of just a string.
@@ -6759,9 +6946,9 @@ Those variables take precedence over this one.  */);
 
   DEFVAR_LISP ("special-display-regexps", &Vspecial_display_regexps,
               doc: /* *List of regexps saying which buffers should have their own special frames.
-If a buffer name matches one of these regexps, it gets its own frame.
-Displaying a buffer whose name is in this list makes a special frame for it
-using `special-display-function'.
+When displaying a buffer with `display-buffer' or `pop-to-buffer',
+if any regexp in this list matches the buffer name, it makes a
+special frame for the buffer by calling `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:
@@ -6849,9 +7036,13 @@ 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.
-This is only when it is impossible to keep point fixed and still
-scroll as specified.  */);
+              doc: /* *Controls if scroll commands move point to keep its screen line unchanged.
+A value of nil means point does not keep its screen position except
+at the scroll margin or window boundary respectively.
+A value of t means point keeps its screen position if the scroll
+command moved it vertically out of the window, e.g. when scrolling
+by full screens.
+Any other value means point always keeps its screen position.  */);
   Vscroll_preserve_screen_position = Qnil;
 
   DEFVAR_LISP ("window-configuration-change-hook",
@@ -6860,16 +7051,6 @@ scroll as specified.  */);
 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.
-If the value is`height', then only the window's height is fixed.
-If the value is `width', then only the window's width is fixed.
-Any other non-nil value fixes both the width and the height.
-Emacs won't change the size of any window displaying that buffer,
-unless you explicitly change the size, or Emacs has no other choice.  */);
-  Fmake_variable_buffer_local (Qwindow_size_fixed);
-  window_size_fixed = 0;
-
   defsubr (&Sselected_window);
   defsubr (&Sminibuffer_window);
   defsubr (&Swindow_minibuffer_p);
@@ -6932,6 +7113,7 @@ unless you explicitly change the size, or Emacs has no other choice.  */);
   defsubr (&Sset_window_configuration);
   defsubr (&Scurrent_window_configuration);
   defsubr (&Ssave_window_excursion);
+  defsubr (&Swindow_tree);
   defsubr (&Sset_window_margins);
   defsubr (&Swindow_margins);
   defsubr (&Sset_window_fringes);