Merge from trunk.
[bpt/emacs.git] / src / window.c
index 605d00b..a0b11e0 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-2011
+   Copyright (C) 1985-1987, 1993-1998, 2000-2012
                  Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
@@ -57,13 +57,13 @@ static Lisp_Object Qreplace_buffer_in_windows, Qget_mru_window;
 static Lisp_Object Qwindow_resize_root_window, Qwindow_resize_root_window_vertically;
 static Lisp_Object Qscroll_up, Qscroll_down, Qscroll_command;
 static Lisp_Object Qsafe, Qabove, Qbelow;
-static Lisp_Object Qauto_buffer_name;
+static Lisp_Object Qauto_buffer_name, Qclone_of;
 
 static int displayed_window_lines (struct window *);
 static struct window *decode_window (Lisp_Object);
 static int count_windows (struct window *);
 static int get_leaf_windows (struct window *, struct window **, int);
-static void window_scroll (Lisp_Object, int, int, int);
+static void window_scroll (Lisp_Object, EMACS_INT, int, int);
 static void window_scroll_pixel_based (Lisp_Object, int, int, int);
 static void window_scroll_line_based (Lisp_Object, int, int, int);
 static int freeze_window_start (struct window *, void *);
@@ -127,8 +127,8 @@ static int window_scroll_pixel_based_preserve_x;
 static int window_scroll_pixel_based_preserve_y;
 
 /* Same for window_scroll_line_based.  */
-static int window_scroll_preserve_hpos;
-static int window_scroll_preserve_vpos;
+static EMACS_INT window_scroll_preserve_hpos;
+static EMACS_INT window_scroll_preserve_vpos;
 \f
 static struct window *
 decode_window (register Lisp_Object window)
@@ -378,7 +378,7 @@ select_window (Lisp_Object window, Lisp_Object norecord, int inhibit_point_swap)
      redisplay_window has altered point after scrolling,
      because it makes the change only in the window.  */
   {
-    register EMACS_INT new_point = marker_position (w->pointm);
+    register ptrdiff_t new_point = marker_position (w->pointm);
     if (new_point < BEGV)
       SET_PT (BEGV);
     else if (new_point > ZV)
@@ -465,67 +465,29 @@ Return nil if WINDOW has no previous sibling.  */)
   return decode_any_window (window)->prev;
 }
 
-DEFUN ("window-splits", Fwindow_splits, Swindow_splits, 0, 1, 0,
-       doc: /* Return splits status for the window WINDOW.
-If WINDOW is omitted or nil, it defaults to the selected window.
-
-If the value returned by this function is nil and WINDOW is resized, the
-corresponding space is preferably taken from (or given to) WINDOW's
-right sibling.  When WINDOW is deleted, its space is given to its left
-sibling.
-
-If the value returned by this function is non-nil, resizing and deleting
-WINDOW may resize all windows in the same combination.  */)
-  (Lisp_Object window)
-{
-  return decode_any_window (window)->splits;
-}
-
-DEFUN ("set-window-splits", Fset_window_splits, Sset_window_splits, 2, 2, 0,
-       doc: /* Set splits status of window WINDOW to STATUS.
-If WINDOW is omitted or nil, it defaults to the selected window.
-
-If STATUS is nil and WINDOW is later resized, the corresponding space is
-preferably taken from (or given to) WINDOW's right sibling.  When WINDOW
-is deleted, its space is given to its left sibling.
-
-If STATUS is non-nil, resizing and deleting WINDOW may resize all
-windows in the same combination.  */)
-  (Lisp_Object window, Lisp_Object status)
-{
-  register struct window *w = decode_any_window (window);
-
-  w->splits = status;
-
-  return w->splits;
-}
-
-DEFUN ("window-nest", Fwindow_nest, Swindow_nest, 0, 1, 0,
-       doc: /* Return nest status of window WINDOW.
-If WINDOW is omitted or nil, it defaults to the selected window.
-
-If the return value is nil, subwindows of WINDOW can be recombined with
-WINDOW's siblings.  A return value of non-nil means that subwindows of
+DEFUN ("window-combination-limit", Fwindow_combination_limit, Swindow_combination_limit, 1, 1, 0,
+       doc: /* Return combination limit of window WINDOW.
+If the return value is nil, child windows of WINDOW can be recombined with
+WINDOW's siblings.  A return value of t means that child windows of
 WINDOW are never \(re-)combined with WINDOW's siblings.  */)
   (Lisp_Object window)
 {
-  return decode_any_window (window)->nest;
+  return decode_any_window (window)->combination_limit;
 }
 
-DEFUN ("set-window-nest", Fset_window_nest, Sset_window_nest, 2, 2, 0,
-       doc: /* Set nest status of window WINDOW to STATUS; return STATUS.
-If WINDOW is omitted or nil, it defaults to the selected window.
-
-If STATUS is nil, subwindows of WINDOW can be recombined with WINDOW's
-siblings.  STATUS non-nil means that subwindows of WINDOW are never
-\(re-)combined with WINDOW's siblings.  */)
-  (Lisp_Object window, Lisp_Object status)
+DEFUN ("set-window-combination-limit", Fset_window_combination_limit, Sset_window_combination_limit, 2, 2, 0,
+       doc: /* Set combination limit of window WINDOW to LIMIT; return LIMIT.
+If LIMIT is nil, child windows of WINDOW can be recombined with
+WINDOW's siblings.  LIMIT t means that child windows of WINDOW are
+never \(re-)combined with WINDOW's siblings.  Other values are reserved
+for future use.  */)
+  (Lisp_Object window, Lisp_Object limit)
 {
   register struct window *w = decode_any_window (window);
 
-  w->nest = status;
+  w->combination_limit = limit;
 
-  return w->nest;
+  return w->combination_limit;
 }
 
 DEFUN ("window-use-time", Fwindow_use_time, Swindow_use_time, 0, 1, 0,
@@ -539,27 +501,34 @@ selected one.  */)
   return decode_window (window)->use_time;
 }
 \f
-DEFUN ("window-total-size", Fwindow_total_size, Swindow_total_size, 0, 2, 0,
-       doc: /* Return the total number of lines of window WINDOW.
+DEFUN ("window-total-height", Fwindow_total_height, Swindow_total_height, 0, 1, 0,
+       doc: /* Return the total height, in lines, of window WINDOW.
 If WINDOW is omitted or nil, it defaults to the selected window.
 
-The return value includes WINDOW's mode line and header line, if any.
-If WINDOW is internal, the return value is the sum of the total number
-of lines of WINDOW's child windows if these are vertically combined
-and the height of WINDOW's first child otherwise.
-
-Optional argument HORIZONTAL non-nil means return the total number of
-columns of WINDOW.  In this case the return value includes any vertical
-dividers or scrollbars of WINDOW.  If WINDOW is internal, the return
-value is the sum of the total number of columns of WINDOW's child
-windows if they are horizontally combined and the width of WINDOW's
-first child otherwise.  */)
-  (Lisp_Object window, Lisp_Object horizontal)
+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.
+
+On a graphical display, this total height is reported as an
+integer multiple of the default character height.  */)
+  (Lisp_Object window)
 {
-  if (NILP (horizontal))
-    return decode_any_window (window)->total_lines;
-  else
-    return decode_any_window (window)->total_cols;
+  return decode_any_window (window)->total_lines;
+}
+
+DEFUN ("window-total-width", Fwindow_total_width, Swindow_total_width, 0, 1, 0,
+       doc: /* Return the total width, in columns, of window WINDOW.
+If WINDOW is omitted or nil, it defaults to the selected window.
+
+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)
+{
+  return decode_any_window (window)->total_cols;
 }
 
 DEFUN ("window-new-total", Fwindow_new_total, Swindow_new_total, 0, 1, 0,
@@ -592,6 +561,10 @@ If WINDOW is omitted or nil, it defaults to the selected window.  */)
 
 DEFUN ("window-left-column", Fwindow_left_column, Swindow_left_column, 0, 1, 0,
        doc: /* Return left column of window WINDOW.
+This is the distance, in columns, between the left edge of WINDOW and
+the left edge of the frame's window area.  For instance, the return
+value is 0 if there is no window to the left of WINDOW.
+
 If WINDOW is omitted or nil, it defaults to the selected window.  */)
   (Lisp_Object window)
 {
@@ -600,6 +573,10 @@ If WINDOW is omitted or nil, it defaults to the selected window.  */)
 
 DEFUN ("window-top-line", Fwindow_top_line, Swindow_top_line, 0, 1, 0,
        doc: /* Return top line of window WINDOW.
+This is the distance, in lines, between the top of WINDOW and the top
+of the frame's window area.  For instance, the return value is 0 if
+there is no window above WINDOW.
+
 If WINDOW is omitted or nil, it defaults to the selected window.  */)
   (Lisp_Object window)
 {
@@ -655,34 +632,34 @@ window_body_cols (struct window *w)
   return width;
 }
 
-DEFUN ("window-body-size", Fwindow_body_size, Swindow_body_size, 0, 2, 0,
-       doc: /* Return the number of lines or columns of WINDOW's body.
-WINDOW must be a live window and defaults to the selected one.
+DEFUN ("window-body-height", Fwindow_body_height, Swindow_body_height, 0, 1, 0,
+       doc: /* Return the height, in lines, of WINDOW's text area.
+If WINDOW is omitted or nil, it defaults to the selected window.
+Signal an error if the window is not live.
 
-If the optional argument HORIZONTAL is omitted or nil, the function
-returns the number of WINDOW's lines, excluding the mode line and
-header line, if any.
-
-If HORIZONTAL is non-nil, the function returns the number of columns
-excluding any vertical dividers or scroll bars owned by WINDOW.  On a
-window-system the return value also excludes the number of columns
-used for WINDOW's fringes or display margins.
-
-Note that the return value is measured in canonical units, i.e. for
-the default frame's face.  If the window shows some characters with
-non-default face, e.g., if the font of some characters is larger or
-smaller than the default font, the value returned by this function
-will not match the actual number of lines or characters per line
-shown in the window.  To get the actual number of columns and lines,
-use `posn-at-point'.  */)
-  (Lisp_Object window, Lisp_Object horizontal)
+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 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'.  */)
+  (Lisp_Object window)
 {
-  struct window *w = decode_any_window (window);
+  struct window *w = decode_window (window);
+  return make_number (window_body_lines (w));
+}
 
-  if (NILP (horizontal))
-    return make_number (window_body_lines (w));
-  else
-    return make_number (window_body_cols (w));
+DEFUN ("window-body-width", Fwindow_body_width, Swindow_body_width, 0, 1, 0,
+       doc: /* Return the width, in columns, of WINDOW's text area.
+If WINDOW is omitted or nil, it defaults to the selected window.
+Signal an error if the window is not live.
+
+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.  */)
+  (Lisp_Object window)
+{
+  struct window *w = decode_window (window);
+  return make_number (window_body_cols (w));
 }
 
 DEFUN ("window-hscroll", Fwindow_hscroll, Swindow_hscroll, 0, 1, 0,
@@ -703,10 +680,10 @@ window so that the location of point moves off-window.  */)
   (Lisp_Object window, Lisp_Object ncol)
 {
   struct window *w = decode_window (window);
-  int hscroll;
+  ptrdiff_t hscroll;
 
   CHECK_NUMBER (ncol);
-  hscroll = max (0, XINT (ncol));
+  hscroll = clip_to_bounds (0, XINT (ncol), PTRDIFF_MAX);
 
   /* Prevent redisplay shortcuts when changing the hscroll.  */
   if (XINT (w->hscroll) != hscroll)
@@ -844,7 +821,7 @@ The inside edges do not include the space used by the WINDOW's scroll
 bar, display margins, fringes, header line, and/or mode line.  */)
   (Lisp_Object window)
 {
-  register struct window *w = decode_any_window (window);
+  register struct window *w = decode_window (window);
 
   return list4 (make_number (WINDOW_BOX_LEFT_EDGE_COL (w)
                             + WINDOW_LEFT_MARGIN_COLS (w)
@@ -859,9 +836,9 @@ bar, 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 pixel coordinates of WINDOW.
-The list has the form (LEFT TOP RIGHT BOTTOM), all relative to 0, 0 at
-the top left corner of the frame.
+       doc: /* Return a list of the edge pixel coordinates of WINDOW's text area.
+The list has the form (LEFT TOP RIGHT BOTTOM), all relative to (0,0)
+at the top left corner of the frame's window area.
 
 RIGHT is one more than the rightmost x position of WINDOW's text area.
 BOTTOM is one more than the bottommost y position of WINDOW's text area.
@@ -869,7 +846,7 @@ The inside edges do not include the space used by WINDOW's scroll bar,
 display margins, fringes, header line, and/or mode line.  */)
   (Lisp_Object window)
 {
-  register struct window *w = decode_any_window (window);
+  register struct window *w = decode_window (window);
 
   return list4 (make_number (WINDOW_BOX_LEFT_EDGE_X (w)
                             + WINDOW_LEFT_MARGIN_WIDTH (w)
@@ -886,9 +863,9 @@ display margins, fringes, header line, and/or mode line.  */)
 DEFUN ("window-inside-absolute-pixel-edges",
        Fwindow_inside_absolute_pixel_edges,
        Swindow_inside_absolute_pixel_edges, 0, 1, 0,
-       doc: /* Return a list of the edge pixel coordinates of WINDOW.
-The list has the form (LEFT TOP RIGHT BOTTOM), all relative to 0, 0 at
-the top left corner of the display.
+       doc: /* Return a list of the edge pixel coordinates of WINDOW's text area.
+The list has the form (LEFT TOP RIGHT BOTTOM), all relative to (0,0)
+at the top left corner of the frame's window area.
 
 RIGHT is one more than the rightmost x position of WINDOW's text area.
 BOTTOM is one more than the bottommost y position of WINDOW's text area.
@@ -896,7 +873,7 @@ The inside edges do not include the space used by WINDOW's scroll bar,
 display margins, fringes, header line, and/or mode line.  */)
   (Lisp_Object window)
 {
-  register struct window *w = decode_any_window (window);
+  register struct window *w = decode_window (window);
   int add_x, add_y;
   calc_absolute_offset (w, &add_x, &add_y);
 
@@ -1075,6 +1052,7 @@ window_relative_x_coord (struct window *w, enum window_part part, int x)
 DEFUN ("coordinates-in-window-p", Fcoordinates_in_window_p,
        Scoordinates_in_window_p, 2, 2, 0,
        doc: /* Return non-nil if COORDINATES are in WINDOW.
+WINDOW must be a live window.
 COORDINATES is a cons of the form (X . Y), X and Y being distances
 measured in characters from the upper-left corner of the frame.
 \(0 . 0) denotes the character in the upper left corner of the
@@ -1096,7 +1074,7 @@ If they are in the windows's left or right marginal areas, `left-margin'\n\
   int x, y;
   Lisp_Object lx, ly;
 
-  CHECK_WINDOW (window);
+  CHECK_LIVE_WINDOW (window);
   w = XWINDOW (window);
   f = XFRAME (w->frame);
   CHECK_CONS (coordinates);
@@ -1517,7 +1495,8 @@ Return nil if window display is not up-to-date.  In that case, use
   register struct window *w;
   register struct buffer *b;
   struct glyph_row *row, *end_row;
-  int max_y, crop, i, n;
+  int max_y, crop, i;
+  EMACS_INT n;
 
   w = decode_window (window);
 
@@ -1899,7 +1878,7 @@ recombine_windows (Lisp_Object window)
 
   w = XWINDOW (window);
   parent = w->parent;
-  if (!NILP (parent) && NILP (w->nest))
+  if (!NILP (parent) && NILP (w->combination_limit))
     {
       p = XWINDOW (parent);
       if (((!NILP (p->vchild) && !NILP (w->vchild))
@@ -2204,7 +2183,7 @@ next_window (Lisp_Object window, Lisp_Object minibuf, Lisp_Object all_frames, in
 
 
 DEFUN ("next-window", Fnext_window, Snext_window, 0, 3, 0,
-       doc: /* Return window following WINDOW in cyclic ordering of windows.
+       doc: /* Return live window after WINDOW in the cyclic ordering of windows.
 WINDOW must be a live window and defaults to the selected one.  The
 optional arguments MINIBUF and ALL-FRAMES specify the set of windows to
 consider.
@@ -2243,7 +2222,7 @@ windows, eventually ending up back at the window you started with.
 
 
 DEFUN ("previous-window", Fprevious_window, Sprevious_window, 0, 3, 0,
-       doc: /* Return window preceding WINDOW in cyclic ordering of windows.
+       doc: /* Return live window before WINDOW in the cyclic ordering of windows.
 WINDOW must be a live window and defaults to the selected one.  The
 optional arguments MINIBUF and ALL-FRAMES specify the set of windows to
 consider.
@@ -2364,7 +2343,7 @@ Anything else means consider all windows on WINDOW's frame and no
 others.
 
 If WINDOW is not on the list of windows returned, some other window will
-be listed first but no error is signalled.  */)
+be listed first but no error is signaled.  */)
   (Lisp_Object window, Lisp_Object minibuf, Lisp_Object all_frames)
 {
   return window_list_1 (window, minibuf, all_frames);
@@ -2571,9 +2550,9 @@ DEFUN ("delete-other-windows-internal", Fdelete_other_windows_internal,
 Only the frame WINDOW is on is affected.  WINDOW may be any window and
 defaults to the selected one.
 
-Optional argument ROOT, if non-nil, must specify an internal window
-containing WINDOW as a subwindow.  If this is the case, replace ROOT by
-WINDOW and leave alone any windows not contained in ROOT.
+Optional argument ROOT, if non-nil, must specify an internal window such
+that WINDOW is in its window subtree.  If this is the case, replace ROOT
+by WINDOW and leave alone any windows not part of ROOT's subtree.
 
 When WINDOW is live try to reduce display jumps by keeping the text
 previously visible in WINDOW in the same place on the frame.  Doing this
@@ -2585,7 +2564,7 @@ window-start value is reasonable when this function is called.  */)
   struct window *w, *r, *s;
   struct frame *f;
   Lisp_Object sibling, pwindow, swindow IF_LINT (= Qnil), delta;
-  EMACS_INT startpos IF_LINT (= 0);
+  ptrdiff_t startpos IF_LINT (= 0);
   int top IF_LINT (= 0), new_top, resize_failed;
 
   w = decode_any_window (window);
@@ -2637,10 +2616,10 @@ window-start value is reasonable when this function is called.  */)
     }
   else
     {
-      /* See if the frame's selected window is a subwindow of WINDOW, by
-        finding all the selected window's parents and comparing each
-        one with WINDOW.  If it isn't we need a new selected window for
-        this frame.  */
+      /* See if the frame's selected window is a part of the window
+        subtree rooted at WINDOW, by finding all the selected window's
+        parents and comparing each one with WINDOW.  If it isn't we
+        need a new selected window for this frame.  */
       swindow = FRAME_SELECTED_WINDOW (f);
       while (1)
        {
@@ -2676,7 +2655,7 @@ window-start value is reasonable when this function is called.  */)
 
   if (NILP (w->buffer))
     {
-      /* Resize subwindows vertically.  */
+      /* Resize child windows vertically.  */
       XSETINT (delta, XINT (r->total_lines) - XINT (w->total_lines));
       w->top_line = r->top_line;
       resize_root_window (window, delta, Qnil, Qnil);
@@ -2691,7 +2670,7 @@ window-start value is reasonable when this function is called.  */)
            resize_failed = 1;
        }
 
-      /* Resize subwindows horizontally.  */
+      /* Resize child windows horizontally.  */
       if (!resize_failed)
        {
          w->left_col = r->left_col;
@@ -2740,23 +2719,20 @@ window-start value is reasonable when this function is called.  */)
        XWINDOW (w->parent)->hchild = sibling;
     }
 
-  /* Delete ROOT and all subwindows of ROOT.  */
+  /* Delete ROOT and all child windows of ROOT.  */
   if (!NILP (r->vchild))
     {
-      delete_all_subwindows (r->vchild);
+      delete_all_child_windows (r->vchild);
       r->vchild = Qnil;
     }
   else if (!NILP (r->hchild))
     {
-      delete_all_subwindows (r->hchild);
+      delete_all_child_windows (r->hchild);
       r->hchild = Qnil;
     }
 
   replace_window (root, window, 1);
 
-  /* Reset WINDOW's splits status.  */
-  w->splits = Qnil;
-
   /* This must become SWINDOW anyway ....... */
   if (!NILP (w->buffer) && !resize_failed)
     {
@@ -2914,7 +2890,7 @@ select_frame_norecord (Lisp_Object frame)
 void
 run_window_configuration_change_hook (struct frame *f)
 {
-  int count = SPECPDL_INDEX ();
+  ptrdiff_t count = SPECPDL_INDEX ();
   Lisp_Object frame, global_wcch
     = Fdefault_value (Qwindow_configuration_change_hook);
   XSETFRAME (frame, f);
@@ -2945,7 +2921,7 @@ run_window_configuration_change_hook (struct frame *f)
        if (!NILP (Flocal_variable_p (Qwindow_configuration_change_hook,
                                      buffer)))
          {
-           int inner_count = SPECPDL_INDEX ();
+           ptrdiff_t inner_count = SPECPDL_INDEX ();
            record_unwind_protect (select_window_norecord, Fselected_window ());
            select_window_norecord (window);
            run_funs (Fbuffer_local_value (Qwindow_configuration_change_hook,
@@ -2980,7 +2956,7 @@ set_window_buffer (Lisp_Object window, Lisp_Object buffer, int run_hooks_p, int
 {
   struct window *w = XWINDOW (window);
   struct buffer *b = XBUFFER (buffer);
-  int count = SPECPDL_INDEX ();
+  ptrdiff_t count = SPECPDL_INDEX ();
   int samebuf = EQ (buffer, w->buffer);
 
   w->buffer = buffer;
@@ -3113,7 +3089,7 @@ This function runs `window-scroll-functions' before running
            error ("Window is dedicated to `%s'", SDATA (BVAR (XBUFFER (tem), name)));
          else
            /* WINDOW is weakly dedicated to its buffer, reset
-              dedicatedness.  */
+              dedication.  */
            w->dedicated = Qnil;
 
          call1 (Qrecord_window_buffer, window);
@@ -3211,7 +3187,7 @@ temp_output_buffer_show (register Lisp_Object buf)
       /* Run temp-buffer-show-hook, with the chosen window selected
         and its buffer current.  */
       {
-        int count = SPECPDL_INDEX ();
+        ptrdiff_t count = SPECPDL_INDEX ();
         Lisp_Object prev_window, prev_buffer;
         prev_window = selected_window;
         XSETBUFFER (prev_buffer, old);
@@ -3271,8 +3247,7 @@ make_parent_window (Lisp_Object window, int horflag)
   p->start = Qnil;
   p->pointm = Qnil;
   p->buffer = Qnil;
-  p->splits = Qnil;
-  p->nest = Qnil;
+  p->combination_limit = Qnil;
   p->window_parameters = Qnil;
 }
 
@@ -3319,7 +3294,7 @@ make_window (void)
   w->start_at_line_beg = w->display_table = w->dedicated = Qnil;
   w->base_line_number = w->base_line_pos = w->region_showing = Qnil;
   w->column_number_displayed = w->redisplay_end_trigger = Qnil;
-  w->splits = w->nest = w->window_parameters = Qnil;
+  w->combination_limit = w->window_parameters = Qnil;
   w->prev_buffers = w->next_buffers = Qnil;
   /* Initialize non-Lisp data.  */
   w->desired_matrix = w->current_matrix = 0;
@@ -3349,7 +3324,7 @@ Return SIZE.
 Optional argument ADD non-nil means add SIZE to the new total size of
 WINDOW and return the sum.
 
-Note: This function does not operate on any subwindows of WINDOW.  */)
+Note: This function does not operate on any child windows of WINDOW.  */)
      (Lisp_Object window, Lisp_Object size, Lisp_Object add)
 {
   struct window *w = decode_any_window (window);
@@ -3367,7 +3342,7 @@ DEFUN ("set-window-new-normal", Fset_window_new_normal, Sset_window_new_normal,
        doc: /* Set new normal size of WINDOW to SIZE.
 Return SIZE.
 
-Note: This function does not operate on any subwindows of WINDOW.  */)
+Note: This function does not operate on any child windows of WINDOW.  */)
      (Lisp_Object window, Lisp_Object size)
 {
   struct window *w = decode_any_window (window);
@@ -3378,7 +3353,7 @@ Note: This function does not operate on any subwindows of WINDOW.  */)
 
 /* Return 1 if setting w->total_lines (w->total_cols if HORFLAG is
    non-zero) to w->new_total would result in correct heights (widths)
-   for window W and recursively all subwindows of W.
+   for window W and recursively all child windows of W.
 
    Note: This function does not check any of `window-fixed-size-p',
    `window-min-height' or `window-min-width'.  It does check that window
@@ -3393,7 +3368,7 @@ window_resize_check (struct window *w, int horflag)
     {
       c = XWINDOW (w->vchild);
       if (horflag)
-       /* All subwindows of W must have the same width as W.  */
+       /* All child windows of W must have the same width as W.  */
        {
          while (c)
            {
@@ -3405,8 +3380,8 @@ window_resize_check (struct window *w, int horflag)
          return 1;
        }
       else
-       /* The sum of the heights of the subwindows of W must equal W's
-          height.  */
+       /* The sum of the heights of the child windows of W must equal
+          W's height.  */
        {
          int sum_of_sizes = 0;
          while (c)
@@ -3424,7 +3399,7 @@ window_resize_check (struct window *w, int horflag)
     {
       c = XWINDOW (w->hchild);
       if (horflag)
-       /* The sum of the widths of the subwindows of W must equal W's
+       /* The sum of the widths of the child windows of W must equal W's
           width.  */
        {
          int sum_of_sizes = 0;
@@ -3438,7 +3413,7 @@ window_resize_check (struct window *w, int horflag)
          return (sum_of_sizes == XINT (w->new_total));
        }
       else
-       /* All subwindows of W must have the same height as W.  */
+       /* All child windows of W must have the same height as W.  */
        {
          while (c)
            {
@@ -3458,9 +3433,9 @@ window_resize_check (struct window *w, int horflag)
 }
 
 /* Set w->total_lines (w->total_cols if HORIZONTAL is non-zero) to
-   w->new_total for window W and recursively all subwindows of W.  Also
-   calculate and assign the new vertical (horizontal) start positions of
-   each of these windows.
+   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.
 
    This function does not perform any error checks.  Make sure you have
    run window_resize_check on W before applying this function.  */
@@ -3534,8 +3509,8 @@ 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 subwindows and
-calculates and assigns the new start positions of these windows.
+window layout, recursively assigns the new sizes of all child windows
+and calculates and assigns the new start positions of these windows.
 
 Note: This function does not check any of `window-fixed-size-p',
 `window-min-height' or `window-min-width'.  All these checks have to
@@ -3692,7 +3667,7 @@ set correctly.  See the code of `split-window' for how this is done.  */)
   int horflag
     /* HORFLAG is 1 when we split side-by-side, 0 otherwise.  */
     = EQ (side, Qt) || EQ (side, Qleft) || EQ (side, Qright);
-  int do_nest = 0;
+  int combination_limit = 0;
 
   CHECK_WINDOW (old);
   o = XWINDOW (old);
@@ -3701,11 +3676,11 @@ set correctly.  See the code of `split-window' for how this is done.  */)
 
   CHECK_NUMBER (total_size);
 
-  /* Set do_nest to 1 if we have to make a new parent window.  We do
-     that if either `window-nest' is non-nil, or OLD has no parent, or
-     OLD is ortho-combined.  */
-  do_nest =
-    !NILP (Vwindow_nest)
+  /* Set combination_limit to 1 if we have to make a new parent window.
+     We do that if either `window-combination-limit' is t, or OLD has no
+     parent, or OLD is ortho-combined.  */
+  combination_limit =
+    !NILP (Vwindow_combination_limit)
     || NILP (o->parent)
     || NILP (horflag
             ? (XWINDOW (o->parent)->hchild)
@@ -3725,8 +3700,8 @@ set correctly.  See the code of `split-window' for how this is done.  */)
     error ("Attempt to split minibuffer window");
   else if (XINT (total_size) < (horflag ? 2 : 1))
     error ("Size of new window too small (after split)");
-  else if (!do_nest && !NILP (Vwindow_splits))
-    /* `window-splits' non-nil means try to resize OLD's siblings
+  else if (!combination_limit && !NILP (Vwindow_combination_resize))
+    /* `window-combination-resize' non-nil means try to resize OLD's siblings
        proportionally.  */
     {
       p = XWINDOW (o->parent);
@@ -3750,7 +3725,7 @@ set correctly.  See the code of `split-window' for how this is done.  */)
     }
 
   /* This is our point of no return. */
-  if (do_nest)
+  if (combination_limit)
     {
       /* Save the old value of o->normal_cols/lines.  It gets corrupted
         by make_parent_window and we need it below for assigning it to
@@ -3759,12 +3734,9 @@ set correctly.  See the code of `split-window' for how this is done.  */)
 
       make_parent_window (old, horflag);
       p = XWINDOW (o->parent);
-      /* Store value of `window-nest' in new parent's nest slot.  */
-      p->nest = Vwindow_nest;
-      /* Have PARENT inherit splits slot value from OLD.  */
-      p->splits = o->splits;
-      /* Store value of `window-splits' in OLD's splits slot.  */
-      o->splits = Vwindow_splits;
+      /* Store value of `window-combination-limit' in new parent's
+        combination_limit slot.  */
+      p->combination_limit = Vwindow_combination_limit;
       /* These get applied below.  */
       p->new_total = horflag ? o->total_cols : o->total_lines;
       p->new_normal = new_normal;
@@ -3815,9 +3787,6 @@ set correctly.  See the code of `split-window' for how this is done.  */)
   n->scroll_bar_width = r->scroll_bar_width;
   n->vertical_scroll_bar_type = r->vertical_scroll_bar_type;
 
-  /* Store `window-splits' in NEW's splits slot.  */
-  n->splits = Vwindow_splits;
-
   /* Directly assign orthogonal coordinates and sizes.  */
   if (horflag)
     {
@@ -3931,12 +3900,12 @@ Signal an error when WINDOW is the only window on its frame.  */)
 
       if (!NILP (w->vchild))
        {
-         delete_all_subwindows (w->vchild);
+         delete_all_child_windows (w->vchild);
          w->vchild = Qnil;
        }
       else if (!NILP (w->hchild))
        {
-         delete_all_subwindows (w->hchild);
+         delete_all_child_windows (w->hchild);
          w->hchild = Qnil;
        }
       else if (!NILP (w->buffer))
@@ -3954,10 +3923,9 @@ Signal an error when WINDOW is the only window on its frame.  */)
          /* Put SIBLING into PARENT's place.  */
          replace_window (parent, sibling, 0);
          /* Have SIBLING inherit the following three slot values from
-            PARENT (the nest slot is not inherited).  */
+            PARENT (the combination_limit slot is not inherited).  */
          s->normal_cols = p->normal_cols;
          s->normal_lines = p->normal_lines;
-         s->splits = p->splits;
          /* Mark PARENT as deleted.  */
          p->vchild = p->hchild = Qnil;
          /* Try to merge SIBLING into its new parent.  */
@@ -4199,9 +4167,10 @@ window_internal_height (struct window *w)
    respectively.  */
 
 static void
-window_scroll (Lisp_Object window, int n, int whole, int noerror)
+window_scroll (Lisp_Object window, EMACS_INT n, int whole, int noerror)
 {
   immediate_quit = 1;
+  n = clip_to_bounds (INT_MIN, n, INT_MAX);
 
   /* If we must, use the pixel-based version which is much slower than
      the line-based one but can handle varying line heights.  */
@@ -4297,7 +4266,7 @@ window_scroll_pixel_based (Lisp_Object window, int n, int whole, int noerror)
              /* Maybe modify window start instead of scrolling.  */
              if (rbot > 0 || w->vscroll < 0)
                {
-                 EMACS_INT spos;
+                 ptrdiff_t spos;
 
                  Fset_window_vscroll (window, make_number (0), Qt);
                  /* If there are other text lines above the current row,
@@ -4352,7 +4321,7 @@ window_scroll_pixel_based (Lisp_Object window, int n, int whole, int noerror)
   start_display (&it, w, start);
   if (whole)
     {
-      EMACS_INT start_pos = IT_CHARPOS (it);
+      ptrdiff_t start_pos = IT_CHARPOS (it);
       int dy = WINDOW_FRAME_LINE_HEIGHT (w);
       dy = max ((window_box_height (w)
                 - next_screen_context_lines * dy),
@@ -4439,8 +4408,8 @@ window_scroll_pixel_based (Lisp_Object window, int n, int whole, int noerror)
 
   if (! vscrolled)
     {
-      EMACS_INT pos = IT_CHARPOS (it);
-      EMACS_INT bytepos;
+      ptrdiff_t pos = IT_CHARPOS (it);
+      ptrdiff_t bytepos;
 
       /* If in the middle of a multi-glyph character move forward to
         the next character.  */
@@ -4510,7 +4479,7 @@ window_scroll_pixel_based (Lisp_Object window, int n, int whole, int noerror)
     }
   else if (n < 0)
     {
-      EMACS_INT charpos, bytepos;
+      ptrdiff_t charpos, bytepos;
       int partial_p;
 
       /* Save our position, for the
@@ -4587,12 +4556,12 @@ window_scroll_line_based (Lisp_Object window, int n, int whole, int noerror)
      in `grep-mode-font-lock-keywords').  So we use a marker to record
      the old point position, to prevent crashes in SET_PT_BOTH.  */
   Lisp_Object opoint_marker = Fpoint_marker ();
-  register EMACS_INT pos, pos_byte;
+  register ptrdiff_t pos, pos_byte;
   register int ht = window_internal_height (w);
   register Lisp_Object tem;
   int lose;
   Lisp_Object bolp;
-  EMACS_INT startpos;
+  ptrdiff_t startpos;
   Lisp_Object original_pos = Qnil;
 
   /* If scrolling screen-fulls, compute the number of lines to
@@ -4741,7 +4710,7 @@ window_scroll_line_based (Lisp_Object window, int n, int whole, int noerror)
 static void
 scroll_command (Lisp_Object n, int direction)
 {
-  int count = SPECPDL_INDEX ();
+  ptrdiff_t count = SPECPDL_INDEX ();
 
   xassert (eabs (direction) == 1);
 
@@ -4856,7 +4825,7 @@ specifies the window to scroll.  This takes precedence over
 {
   Lisp_Object window;
   struct window *w;
-  int count = SPECPDL_INDEX ();
+  ptrdiff_t count = SPECPDL_INDEX ();
 
   window = Fother_window_for_scrolling ();
   w = XWINDOW (window);
@@ -4898,7 +4867,7 @@ by this function.  This happens in an interactive call.  */)
   (register Lisp_Object arg, Lisp_Object set_minimum)
 {
   Lisp_Object result;
-  int hscroll;
+  EMACS_INT hscroll;
   struct window *w = XWINDOW (selected_window);
 
   if (NILP (arg))
@@ -4927,7 +4896,7 @@ by this function.  This happens in an interactive call.  */)
   (register Lisp_Object arg, Lisp_Object set_minimum)
 {
   Lisp_Object result;
-  int hscroll;
+  EMACS_INT hscroll;
   struct window *w = XWINDOW (selected_window);
 
   if (NILP (arg))
@@ -5028,7 +4997,7 @@ the selected window; if the variable `recenter-redisplay' is non-nil,
 also erase the entire frame and redraw it (when `auto-resize-tool-bars'
 is set to `grow-only', this resets the tool-bar's height to the minimum
 height needed); if `recenter-redisplay' has the special value `tty',
-then only tty frame are redrawn.
+then only tty frames are redrawn.
 
 Just C-u as prefix means put point in the center of the window
 and redisplay normally--don't erase and redraw the frame.  */)
@@ -5038,7 +5007,7 @@ and redisplay normally--don't erase and redraw the frame.  */)
   struct buffer *buf = XBUFFER (w->buffer);
   struct buffer *obuf = current_buffer;
   int center_p = 0;
-  EMACS_INT charpos, bytepos;
+  ptrdiff_t charpos, bytepos;
   EMACS_INT iarg IF_LINT (= 0);
   int this_scroll_margin;
 
@@ -5103,7 +5072,7 @@ and redisplay normally--don't erase and redraw the frame.  */)
        {
          struct it it;
          struct text_pos pt;
-         int nlines = min (INT_MAX, -iarg);
+         ptrdiff_t nlines = min (PTRDIFF_MAX, -iarg);
          int extra_line_spacing;
          int h = window_box_height (w);
          void *itdata = bidi_shelve_cache ();
@@ -5218,10 +5187,10 @@ and redisplay normally--don't erase and redraw the frame.  */)
 DEFUN ("window-text-height", Fwindow_text_height, Swindow_text_height,
        0, 1, 0,
        doc: /* Return the height in lines of the text display area of WINDOW.
-WINDOW defaults to the selected window.
+If WINDOW is omitted or nil, it defaults to the selected window.
 
-The return value does not include the mode line, any header line, nor
-any partial-height lines in the text display area.  */)
+The returned height does not include the mode line, any header line,
+nor any partial-height lines at the bottom of the text area.  */)
   (Lisp_Object window)
 {
   struct window *w = decode_window (window);
@@ -5344,7 +5313,7 @@ struct saved_window
   Lisp_Object left_margin_cols, right_margin_cols;
   Lisp_Object left_fringe_width, right_fringe_width, fringes_outside_margins;
   Lisp_Object scroll_bar_width, vertical_scroll_bar_type, dedicated;
-  Lisp_Object splits, nest, window_parameters;
+  Lisp_Object combination_limit, window_parameters;
 };
 
 #define SAVED_WINDOW_N(swv,n) \
@@ -5387,7 +5356,7 @@ the return value is nil.  Otherwise the value is t.  */)
   Lisp_Object frame;
   Lisp_Object auto_buffer_name;
   FRAME_PTR f;
-  EMACS_INT old_point = -1;
+  ptrdiff_t old_point = -1;
 
   CHECK_WINDOW_CONFIGURATION (configuration);
 
@@ -5443,6 +5412,7 @@ the return value is nil.  Otherwise the value is t.  */)
     {
       Lisp_Object window;
       Lisp_Object dead_windows = Qnil;
+      register Lisp_Object tem, par, pers;
       register struct window *w;
       register struct saved_window *p;
       struct window *root_window;
@@ -5515,7 +5485,7 @@ the return value is nil.  Otherwise the value is t.  */)
         Save their current buffers in their height fields, since we may
         need it later, if a buffer saved in the configuration is now
         dead.  */
-      delete_all_subwindows (FRAME_ROOT_WINDOW (f));
+      delete_all_child_windows (FRAME_ROOT_WINDOW (f));
 
       for (k = 0; k < saved_windows->header.size; k++)
        {
@@ -5575,9 +5545,29 @@ the return value is nil.  Otherwise the value is t.  */)
          w->scroll_bar_width = p->scroll_bar_width;
          w->vertical_scroll_bar_type = p->vertical_scroll_bar_type;
          w->dedicated = p->dedicated;
-         w->splits = p->splits;
-         w->nest = p->nest;
-         w->window_parameters = p->window_parameters;
+         w->combination_limit = p->combination_limit;
+         /* Restore any window parameters that have been saved.
+            Parameters that have not been saved are left alone.  */
+         for (tem = p->window_parameters; CONSP (tem); tem = XCDR (tem))
+           {
+             pers = XCAR (tem);
+             if (CONSP (pers))
+               {
+                 if (NILP (XCDR (pers)))
+                   {
+                     par = Fassq (XCAR (pers), w->window_parameters);
+                     if (CONSP (par) && !NILP (XCDR (par)))
+                       /* Reset a parameter to nil if and only if it
+                          has a non-nil association.  Don't make new
+                          associations.  */
+                       Fsetcdr (par, Qnil);
+                   }
+                 else
+                   /* Always restore a non-nil value.  */
+                   Fset_window_parameter (window, XCAR (pers), XCDR (pers));
+               }
+           }
+
          XSETFASTINT (w->last_modified, 0);
          XSETFASTINT (w->last_overlay_modified, 0);
 
@@ -5729,10 +5719,10 @@ the return value is nil.  Otherwise the value is t.  */)
 }
 
 
-/* Delete all subwindows reachable via the next, vchild, and hchild
-   slots of WINDOW.  */
+/* Recursively delete all child windows reachable via the next, vchild,
+   and hchild slots of WINDOW.  */
 void
-delete_all_subwindows (Lisp_Object window)
+delete_all_child_windows (Lisp_Object window)
 {
   register struct window *w;
 
@@ -5740,18 +5730,18 @@ delete_all_subwindows (Lisp_Object window)
 
   if (!NILP (w->next))
     /* Delete WINDOW's siblings (we traverse postorderly).  */
-    delete_all_subwindows (w->next);
+    delete_all_child_windows (w->next);
 
   w->total_lines = w->buffer;       /* See Fset_window_configuration for excuse.  */
 
   if (!NILP (w->vchild))
     {
-      delete_all_subwindows (w->vchild);
+      delete_all_child_windows (w->vchild);
       w->vchild = Qnil;
     }
   else if (!NILP (w->hchild))
     {
-      delete_all_subwindows (w->hchild);
+      delete_all_child_windows (w->hchild);
       w->hchild = Qnil;
     }
   else if (!NILP (w->buffer))
@@ -5801,20 +5791,37 @@ get_leaf_windows (struct window *w, struct window **flat, int i)
 
 
 /* Return a pointer to the glyph W's physical cursor is on.  Value is
-   null if W's current matrix is invalid, so that no meaningfull glyph
+   null if W's current matrix is invalid, so that no meaningful glyph
    can be returned.  */
 struct glyph *
 get_phys_cursor_glyph (struct window *w)
 {
   struct glyph_row *row;
   struct glyph *glyph;
+  int hpos = w->phys_cursor.hpos;
+
+  if (!(w->phys_cursor.vpos >= 0
+       && w->phys_cursor.vpos < w->current_matrix->nrows))
+    return NULL;
+
+  row = MATRIX_ROW (w->current_matrix, w->phys_cursor.vpos);
+  if (!row->enabled_p)
+    return NULL;
 
-  if (w->phys_cursor.vpos >= 0
-      && w->phys_cursor.vpos < w->current_matrix->nrows
-      && (row = MATRIX_ROW (w->current_matrix, w->phys_cursor.vpos),
-         row->enabled_p)
-      && row->used[TEXT_AREA] > w->phys_cursor.hpos)
-    glyph = row->glyphs[TEXT_AREA] + w->phys_cursor.hpos;
+  if (XINT (w->hscroll))
+    {
+      /* When the window is hscrolled, cursor hpos can legitimately be
+        out of bounds, but we draw the cursor at the corresponding
+        window margin in that case.  */
+      if (!row->reversed_p && hpos < 0)
+       hpos = 0;
+      if (row->reversed_p && hpos >= row->used[TEXT_AREA])
+       hpos = row->used[TEXT_AREA] - 1;
+    }
+
+  if (row->used[TEXT_AREA] > hpos
+      && 0 <= hpos)
+    glyph = row->glyphs[TEXT_AREA] + hpos;
   else
     glyph = NULL;
 
@@ -5827,7 +5834,7 @@ save_window_save (Lisp_Object window, struct Lisp_Vector *vector, int i)
 {
   register struct saved_window *p;
   register struct window *w;
-  register Lisp_Object tem;
+  register Lisp_Object tem, pers, par;
 
   for (;!NILP (window); window = w->next)
     {
@@ -5854,14 +5861,60 @@ save_window_save (Lisp_Object window, struct Lisp_Vector *vector, int i)
       p->scroll_bar_width = w->scroll_bar_width;
       p->vertical_scroll_bar_type = w->vertical_scroll_bar_type;
       p->dedicated = w->dedicated;
-      p->splits = w->splits;
-      p->nest = w->nest;
-      p->window_parameters = w->window_parameters;
+      p->combination_limit = w->combination_limit;
+      p->window_parameters = Qnil;
+
+      if (!NILP (Vwindow_persistent_parameters))
+       {
+         /* Run cycle detection on Vwindow_persistent_parameters.  */
+         Lisp_Object tortoise, hare;
+
+         hare = tortoise = Vwindow_persistent_parameters;
+         while (CONSP (hare))
+           {
+             hare = XCDR (hare);
+             if (!CONSP (hare))
+               break;
+
+             hare = XCDR (hare);
+             tortoise = XCDR (tortoise);
+
+             if (EQ (hare, tortoise))
+               /* Reset Vwindow_persistent_parameters to Qnil.  */
+               {
+                 Vwindow_persistent_parameters = Qnil;
+                 break;
+               }
+           }
+
+         for (tem = Vwindow_persistent_parameters; CONSP (tem);
+              tem = XCDR (tem))
+           {
+             pers = XCAR (tem);
+             /* Save values for persistent window parameters. */
+             if (CONSP (pers) && !NILP (XCDR (pers)))
+               {
+                 par = Fassq (XCAR (pers), w->window_parameters);
+                 if (NILP (par))
+                   /* If the window has no value for the parameter,
+                      make one.  */
+                   p->window_parameters = Fcons (Fcons (XCAR (pers), Qnil),
+                                                 p->window_parameters);
+                 else
+                   /* If the window has a value for the parameter,
+                      save it.  */
+                   p->window_parameters = Fcons (Fcons (XCAR (par),
+                                                        XCDR (par)),
+                                                 p->window_parameters);
+               }
+           }
+       }
+
       if (!NILP (w->buffer))
        {
-         /* Save w's value of point in the window configuration.
-            If w is the selected window, then get the value of point
-            from the buffer; pointm is garbage in the selected window.  */
+         /* Save w's value of point in the window configuration.  If w
+            is the selected window, then get the value of point from
+            the buffer; pointm is garbage in the selected window.  */
          if (EQ (window, selected_window))
            {
              p->pointm = Fmake_marker ();
@@ -5914,7 +5967,9 @@ and for each displayed buffer, where display starts, and the positions of
 point and mark.  An exception is made for point in the current buffer:
 its value is -not- saved.
 This also records the currently selected frame, and FRAME's focus
-redirection (see `redirect-frame-focus').  */)
+redirection (see `redirect-frame-focus').  The variable
+`window-persistent-parameters' specifies which window parameters are
+saved by this function.  */)
   (Lisp_Object frame)
 {
   register Lisp_Object tem;
@@ -6104,7 +6159,7 @@ Fourth parameter HORIZONTAL-TYPE is currently unused.  */)
 
   if (!NILP (width))
     {
-      CHECK_NATNUM (width);
+      CHECK_RANGED_INTEGER (0, width, INT_MAX);
 
       if (XINT (width) == 0)
        vertical_type = Qnil;
@@ -6317,8 +6372,9 @@ freeze_window_starts (struct frame *f, int freeze_p)
    ignore_positions non-zero means ignore non-matching scroll positions
    and the like.
 
-   This ignores a couple of things like the dedicatedness status of
-   window, splits, nest and the like.  This might have to be fixed.  */
+   This ignores a couple of things like the dedication status of
+   window, combination_limit and the like.  This might have to be
+   fixed.  */
 
 int
 compare_window_configurations (Lisp_Object configuration1, Lisp_Object configuration2, int ignore_positions)
@@ -6450,6 +6506,7 @@ syms_of_window (void)
   DEFSYM (Qabove, "above");
   DEFSYM (Qbelow, "below");
   DEFSYM (Qauto_buffer_name, "auto-buffer-name");
+  DEFSYM (Qclone_of, "clone-of");
 
   staticpro (&Vwindow_list);
 
@@ -6517,46 +6574,72 @@ with the relevant frame selected.  */);
   Vwindow_configuration_change_hook = Qnil;
 
   DEFVAR_LISP ("recenter-redisplay", Vrecenter_redisplay,
-              doc: /* If non-nil, then the `recenter' command with a nil argument
-will redraw the entire frame; the special value `tty' causes the
-frame to be redrawn only if it is a tty frame.  */);
+              doc: /* Non-nil means `recenter' redraws entire frame.
+If this option is non-nil, then the `recenter' command with a nil
+argument will redraw the entire frame; the special value `tty' causes
+the frame to be redrawn only if it is a tty frame.  */);
   Vrecenter_redisplay = Qtty;
 
-  DEFVAR_LISP ("window-splits", Vwindow_splits,
-              doc: /* Non-nil means splitting windows is handled specially.
+  DEFVAR_LISP ("window-combination-resize", Vwindow_combination_resize,
+              doc: /* If t, resize window combinations proportionally.
 If this variable is nil, splitting a window gets the entire screen space
-for displaying the new window from the window to split.  If this
-variable is non-nil, splitting a window may resize all windows in the
-same combination.  This also allows to split a window that is otherwise
-too small or of fixed size.
-
-The value of this variable is also assigned to the split status of the
-new window and, provided the old and new window form a new combination,
-to the window that was split as well.  The split status of a window can
-be retrieved with the function `window-splits' and altered by the
-function `set-window-splits'.
-
-If the value of the variable `window-nest' is non-nil, the space for the
-new window is exclusively taken from the window that shall be split, but
-the split status of the window that is split as well as that of the new
-window are still set to the value of this variable.  */);
-  Vwindow_splits = Qnil;
-
-  DEFVAR_LISP ("window-nest", Vwindow_nest,
-              doc: /* Non-nil means splitting a window makes a new parent window.
+for displaying the new window from the window to split.  Deleting and
+resizing a window preferably resizes one adjacent window only.
+
+If this variable is t, splitting a window tries to get the space
+proportionally from all windows in the same combination.  This also
+allows to split a window that is otherwise too small or of fixed size.
+Resizing and deleting a window proportionally resize all windows in the
+same combination.
+
+Other values are reserved for future use.
+
+This variable takes no effect if `window-combination-limit' is non-nil.  */);
+  Vwindow_combination_resize = Qnil;
+
+  DEFVAR_LISP ("window-combination-limit", Vwindow_combination_limit,
+              doc: /* If t, splitting a window makes a new parent window.
 If this variable is nil, splitting a window will create a new parent
 window only if the window has no parent window or the window shall
-become a combination orthogonal to the one it it is part of.
+become a combination orthogonal to the one it is part of.
+
+If this variable is t, splitting a window always creates a new parent
+window.  If all splits behave this way, each frame's window tree is a
+binary tree and every window but the frame's root window has exactly one
+sibling.
+
+Other values are reserved for future use.
+
+The value of this variable is also assigned to the combination limit of
+the new parent window.  The combination limit of a window can be
+retrieved via the function `window-combination-limit' and altered by the
+function `set-window-combination-limit'.  */);
+  Vwindow_combination_limit = Qnil;
+
+  DEFVAR_LISP ("window-persistent-parameters", Vwindow_persistent_parameters,
+              doc: /* Alist of persistent window parameters.
+This alist specifies which window parameters shall get saved by
+`current-window-configuration' and `window-state-get' and subsequently
+restored to their previous values by `set-window-configuration' and
+`window-state-put'.
+
+The car of each entry of this alist is the symbol specifying the
+parameter.  The cdr is one of the following:
+
+nil means the parameter is neither saved by `window-state-get' nor by
+`current-window-configuration'.
+
+t means the parameter is saved by `current-window-configuration' and,
+provided its WRITABLE argument is nil, by `window-state-get'.
 
-If this variable is non-nil, splitting a window always creates a new
-parent window.  If all splits behave this way, each frame's window tree
-is a binary tree and every window but the frame's root window has
-exactly one sibling.
+The symbol `writable' means the parameter is saved unconditionally by
+both `current-window-configuration' and `window-state-get'.  Do not use
+this value for parameters without read syntax (like windows or frames).
 
-The value of this variable is also assigned to the nest status of the
-new parent window.  The nest status of a window can be retrieved via the
-function `window-nest' and altered by the function `set-window-nest'.  */);
-  Vwindow_nest = Qnil;
+Parameters not saved by `current-window-configuration' or
+`window-state-get' are left alone by `set-window-configuration'
+respectively are not installed by `window-state-put'.  */);
+  Vwindow_persistent_parameters = list1 (Fcons (Qclone_of, Qt));
 
   defsubr (&Sselected_window);
   defsubr (&Sminibuffer_window);
@@ -6576,21 +6659,21 @@ function `window-nest' and altered by the function `set-window-nest'.  */);
   defsubr (&Swindow_left_child);
   defsubr (&Swindow_next_sibling);
   defsubr (&Swindow_prev_sibling);
-  defsubr (&Swindow_splits);
-  defsubr (&Sset_window_splits);
-  defsubr (&Swindow_nest);
-  defsubr (&Sset_window_nest);
+  defsubr (&Swindow_combination_limit);
+  defsubr (&Sset_window_combination_limit);
   defsubr (&Swindow_use_time);
   defsubr (&Swindow_top_line);
   defsubr (&Swindow_left_column);
-  defsubr (&Swindow_total_size);
+  defsubr (&Swindow_total_height);
+  defsubr (&Swindow_total_width);
   defsubr (&Swindow_normal_size);
   defsubr (&Swindow_new_total);
   defsubr (&Swindow_new_normal);
   defsubr (&Sset_window_new_total);
   defsubr (&Sset_window_new_normal);
   defsubr (&Swindow_resize_apply);
-  defsubr (&Swindow_body_size);
+  defsubr (&Swindow_body_height);
+  defsubr (&Swindow_body_width);
   defsubr (&Swindow_hscroll);
   defsubr (&Sset_window_hscroll);
   defsubr (&Swindow_redisplay_end_trigger);