unofficial mirror of emacs-devel@gnu.org 
 help / color / mirror / code / Atom feed
* [RFC] some reworking of struct window
@ 2013-03-21  9:39 Dmitry Antipov
  2013-03-21 11:38 ` martin rudalics
                   ` (3 more replies)
  0 siblings, 4 replies; 16+ messages in thread
From: Dmitry Antipov @ 2013-03-21  9:39 UTC (permalink / raw)
  To: Emacs development discussions

[-- Attachment #1: Type: text/plain, Size: 750 bytes --]

This patch implements the further generalization of an idea suggested by Stefan
at http://lists.gnu.org/archive/html/emacs-devel/2013-02/msg00088.html. The main
motivations are 1) make 'struct window' even bit smaller and 2) simplify the code
like:

if (!NILP (w->hchild))
   foo (w->hchild);
else if (!NILP (w->vchild))
   foo (w->vchild);
else /* assume leaf window with w->buffer */
   bar (w->buffer);

to:

if (WINDOWP (w->object))
   foo (w->object);
else /* assume leaf window with buffer at w->object */
   bar (w->object);

As usual, reviews and comments are highly appreciated, especially for the
'struct window' member which replaces hchild/vchild/buffer (I don't like
too generic 'object', but couldn't think up the better name).

Dmitry

[-- Attachment #2: window_object.patch --]
[-- Type: text/plain, Size: 98994 bytes --]

=== modified file 'src/alloc.c'
--- src/alloc.c	2013-03-19 04:41:53 +0000
+++ src/alloc.c	2013-03-21 05:17:12 +0000
@@ -5837,14 +5837,13 @@
 	  case PVEC_WINDOW:
 	    {
 	      struct window *w = (struct window *) ptr;
-	      bool leaf = NILP (w->hchild) && NILP (w->vchild);
 
 	      mark_vectorlike (ptr);
 
 	      /* Mark glyphs for leaf windows.  Marking window
 		 matrices is sufficient because frame matrices
 		 use the same glyph memory.  */
-	      if (leaf && w->current_matrix)
+	      if (w->type == WINDOW_LEAF && w->current_matrix)
 		{
 		  mark_glyph_matrix (w->current_matrix);
 		  mark_glyph_matrix (w->desired_matrix);

=== modified file 'src/buffer.c'
--- src/buffer.c	2013-01-19 20:04:33 +0000
+++ src/buffer.c	2013-03-21 08:56:01 +0000
@@ -1769,7 +1769,7 @@
      since anything can happen within do_yes_or_no_p.  */
 
   /* Don't kill the minibuffer now current.  */
-  if (EQ (buffer, XWINDOW (minibuf_window)->buffer))
+  if (EQ (buffer, XWINDOW (minibuf_window)->object))
     return Qnil;
 
   /* When we kill an ordinary buffer which shares it's buffer text
@@ -1820,7 +1820,7 @@
   /* If the buffer now current is shown in the minibuffer and our buffer
      is the sole other buffer give up.  */
   XSETBUFFER (tem, current_buffer);
-  if (EQ (tem, XWINDOW (minibuf_window)->buffer)
+  if (EQ (tem, XWINDOW (minibuf_window)->object)
       && EQ (buffer, Fother_buffer (buffer, Qnil, Qnil)))
     return Qnil;
 
@@ -2394,7 +2394,7 @@
 	   BUF_MARKERS(buf) should either be for `buf' or dead.  */
 	eassert (!m->buffer);
   }
-  { /* Some of the C code expects that w->buffer == w->pointm->buffer.
+  { /* Some of the C code expects that w->object == w->pointm->buffer.
        So since we just swapped the markers between the two buffers, we need
        to undo the effect of this swap for window markers.  */
     Lisp_Object w = Fselected_window (), ws = Qnil;
@@ -2405,12 +2405,12 @@
       {
 	ws = Fcons (w, ws);
 	if (MARKERP (XWINDOW (w)->pointm)
-	    && (EQ (XWINDOW (w)->buffer, buf1)
-		|| EQ (XWINDOW (w)->buffer, buf2)))
+	    && (EQ (XWINDOW (w)->object, buf1)
+		|| EQ (XWINDOW (w)->object, buf2)))
 	  Fset_marker (XWINDOW (w)->pointm,
 		       make_number
-		       (BUF_BEGV (XBUFFER (XWINDOW (w)->buffer))),
-		       XWINDOW (w)->buffer);
+		       (BUF_BEGV (XBUFFER (XWINDOW (w)->object))),
+		       XWINDOW (w)->object);
 	w = Fnext_window (w, Qt, Qt);
       }
   }
@@ -3893,7 +3893,7 @@
   if (buffer_window_count (buf) > 0)
     {
       /* ... it's visible in other window than selected,  */
-      if (buf != XBUFFER (XWINDOW (selected_window)->buffer))
+      if (buf != XBUFFER (XWINDOW (selected_window)->object))
 	windows_or_buffers_changed = 1;
       /* ... or if we modify an overlay at the end of the buffer
 	 and so we cannot be sure that window end is still valid.  */

=== modified file 'src/dispextern.h'
--- src/dispextern.h	2013-03-19 04:41:53 +0000
+++ src/dispextern.h	2013-03-21 05:05:23 +0000
@@ -1412,24 +1412,24 @@
 
 /* Value is non-zero if window W wants a mode line.  */
 
-#define WINDOW_WANTS_MODELINE_P(W)					\
-     (!MINI_WINDOW_P ((W))						\
-      && !(W)->pseudo_window_p						\
-      && FRAME_WANTS_MODELINE_P (XFRAME (WINDOW_FRAME ((W))))		\
-      && BUFFERP (W->buffer)					\
-      && !NILP (BVAR (XBUFFER (W->buffer), mode_line_format))	\
+#define WINDOW_WANTS_MODELINE_P(W)				\
+     (!MINI_WINDOW_P ((W))					\
+      && !(W)->pseudo_window_p					\
+      && FRAME_WANTS_MODELINE_P (XFRAME (WINDOW_FRAME ((W))))	\
+      && BUFFERP (W->object)					\
+      && !NILP (BVAR (XBUFFER (W->object), mode_line_format))	\
       && WINDOW_TOTAL_LINES (W) > 1)
 
 /* Value is true if window W wants a header line.  */
 
-#define WINDOW_WANTS_HEADER_LINE_P(W)					\
-     (!MINI_WINDOW_P ((W))						\
-      && !(W)->pseudo_window_p						\
-      && FRAME_WANTS_MODELINE_P (XFRAME (WINDOW_FRAME ((W))))		\
-      && BUFFERP (W->buffer)					\
-      && !NILP (BVAR (XBUFFER (W->buffer), header_line_format))	\
-      && WINDOW_TOTAL_LINES (W) > 1					\
-      + !NILP (BVAR (XBUFFER (W->buffer), mode_line_format)))
+#define WINDOW_WANTS_HEADER_LINE_P(W)				\
+     (!MINI_WINDOW_P ((W))					\
+      && !(W)->pseudo_window_p					\
+      && FRAME_WANTS_MODELINE_P (XFRAME (WINDOW_FRAME ((W))))	\
+      && BUFFERP (W->object)					\
+      && !NILP (BVAR (XBUFFER (W->object), header_line_format))	\
+      && WINDOW_TOTAL_LINES (W) > 1				\
+      + !NILP (BVAR (XBUFFER (W->object), mode_line_format)))
 
 
 /* Return proper value to be used as baseline offset of font that has

=== modified file 'src/dispnew.c'
--- src/dispnew.c	2013-03-20 11:29:37 +0000
+++ src/dispnew.c	2013-03-21 08:57:55 +0000
@@ -223,9 +223,9 @@
 	    "%"pMu": window %p (`%s')%s\n%s",
 	    history_tick++,
 	    w,
-	    ((BUFFERP (w->buffer)
-	      && STRINGP (BVAR (XBUFFER (w->buffer), name)))
-	     ? SSDATA (BVAR (XBUFFER (w->buffer), name))
+	    ((BUFFERP (w->object)
+	      && STRINGP (BVAR (XBUFFER (w->object), name)))
+	     ? SSDATA (BVAR (XBUFFER (w->object), name))
 	     : "???"),
 	    paused_p ? " ***paused***" : "",
 	    msg);
@@ -838,16 +838,8 @@
 {
   while (w)
     {
-      if (!NILP (w->hchild))
-	{
-	  eassert (WINDOWP (w->hchild));
-	  clear_window_matrices (XWINDOW (w->hchild), desired_p);
-	}
-      else if (!NILP (w->vchild))
-	{
-	  eassert (WINDOWP (w->vchild));
-	  clear_window_matrices (XWINDOW (w->vchild), desired_p);
-	}
+      if (WINDOWP (w->object))
+	clear_window_matrices (XWINDOW (w->object), desired_p);
       else
 	{
 	  if (desired_p)
@@ -1468,7 +1460,7 @@
   struct glyph_row *row = matrix->rows;
   struct glyph_row *last_text_row = NULL;
   struct buffer *saved = current_buffer;
-  struct buffer *buffer = XBUFFER (w->buffer);
+  struct buffer *buffer = XBUFFER (w->object);
   int c;
 
   /* This can sometimes happen for a fresh window.  */
@@ -1632,7 +1624,8 @@
      vertically below other windows.  */
   in_horz_combination_p
     = (!NILP (XWINDOW (window)->parent)
-       && !NILP (XWINDOW (XWINDOW (window)->parent)->hchild));
+       && (XWINDOW (XWINDOW (window)->parent)->type
+	   == WINDOW_HORIZONTAL_COMBINATION));
 
   /* For WINDOW and all windows on the same level.  */
   do
@@ -1641,12 +1634,8 @@
 
       /* Get the dimension of the window sub-matrix for W, depending
 	 on whether this is a combination or a leaf window.  */
-      if (!NILP (w->hchild))
-	dim = allocate_matrices_for_frame_redisplay (w->hchild, x, y,
-						     dim_only_p,
-						     window_change_flags);
-      else if (!NILP (w->vchild))
-	dim = allocate_matrices_for_frame_redisplay (w->vchild, x, y,
+      if (WINDOWP (w->object))
+	dim = allocate_matrices_for_frame_redisplay (w->object, x, y,
 						     dim_only_p,
 						     window_change_flags);
       else
@@ -1788,10 +1777,8 @@
 {
   while (w)
     {
-      if (!NILP (w->vchild))
-	allocate_matrices_for_window_redisplay (XWINDOW (w->vchild));
-      else if (!NILP (w->hchild))
-	allocate_matrices_for_window_redisplay (XWINDOW (w->hchild));
+      if (WINDOWP (w->object))
+	allocate_matrices_for_window_redisplay (XWINDOW (w->object));
       else
 	{
 	  /* W is a leaf window.  */
@@ -1863,18 +1850,12 @@
 {
   while (w)
     {
-      if (!NILP (w->hchild))
-	{
-	  if (showing_window_margins_p (XWINDOW (w->hchild)))
-	    return 1;
-	}
-      else if (!NILP (w->vchild))
-	{
-	  if (showing_window_margins_p (XWINDOW (w->vchild)))
-	    return 1;
-	}
-      else if (!NILP (w->left_margin_cols)
-	       || !NILP (w->right_margin_cols))
+      if (WINDOWP (w->object))
+	{
+	  if (showing_window_margins_p (XWINDOW (w->object)))
+	    return 1;
+	}
+      else if (!NILP (w->left_margin_cols) || !NILP (w->right_margin_cols))
 	return 1;
 
       w = NILP (w->next) ? 0 : XWINDOW (w->next);
@@ -1895,10 +1876,8 @@
     {
       w = XWINDOW (window);
 
-      if (!NILP (w->hchild))
-	fake_current_matrices (w->hchild);
-      else if (!NILP (w->vchild))
-	fake_current_matrices (w->vchild);
+      if (WINDOWP (w->object))
+	fake_current_matrices (w->object);
       else
 	{
 	  int i;
@@ -2236,10 +2215,8 @@
 {
   while (w)
     {
-      if (!NILP (w->hchild))
-	free_window_matrices (XWINDOW (w->hchild));
-      else if (!NILP (w->vchild))
-	free_window_matrices (XWINDOW (w->vchild));
+      if (WINDOWP (w->object))
+	free_window_matrices (XWINDOW (w->object));
       else
 	{
 	  /* This is a leaf window.  Free its memory and reset fields
@@ -2372,10 +2349,8 @@
 {
   while (w)
     {
-      if (!NILP (w->hchild))
-	build_frame_matrix_from_window_tree (matrix, XWINDOW (w->hchild));
-      else if (!NILP (w->vchild))
-	build_frame_matrix_from_window_tree (matrix, XWINDOW (w->vchild));
+      if (WINDOWP (w->object))
+	build_frame_matrix_from_window_tree (matrix, XWINDOW (w->object));
       else
 	build_frame_matrix_from_leaf_window (matrix, w);
 
@@ -2639,10 +2614,8 @@
 {
   while (w)
     {
-      if (!NILP (w->hchild))
- 	mirror_make_current (XWINDOW (w->hchild), frame_row);
-      else if (!NILP (w->vchild))
-	mirror_make_current (XWINDOW (w->vchild), frame_row);
+      if (WINDOWP (w->object))
+ 	mirror_make_current (XWINDOW (w->object), frame_row);
       else
 	{
 	  /* Row relative to window W.  Don't use FRAME_TO_WINDOW_VPOS
@@ -2739,7 +2712,7 @@
   int left, right, x, width;
 
   /* Preconditions: W must be a leaf window on a tty frame.  */
-  eassert (NILP (w->hchild) && NILP (w->vchild));
+  eassert (w->type == WINDOW_LEAF);
   eassert (!FRAME_WINDOW_P (f));
 
   left = margin_glyphs_to_reserve (w, 1, w->left_margin_cols);
@@ -2775,10 +2748,8 @@
 
   while (w && !found)
     {
-      if (!NILP (w->hchild))
- 	found = frame_row_to_window (XWINDOW (w->hchild), row);
-      else if (!NILP (w->vchild))
-	found = frame_row_to_window (XWINDOW (w->vchild), row);
+      if (WINDOWP (w->object))
+ 	found = frame_row_to_window (XWINDOW (w->object), row);
       else if (row >= WINDOW_TOP_EDGE_LINE (w)
 	       && row < WINDOW_BOTTOM_EDGE_LINE (w))
 	found = w;
@@ -2806,11 +2777,8 @@
 {
   while (w)
     {
-      if (!NILP (w->hchild))
-	mirror_line_dance (XWINDOW (w->hchild), unchanged_at_top,
-			   nlines, copy_from, retained_p);
-      else if (!NILP (w->vchild))
-	mirror_line_dance (XWINDOW (w->vchild), unchanged_at_top,
+      if (WINDOWP (w->object))
+	mirror_line_dance (XWINDOW (w->object), unchanged_at_top,
 			   nlines, copy_from, retained_p);
       else
 	{
@@ -3186,10 +3154,8 @@
 
   while (w && !paused_p)
     {
-      if (!NILP (w->hchild))
-	paused_p |= update_window_tree (XWINDOW (w->hchild), force_p);
-      else if (!NILP (w->vchild))
-	paused_p |= update_window_tree (XWINDOW (w->vchild), force_p);
+      if (WINDOWP (w->object))
+	paused_p |= update_window_tree (XWINDOW (w->object), force_p);
       else if (w->must_be_updated_p)
 	paused_p |= update_window (w, force_p);
 
@@ -3967,10 +3933,8 @@
 {
   while (w)
     {
-      if (!NILP (w->hchild))
-	set_window_update_flags (XWINDOW (w->hchild), on_p);
-      else if (!NILP (w->vchild))
-	set_window_update_flags (XWINDOW (w->vchild), on_p);
+      if (WINDOWP (w->object))
+	set_window_update_flags (XWINDOW (w->object), on_p);
       else
 	w->must_be_updated_p = on_p;
 
@@ -5117,7 +5081,7 @@
 
   /* We used to set current_buffer directly here, but that does the
      wrong thing with `face-remapping-alist' (bug#2044).  */
-  Fset_buffer (w->buffer);
+  Fset_buffer (w->object);
   itdata = bidi_shelve_cache ();
   SET_TEXT_POS_FROM_MARKER (startp, w->start);
   CHARPOS (startp) = min (ZV, max (BEGV, CHARPOS (startp)));
@@ -5163,7 +5127,7 @@
   *dx = x0 + it.first_visible_x - it.current_x;
   *dy = *y - it.current_y;
 
-  string =  w->buffer;
+  string = w->object;
   if (STRINGP (it.string))
     string = it.string;
   *pos = it.current;
@@ -5181,7 +5145,7 @@
       if (STRINGP (it.string))
 	BYTEPOS (pos->pos) = string_char_to_byte (string, CHARPOS (pos->pos));
       else
-	BYTEPOS (pos->pos) = buf_charpos_to_bytepos (XBUFFER (w->buffer),
+	BYTEPOS (pos->pos) = buf_charpos_to_bytepos (XBUFFER (w->object),
 						     CHARPOS (pos->pos));
     }
 

=== modified file 'src/editfns.c'
--- src/editfns.c	2013-03-08 09:34:35 +0000
+++ src/editfns.c	2013-03-21 05:05:23 +0000
@@ -373,7 +373,7 @@
   if (NILP (object))
     XSETBUFFER (object, current_buffer);
   else if (WINDOWP (object))
-    object = XWINDOW (object)->buffer;
+    object = XWINDOW (object)->object;
 
   if (!BUFFERP (object))
     /* pos-property only makes sense in buffers right now, since strings
@@ -846,7 +846,7 @@
       ? Fcopy_marker (BVAR (current_buffer, mark), Qnil)
       : Qnil),
      /* Selected window if current buffer is shown in it, nil otherwise.  */
-     ((XBUFFER (XWINDOW (selected_window)->buffer) == current_buffer)
+     ((XBUFFER (XWINDOW (selected_window)->object) == current_buffer)
       ? selected_window : Qnil),
      BVAR (current_buffer, mark_active));
 }
@@ -915,7 +915,7 @@
   tem = XSAVE_OBJECT (info, 2);
   if (WINDOWP (tem)
       && !EQ (tem, selected_window)
-      && (tem1 = XWINDOW (tem)->buffer,
+      && (tem1 = XWINDOW (tem)->object,
 	  (/* Window is live...  */
 	   BUFFERP (tem1)
 	   /* ...and it shows the current buffer.  */

=== modified file 'src/fileio.c'
--- src/fileio.c	2013-03-13 18:42:22 +0000
+++ src/fileio.c	2013-03-21 05:05:23 +0000
@@ -3958,7 +3958,7 @@
 
 	  /* If display currently starts at beginning of line,
 	     keep it that way.  */
-	  if (XBUFFER (XWINDOW (selected_window)->buffer) == current_buffer)
+	  if (XBUFFER (XWINDOW (selected_window)->object) == current_buffer)
 	    XWINDOW (selected_window)->start_at_line_beg = !NILP (Fbolp ());
 
 	  replace_handled = 1;
@@ -4108,7 +4108,7 @@
 
       /* If display currently starts at beginning of line,
 	 keep it that way.  */
-      if (XBUFFER (XWINDOW (selected_window)->buffer) == current_buffer)
+      if (XBUFFER (XWINDOW (selected_window)->object) == current_buffer)
 	XWINDOW (selected_window)->start_at_line_beg = !NILP (Fbolp ());
 
       /* Replace the chars that we need to replace,

=== modified file 'src/font.c'
--- src/font.c	2013-03-20 09:56:19 +0000
+++ src/font.c	2013-03-21 05:05:23 +0000
@@ -4761,7 +4761,7 @@
 
   if (NILP (string))
     {
-      if (XBUFFER (w->buffer) != current_buffer)
+      if (XBUFFER (w->object) != current_buffer)
 	error ("Specified window is not displaying the current buffer.");
       CHECK_NUMBER_COERCE_MARKER (position);
       if (! (BEGV <= XINT (position) && XINT (position) < ZV))

=== modified file 'src/frame.c'
--- src/frame.c	2013-03-20 11:29:37 +0000
+++ src/frame.c	2013-03-21 05:39:37 +0000
@@ -159,15 +159,15 @@
   w->total_lines -= n;
 
   /* Handle just the top child in a vertical split.  */
-  if (!NILP (w->vchild))
-    set_menu_bar_lines_1 (w->vchild, n);
-
-  /* Adjust all children in a horizontal split.  */
-  for (window = w->hchild; !NILP (window); window = w->next)
-    {
-      w = XWINDOW (window);
-      set_menu_bar_lines_1 (window, n);
-    }
+  if (w->type == WINDOW_VERTICAL_COMBINATION)
+    set_menu_bar_lines_1 (w->object, n);
+  else if (w->type == WINDOW_HORIZONTAL_COMBINATION)
+    /* Adjust all children in a horizontal split.  */
+    for (window = w->object; !NILP (window); window = w->next)
+      {
+	w = XWINDOW (window);
+	set_menu_bar_lines_1 (window, n);
+      }
 }
 
 void
@@ -421,7 +421,7 @@
 
   /* Make the chosen minibuffer window display the proper minibuffer,
      unless it is already showing a minibuffer.  */
-  if (NILP (Fmemq (XWINDOW (mini_window)->buffer, Vminibuffer_list)))
+  if (NILP (Fmemq (XWINDOW (mini_window)->object, Vminibuffer_list)))
     /* Use set_window_buffer instead of Fset_window_buffer (see
        discussion of bug#11984, bug#12025, bug#12026).  */
     set_window_buffer (mini_window,
@@ -1189,7 +1189,7 @@
       /* Use set_window_buffer instead of Fset_window_buffer (see
 	 discussion of bug#11984, bug#12025, bug#12026).  */
       set_window_buffer (sf->minibuffer_window,
-			 XWINDOW (minibuf_window)->buffer, 0, 0);
+			 XWINDOW (minibuf_window)->object, 0, 0);
       minibuf_window = sf->minibuffer_window;
 
       /* If the dying minibuffer window was selected,
@@ -1593,17 +1593,13 @@
 {
   struct window *w;
 
-  for (;!NILP (window); window = w->next)
+  for (; !NILP (window); window = w->next)
     {
       w = XWINDOW (window);
-
-      if (!NILP (w->buffer))
-	bset_display_time (XBUFFER (w->buffer), Fcurrent_time ());
-
-      if (!NILP (w->vchild))
-	make_frame_visible_1 (w->vchild);
-      if (!NILP (w->hchild))
-	make_frame_visible_1 (w->hchild);
+      if (WINDOWP (w->object))
+	make_frame_visible_1 (w->object);
+      else
+	bset_display_time (XBUFFER (w->object), Fcurrent_time ());
     }
 }
 
@@ -1634,7 +1630,7 @@
       /* Use set_window_buffer instead of Fset_window_buffer (see
 	 discussion of bug#11984, bug#12025, bug#12026).  */
       set_window_buffer (sf->minibuffer_window,
-			 XWINDOW (minibuf_window)->buffer, 0, 0);
+			 XWINDOW (minibuf_window)->object, 0, 0);
       minibuf_window = sf->minibuffer_window;
     }
 
@@ -1665,7 +1661,7 @@
       /* Use set_window_buffer instead of Fset_window_buffer (see
 	 discussion of bug#11984, bug#12025, bug#12026).  */
       set_window_buffer (sf->minibuffer_window,
-			 XWINDOW (minibuf_window)->buffer, 0, 0);
+			 XWINDOW (minibuf_window)->object, 0, 0);
       minibuf_window = sf->minibuffer_window;
     }
 

=== modified file 'src/fringe.c'
--- src/fringe.c	2013-01-02 16:13:04 +0000
+++ src/fringe.c	2013-03-21 05:05:23 +0000
@@ -699,7 +699,7 @@
 {
   Lisp_Object cmap, bm = Qnil;
 
-  if ((cmap = BVAR (XBUFFER (w->buffer), fringe_cursor_alist)), !NILP (cmap))
+  if ((cmap = BVAR (XBUFFER (w->object), fringe_cursor_alist)), !NILP (cmap))
     {
       bm = Fassq (cursor, cmap);
       if (CONSP (bm))
@@ -736,7 +736,7 @@
      If partial, lookup partial bitmap in default value if not found here.
      If not partial, or no partial spec is present, use non-partial bitmap.  */
 
-  if ((cmap = BVAR (XBUFFER (w->buffer), fringe_indicator_alist)), !NILP (cmap))
+  if ((cmap = BVAR (XBUFFER (w->object), fringe_indicator_alist)), !NILP (cmap))
     {
       bm1 = Fassq (bitmap, cmap);
       if (CONSP (bm1))
@@ -963,7 +963,7 @@
     return 0;
 
   if (!MINI_WINDOW_P (w)
-      && (ind = BVAR (XBUFFER (w->buffer), indicate_buffer_boundaries), !NILP (ind)))
+      && (ind = BVAR (XBUFFER (w->object), indicate_buffer_boundaries), !NILP (ind)))
     {
       if (EQ (ind, Qleft) || EQ (ind, Qright))
 	boundary_top = boundary_bot = arrow_top = arrow_bot = ind;
@@ -1004,7 +1004,7 @@
 	    {
 	      if (top_ind_rn < 0 && row->visible_height > 0)
 		{
-		  if (MATRIX_ROW_START_CHARPOS (row) <= BUF_BEGV (XBUFFER (w->buffer))
+		  if (MATRIX_ROW_START_CHARPOS (row) <= BUF_BEGV (XBUFFER (w->object))
 		      && !MATRIX_ROW_PARTIALLY_VISIBLE_AT_TOP_P (w, row))
 		    row->indicate_bob_p = !NILP (boundary_top);
 		  else
@@ -1014,7 +1014,7 @@
 
 	      if (bot_ind_rn < 0)
 		{
-		  if (MATRIX_ROW_END_CHARPOS (row) >= BUF_ZV (XBUFFER (w->buffer))
+		  if (MATRIX_ROW_END_CHARPOS (row) >= BUF_ZV (XBUFFER (w->object))
 		      && !MATRIX_ROW_PARTIALLY_VISIBLE_AT_BOTTOM_P (w, row))
 		    row->indicate_eob_p = !NILP (boundary_bot), bot_ind_rn = rn;
 		  else if (y + row->height >= yb)
@@ -1024,7 +1024,7 @@
 	}
     }
 
-  empty_pos = BVAR (XBUFFER (w->buffer), indicate_empty_lines);
+  empty_pos = BVAR (XBUFFER (w->object), indicate_empty_lines);
   if (!NILP (empty_pos) && !EQ (empty_pos, Qright))
     empty_pos = WINDOW_LEFT_FRINGE_WIDTH (w) == 0 ? Qright : Qleft;
 

=== modified file 'src/indent.c'
--- src/indent.c	2013-03-08 09:34:35 +0000
+++ src/indent.c	2013-03-21 05:05:23 +0000
@@ -254,7 +254,7 @@
      the next property change */
   prop = Fget_char_property (position, Qinvisible,
 			     (!NILP (window)
-			      && EQ (XWINDOW (window)->buffer, buffer))
+			      && EQ (XWINDOW (window)->object, buffer))
 			     ? window : buffer);
   inv_p = TEXT_PROP_MEANS_INVISIBLE (prop);
   /* When counting columns (window == nil), don't skip over ellipsis text.  */
@@ -1826,7 +1826,7 @@
 
   /* If the window contains this buffer, use it for getting text properties.
      Otherwise use the current buffer as arg for doing that.  */
-  if (EQ (w->buffer, Fcurrent_buffer ()))
+  if (EQ (w->object, Fcurrent_buffer ()))
     text_prop_object = window;
   else
     text_prop_object = Fcurrent_buffer ();
@@ -1979,14 +1979,14 @@
 
   old_buffer = Qnil;
   GCPRO1 (old_buffer);
-  if (XBUFFER (w->buffer) != current_buffer)
+  if (XBUFFER (w->object) != current_buffer)
     {
       /* Set the window's buffer temporarily to the current buffer.  */
-      old_buffer = w->buffer;
+      old_buffer = w->object;
       old_charpos = marker_position (w->pointm);
       old_bytepos = marker_byte_position (w->pointm);
       wset_buffer (w, Fcurrent_buffer ());
-      set_marker_both (w->pointm, w->buffer,
+      set_marker_both (w->pointm, w->object,
 		       BUF_PT (current_buffer), BUF_PT_BYTE (current_buffer));
     }
 
@@ -2139,7 +2139,7 @@
   if (BUFFERP (old_buffer))
     {
       wset_buffer (w, old_buffer);
-      set_marker_both (w->pointm, w->buffer,
+      set_marker_both (w->pointm, w->object,
 		       old_charpos, old_bytepos);
     }
 

=== modified file 'src/insdel.c'
--- src/insdel.c	2013-03-15 16:03:54 +0000
+++ src/insdel.c	2013-03-21 05:05:23 +0000
@@ -1798,7 +1798,7 @@
 
   /* If we're modifying the buffer other than shown in a selected window,
      let redisplay consider other windows if this buffer is visible.  */
-  if (XBUFFER (XWINDOW (selected_window)->buffer) != current_buffer
+  if (XBUFFER (XWINDOW (selected_window)->object) != current_buffer
       && buffer_window_count (current_buffer))
     ++windows_or_buffers_changed;
 

=== modified file 'src/keyboard.c'
--- src/keyboard.c	2013-03-13 07:27:34 +0000
+++ src/keyboard.c	2013-03-21 05:05:23 +0000
@@ -833,7 +833,7 @@
   update_mode_lines = 1;
 
   if (command_loop_level
-      && current_buffer != XBUFFER (XWINDOW (selected_window)->buffer))
+      && current_buffer != XBUFFER (XWINDOW (selected_window)->object))
     buffer = Fcurrent_buffer ();
   else
     buffer = Qnil;
@@ -1395,7 +1395,7 @@
 	Fkill_emacs (Qnil);
 
       /* Make sure the current window's buffer is selected.  */
-      set_buffer_internal (XBUFFER (XWINDOW (selected_window)->buffer));
+      set_buffer_internal (XBUFFER (XWINDOW (selected_window)->object));
 
       /* Display any malloc warning that just came out.  Use while because
 	 displaying one warning can cause another.  */
@@ -1461,7 +1461,7 @@
       /* A filter may have run while we were reading the input.  */
       if (! FRAME_LIVE_P (XFRAME (selected_frame)))
 	Fkill_emacs (Qnil);
-      set_buffer_internal (XBUFFER (XWINDOW (selected_window)->buffer));
+      set_buffer_internal (XBUFFER (XWINDOW (selected_window)->object));
 
       ++num_input_keys;
 
@@ -1492,7 +1492,7 @@
 	{
 	  struct buffer *b;
 	  XWINDOW (selected_window)->force_start = 0;
-	  b = XBUFFER (XWINDOW (selected_window)->buffer);
+	  b = XBUFFER (XWINDOW (selected_window)->object);
 	  BUF_BEG_UNCHANGED (b) = BUF_END_UNCHANGED (b) = 0;
 	}
 
@@ -5142,7 +5142,7 @@
 	  if (STRINGP (string))
 	    string_info = Fcons (string, make_number (charpos));
 	  textpos = (w == XWINDOW (selected_window)
-		     && current_buffer == XBUFFER (w->buffer))
+		     && current_buffer == XBUFFER (w->object))
 	    ? PT : marker_position (w->pointm);
 
 	  xret = wx;
@@ -9146,9 +9146,9 @@
 		{
 		  if (! FRAME_LIVE_P (XFRAME (selected_frame)))
 		    Fkill_emacs (Qnil);
-		  if (XBUFFER (XWINDOW (selected_window)->buffer)
+		  if (XBUFFER (XWINDOW (selected_window)->object)
 		      != current_buffer)
-		    Fset_buffer (XWINDOW (selected_window)->buffer);
+		    Fset_buffer (XWINDOW (selected_window)->object);
 		}
 
 	      goto replay_sequence;
@@ -9196,9 +9196,9 @@
 		 special-event-map, ...) might have switched the current buffer
 		 or the selected window from under us in the mean time.  */
 	      if (fix_current_buffer
-		  && (XBUFFER (XWINDOW (selected_window)->buffer)
+		  && (XBUFFER (XWINDOW (selected_window)->object)
 		      != current_buffer))
-		Fset_buffer (XWINDOW (selected_window)->buffer);
+		Fset_buffer (XWINDOW (selected_window)->object);
 	      current_binding = active_maps (first_event);
 	    }
 
@@ -9247,8 +9247,8 @@
 		     not the current buffer.  If we're at the
 		     beginning of a key sequence, switch buffers.  */
 		  if (WINDOWP (window)
-		      && BUFFERP (XWINDOW (window)->buffer)
-		      && XBUFFER (XWINDOW (window)->buffer) != current_buffer)
+		      && BUFFERP (XWINDOW (window)->object)
+		      && XBUFFER (XWINDOW (window)->object) != current_buffer)
 		    {
 		      ASET (raw_keybuf, raw_keybuf_count, key);
 		      raw_keybuf_count++;
@@ -9269,7 +9269,7 @@
 
 		      if (! FRAME_LIVE_P (XFRAME (selected_frame)))
 			Fkill_emacs (Qnil);
-		      set_buffer_internal (XBUFFER (XWINDOW (window)->buffer));
+		      set_buffer_internal (XBUFFER (XWINDOW (window)->object));
 		      goto replay_sequence;
 		    }
 		}

=== modified file 'src/keymap.c'
--- src/keymap.c	2013-03-13 07:27:34 +0000
+++ src/keymap.c	2013-03-21 05:05:23 +0000
@@ -1555,8 +1555,8 @@
       window = POSN_WINDOW (position);
 
       if (WINDOWP (window)
-	  && BUFFERP (XWINDOW (window)->buffer)
-	  && XBUFFER (XWINDOW (window)->buffer) != current_buffer)
+	  && BUFFERP (XWINDOW (window)->object)
+	  && XBUFFER (XWINDOW (window)->object) != current_buffer)
 	{
 	  /* Arrange to go back to the original buffer once we're done
 	     processing the key sequence.  We don't use
@@ -1566,7 +1566,7 @@
 	     things the same.
 	  */
 	  record_unwind_current_buffer ();
-	  set_buffer_internal (XBUFFER (XWINDOW (window)->buffer));
+	  set_buffer_internal (XBUFFER (XWINDOW (window)->object));
 	}
     }
 

=== modified file 'src/minibuf.c'
--- src/minibuf.c	2013-01-02 16:13:04 +0000
+++ src/minibuf.c	2013-03-21 05:05:23 +0000
@@ -114,7 +114,7 @@
       /* Under X, we come here with minibuf_window being the
 	 minibuffer window of the unused termcap window created in
 	 init_window_once.  That window doesn't have a buffer.  */
-      buffer = XWINDOW (minibuf_window)->buffer;
+      buffer = XWINDOW (minibuf_window)->object;
       if (BUFFERP (buffer))
 	/* Use set_window_buffer instead of Fset_window_buffer (see
 	   discussion of bug#11984, bug#12025, bug#12026).  */
@@ -844,7 +844,7 @@
   window = minibuf_window;
   /* To keep things predictable, in case it matters, let's be in the
      minibuffer when we reset the relevant variables.  */
-  Fset_buffer (XWINDOW (window)->buffer);
+  Fset_buffer (XWINDOW (window)->object);
 
   /* Restore prompt, etc, from outer minibuffer level.  */
   minibuf_prompt = Fcar (minibuf_save_list);

=== modified file 'src/msdos.c'
--- src/msdos.c	2013-03-06 16:21:26 +0000
+++ src/msdos.c	2013-03-21 05:05:23 +0000
@@ -1261,7 +1261,7 @@
 	  /* If the mouse highlight is in the window that was deleted
 	     (e.g., if it was popped by completion), clear highlight
 	     unconditionally.  */
-	  if (NILP (w->buffer))
+	  if (NILP (w->object))
 	    hlinfo->mouse_face_window = Qnil;
 	  else
 	    {
@@ -1271,7 +1271,7 @@
 		  break;
 	    }
 
-	  if (NILP (w->buffer) || i < w->desired_matrix->nrows)
+	  if (NILP (w->object) || i < w->desired_matrix->nrows)
 	    clear_mouse_face (hlinfo);
 	}
     }
@@ -1321,7 +1321,7 @@
     new_cursor = frame_desired_cursor;
   else
     {
-      struct buffer *b = XBUFFER (sw->buffer);
+      struct buffer *b = XBUFFER (sw->object);
 
       if (EQ (BVAR (b,cursor_type), Qt))
 	new_cursor = frame_desired_cursor;

=== modified file 'src/nsfns.m'
--- src/nsfns.m	2013-03-20 09:56:19 +0000
+++ src/nsfns.m	2013-03-21 05:05:23 +0000
@@ -619,7 +619,7 @@
 {
   NSView *view;
   Lisp_Object name, filename;
-  Lisp_Object buf = XWINDOW (f->selected_window)->buffer;
+  Lisp_Object buf = XWINDOW (f->selected_window)->object;
   const char *title;
   NSAutoreleasePool *pool;
   struct gcpro gcpro1;

=== modified file 'src/nsmenu.m'
--- src/nsmenu.m	2013-02-05 12:16:35 +0000
+++ src/nsmenu.m	2013-03-21 05:05:23 +0000
@@ -191,7 +191,7 @@
 	= alloca (previous_menu_items_used * sizeof *previous_items);
 
       /* lisp preliminaries */
-      buffer = XWINDOW (FRAME_SELECTED_WINDOW (f))->buffer;
+      buffer = XWINDOW (FRAME_SELECTED_WINDOW (f))->object;
       specbind (Qinhibit_quit, Qt);
       specbind (Qdebug_on_next_call, Qnil);
       record_unwind_save_match_data ();

=== modified file 'src/nsterm.m'
--- src/nsterm.m	2013-03-16 14:22:37 +0000
+++ src/nsterm.m	2013-03-21 05:05:23 +0000
@@ -6532,7 +6532,7 @@
 {
   Lisp_Object str = Qnil;
   struct frame *f = SELECTED_FRAME ();
-  struct buffer *curbuf = XBUFFER (XWINDOW (f->selected_window)->buffer);
+  struct buffer *curbuf = XBUFFER (XWINDOW (f->selected_window)->object);
 
   if ([attribute isEqualToString:NSAccessibilityRoleAttribute])
     return NSAccessibilityTextFieldRole;

=== modified file 'src/print.c'
--- src/print.c	2013-03-19 14:09:05 +0000
+++ src/print.c	2013-03-21 05:05:23 +0000
@@ -1769,10 +1769,10 @@
 	  strout ("#<window ", -1, -1, printcharfun);
 	  len = sprintf (buf, "%p", XWINDOW (obj));
 	  strout (buf, len, len, printcharfun);
-	  if (!NILP (XWINDOW (obj)->buffer))
+	  if (!NILP (XWINDOW (obj)->object))
 	    {
 	      strout (" on ", -1, -1, printcharfun);
-	      print_string (BVAR (XBUFFER (XWINDOW (obj)->buffer), name),
+	      print_string (BVAR (XBUFFER (XWINDOW (obj)->object), name),
 			    printcharfun);
 	    }
 	  PRINTCHAR ('>');

=== modified file 'src/textprop.c'
--- src/textprop.c	2013-03-11 01:17:40 +0000
+++ src/textprop.c	2013-03-21 05:05:23 +0000
@@ -598,7 +598,7 @@
   if (WINDOWP (object))
     {
       w = XWINDOW (object);
-      object = w->buffer;
+      object = w->object;
     }
   if (BUFFERP (object))
     {

=== modified file 'src/w32fns.c'
--- src/w32fns.c	2013-03-20 11:29:37 +0000
+++ src/w32fns.c	2013-03-21 05:05:23 +0000
@@ -5798,7 +5798,7 @@
 
   /* Display the tooltip text in a temporary buffer.  */
   old_buffer = current_buffer;
-  set_buffer_internal_1 (XBUFFER (XWINDOW (FRAME_ROOT_WINDOW (f))->buffer));
+  set_buffer_internal_1 (XBUFFER (XWINDOW (FRAME_ROOT_WINDOW (f))->object));
   bset_truncate_lines (current_buffer, Qnil);
   clear_glyph_matrix (w->desired_matrix);
   clear_glyph_matrix (w->current_matrix);

=== modified file 'src/w32menu.c'
--- src/w32menu.c	2013-01-02 16:13:04 +0000
+++ src/w32menu.c	2013-03-21 05:05:23 +0000
@@ -396,7 +396,7 @@
       if (! menubar_widget)
 	previous_menu_items_used = 0;
 
-      buffer = XWINDOW (FRAME_SELECTED_WINDOW (f))->buffer;
+      buffer = XWINDOW (FRAME_SELECTED_WINDOW (f))->object;
       specbind (Qinhibit_quit, Qt);
       /* Don't let the debugger step into this code
 	 because it is not reentrant.  */

=== modified file 'src/window.c'
--- src/window.c	2013-03-20 11:29:37 +0000
+++ src/window.c	2013-03-21 08:52:45 +0000
@@ -147,11 +147,6 @@
   w->display_table = val;
 }
 static void
-wset_hchild (struct window *w, Lisp_Object val)
-{
-  w->hchild = val;
-}
-static void
 wset_left_fringe_width (struct window *w, Lisp_Object val)
 {
   w->left_fringe_width = val;
@@ -217,11 +212,6 @@
   w->temslot = val;
 }
 static void
-wset_vchild (struct window *w, Lisp_Object val)
-{
-  w->vchild = val;
-}
-static void
 wset_vertical_scroll_bar_type (struct window *w, Lisp_Object val)
 {
   w->vertical_scroll_bar_type = val;
@@ -231,6 +221,14 @@
 {
   w->window_parameters = val;
 }
+static void
+wset_combination (struct window *w, bool horflag, Lisp_Object val)
+{
+  w->type = (horflag 
+	     ? WINDOW_HORIZONTAL_COMBINATION
+	     : WINDOW_VERTICAL_COMBINATION);
+  w->object = val;
+}
 
 struct window *
 decode_live_window (register Lisp_Object window)
@@ -275,9 +273,9 @@
 adjust_window_count (struct window *w, int arg)
 {
   eassert (eabs (arg) == 1);
-  if (BUFFERP (w->buffer))
+  if (BUFFERP (w->object))
     {
-      struct buffer *b = XBUFFER (w->buffer);
+      struct buffer *b = XBUFFER (w->object);
 
       if (b->base_buffer)
 	b = b->base_buffer;
@@ -296,7 +294,7 @@
 wset_buffer (struct window *w, Lisp_Object val)
 {
   adjust_window_count (w, -1);
-  w->buffer = val;
+  w->object = val;
   adjust_window_count (w, 1);
 }
 
@@ -394,15 +392,8 @@
       window = XFRAME (frame_or_window)->root_window;
     }
 
-  while (NILP (XWINDOW (window)->buffer))
-    {
-      if (! NILP (XWINDOW (window)->hchild))
-	window = XWINDOW (window)->hchild;
-      else if (! NILP (XWINDOW (window)->vchild))
-	window = XWINDOW (window)->vchild;
-      else
-	emacs_abort ();
-    }
+  while (WINDOWP (XWINDOW (window)->object))
+    window = XWINDOW (window)->object;
 
   return window;
 }
@@ -489,11 +480,11 @@
   if (NILP (norecord))
     {
       w->use_time = ++window_select_count;
-      record_buffer (w->buffer);
+      record_buffer (w->object);
     }
 
   /* Make the selected window's buffer current.  */
-  Fset_buffer (w->buffer);
+  Fset_buffer (w->object);
 
   if (EQ (window, selected_window) && !inhibit_point_swap)
     return window;
@@ -516,7 +507,7 @@
 
   select_window_1 (window, inhibit_point_swap);
 
-  bset_last_selected_window (XBUFFER (w->buffer), window);
+  bset_last_selected_window (XBUFFER (w->object), window);
   windows_or_buffers_changed++;
   return window;
 }
@@ -533,10 +524,10 @@
   if (!inhibit_point_swap)
     {
       struct window *ow = XWINDOW (selected_window);
-      if (! NILP (ow->buffer))
-	set_marker_both (ow->pointm, ow->buffer,
-			 BUF_PT (XBUFFER (ow->buffer)),
-			 BUF_PT_BYTE (XBUFFER (ow->buffer)));
+      if (BUFFERP (ow->object))
+	set_marker_both (ow->pointm, ow->object,
+			 BUF_PT (XBUFFER (ow->object)),
+			 BUF_PT_BYTE (XBUFFER (ow->object)));
     }
 
   selected_window = window;
@@ -581,7 +572,7 @@
 Return nil for an internal window or a deleted window.  */)
   (Lisp_Object window)
 {
-  return decode_any_window (window)->buffer;
+  return decode_any_window (window)->object;
 }
 
 DEFUN ("window-parent", Fwindow_parent, Swindow_parent, 0, 1, 0,
@@ -601,7 +592,8 @@
 horizontal combination.  */)
   (Lisp_Object window)
 {
-  return decode_valid_window (window)->vchild;
+  struct window *w = decode_valid_window (window);
+  return w->type == WINDOW_VERTICAL_COMBINATION ? w->object : Qnil;
 }
 
 DEFUN ("window-left-child", Fwindow_left_child, Swindow_left_child, 0, 1, 0,
@@ -612,7 +604,8 @@
 vertical combination.  */)
   (Lisp_Object window)
 {
-  return decode_valid_window (window)->hchild;
+  struct window *w = decode_valid_window (window);
+  return w->type == WINDOW_HORIZONTAL_COMBINATION ? w->object : Qnil;
 }
 
 DEFUN ("window-next-sibling", Fwindow_next_sibling, Swindow_next_sibling, 0, 1, 0,
@@ -645,7 +638,7 @@
 
   CHECK_VALID_WINDOW (window);
   w = XWINDOW (window);
-  if (!NILP (w->buffer))
+  if (w->type == WINDOW_LEAF)
     error ("Combination limit is meaningful for internal windows only");
   return XWINDOW (window)->combination_limit;
 }
@@ -663,7 +656,7 @@
 
   CHECK_VALID_WINDOW (window);
   w = XWINDOW (window);
-  if (!NILP (w->buffer))
+  if (w->type == WINDOW_LEAF)
     error ("Combination limit is meaningful for internal windows only");
   wset_combination_limit (w, limit);
   return limit;
@@ -860,7 +853,7 @@
 
   /* Prevent redisplay shortcuts when changing the hscroll.  */
   if (w->hscroll != new_hscroll)
-    XBUFFER (w->buffer)->prevent_redisplay_optimizations_p = 1;
+    XBUFFER (w->object)->prevent_redisplay_optimizations_p = 1;
 
   w->hscroll = new_hscroll;
   return make_number (new_hscroll);
@@ -1441,7 +1434,7 @@
   register struct window *w = decode_live_window (window);
 
   if (w == XWINDOW (selected_window))
-    return make_number (BUF_PT (XBUFFER (w->buffer)));
+    return make_number (BUF_PT (XBUFFER (w->object)));
   else
     return Fmarker_position (w->pointm);
 }
@@ -1483,7 +1476,7 @@
   Lisp_Object buf;
   struct buffer *b;
 
-  buf = w->buffer;
+  buf = w->object;
   CHECK_BUFFER (buf);
   b = XBUFFER (buf);
 
@@ -1546,7 +1539,7 @@
 
   if (w == XWINDOW (selected_window))
     {
-      if (XBUFFER (w->buffer) == current_buffer)
+      if (XBUFFER (w->object) == current_buffer)
 	Fgoto_char (pos);
       else
 	{
@@ -1554,14 +1547,14 @@
 
 	  /* ... but here we want to catch type error before buffer change.  */
 	  CHECK_NUMBER_COERCE_MARKER (pos);
-	  set_buffer_internal (XBUFFER (w->buffer));
+	  set_buffer_internal (XBUFFER (w->object));
 	  Fgoto_char (pos);
 	  set_buffer_internal (old_buffer);
 	}
     }
   else
     {
-      set_marker_restricted (w->pointm, pos, w->buffer);
+      set_marker_restricted (w->pointm, pos, w->object);
       /* We have to make sure that redisplay updates the window to show
 	 the new value of point.  */
       ++windows_or_buffers_changed;
@@ -1579,7 +1572,7 @@
 {
   register struct window *w = decode_live_window (window);
 
-  set_marker_restricted (w->start, pos, w->buffer);
+  set_marker_restricted (w->start, pos, w->object);
   /* This is not right, but much easier than doing what is right.  */
   w->start_at_line_beg = 0;
   if (NILP (noforce))
@@ -1623,7 +1616,7 @@
   int x, y;
 
   w = decode_live_window (window);
-  buf = XBUFFER (w->buffer);
+  buf = XBUFFER (w->object);
   SET_TEXT_POS_FROM_MARKER (top, w->start);
 
   if (EQ (pos, Qt))
@@ -1692,8 +1685,8 @@
   if (noninteractive || w->pseudo_window_p)
     return Qnil;
 
-  CHECK_BUFFER (w->buffer);
-  b = XBUFFER (w->buffer);
+  CHECK_BUFFER (w->object);
+  b = XBUFFER (w->object);
 
   /* Fail if current matrix is not up-to-date.  */
   if (!w->window_end_valid
@@ -1919,9 +1912,9 @@
 
   if (DISP_TABLE_P (w->display_table))
     dp = XCHAR_TABLE (w->display_table);
-  else if (BUFFERP (w->buffer))
+  else if (BUFFERP (w->object))
     {
-      struct buffer *b = XBUFFER (w->buffer);
+      struct buffer *b = XBUFFER (w->object);
 
       if (DISP_TABLE_P (BVAR (b, display_table)))
 	dp = XCHAR_TABLE (BVAR (b, display_table));
@@ -1949,14 +1942,14 @@
   Lisp_Object buf;
   struct buffer *b;
 
-  buf = w->buffer;
+  buf = w->object;
   b = XBUFFER (buf);
   if (b != XMARKER (w->pointm)->buffer)
     emacs_abort ();
 
 #if 0
   if (w == XWINDOW (selected_window)
-      || ! EQ (buf, XWINDOW (selected_window)->buffer))
+      || ! EQ (buf, XWINDOW (selected_window)->object))
     /* Do this except when the selected window's buffer
        is being removed from some other window.  */
 #endif
@@ -1972,14 +1965,14 @@
   /* Point in the selected window's buffer
      is actually stored in that buffer, and the window's pointm isn't used.
      So don't clobber point in that buffer.  */
-  if (! EQ (buf, XWINDOW (selected_window)->buffer)
+  if (! EQ (buf, XWINDOW (selected_window)->object)
       /* Don't clobber point in current buffer either (this could be
 	 useful in connection with bug#12208).
       && XBUFFER (buf) != current_buffer  */
       /* This line helps to fix Horsley's testbug.el bug.  */
       && !(WINDOWP (BVAR (b, last_selected_window))
 	   && w != XWINDOW (BVAR (b, last_selected_window))
-	   && EQ (buf, XWINDOW (BVAR (b, last_selected_window))->buffer)))
+	   && EQ (buf, XWINDOW (BVAR (b, last_selected_window))->object)))
     temp_set_point_both (b,
 			 clip_to_bounds (BUF_BEGV (b),
 					 marker_position (w->pointm),
@@ -2046,10 +2039,8 @@
   wset_parent (n, tem);
   if (!NILP (tem))
     {
-      if (EQ (XWINDOW (tem)->vchild, old))
-	wset_vchild (XWINDOW (tem), new);
-      if (EQ (XWINDOW (tem)->hchild, old))
-	wset_hchild (XWINDOW (tem), new);
+      if (EQ (XWINDOW (tem)->object, old))
+	XWINDOW (tem)->object = new;
     }
 }
 
@@ -2069,22 +2060,18 @@
   if (!NILP (parent) && NILP (w->combination_limit))
     {
       p = XWINDOW (parent);
-      if (((!NILP (p->vchild) && !NILP (w->vchild))
-	   || (!NILP (p->hchild) && !NILP (w->hchild))))
+      if (p->type == w->type && p->type > WINDOW_LEAF)
 	/* WINDOW and PARENT are both either a vertical or a horizontal
 	   combination.  */
 	{
-	  horflag = NILP (w->vchild);
-	  child = horflag ? w->hchild : w->vchild;
+	  horflag = w->type == WINDOW_HORIZONTAL_COMBINATION;
+	  child = w->object;
 	  c = XWINDOW (child);
 
 	  /* Splice WINDOW's children into its parent's children and
 	     assign new normal sizes.  */
 	  if (NILP (w->prev))
-	    if (horflag)
-	      wset_hchild (p, child);
-	    else
-	      wset_vchild (p, child);
+	    wset_combination (p, horflag, child);
 	  else
 	    {
 	      wset_prev (c, w->prev);
@@ -2122,8 +2109,8 @@
 	    }
 
 	  /* WINDOW can be deleted now.  */
-	  wset_vchild (w, Qnil);
-	  wset_hchild (w, Qnil);
+	  eassert (w->type != WINDOW_LEAF);
+	  w->object = Qnil;
 	}
     }
 }
@@ -2209,7 +2196,7 @@
   struct frame *f = XFRAME (w->frame);
   int candidate_p = 1;
 
-  if (!BUFFERP (w->buffer))
+  if (!BUFFERP (w->object))
     candidate_p = 0;
   else if (MINI_WINDOW_P (w)
            && (EQ (minibuf, Qlambda)
@@ -2613,7 +2600,7 @@
 	switch (type)
 	  {
 	  case GET_BUFFER_WINDOW:
-	    if (EQ (w->buffer, obj)
+	    if (EQ (w->object, obj)
 		/* Don't find any minibuffer window except the one that
 		   is currently in use.  */
 		&& (MINI_WINDOW_P (w) ? EQ (window, minibuf_window) : 1))
@@ -2637,25 +2624,25 @@
 	  case REPLACE_BUFFER_IN_WINDOWS_SAFELY:
 	    /* We could simply check whether the buffer shown by window
 	       is live, and show another buffer in case it isn't.  */
-	    if (EQ (w->buffer, obj))
+	    if (EQ (w->object, obj))
 	      {
 		/* Undedicate WINDOW.  */
 		wset_dedicated (w, Qnil);
 		/* Make WINDOW show the buffer returned by
 		   other_buffer_safely, don't run any hooks.  */
 		set_window_buffer
-		  (window, other_buffer_safely (w->buffer), 0, 0);
+		  (window, other_buffer_safely (w->object), 0, 0);
 		/* If WINDOW is the selected window, make its buffer
 		   current.  But do so only if the window shows the
 		   current buffer (Bug#6454).  */
 		if (EQ (window, selected_window)
-		    && XBUFFER (w->buffer) == current_buffer)
-		  Fset_buffer (w->buffer);
+		    && XBUFFER (w->object) == current_buffer)
+		  Fset_buffer (w->object);
 	      }
 	    break;
 
 	  case REDISPLAY_BUFFER_WINDOWS:
-	    if (EQ (w->buffer, obj))
+	    if (EQ (w->object, obj))
 	      {
 		mark_window_display_accurate (window, 0);
 		w->update_mode_line = 1;
@@ -2667,8 +2654,7 @@
 
 	    /* Check for a window that has a killed buffer.  */
 	  case CHECK_ALL_WINDOWS:
-	    if (! NILP (w->buffer)
-		&& !BUFFER_LIVE_P (XBUFFER (w->buffer)))
+	    if (BUFFERP (w->object) && !BUFFER_LIVE_P (XBUFFER (w->object)))
 	      emacs_abort ();
 	    break;
 
@@ -2786,7 +2772,7 @@
   else if (MINI_WINDOW_P (w)) /* && top > 0) */
     error ("Can't expand minibuffer to full frame");
 
-  if (!NILP (w->buffer))
+  if (BUFFERP (w->object))
     {
       startpos = marker_position (w->start);
       startbyte = marker_byte_position (w->start);
@@ -2858,7 +2844,7 @@
   FRAME_WINDOW_SIZES_CHANGED (f) = 1;
   resize_failed = 0;
 
-  if (NILP (w->buffer))
+  if (w->type != WINDOW_LEAF)
     {
       /* Resize child windows vertically.  */
       XSETINT (delta, r->total_lines - w->total_lines);
@@ -2917,28 +2903,20 @@
       sibling = w->next;
       s = XWINDOW (sibling);
       wset_prev (s, Qnil);
-      if (!NILP (XWINDOW (w->parent)->vchild))
-	wset_vchild (XWINDOW (w->parent), sibling);
-      else
-	wset_hchild (XWINDOW (w->parent), sibling);
+      XWINDOW (w->parent)->object = sibling;
     }
 
   /* Delete ROOT and all child windows of ROOT.  */
-  if (!NILP (r->vchild))
-    {
-      delete_all_child_windows (r->vchild);
-      wset_vchild (r, Qnil);
-    }
-  else if (!NILP (r->hchild))
-    {
-      delete_all_child_windows (r->hchild);
-      wset_hchild (r, Qnil);
+  if (WINDOWP (r->object))
+    {
+      delete_all_child_windows (r->object);
+      r->object = Qnil;
     }
 
   replace_window (root, window, 1);
 
   /* This must become SWINDOW anyway ....... */
-  if (!NILP (w->buffer) && !resize_failed)
+  if (BUFFERP (w->object) && !resize_failed)
     {
       /* Try to minimize scrolling, by setting the window start to the
 	 point will cause the text at the old window start to be at the
@@ -2947,18 +2925,18 @@
 	 when the display is not current, due to typeahead).  */
       new_top = WINDOW_TOP_EDGE_LINE (w) - FRAME_TOP_MARGIN (XFRAME (WINDOW_FRAME (w)));
       if (new_top != top
-	  && startpos >= BUF_BEGV (XBUFFER (w->buffer))
-	  && startpos <= BUF_ZV (XBUFFER (w->buffer)))
+	  && startpos >= BUF_BEGV (XBUFFER (w->object))
+	  && startpos <= BUF_ZV (XBUFFER (w->object)))
 	{
 	  struct position pos;
 	  struct buffer *obuf = current_buffer;
 
-	  Fset_buffer (w->buffer);
+	  Fset_buffer (w->object);
 	  /* This computation used to temporarily move point, but that
 	     can have unwanted side effects due to text properties.  */
 	  pos = *vmotion (startpos, startbyte, -top, w);
 
-	  set_marker_both (w->start, w->buffer, pos.bufpos, pos.bytepos);
+	  set_marker_both (w->start, w->object, pos.bufpos, pos.bytepos);
 	  w->window_end_valid = 0;
 	  w->start_at_line_beg = (pos.bytepos == BEGV_BYTE
 				    || FETCH_BYTE (pos.bytepos - 1) == '\n');
@@ -3158,7 +3136,7 @@
   struct window *w = XWINDOW (window);
   struct buffer *b = XBUFFER (buffer);
   ptrdiff_t count = SPECPDL_INDEX ();
-  int samebuf = EQ (buffer, w->buffer);
+  int samebuf = EQ (buffer, w->object);
 
   wset_buffer (w, buffer);
 
@@ -3277,7 +3255,7 @@
   if (!BUFFER_LIVE_P (XBUFFER (buffer)))
     error ("Attempt to display deleted buffer");
 
-  tem = w->buffer;
+  tem = w->object;
   if (NILP (tem))
     error ("Window is deleted");
   else
@@ -3330,8 +3308,8 @@
       struct window *w = XWINDOW (object);
       mark_window_display_accurate (object, 0);
       w->update_mode_line = 1;
-      if (BUFFERP (w->buffer))
-	XBUFFER (w->buffer)->prevent_redisplay_optimizations_p = 1;
+      if (BUFFERP (w->object))
+	XBUFFER (w->object)->prevent_redisplay_optimizations_p = 1;
       ++update_mode_lines;
       return Qt;
     }
@@ -3400,7 +3378,7 @@
         record_unwind_protect (Fset_buffer, prev_buffer);
         record_unwind_protect (select_window_norecord, prev_window);
         Fselect_window (window, Qt);
-        Fset_buffer (w->buffer);
+        Fset_buffer (w->object);
         Frun_hooks (1, &Qtemp_buffer_show_hook);
         unbind_to (count, Qnil);
       }
@@ -3421,8 +3399,6 @@
   memcpy ((char *) p + sizeof (struct vectorlike_header),
 	  (char *) o + sizeof (struct vectorlike_header),
 	  word_size * VECSIZE (struct window));
-  /* P's buffer slot may change from nil to a buffer.  */
-  adjust_window_count (p, 1);
   XSETWINDOW (parent, p);
 
   replace_window (window, parent, 1);
@@ -3430,12 +3406,9 @@
   wset_next (o, Qnil);
   wset_prev (o, Qnil);
   wset_parent (o, parent);
-
-  wset_hchild (p, horflag ? window : Qnil);
-  wset_vchild (p, horflag ? Qnil : window);
+  wset_combination (p, horflag, window);
   wset_start (p, Qnil);
   wset_pointm (p, Qnil);
-  wset_buffer (p, Qnil);
   wset_combination_limit (p, Qnil);
   wset_window_parameters (p, Qnil);
 }
@@ -3524,10 +3497,10 @@
 {
   struct window *c;
 
-  if (!NILP (w->vchild))
+  if (w->type == WINDOW_VERTICAL_COMBINATION)
     /* W is a vertical combination.  */
     {
-      c = XWINDOW (w->vchild);
+      c = XWINDOW (w->object);
       if (horflag)
 	/* All child windows of W must have the same width as W.  */
 	{
@@ -3555,10 +3528,10 @@
 	  return (sum_of_sizes == XINT (w->new_total));
 	}
     }
-  else if (!NILP (w->hchild))
+  else if (w->type == WINDOW_HORIZONTAL_COMBINATION)
     /* W is a horizontal combination.  */
     {
-      c = XWINDOW (w->hchild);
+      c = XWINDOW (w->object);
       if (horflag)
 	/* The sum of the widths of the child windows of W must equal W's
 	   width.  */
@@ -3625,10 +3598,10 @@
       pos = w->top_line;
     }
 
-  if (!NILP (w->vchild))
+  if (w->type == WINDOW_VERTICAL_COMBINATION)
     /* W is a vertical combination.  */
     {
-      c = XWINDOW (w->vchild);
+      c = XWINDOW (w->object);
       while (c)
 	{
 	  if (horflag)
@@ -3641,10 +3614,10 @@
 	  c = NILP (c->next) ? 0 : XWINDOW (c->next);
 	}
     }
-  else if (!NILP (w->hchild))
+  else if (w->type == WINDOW_HORIZONTAL_COMBINATION)
     /* W is a horizontal combination.  */
     {
-      c = XWINDOW (w->hchild);
+      c = XWINDOW (w->object);
       while (c)
 	{
 	  if (horflag)
@@ -3727,7 +3700,7 @@
 			? 1 : 0)));
 
   r->top_line = FRAME_TOP_MARGIN (f);
-  if (NILP (r->vchild) && NILP (r->hchild))
+  if (r->type == WINDOW_LEAF)
     /* For a leaf root window just set the size.  */
     if (horflag)
       r->total_cols = new_size;
@@ -3842,9 +3815,9 @@
   combination_limit =
     EQ (Vwindow_combination_limit, Qt)
     || NILP (o->parent)
-    || NILP (horflag
-	     ? (XWINDOW (o->parent)->hchild)
-	     : (XWINDOW (o->parent)->vchild));
+    || (horflag
+	? (XWINDOW (o->parent)->type == WINDOW_VERTICAL_COMBINATION)
+	: (XWINDOW (o->parent)->type == WINDOW_HORIZONTAL_COMBINATION));
 
   /* We need a live reference window to initialize some parameters.  */
   if (WINDOW_LIVE_P (old))
@@ -3914,17 +3887,12 @@
   n = XWINDOW (new);
   wset_frame (n, frame);
   wset_parent (n, o->parent);
-  wset_vchild (n, Qnil);
-  wset_hchild (n, Qnil);
 
   if (EQ (side, Qabove) || EQ (side, Qleft))
     {
       wset_prev (n, o->prev);
       if (NILP (n->prev))
-	if (horflag)
-	  wset_hchild (p, new);
-	else
-	  wset_vchild (p, new);
+	wset_combination (p, horflag, new);
       else
 	wset_next (XWINDOW (n->prev), new);
       wset_next (n, old);
@@ -3973,7 +3941,7 @@
   adjust_glyphs (f);
   /* Set buffer of NEW to buffer of reference window.  Don't run
      any hooks.  */
-  set_window_buffer (new, r->buffer, 0, 1);
+  set_window_buffer (new, r->object, 0, 1);
   unblock_input ();
 
   /* Maybe we should run the scroll functions in Elisp (which already
@@ -4000,8 +3968,7 @@
 
   w = decode_any_window (window);
   XSETWINDOW (window, w);
-  if (NILP (w->buffer)
-      && NILP (w->hchild) && NILP (w->vchild))
+  if (NILP (w->object))
     /* It's a no-op to delete an already deleted window.  */
     return Qnil;
 
@@ -4015,7 +3982,7 @@
     error ("Attempt to delete sole window of parent");
 
   p = XWINDOW (parent);
-  horflag = NILP (p->vchild);
+  horflag = p->type == WINDOW_HORIZONTAL_COMBINATION;
 
   frame = WINDOW_FRAME (w);
   f = XFRAME (frame);
@@ -4033,10 +4000,7 @@
       sibling = w->next;
       s = XWINDOW (sibling);
       wset_prev (s, Qnil);
-      if (horflag)
-	wset_hchild (p, sibling);
-      else
-	wset_vchild (p, sibling);
+      wset_combination (p, horflag, sibling);
     }
   else
     /* Get SIBLING above (on the left of) WINDOW.  */
@@ -4075,17 +4039,12 @@
       wset_next (w, Qnil);  /* Don't delete w->next too.  */
       free_window_matrices (w);
 
-      if (!NILP (w->vchild))
-	{
-	  delete_all_child_windows (w->vchild);
-	  wset_vchild (w, Qnil);
-	}
-      else if (!NILP (w->hchild))
-	{
-	  delete_all_child_windows (w->hchild);
-	  wset_hchild (w, Qnil);
-	}
-      else if (!NILP (w->buffer))
+      if (WINDOWP (w->object))
+	{
+	  delete_all_child_windows (w->object);
+	  w->object = Qnil;
+	}
+      else
 	{
 	  unshow_buffer (w);
 	  unchain_marker (XMARKER (w->pointm));
@@ -4104,8 +4063,8 @@
 	  wset_normal_cols (s, p->normal_cols);
 	  wset_normal_lines (s, p->normal_lines);
 	  /* Mark PARENT as deleted.  */
-	  wset_vchild (p, Qnil);
-	  wset_hchild (p, Qnil);
+	  eassert (p->type != WINDOW_LEAF);
+	  p->object = Qnil;
 	  /* Try to merge SIBLING into its new parent.  */
 	  recombine_windows (sibling);
 	}
@@ -4153,10 +4112,7 @@
       if (before_sibling)
 	{
 	  wset_prev (s, window);
-	  if (horflag)
-	    wset_hchild (p, window);
-	  else
-	    wset_vchild (p, window);
+	  wset_combination (p, horflag, window);
 	}
       else
 	{
@@ -4299,10 +4255,8 @@
 {
   while (w)
     {
-      if (!NILP (w->hchild))
-	mark_window_cursors_off (XWINDOW (w->hchild));
-      else if (!NILP (w->vchild))
-	mark_window_cursors_off (XWINDOW (w->vchild));
+      if (WINDOWP (w->object))
+	mark_window_cursors_off (XWINDOW (w->object));
       else
 	w->phys_cursor_on_p = 0;
 
@@ -4321,8 +4275,8 @@
   if (!MINI_WINDOW_P (w))
     {
       if (!NILP (w->parent)
-	  || !NILP (w->vchild)
-	  || !NILP (w->hchild)
+	  || (w->type == WINDOW_VERTICAL_COMBINATION)
+	  || (w->type == WINDOW_HORIZONTAL_COMBINATION)
 	  || !NILP (w->next)
 	  || !NILP (w->prev)
 	  || WINDOW_WANTS_MODELINE_P (w))
@@ -4461,7 +4415,7 @@
 		  else
 		    spos = min (XINT (Fline_end_position (Qnil)) + 1, ZV);
 		  set_marker_restricted (w->start, make_number (spos),
-					 w->buffer);
+					 w->object);
 		  w->start_at_line_beg = 1;
 		  w->update_mode_line = 1;
 		  w->last_modified = 0;
@@ -4585,7 +4539,7 @@
 
       /* If control gets here, then we vscrolled.  */
 
-      XBUFFER (w->buffer)->prevent_redisplay_optimizations_p = 1;
+      XBUFFER (w->object)->prevent_redisplay_optimizations_p = 1;
 
       /* Don't try to change the window start below.  */
       vscrolled = 1;
@@ -4605,7 +4559,7 @@
 	}
 
       /* Set the window start, and set up the window for redisplay.  */
-      set_marker_restricted_both (w->start, w->buffer, IT_CHARPOS (it),
+      set_marker_restricted_both (w->start, w->object, IT_CHARPOS (it),
 				  IT_BYTEPOS (it));
       bytepos = marker_byte_position (w->start);
       w->start_at_line_beg = (pos == BEGV || FETCH_BYTE (bytepos - 1) == '\n');
@@ -4805,7 +4759,7 @@
       int this_scroll_margin =
 	max (0, min (scroll_margin, w->total_lines / 4));
 
-      set_marker_restricted_both (w->start, w->buffer, pos, pos_byte);
+      set_marker_restricted_both (w->start, w->object, pos, pos_byte);
       w->start_at_line_beg = !NILP (bolp);
       w->update_mode_line = 1;
       w->last_modified = 0;
@@ -4899,10 +4853,10 @@
 
   /* If selected window's buffer isn't current, make it current for
      the moment.  But don't screw up if window_scroll gets an error.  */
-  if (XBUFFER (XWINDOW (selected_window)->buffer) != current_buffer)
+  if (XBUFFER (XWINDOW (selected_window)->object) != current_buffer)
     {
       record_unwind_protect (save_excursion_restore, save_excursion_save ());
-      Fset_buffer (XWINDOW (selected_window)->buffer);
+      Fset_buffer (XWINDOW (selected_window)->object);
 
       /* Make redisplay consider other windows than just selected_window.  */
       ++windows_or_buffers_changed;
@@ -5017,7 +4971,7 @@
   record_unwind_protect (save_excursion_restore, save_excursion_save ());
   ++windows_or_buffers_changed;
 
-  Fset_buffer (w->buffer);
+  Fset_buffer (w->object);
   SET_PT_BOTH (marker_position (w->pointm), marker_byte_position (w->pointm));
 
   if (NILP (arg))
@@ -5111,10 +5065,10 @@
   int bottom_y;
   void *itdata = NULL;
 
-  if (XBUFFER (w->buffer) != current_buffer)
+  if (XBUFFER (w->object) != current_buffer)
     {
       old_buffer = current_buffer;
-      set_buffer_internal (XBUFFER (w->buffer));
+      set_buffer_internal (XBUFFER (w->object));
     }
   else
     old_buffer = NULL;
@@ -5176,7 +5130,7 @@
   (register Lisp_Object arg)
 {
   struct window *w = XWINDOW (selected_window);
-  struct buffer *buf = XBUFFER (w->buffer);
+  struct buffer *buf = XBUFFER (w->object);
   struct buffer *obuf = current_buffer;
   int center_p = 0;
   ptrdiff_t charpos, bytepos;
@@ -5342,7 +5296,7 @@
     }
 
   /* Set the new window start.  */
-  set_marker_both (w->start, w->buffer, charpos, bytepos);
+  set_marker_both (w->start, w->object, charpos, bytepos);
   w->window_end_valid = 0;
 
   w->optional_new_start = 1;
@@ -5386,9 +5340,9 @@
   int this_scroll_margin;
 #endif
 
-  if (!(BUFFERP (w->buffer)
-	&& XBUFFER (w->buffer) == current_buffer))
-    /* This test is needed to make sure PT/PT_BYTE make sense in w->buffer
+  if (!(BUFFERP (w->object)
+	&& XBUFFER (w->object) == current_buffer))
+    /* This test is needed to make sure PT/PT_BYTE make sense in w->object
        when passed below to set_marker_both.  */
     error ("move-to-window-line called from unrelated buffer");
 
@@ -5398,7 +5352,7 @@
     {
       int height = window_internal_height (w);
       Fvertical_motion (make_number (- (height / 2)), window);
-      set_marker_both (w->start, w->buffer, PT, PT_BYTE);
+      set_marker_both (w->start, w->object, PT, PT_BYTE);
       w->start_at_line_beg = !NILP (Fbolp ());
       w->force_start = 1;
     }
@@ -5548,9 +5502,9 @@
 	   window-point of the final-selected-window to the window-point of
 	   the current-selected-window.  So we have to be careful which
 	   point of the current-buffer we copy into old_point.  */
-	if (EQ (XWINDOW (data->current_window)->buffer, new_current_buffer)
+	if (EQ (XWINDOW (data->current_window)->object, new_current_buffer)
 	    && WINDOWP (selected_window)
-	    && EQ (XWINDOW (selected_window)->buffer, new_current_buffer)
+	    && EQ (XWINDOW (selected_window)->object, new_current_buffer)
 	    && !EQ (selected_window, data->current_window))
 	  old_point = marker_position (XWINDOW (data->current_window)->pointm);
 	else
@@ -5564,7 +5518,7 @@
 	   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 (EQ (XWINDOW (data->current_window)->object, new_current_buffer)
 	    /* If current_window = selected_window, its point is in BUF_PT.  */
 	    && !EQ (selected_window, data->current_window))
 	  old_point = marker_position (XWINDOW (data->current_window)->pointm);
@@ -5606,8 +5560,8 @@
 	  p = SAVED_WINDOW_N (saved_windows, k);
 	  window = p->window;
 	  w = XWINDOW (window);
-	  if (!NILP (w->buffer)
-	      && !EQ (w->buffer, p->buffer)
+	  if (BUFFERP (w->object)
+	      && !EQ (w->object, p->buffer)
 	      && BUFFER_LIVE_P (XBUFFER (p->buffer)))
 	    /* If a window we restore gets another buffer, record the
 	       window's old buffer.  */
@@ -5640,13 +5594,13 @@
 	 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))
+      if (! NILP (XWINDOW (selected_window)->object))
 	{
 	  w = XWINDOW (selected_window);
 	  set_marker_both (w->pointm,
-			   w->buffer,
-			   BUF_PT (XBUFFER (w->buffer)),
-			   BUF_PT_BYTE (XBUFFER (w->buffer)));
+			   w->object,
+			   BUF_PT (XBUFFER (w->object)),
+			   BUF_PT_BYTE (XBUFFER (w->object)));
 	}
 
       windows_or_buffers_changed++;
@@ -5693,18 +5647,10 @@
 	    {
 	      wset_prev (w, Qnil);
 	      if (!NILP (w->parent))
-		{
-		  if (XINT (p->total_cols) == XWINDOW (w->parent)->total_cols)
-		    {
-		      wset_vchild (XWINDOW (w->parent), p->window);
-		      wset_hchild (XWINDOW (w->parent), Qnil);
-		    }
-		  else
-		    {
-		      wset_hchild (XWINDOW (w->parent), p->window);
-		      wset_vchild (XWINDOW (w->parent), Qnil);
-		    }
-		}
+		wset_combination (XWINDOW (w->parent),
+				  (XINT (p->total_cols)
+				   != XWINDOW (w->parent)->total_cols),
+				  p->window);
 	    }
 
 	  /* If we squirreled away the buffer, restore it now.  */
@@ -5753,20 +5699,16 @@
 	  w->last_modified = 0;
 	  w->last_overlay_modified = 0;
 
-	  /* Reinstall the saved buffer and pointers into it.  */
-	  if (NILP (p->buffer))
-	    /* An internal window.  */
-	    wset_buffer (w, p->buffer);
-	  else if (BUFFER_LIVE_P (XBUFFER (p->buffer)))
+	  if (BUFFERP (p->buffer) && BUFFER_LIVE_P (XBUFFER (p->buffer)))
 	    /* If saved buffer is alive, install it.  */
 	    {
 	      wset_buffer (w, p->buffer);
 	      w->start_at_line_beg = !NILP (p->start_at_line_beg);
-	      set_marker_restricted (w->start, p->start, w->buffer);
+	      set_marker_restricted (w->start, p->start, w->object);
 	      set_marker_restricted (w->pointm, p->pointm,
-				     w->buffer);
-	      Fset_marker (BVAR (XBUFFER (w->buffer), mark),
-			   p->mark, w->buffer);
+				     w->object);
+	      Fset_marker (BVAR (XBUFFER (w->object), mark),
+			   p->mark, w->object);
 
 	      /* As documented in Fcurrent_window_configuration, don't
 		 restore the location of point in the buffer which was
@@ -5775,23 +5717,21 @@
 		  && XBUFFER (p->buffer) == current_buffer)
 		Fgoto_char (w->pointm);
 	     }
-	   else if (!NILP (w->buffer)
-		    && BUFFER_LIVE_P (XBUFFER (w->buffer)))
-	     /* Keep window's old buffer; make sure the markers are
-		real.  */
-	     {
-	       /* Set window markers at start of visible range.  */
-	       if (XMARKER (w->start)->buffer == 0)
-		 set_marker_restricted_both (w->start, w->buffer, 0, 0);
-	       if (XMARKER (w->pointm)->buffer == 0)
-		 set_marker_restricted_both
-		   (w->pointm, w->buffer,
-		    BUF_PT (XBUFFER (w->buffer)),
-		    BUF_PT_BYTE (XBUFFER (w->buffer)));
-	       w->start_at_line_beg = 1;
-	     }
-	  else
-	    /* Window has no live buffer, get one.  */
+	  else if (BUFFERP (w->object) && BUFFER_LIVE_P (XBUFFER (w->object)))
+	    /* Keep window's old buffer; make sure the markers are real.  */
+	    {
+	      /* Set window markers at start of visible range.  */
+	      if (XMARKER (w->start)->buffer == 0)
+		set_marker_restricted_both (w->start, w->object, 0, 0);
+	      if (XMARKER (w->pointm)->buffer == 0)
+		set_marker_restricted_both
+		  (w->pointm, w->object,
+		   BUF_PT (XBUFFER (w->object)),
+		   BUF_PT_BYTE (XBUFFER (w->object)));
+	      w->start_at_line_beg = 1;
+	    }
+	  else if (w->type == WINDOW_LEAF)
+	    /* Leaf window has no live buffer, get one.  */
 	    {
 	      /* Get the buffer via other_buffer_safely in order to
 	      avoid showing an unimportant buffer and, if necessary, to
@@ -5800,8 +5740,8 @@
 	      wset_buffer (w, other_buffer_safely (Fcurrent_buffer ()));
 	      /* This will set the markers to beginning of visible
 		 range.  */
-	      set_marker_restricted_both (w->start, w->buffer, 0, 0);
-	      set_marker_restricted_both (w->pointm, w->buffer, 0, 0);
+	      set_marker_restricted_both (w->start, w->object, 0, 0);
+	      set_marker_restricted_both (w->pointm, w->object, 0, 0);
 	      w->start_at_line_beg = 1;
 	      if (!NILP (w->dedicated))
 		/* Record this window as dead.  */
@@ -5814,17 +5754,17 @@
       fset_root_window (f, data->root_window);
       /* Arrange *not* to restore point in the buffer that was
 	 current when the window configuration was saved.  */
-      if (EQ (XWINDOW (data->current_window)->buffer, new_current_buffer))
+      if (EQ (XWINDOW (data->current_window)->object, new_current_buffer))
 	set_marker_restricted (XWINDOW (data->current_window)->pointm,
 			       make_number (old_point),
-			       XWINDOW (data->current_window)->buffer);
+			       XWINDOW (data->current_window)->object);
 
       /* In the following call to `select-window', prevent "swapping out
 	 point" in the old selected window using the buffer that has
 	 been restored into it.  We already swapped out that point from
 	 that window's old buffer.  */
       select_window (data->current_window, Qnil, 1);
-      BVAR (XBUFFER (XWINDOW (selected_window)->buffer), last_selected_window)
+      BVAR (XBUFFER (XWINDOW (selected_window)->object), last_selected_window)
 	= selected_window;
 
       if (NILP (data->focus_frame)
@@ -5851,14 +5791,13 @@
       /* Now, free glyph matrices in windows that were not reused.  */
       for (i = n = 0; i < n_leaf_windows; ++i)
 	{
-	  if (NILP (leaf_windows[i]->buffer))
+	  if (NILP (leaf_windows[i]->object))
 	    {
 	      /* Assert it's not reused as a combination.  */
-	      eassert (NILP (leaf_windows[i]->hchild)
-		       && NILP (leaf_windows[i]->vchild));
+	      eassert (leaf_windows[i]->type == WINDOW_LEAF);
 	      free_window_matrices (leaf_windows[i]);
 	    }
-	  else if (EQ (leaf_windows[i]->buffer, new_current_buffer))
+	  else if (EQ (leaf_windows[i]->object, new_current_buffer))
 	    ++n;
 	}
 
@@ -5889,7 +5828,7 @@
       Fset_buffer (new_current_buffer);
       /* If the new current buffer doesn't appear in the selected
 	 window, go to its old point (see bug#12208).  */
-      if (!EQ (XWINDOW (data->current_window)->buffer, new_current_buffer))
+      if (!EQ (XWINDOW (data->current_window)->object, new_current_buffer))
 	Fgoto_char (make_number (old_point));
     }
 
@@ -5913,17 +5852,12 @@
     /* Delete WINDOW's siblings (we traverse postorderly).  */
     delete_all_child_windows (w->next);
 
-  if (!NILP (w->vchild))
-    {
-      delete_all_child_windows (w->vchild);
-      wset_vchild (w, Qnil);
-    }
-  else if (!NILP (w->hchild))
-    {
-      delete_all_child_windows (w->hchild);
-      wset_hchild (w, Qnil);
-    }
-  else if (!NILP (w->buffer))
+  if (WINDOWP (w->object))
+    {
+      delete_all_child_windows (w->object);
+      w->object = Qnil;
+    }
+  else if (BUFFERP (w->object))
     {
       unshow_buffer (w);
       unchain_marker (XMARKER (w->pointm));
@@ -5931,7 +5865,7 @@
       /* Since combination limit makes sense for an internal windows
 	 only, we use this slot to save the buffer for the sake of
 	 possible resurrection in Fset_window_configuration.  */
-      wset_combination_limit (w, w->buffer);
+      wset_combination_limit (w, w->object);
       wset_buffer (w, Qnil);
     }
 
@@ -5944,10 +5878,8 @@
   register int count = 1;
   if (!NILP (window->next))
     count += count_windows (XWINDOW (window->next));
-  if (!NILP (window->vchild))
-    count += count_windows (XWINDOW (window->vchild));
-  if (!NILP (window->hchild))
-    count += count_windows (XWINDOW (window->hchild));
+  if (WINDOWP (window->object))
+    count += count_windows (XWINDOW (window->object));
   return count;
 }
 
@@ -5959,10 +5891,8 @@
 {
   while (w)
     {
-      if (!NILP (w->hchild))
-	i = get_leaf_windows (XWINDOW (w->hchild), flat, i);
-      else if (!NILP (w->vchild))
-	i = get_leaf_windows (XWINDOW (w->vchild), flat, i);
+      if (WINDOWP (w->object))
+	i = get_leaf_windows (XWINDOW (w->object), flat, i);
       else
 	flat[i++] = w;
 
@@ -6026,7 +5956,7 @@
 
       wset_temslot (w, make_number (i)); i++;
       p->window = window;
-      p->buffer = w->buffer;
+      p->buffer = (w->type == WINDOW_LEAF ? w->object : Qnil);
       p->left_col = make_number (w->left_col);
       p->top_line = make_number (w->top_line);
       p->total_cols = make_number (w->total_cols);
@@ -6093,15 +6023,15 @@
 	    }
 	}
 
-      if (!NILP (w->buffer))
+      if (BUFFERP (w->object))
 	{
 	  /* 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 = build_marker (XBUFFER (w->buffer),
-				      BUF_PT (XBUFFER (w->buffer)),
-				      BUF_PT_BYTE (XBUFFER (w->buffer)));
+	    p->pointm = build_marker (XBUFFER (w->object),
+				      BUF_PT (XBUFFER (w->object)),
+				      BUF_PT_BYTE (XBUFFER (w->object)));
 	  else
 	    p->pointm = Fcopy_marker (w->pointm, Qnil);
 	  XMARKER (p->pointm)->insertion_type
@@ -6110,7 +6040,7 @@
 	  p->start = Fcopy_marker (w->start, Qnil);
 	  p->start_at_line_beg = w->start_at_line_beg ? Qt : Qnil;
 
-	  tem = BVAR (XBUFFER (w->buffer), mark);
+	  tem = BVAR (XBUFFER (w->object), mark);
 	  p->mark = Fcopy_marker (tem, Qnil);
 	}
       else
@@ -6131,10 +6061,8 @@
       else
 	p->prev = XWINDOW (w->prev)->temslot;
 
-      if (!NILP (w->vchild))
-	i = save_window_save (w->vchild, vector, i);
-      if (!NILP (w->hchild))
-	i = save_window_save (w->hchild, vector, i);
+      if (WINDOWP (w->object))
+	i = save_window_save (w->object, vector, i);
     }
 
   return i;
@@ -6451,7 +6379,7 @@
 	    adjust_glyphs (f);
 
 	  /* Prevent redisplay shortcuts.  */
-	  XBUFFER (w->buffer)->prevent_redisplay_optimizations_p = 1;
+	  XBUFFER (w->object)->prevent_redisplay_optimizations_p = 1;
 	}
     }
 
@@ -6485,10 +6413,8 @@
 
   for (cont = 1; w && cont;)
     {
-      if (!NILP (w->hchild))
- 	cont = foreach_window_1 (XWINDOW (w->hchild), fn, user_data);
-      else if (!NILP (w->vchild))
- 	cont = foreach_window_1 (XWINDOW (w->vchild), fn, user_data);
+      if (WINDOWP (w->object))
+ 	cont = foreach_window_1 (XWINDOW (w->object), fn, user_data);
       else
 	cont = fn (w, user_data);
 

=== modified file 'src/window.h'
--- src/window.h	2013-03-20 11:29:37 +0000
+++ src/window.h	2013-03-21 08:36:19 +0000
@@ -41,14 +41,13 @@
 this can be done implicitly).  Combination windows can be created
 and deleted at any time.
 
-A leaf window has a non-nil buffer field, and also
- has markers in its start and pointm fields.  Non-leaf windows
- have nil in these fields.
+A leaf window has a buffer stored in object field and markers in its start
+and pointm fields.  Non-leaf windows have nil in the latter two fields.
 
 Non-leaf windows are either vertical or horizontal combinations.
 
 A vertical combination window has children that are arranged on the frame
-one above the next.  Its vchild field points to the uppermost child.
+one above the next.  Its object field points to the uppermost child.
 The parent field of each of the children points to the vertical
 combination window.  The next field of each child points to the
 child below it, or is nil for the lowest child.  The prev field
@@ -56,7 +55,7 @@
 highest child.
 
 A horizontal combination window has children that are side by side.
-Its hchild field points to the leftmost child.  In each child
+Its object field points to the leftmost child.  In each child
 the next field points to the child to the right and the prev field
 points to the child to the left.
 
@@ -78,7 +77,7 @@
 minibuffer-only screens, the root window and the minibuffer window are
 one and the same, so its prev and next members are nil.
 
-A dead window has its buffer, hchild, and vchild windows all nil.  */
+A dead window has its object field set to nil.  */
 
 struct cursor_pos
 {
@@ -89,6 +88,15 @@
   int hpos, vpos;
 };
 
+/* Window types, see the comment above.  */
+
+enum window_type
+  {
+    WINDOW_LEAF,
+    WINDOW_HORIZONTAL_COMBINATION,
+    WINDOW_VERTICAL_COMBINATION,
+  };
+
 struct window
   {
     /* This is for Lisp; the terminal code does not refer to it.  */
@@ -102,13 +110,6 @@
     Lisp_Object next;
     Lisp_Object prev;
 
-    /* First child of this window: vchild is used if this is a vertical
-       combination, hchild if this is a horizontal combination.  Of the
-       fields vchild, hchild and buffer, one and only one is non-nil
-       unless the window is dead.  */
-    Lisp_Object hchild;
-    Lisp_Object vchild;
-
     /* The window this one is a child of.  */
     Lisp_Object parent;
 
@@ -123,10 +124,8 @@
     Lisp_Object new_total;
     Lisp_Object new_normal;
 
-    /* The buffer displayed in this window.  Of the fields vchild,
-       hchild and buffer, one and only one is non-nil unless the window
-       is dead.  */
-    Lisp_Object buffer;
+    /* May be buffer or window, see comment above.  */
+    Lisp_Object object;
 
     /* A marker pointing to where in the text to start displaying.
        BIDI Note: This is the _logical-order_ start, i.e. the smallest
@@ -282,6 +281,9 @@
     /* Non-zero if this window is a minibuffer window.  */
     unsigned mini : 1;
 
+    /* Window type, see above.  */
+    ENUM_BF (window_type) type : 2;
+
     /* Non-zero means must regenerate mode line of this window.  */
     unsigned update_mode_line : 1;
 
@@ -926,20 +928,17 @@
 struct glyph *get_phys_cursor_glyph (struct window *w);
 
 /* Value is non-zero if WINDOW is a valid window.  */
-#define WINDOW_VALID_P(WINDOW)				\
-  (WINDOWP (WINDOW)					\
-   && (!NILP (XWINDOW (WINDOW)->buffer)			\
-       || !NILP (XWINDOW (WINDOW)->vchild)		\
-       || !NILP (XWINDOW (WINDOW)->hchild)))
+#define WINDOW_VALID_P(WINDOW)					\
+  (WINDOWP (WINDOW) && !NILP (XWINDOW (WINDOW)->object))	\
 
-/* A window of any sort, leaf or interior, is "valid" if one
-   of its buffer, vchild, or hchild members is non-nil.  */
+/* A window of any sort, leaf or interior, is "valid" if its object
+   slot is non-nil.  */
 #define CHECK_VALID_WINDOW(WINDOW)				\
   CHECK_TYPE (WINDOW_VALID_P (WINDOW), Qwindow_valid_p, WINDOW)
 
 /* Value is non-zero if WINDOW is a live window.  */
 #define WINDOW_LIVE_P(WINDOW)					\
-  (WINDOWP (WINDOW) && !NILP (XWINDOW (WINDOW)->buffer))
+  (WINDOWP (WINDOW) && BUFFERP (XWINDOW (WINDOW)->object))
 
 /* A window is "live" if and only if it shows a buffer.  */
 #define CHECK_LIVE_WINDOW(WINDOW)				\

=== modified file 'src/xdisp.c'
--- src/xdisp.c	2013-03-20 11:29:37 +0000
+++ src/xdisp.c	2013-03-21 05:15:51 +0000
@@ -1283,10 +1283,10 @@
   if (FRAME_INITIAL_P (XFRAME (WINDOW_FRAME (w))))
     return visible_p;
 
-  if (XBUFFER (w->buffer) != current_buffer)
+  if (XBUFFER (w->object) != current_buffer)
     {
       old_buffer = current_buffer;
-      set_buffer_internal_1 (XBUFFER (w->buffer));
+      set_buffer_internal_1 (XBUFFER (w->object));
     }
 
   SET_TEXT_POS_FROM_MARKER (top, w->start);
@@ -4458,7 +4458,7 @@
      if it was a text property.  */
 
   if (!STRINGP (it->string))
-    object = it->w->buffer;
+    object = it->w->object;
 
   display_replaced_p = handle_display_spec (it, propval, object, overlay,
 					    position, bufpos,
@@ -4866,7 +4866,7 @@
 	  it->what = IT_IMAGE;
 	  it->image_id = -1; /* no image */
 	  it->position = start_pos;
-	  it->object = NILP (object) ? it->w->buffer : object;
+	  it->object = NILP (object) ? it->w->object : object;
 	  it->method = GET_FROM_IMAGE;
 	  it->from_overlay = Qnil;
 	  it->face_id = face_id;
@@ -5012,7 +5012,7 @@
 	  it->what = IT_IMAGE;
 	  it->image_id = lookup_image (it->f, value);
 	  it->position = start_pos;
-	  it->object = NILP (object) ? it->w->buffer : object;
+	  it->object = NILP (object) ? it->w->object : object;
 	  it->method = GET_FROM_IMAGE;
 
 	  /* Say that we haven't consumed the characters with
@@ -5836,7 +5836,7 @@
       it->object = p->u.stretch.object;
       break;
     case GET_FROM_BUFFER:
-      it->object = it->w->buffer;
+      it->object = it->w->object;
       break;
     case GET_FROM_STRING:
       it->object = it->string;
@@ -5849,7 +5849,7 @@
       else
 	{
 	  it->method = GET_FROM_BUFFER;
-	  it->object = it->w->buffer;
+	  it->object = it->w->object;
 	}
     }
   it->end_charpos = p->end_charpos;
@@ -6290,7 +6290,7 @@
   IT_STRING_BYTEPOS (*it) = -1;
   it->string = Qnil;
   it->method = GET_FROM_BUFFER;
-  it->object = it->w->buffer;
+  it->object = it->w->object;
   it->area = TEXT_AREA;
   it->multibyte_p = !NILP (BVAR (current_buffer, enable_multibyte_characters));
   it->sp = 0;
@@ -7141,7 +7141,7 @@
 	  else
 	    {
 	      it->method = GET_FROM_BUFFER;
-	      it->object = it->w->buffer;
+	      it->object = it->w->object;
 	    }
 
 	  it->dpvec = NULL;
@@ -7714,7 +7714,7 @@
 	 setting face_before_selective_p.  */
       it->saved_face_id = it->face_id;
       it->method = GET_FROM_BUFFER;
-      it->object = it->w->buffer;
+      it->object = it->w->object;
       reseat_at_next_visible_line_start (it, 1);
       it->face_before_selective_p = 1;
     }
@@ -7978,7 +7978,7 @@
 
       /* Record what we have and where it came from.  */
       it->what = IT_CHARACTER;
-      it->object = it->w->buffer;
+      it->object = it->w->object;
       it->position = it->current.pos;
 
       /* Normally we return the character found above, except when we
@@ -8084,7 +8084,7 @@
 	  return 0;
 	}
       it->position = it->current.pos;
-      it->object = it->w->buffer;
+      it->object = it->w->object;
       it->c = composition_update_it (&it->cmp_it, IT_CHARPOS (*it),
 				     IT_BYTEPOS (*it), Qnil);
     }
@@ -10003,7 +10003,7 @@
   if (w)
     {
       XSETWINDOW (tmp, w); ASET (vector, i, tmp); ++i;
-      ASET (vector, i, w->buffer); ++i;
+      ASET (vector, i, w->object); ++i;
       ASET (vector, i, make_number (marker_position (w->pointm))); ++i;
       ASET (vector, i, make_number (marker_byte_position (w->pointm))); ++i;
     }
@@ -10255,9 +10255,9 @@
   eassert (MINI_WINDOW_P (w));
 
   /* By default, start display at the beginning.  */
-  set_marker_both (w->start, w->buffer,
-		   BUF_BEGV (XBUFFER (w->buffer)),
-		   BUF_BEGV_BYTE (XBUFFER (w->buffer)));
+  set_marker_both (w->start, w->object,
+		   BUF_BEGV (XBUFFER (w->object)),
+		   BUF_BEGV_BYTE (XBUFFER (w->object)));
 
   /* Don't resize windows while redisplaying a window; it would
      confuse redisplay functions when the size of the window they are
@@ -10284,10 +10284,10 @@
       struct text_pos start;
       struct buffer *old_current_buffer = NULL;
 
-      if (current_buffer != XBUFFER (w->buffer))
+      if (current_buffer != XBUFFER (w->object))
 	{
 	  old_current_buffer = current_buffer;
-	  set_buffer_internal (XBUFFER (w->buffer));
+	  set_buffer_internal (XBUFFER (w->object));
 	}
 
       init_iterator (&it, w, BEGV, BEGV_BYTE, NULL, DEFAULT_FACE_ID);
@@ -10736,7 +10736,7 @@
 
 /* Nonzero if W doesn't reflect the actual state of current buffer due
    to its text or overlays change.  FIXME: this may be called when
-   XBUFFER (w->buffer) != current_buffer, which looks suspicious.  */
+   XBUFFER (w->object) != current_buffer, which looks suspicious.  */
 
 static int
 window_outdated (struct window *w)
@@ -10751,7 +10751,7 @@
 static int
 window_buffer_changed (struct window *w)
 {
-  struct buffer *b = XBUFFER (w->buffer);
+  struct buffer *b = XBUFFER (w->object);
 
   eassert (BUFFER_LIVE_P (b));
 
@@ -11005,7 +11005,7 @@
 
       Fselect_window (f->selected_window, Qt);
       set_buffer_internal_1
-	(XBUFFER (XWINDOW (f->selected_window)->buffer));
+	(XBUFFER (XWINDOW (f->selected_window)->object));
       fmt = FRAME_ICONIFIED_P (f) ? Vicon_title_format : Vframe_title_format;
 
       mode_line_target = MODE_LINE_TITLE;
@@ -11124,7 +11124,7 @@
           if (windows_or_buffers_changed
 	      && FRAME_NS_P (f))
             ns_set_doc_edited
-	      (f, Fbuffer_modified_p (XWINDOW (f->selected_window)->buffer));
+	      (f, Fbuffer_modified_p (XWINDOW (f->selected_window)->object));
 #endif
 	  UNGCPRO;
 	}
@@ -11196,7 +11196,7 @@
 
 	  specbind (Qinhibit_menubar_update, Qt);
 
-	  set_buffer_internal_1 (XBUFFER (w->buffer));
+	  set_buffer_internal_1 (XBUFFER (w->object));
 	  if (save_match_data)
 	    record_unwind_save_match_data ();
 	  if (NILP (Voverriding_local_map_menu_flag))
@@ -11400,7 +11400,7 @@
 	  /* Set current_buffer to the buffer of the selected
 	     window of the frame, so that we get the right local
 	     keymaps.  */
-	  set_buffer_internal_1 (XBUFFER (w->buffer));
+	  set_buffer_internal_1 (XBUFFER (w->object));
 
 	  /* Save match data, if we must.  */
 	  if (save_match_data)
@@ -12267,10 +12267,8 @@
     {
       struct window *w = XWINDOW (window);
 
-      if (WINDOWP (w->hchild))
-	hscrolled_p |= hscroll_window_tree (w->hchild);
-      else if (WINDOWP (w->vchild))
-	hscrolled_p |= hscroll_window_tree (w->vchild);
+      if (WINDOWP (w->object))
+	hscrolled_p |= hscroll_window_tree (w->object);
       else if (w->cursor.vpos >= 0)
 	{
 	  int h_margin;
@@ -12290,7 +12288,7 @@
 	  /* Scroll when cursor is inside this scroll margin.  */
 	  h_margin = hscroll_margin * WINDOW_FRAME_COLUMN_WIDTH (w);
 
-	  if (!NILP (Fbuffer_local_value (Qauto_hscroll_mode, w->buffer))
+	  if (!NILP (Fbuffer_local_value (Qauto_hscroll_mode, w->object))
 	      /* For left-to-right rows, hscroll when cursor is either
 		 (i) inside the right hscroll margin, or (ii) if it is
 		 inside the left margin and the window is already
@@ -12325,7 +12323,7 @@
 
 	      /* Find point in a display of infinite width.  */
 	      saved_current_buffer = current_buffer;
-	      current_buffer = XBUFFER (w->buffer);
+	      current_buffer = XBUFFER (w->object);
 
 	      if (w == XWINDOW (selected_window))
 		pt = PT;
@@ -12378,7 +12376,7 @@
 		 redisplay.  */
 	      if (w->hscroll != hscroll)
 		{
-		  XBUFFER (w->buffer)->prevent_redisplay_optimizations_p = 1;
+		  XBUFFER (w->object)->prevent_redisplay_optimizations_p = 1;
 		  w->hscroll = hscroll;
 		  hscrolled_p = 1;
 		}
@@ -12467,9 +12465,9 @@
   if (trace_redisplay_p)
     fprintf (stderr, "%p (%s): %s\n",
 	     w,
-	     ((BUFFERP (w->buffer)
-	       && STRINGP (BVAR (XBUFFER (w->buffer), name)))
-	      ? SSDATA (BVAR (XBUFFER (w->buffer), name))
+	     ((BUFFERP (w->object)
+	       && STRINGP (BVAR (XBUFFER (w->object), name)))
+	      ? SSDATA (BVAR (XBUFFER (w->object), name))
 	      : "no buffer"),
 	     method + len);
 }
@@ -12533,8 +12531,8 @@
 	 require to redisplay the whole paragraph.  It might be worthwhile
 	 to find the paragraph limits and widen the range of redisplayed
 	 lines to that, but for now just give up this optimization.  */
-      if (!NILP (BVAR (XBUFFER (w->buffer), bidi_display_reordering))
-	  && NILP (BVAR (XBUFFER (w->buffer), bidi_paragraph_direction)))
+      if (!NILP (BVAR (XBUFFER (w->object), bidi_display_reordering))
+	  && NILP (BVAR (XBUFFER (w->object), bidi_paragraph_direction)))
 	unchanged_p = 0;
     }
 
@@ -12757,7 +12755,7 @@
      we set b->clip_changed to 1 to force updating the screen.  If
      b->clip_changed has already been set to 1, we can skip this
      check.  */
-  if (!b->clip_changed && BUFFERP (w->buffer) && w->window_end_valid)
+  if (!b->clip_changed && BUFFERP (w->object) && w->window_end_valid)
     {
       ptrdiff_t pt;
 
@@ -12766,11 +12764,11 @@
       else
 	pt = marker_position (w->pointm);
 
-      if ((w->current_matrix->buffer != XBUFFER (w->buffer)
+      if ((w->current_matrix->buffer != XBUFFER (w->object)
 	   || pt != w->last_point)
 	  && check_point_in_composition (w->current_matrix->buffer,
 					 w->last_point,
-					 XBUFFER (w->buffer), pt))
+					 XBUFFER (w->object), pt))
 	b->clip_changed = 1;
     }
 }
@@ -13025,11 +13023,11 @@
      the whole window.  The assignment to this_line_start_pos prevents
      the optimization directly below this if-statement.  */
   if (((!NILP (Vtransient_mark_mode)
-	&& !NILP (BVAR (XBUFFER (w->buffer), mark_active)))
+	&& !NILP (BVAR (XBUFFER (w->object), mark_active)))
        != (w->region_showing > 0))
       || (w->region_showing
 	  && w->region_showing
-	  != XINT (Fmarker_position (BVAR (XBUFFER (w->buffer), mark)))))
+	  != XINT (Fmarker_position (BVAR (XBUFFER (w->object), mark)))))
     CHARPOS (this_line_start_pos) = 0;
 
   /* Optimize the case that only the line containing the cursor in the
@@ -13047,7 +13045,7 @@
       && !FRAME_OBSCURED_P (XFRAME (w->frame))
       /* Make sure recorded data applies to current buffer, etc.  */
       && this_line_buffer == current_buffer
-      && current_buffer == XBUFFER (w->buffer)
+      && current_buffer == XBUFFER (w->object)
       && !w->force_start
       && !w->optional_new_start
       /* Point must be on the line that we have info recorded about.  */
@@ -13338,7 +13336,7 @@
       Lisp_Object mini_window = FRAME_MINIBUF_WINDOW (sf);
       struct frame *mini_frame;
 
-      displayed_buffer = XBUFFER (XWINDOW (selected_window)->buffer);
+      displayed_buffer = XBUFFER (XWINDOW (selected_window)->object);
       /* Use list_of_error, not Qerror, so that
 	 we catch only errors and don't run the debugger.  */
       internal_condition_case_1 (redisplay_window_1, selected_window,
@@ -13548,7 +13546,7 @@
 static void
 mark_window_display_accurate_1 (struct window *w, int accurate_p)
 {
-  struct buffer *b = XBUFFER (w->buffer);
+  struct buffer *b = XBUFFER (w->object);
 
   w->last_modified = accurate_p ? BUF_MODIFF (b) : 0;
   w->last_overlay_modified = accurate_p ? BUF_OVERLAY_MODIFF (b) : 0;
@@ -13595,11 +13593,9 @@
   for (; !NILP (window); window = w->next)
     {
       w = XWINDOW (window);
-      if (!NILP (w->vchild))
-	mark_window_display_accurate (w->vchild, accurate_p);
-      else if (!NILP (w->hchild))
-	mark_window_display_accurate (w->hchild, accurate_p);
-      else if (BUFFERP (w->buffer))
+      if (WINDOWP (w->object))
+	mark_window_display_accurate (w->object, accurate_p);
+      else
 	mark_window_display_accurate_1 (w, accurate_p);
     }
 
@@ -13656,13 +13652,11 @@
     {
       struct window *w = XWINDOW (window);
 
-      if (!NILP (w->hchild))
-	redisplay_windows (w->hchild);
-      else if (!NILP (w->vchild))
-	redisplay_windows (w->vchild);
-      else if (!NILP (w->buffer))
+      if (WINDOWP (w->object))
+	redisplay_windows (w->object);
+      else
 	{
-	  displayed_buffer = XBUFFER (w->buffer);
+	  displayed_buffer = XBUFFER (w->object);
 	  /* Use list_of_error, not Qerror, so that
 	     we catch only errors and don't run the debugger.  */
 	  internal_condition_case_1 (redisplay_window_0, window,
@@ -14309,7 +14303,7 @@
 	  && !MATRIX_ROW_CONTINUATION_LINE_P (row)
 	  && row->x == 0)
 	{
-	  this_line_buffer = XBUFFER (w->buffer);
+	  this_line_buffer = XBUFFER (w->object);
 
 	  CHARPOS (this_line_start_pos)
 	    = MATRIX_ROW_START_CHARPOS (row) + delta;
@@ -14345,7 +14339,7 @@
   struct window *w = XWINDOW (window);
   SET_MARKER_FROM_TEXT_POS (w->start, startp);
 
-  if (current_buffer != XBUFFER (w->buffer))
+  if (current_buffer != XBUFFER (w->object))
     emacs_abort ();
 
   if (!NILP (Vwindow_scroll_functions))
@@ -14354,7 +14348,7 @@
 			    make_number (CHARPOS (startp)));
       SET_TEXT_POS_FROM_MARKER (startp, w->start);
       /* In case the hook functions switch buffers.  */
-      set_buffer_internal (XBUFFER (w->buffer));
+      set_buffer_internal (XBUFFER (w->object));
     }
 
   return startp;
@@ -15005,7 +14999,7 @@
 	      must_scroll = 1;
 	    }
 	  else if (rc != CURSOR_MOVEMENT_SUCCESS
-		   && !NILP (BVAR (XBUFFER (w->buffer), bidi_display_reordering)))
+		   && !NILP (BVAR (XBUFFER (w->object), bidi_display_reordering)))
 	    {
 	      struct glyph_row *row1;
 
@@ -15068,7 +15062,7 @@
 	  else if (scroll_p)
 	    rc = CURSOR_MOVEMENT_MUST_SCROLL;
 	  else if (rc != CURSOR_MOVEMENT_SUCCESS
-		   && !NILP (BVAR (XBUFFER (w->buffer), bidi_display_reordering)))
+		   && !NILP (BVAR (XBUFFER (w->object), bidi_display_reordering)))
 	    {
 	      /* With bidi-reordered rows, there could be more than
 		 one candidate row whose start and end positions
@@ -15175,7 +15169,7 @@
       || (w == XWINDOW (minibuf_window)
 	  && NILP (echo_area_buffer[0])))
     {
-      struct buffer *buf = XBUFFER (w->buffer);
+      struct buffer *buf = XBUFFER (w->object);
       whole = BUF_ZV (buf) - BUF_BEGV (buf);
       start = marker_position (w->start) - BUF_BEGV (buf);
       /* I don't think this is guaranteed to be right.  For the
@@ -15209,7 +15203,7 @@
 {
   struct window *w = XWINDOW (window);
   struct frame *f = XFRAME (w->frame);
-  struct buffer *buffer = XBUFFER (w->buffer);
+  struct buffer *buffer = XBUFFER (w->object);
   struct buffer *old = current_buffer;
   struct text_pos lpoint, opoint, startp;
   int update_mode_line;
@@ -15232,7 +15226,7 @@
   opoint = lpoint;
 
   /* W must be a leaf window here.  */
-  eassert (!NILP (w->buffer));
+  eassert (!NILP (w->object));
 #ifdef GLYPH_DEBUG
   *w->desired_matrix->method = 0;
 #endif
@@ -15262,10 +15256,10 @@
       else if ((w != XWINDOW (minibuf_window)
 		|| minibuf_level == 0)
 	       /* When buffer is nonempty, redisplay window normally. */
-	       && BUF_Z (XBUFFER (w->buffer)) == BUF_BEG (XBUFFER (w->buffer))
+	       && BUF_Z (XBUFFER (w->object)) == BUF_BEG (XBUFFER (w->object))
 	       /* Quail displays non-mini buffers in minibuffer window.
 		  In that case, redisplay the window normally.  */
-	       && !NILP (Fmemq (w->buffer, Vminibuffer_list)))
+	       && !NILP (Fmemq (w->object, Vminibuffer_list)))
 	{
 	  /* W is a mini-buffer window, but it's not active, so clear
 	     it.  */
@@ -15287,7 +15281,7 @@
      value.  */
   /* Really select the buffer, for the sake of buffer-local
      variables.  */
-  set_buffer_internal_1 (XBUFFER (w->buffer));
+  set_buffer_internal_1 (XBUFFER (w->object));
 
   current_matrix_up_to_date_p
     = (w->window_end_valid
@@ -16578,7 +16572,7 @@
 		 bidi-reordered glyph rows.  Let set_cursor_from_row
 		 figure out where to put the cursor, and if it fails,
 		 give up.  */
-	      if (!NILP (BVAR (XBUFFER (w->buffer), bidi_display_reordering)))
+	      if (!NILP (BVAR (XBUFFER (w->object), bidi_display_reordering)))
 		{
 		  if (!set_cursor_from_row (w, row, w->current_matrix,
 					    0, 0, 0, 0))
@@ -16829,7 +16823,7 @@
 
   /* Preconditions: W must be a leaf window and full-width.  Its frame
      must have a frame matrix.  */
-  eassert (NILP (w->hchild) && NILP (w->vchild));
+  eassert (w->type == WINDOW_LEAF);
   eassert (WINDOW_FULL_WIDTH_P (w));
   eassert (!FRAME_WINDOW_P (f));
 
@@ -16871,7 +16865,7 @@
 {
   struct glyph_row *row = start;
   struct glyph_row *best_row = NULL;
-  ptrdiff_t mindif = BUF_ZV (XBUFFER (w->buffer)) + 1;
+  ptrdiff_t mindif = BUF_ZV (XBUFFER (w->object)) + 1;
   int last_y;
 
   /* If we happen to start on a header-line, skip that.  */
@@ -16907,7 +16901,7 @@
 	{
 	  struct glyph *g;
 
-	  if (NILP (BVAR (XBUFFER (w->buffer), bidi_display_reordering))
+	  if (NILP (BVAR (XBUFFER (w->object), bidi_display_reordering))
 	      || (!best_row && !row->continued_p))
 	    return row;
 	  /* In bidi-reordered rows, there could be several rows
@@ -17073,7 +17067,7 @@
      wrapped line can change the wrap position, altering the line
      above it.  It might be worthwhile to handle this more
      intelligently, but for now just redisplay from scratch.  */
-  if (!NILP (BVAR (XBUFFER (w->buffer), word_wrap)))
+  if (!NILP (BVAR (XBUFFER (w->object), word_wrap)))
     GIVE_UP (21);
 
   /* Under bidi reordering, adding or deleting a character in the
@@ -17084,8 +17078,8 @@
      to find the paragraph limits and widen the range of redisplayed
      lines to that, but for now just give up this optimization and
      redisplay from scratch.  */
-  if (!NILP (BVAR (XBUFFER (w->buffer), bidi_display_reordering))
-      && NILP (BVAR (XBUFFER (w->buffer), bidi_paragraph_direction)))
+  if (!NILP (BVAR (XBUFFER (w->object), bidi_display_reordering))
+      && NILP (BVAR (XBUFFER (w->object), bidi_paragraph_direction)))
     GIVE_UP (22);
 
   /* Make sure beg_unchanged and end_unchanged are up to date.  Do it
@@ -17950,7 +17944,7 @@
   (Lisp_Object glyphs)
 {
   struct window *w = XWINDOW (selected_window);
-  struct buffer *buffer = XBUFFER (w->buffer);
+  struct buffer *buffer = XBUFFER (w->object);
 
   fprintf (stderr, "PT = %"pI"d, BEGV = %"pI"d. ZV = %"pI"d\n",
 	   BUF_PT (buffer), BUF_BEGV (buffer), BUF_ZV (buffer));
@@ -18056,7 +18050,7 @@
 get_overlay_arrow_glyph_row (struct window *w, Lisp_Object overlay_arrow_string)
 {
   struct frame *f = XFRAME (WINDOW_FRAME (w));
-  struct buffer *buffer = XBUFFER (w->buffer);
+  struct buffer *buffer = XBUFFER (w->object);
   struct buffer *old = current_buffer;
   const unsigned char *arrow_string = SDATA (overlay_arrow_string);
   int arrow_len = SCHARS (overlay_arrow_string);
@@ -19263,7 +19257,7 @@
 	      row->glyphs[TEXT_AREA]->charpos = -1;
 	      row->displays_text_p = 0;
 
-	      if (!NILP (BVAR (XBUFFER (it->w->buffer), indicate_empty_lines))
+	      if (!NILP (BVAR (XBUFFER (it->w->object), indicate_empty_lines))
 		  && (!MINI_WINDOW_P (it->w)
 		      || (minibuf_level && EQ (it->window, minibuf_window))))
 		row->indicate_empty_line_p = 1;
@@ -20079,10 +20073,8 @@
     {
       struct window *w = XWINDOW (window);
 
-      if (WINDOWP (w->hchild))
-	nwindows += redisplay_mode_lines (w->hchild, force);
-      else if (WINDOWP (w->vchild))
-	nwindows += redisplay_mode_lines (w->vchild, force);
+      if (WINDOWP (w->object))
+	nwindows += redisplay_mode_lines (w->object, force);
       else if (force
 	       || FRAME_GARBAGED_P (XFRAME (w->frame))
 	       || !MATRIX_MODE_LINE_ROW (w->current_matrix)->enabled_p)
@@ -20092,7 +20084,7 @@
 
 	  /* Set the window's buffer for the mode line display.  */
 	  SET_TEXT_POS (lpoint, PT, PT_BYTE);
-	  set_buffer_internal_1 (XBUFFER (w->buffer));
+	  set_buffer_internal_1 (XBUFFER (w->object));
 
 	  /* Point refers normally to the selected window.  For any
 	     other window, set up appropriate value.  */
@@ -20874,7 +20866,7 @@
   XSETWINDOW (window, w);
 
   if (NILP (buffer))
-    buffer = w->buffer;
+    buffer = w->object;
   CHECK_BUFFER (buffer);
 
   /* Make formatting the modeline a non-op when noninteractive, otherwise
@@ -22180,7 +22172,7 @@
 	    return OK_PIXELS (WINDOW_SCROLL_BAR_AREA_WIDTH (it->w));
 	}
 
-      prop = buffer_local_value_1 (prop, it->w->buffer);
+      prop = buffer_local_value_1 (prop, it->w->object);
       if (EQ (prop, Qunbound))
 	prop = Qnil;
     }
@@ -22232,7 +22224,7 @@
 	      return OK_PIXELS (pixels);
 	    }
 
-	  car = buffer_local_value_1 (car, it->w->buffer);
+	  car = buffer_local_value_1 (car, it->w->object);
 	  if (EQ (car, Qunbound))
 	    car = Qnil;
 	}
@@ -24082,7 +24074,7 @@
       int n = width;
 
       if (!STRINGP (object))
-	object = it->w->buffer;
+	object = it->w->object;
 #ifdef HAVE_WINDOW_SYSTEM
       if (FRAME_WINDOW_P (it->f))
 	append_stretch_glyph (it, object, width, height, ascent);
@@ -25478,7 +25470,7 @@
 			int *active_cursor)
 {
   struct frame *f = XFRAME (w->frame);
-  struct buffer *b = XBUFFER (w->buffer);
+  struct buffer *b = XBUFFER (w->object);
   int cursor_type = DEFAULT_CURSOR;
   Lisp_Object alt_cursor;
   int non_selected = 0;
@@ -26029,10 +26021,8 @@
 {
   while (w)
     {
-      if (!NILP (w->hchild))
-	update_cursor_in_window_tree (XWINDOW (w->hchild), on_p);
-      else if (!NILP (w->vchild))
-	update_cursor_in_window_tree (XWINDOW (w->vchild), on_p);
+      if (WINDOWP (w->object))
+	update_cursor_in_window_tree (XWINDOW (w->object), on_p);
       else
 	update_window_cursor (w, on_p);
 
@@ -27278,7 +27268,7 @@
 		{
 		  help_echo_string = help;
 		  XSETWINDOW (help_echo_window, w);
-		  help_echo_object = w->buffer;
+		  help_echo_object = w->object;
 		  help_echo_pos = charpos;
 		}
 	    }
@@ -27314,7 +27304,7 @@
 	    {
 	      Lisp_Object default_help
 		= buffer_local_value_1 (Qmode_line_default_help_echo,
-					w->buffer);
+					w->object);
 
 	      if (STRINGP (default_help))
 		{
@@ -27589,7 +27579,7 @@
 
   /* Are we in a window whose display is up to date?
      And verify the buffer's text has not changed.  */
-  b = XBUFFER (w->buffer);
+  b = XBUFFER (w->object);
   if (part == ON_TEXT
       && w->window_end_valid
       && w->last_modified == BUF_MODIFF (b)
@@ -27798,8 +27788,8 @@
 		  if (pos > 0)
 		    {
 		      mouse_face = get_char_property_and_overlay
-			(make_number (pos), Qmouse_face, w->buffer, &overlay);
-		      buffer = w->buffer;
+			(make_number (pos), Qmouse_face, w->object, &overlay);
+		      buffer = w->object;
 		      disp_string = object;
 		    }
 		}
@@ -27912,11 +27902,11 @@
 		    if (p > 0)
 		      {
 			help = Fget_char_property (make_number (p),
-						   Qhelp_echo, w->buffer);
+						   Qhelp_echo, w->object);
 			if (!NILP (help))
 			  {
 			    charpos = p;
-			    obj = w->buffer;
+			    obj = w->object;
 			  }
 		      }
 		  }
@@ -27967,7 +27957,7 @@
 		      ptrdiff_t p = string_buffer_position (obj, start);
 		      if (p > 0)
 			pointer = Fget_char_property (make_number (p),
-						      Qpointer, w->buffer);
+						      Qpointer, w->object);
 		    }
 		}
 	      else if (BUFFERP (obj)
@@ -28410,12 +28400,9 @@
 
   while (w && !FRAME_GARBAGED_P (f))
     {
-      if (!NILP (w->hchild))
-	mouse_face_overwritten_p
-	  |= expose_window_tree (XWINDOW (w->hchild), r);
-      else if (!NILP (w->vchild))
-	mouse_face_overwritten_p
-	  |= expose_window_tree (XWINDOW (w->vchild), r);
+      if (WINDOWP (w->object))
+	mouse_face_overwritten_p
+	  |= expose_window_tree (XWINDOW (w->object), r);
       else
 	mouse_face_overwritten_p |= expose_window (w, r);
 

=== modified file 'src/xfaces.c'
--- src/xfaces.c	2013-03-20 09:56:19 +0000
+++ src/xfaces.c	2013-03-21 05:05:23 +0000
@@ -5963,7 +5963,7 @@
 
   /* W must display the current buffer.  We could write this function
      to use the frame and buffer of W, but right now it doesn't.  */
-  /* eassert (XBUFFER (w->buffer) == current_buffer); */
+  /* eassert (XBUFFER (w->object) == current_buffer); */
 
   XSETFASTINT (position, pos);
 
@@ -5973,9 +5973,9 @@
 
   /* Get the `face' or `mouse_face' text property at POS, and
      determine the next position at which the property changes.  */
-  prop = Fget_text_property (position, propname, w->buffer);
+  prop = Fget_text_property (position, propname, w->object);
   XSETFASTINT (limit1, (limit < endpos ? limit : endpos));
-  end = Fnext_single_property_change (position, propname, w->buffer, limit1);
+  end = Fnext_single_property_change (position, propname, w->object, limit1);
   if (INTEGERP (end))
     endpos = XINT (end);
 
@@ -6071,7 +6071,7 @@
 
   /* W must display the current buffer.  We could write this function
      to use the frame and buffer of W, but right now it doesn't.  */
-  /* eassert (XBUFFER (w->buffer) == current_buffer); */
+  /* eassert (XBUFFER (w->object) == current_buffer); */
 
   XSETFASTINT (position, pos);
 
@@ -6081,9 +6081,9 @@
 
   /* Get the `face' or `mouse_face' text property at POS, and
      determine the next position at which the property changes.  */
-  prop = Fget_text_property (position, propname, w->buffer);
+  prop = Fget_text_property (position, propname, w->object);
   XSETFASTINT (limit1, (limit < endpos ? limit : endpos));
-  end = Fnext_single_property_change (position, propname, w->buffer, limit1);
+  end = Fnext_single_property_change (position, propname, w->object, limit1);
   if (INTEGERP (end))
     endpos = XINT (end);
 

=== modified file 'src/xfns.c'
--- src/xfns.c	2013-03-20 11:29:37 +0000
+++ src/xfns.c	2013-03-21 05:05:23 +0000
@@ -5043,7 +5043,7 @@
 
   /* Display the tooltip text in a temporary buffer.  */
   old_buffer = current_buffer;
-  set_buffer_internal_1 (XBUFFER (XWINDOW (FRAME_ROOT_WINDOW (f))->buffer));
+  set_buffer_internal_1 (XBUFFER (XWINDOW (FRAME_ROOT_WINDOW (f))->object));
   bset_truncate_lines (current_buffer, Qnil);
   clear_glyph_matrix (w->desired_matrix);
   clear_glyph_matrix (w->current_matrix);

=== modified file 'src/xmenu.c'
--- src/xmenu.c	2013-01-17 06:29:40 +0000
+++ src/xmenu.c	2013-03-21 05:05:23 +0000
@@ -976,7 +976,7 @@
       if (! menubar_widget)
 	previous_menu_items_used = 0;
 
-      buffer = XWINDOW (FRAME_SELECTED_WINDOW (f))->buffer;
+      buffer = XWINDOW (FRAME_SELECTED_WINDOW (f))->object;
       specbind (Qinhibit_quit, Qt);
       /* Don't let the debugger step into this code
 	 because it is not reentrant.  */


^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [RFC] some reworking of struct window
  2013-03-21  9:39 [RFC] some reworking of struct window Dmitry Antipov
@ 2013-03-21 11:38 ` martin rudalics
  2013-03-21 18:45   ` Eli Zaretskii
  2013-03-21 14:26 ` Davis Herring
                   ` (2 subsequent siblings)
  3 siblings, 1 reply; 16+ messages in thread
From: martin rudalics @ 2013-03-21 11:38 UTC (permalink / raw)
  To: Dmitry Antipov; +Cc: Emacs development discussions

 > As usual, reviews and comments are highly appreciated, especially for the
 > 'struct window' member which replaces hchild/vchild/buffer (I don't like
 > too generic 'object', but couldn't think up the better name).

I'd use macros like WINDOW_BUFFER (w) and WINDOW_CHILD (w) where
appropriate to hide this detail (most callers care only about the one or
the other).

martin



^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [RFC] some reworking of struct window
  2013-03-21  9:39 [RFC] some reworking of struct window Dmitry Antipov
  2013-03-21 11:38 ` martin rudalics
@ 2013-03-21 14:26 ` Davis Herring
  2013-03-21 14:46 ` Stefan Monnier
  2013-03-21 18:21 ` Eli Zaretskii
  3 siblings, 0 replies; 16+ messages in thread
From: Davis Herring @ 2013-03-21 14:26 UTC (permalink / raw)
  To: emacs-devel

> 'struct window' member which replaces hchild/vchild/buffer (I don't like
> too generic 'object', but couldn't think up the better name).

How about "contained", if it's not too confusing for the split case?

Davis

-- 
This product is sold by volume, not by mass.  If it appears too dense or
too sparse, it is because mass-energy conversion has occurred during
shipping.



^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [RFC] some reworking of struct window
  2013-03-21  9:39 [RFC] some reworking of struct window Dmitry Antipov
  2013-03-21 11:38 ` martin rudalics
  2013-03-21 14:26 ` Davis Herring
@ 2013-03-21 14:46 ` Stefan Monnier
  2013-03-21 15:01   ` Dmitry Antipov
  2013-03-21 18:21 ` Eli Zaretskii
  3 siblings, 1 reply; 16+ messages in thread
From: Stefan Monnier @ 2013-03-21 14:46 UTC (permalink / raw)
  To: Dmitry Antipov; +Cc: Emacs development discussions

> As usual, reviews and comments are highly appreciated, especially for the
> 'struct window' member which replaces hchild/vchild/buffer (I don't like
> too generic 'object', but couldn't think up the better name).

I don't like "object" either.  I'd *much* prefer "content", "child", or
"children".

I didn't check the whole patch, but what I looked at seemed just fine,
thank you,


        Stefan



^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [RFC] some reworking of struct window
  2013-03-21 14:46 ` Stefan Monnier
@ 2013-03-21 15:01   ` Dmitry Antipov
  2013-03-21 17:40     ` Eli Zaretskii
  0 siblings, 1 reply; 16+ messages in thread
From: Dmitry Antipov @ 2013-03-21 15:01 UTC (permalink / raw)
  To: Stefan Monnier; +Cc: Emacs development discussions

On 03/21/2013 06:46 PM, Stefan Monnier wrote:

> I don't like "object" either.  I'd *much* prefer "content", "child", or
> "children".

Hm... "contained" or "content" looks much better, I'm also thinking
about "payload" (not used too much and so easy to grep/tags/whatever).

> I didn't check the whole patch, but what I looked at seemed just fine,
> thank you,

I found one quite serious bug in 1hr after it was posted; anyway, this
code definitely needs more debugging.

Dmitry




^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [RFC] some reworking of struct window
  2013-03-21 15:01   ` Dmitry Antipov
@ 2013-03-21 17:40     ` Eli Zaretskii
  0 siblings, 0 replies; 16+ messages in thread
From: Eli Zaretskii @ 2013-03-21 17:40 UTC (permalink / raw)
  To: Dmitry Antipov; +Cc: monnier, emacs-devel

> Date: Thu, 21 Mar 2013 19:01:04 +0400
> From: Dmitry Antipov <dmantipov@yandex.ru>
> Cc: Emacs development discussions <emacs-devel@gnu.org>
> 
> On 03/21/2013 06:46 PM, Stefan Monnier wrote:
> 
> > I don't like "object" either.  I'd *much* prefer "content", "child", or
> > "children".
> 
> Hm... "contained" or "content" looks much better, I'm also thinking
> about "payload" (not used too much and so easy to grep/tags/whatever).

Another possibility is buffer_or_window (or window_or_buffer), since
that's what they can be, after all.



^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [RFC] some reworking of struct window
  2013-03-21  9:39 [RFC] some reworking of struct window Dmitry Antipov
                   ` (2 preceding siblings ...)
  2013-03-21 14:46 ` Stefan Monnier
@ 2013-03-21 18:21 ` Eli Zaretskii
  2013-03-21 23:50   ` Stefan Monnier
  2013-03-22  6:13   ` [RFC] some reworking of struct window Dmitry Antipov
  3 siblings, 2 replies; 16+ messages in thread
From: Eli Zaretskii @ 2013-03-21 18:21 UTC (permalink / raw)
  To: Dmitry Antipov; +Cc: emacs-devel

> Date: Thu, 21 Mar 2013 13:39:27 +0400
> From: Dmitry Antipov <dmantipov@yandex.ru>
> 
> This patch implements the further generalization of an idea suggested by Stefan
> at http://lists.gnu.org/archive/html/emacs-devel/2013-02/msg00088.html. The main
> motivations are 1) make 'struct window' even bit smaller and 2) simplify the code
> like:
> 
> if (!NILP (w->hchild))
>    foo (w->hchild);
> else if (!NILP (w->vchild))
>    foo (w->vchild);
> else /* assume leaf window with w->buffer */
>    bar (w->buffer);
> 
> to:
> 
> if (WINDOWP (w->object))
>    foo (w->object);
> else /* assume leaf window with buffer at w->object */
>    bar (w->object);

Thanks.

> As usual, reviews and comments are highly appreciated, especially for the
> 'struct window' member which replaces hchild/vchild/buffer (I don't like
> too generic 'object', but couldn't think up the better name).

Most of the changes are mechanical, so the review could be much more
efficient if you could point out non-trivial ones.

> @@ -838,16 +838,8 @@
>  {
>    while (w)
>      {
> -      if (!NILP (w->hchild))
> -	{
> -	  eassert (WINDOWP (w->hchild));
> -	  clear_window_matrices (XWINDOW (w->hchild), desired_p);
> -	}
> -      else if (!NILP (w->vchild))
> -	{
> -	  eassert (WINDOWP (w->vchild));
> -	  clear_window_matrices (XWINDOW (w->vchild), desired_p);
> -	}
> +      if (WINDOWP (w->object))
> +	clear_window_matrices (XWINDOW (w->object), desired_p);
>        else
>  	{
>  	  if (desired_p)

Here, you effectively lost the assertion that w->object can only be a
window or a buffer.  With the new code, if it's neither a window nor a
buffer, you will behave as if it were a buffer, without checking.

> -  eassert (NILP (w->hchild) && NILP (w->vchild));
> +  eassert (w->type == WINDOW_LEAF);

Why do you need to store the WINDOW_LEAF type explicitly, if you can
test w->object for being a buffer?  And if you do need this type, why
not use it instead of WINDOWP in the various tests above and below?

> @@ -2069,22 +2060,18 @@
>    if (!NILP (parent) && NILP (w->combination_limit))
>      {
>        p = XWINDOW (parent);
> -      if (((!NILP (p->vchild) && !NILP (w->vchild))
> -	   || (!NILP (p->hchild) && !NILP (w->hchild))))
> +      if (p->type == w->type && p->type > WINDOW_LEAF)
                                   ^^^^^^^^^^^^^^^^^^^^^
I think you are not supposed to compare enumerated types, except for
equality.  How exactly the compiler assigns numerical values to
enumerated types is implementation-defined, I think.

> -  /* P's buffer slot may change from nil to a buffer.  */
> -  adjust_window_count (p, 1);

Why did you remove this call?

> -      if (!NILP (w->vchild))
> -	{
> -	  delete_all_child_windows (w->vchild);
> -	  wset_vchild (w, Qnil);
> -	}
> -      else if (!NILP (w->hchild))
> -	{
> -	  delete_all_child_windows (w->hchild);
> -	  wset_hchild (w, Qnil);
> -	}
> -      else if (!NILP (w->buffer))
> +      if (WINDOWP (w->object))
> +	{
> +	  delete_all_child_windows (w->object);
> +	  w->object = Qnil;
> +	}
> +      else
>  	{
>  	  unshow_buffer (w);
>  	  unchain_marker (XMARKER (w->pointm));

Maybe instead of just "else" you should make sure w->object is a
buffer.

> +/* Window types, see the comment above.  */
> +
> +enum window_type
> +  {
> +    WINDOW_LEAF,
> +    WINDOW_HORIZONTAL_COMBINATION,
> +    WINDOW_VERTICAL_COMBINATION,
> +  };

The test BUFFERP (w->object) already gives you the same info as
WINDOW_LEAF type, no?



^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [RFC] some reworking of struct window
  2013-03-21 11:38 ` martin rudalics
@ 2013-03-21 18:45   ` Eli Zaretskii
  2013-03-21 21:17     ` martin rudalics
  0 siblings, 1 reply; 16+ messages in thread
From: Eli Zaretskii @ 2013-03-21 18:45 UTC (permalink / raw)
  To: martin rudalics; +Cc: dmantipov, emacs-devel

> Date: Thu, 21 Mar 2013 12:38:01 +0100
> From: martin rudalics <rudalics@gmx.at>
> Cc: Emacs development discussions <emacs-devel@gnu.org>
> 
>  > As usual, reviews and comments are highly appreciated, especially for the
>  > 'struct window' member which replaces hchild/vchild/buffer (I don't like
>  > too generic 'object', but couldn't think up the better name).
> 
> I'd use macros like WINDOW_BUFFER (w) and WINDOW_CHILD (w) where
> appropriate to hide this detail (most callers care only about the one or
> the other).

I agree.  And another macro for testing that a window is a leaf
window.



^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [RFC] some reworking of struct window
  2013-03-21 18:45   ` Eli Zaretskii
@ 2013-03-21 21:17     ` martin rudalics
  0 siblings, 0 replies; 16+ messages in thread
From: martin rudalics @ 2013-03-21 21:17 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: dmantipov, emacs-devel

> I agree.  And another macro for testing that a window is a leaf
> window.

WINDOW_BUFFER (w)

or

! WINDOW_CHILD (w) ?

martin




^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [RFC] some reworking of struct window
  2013-03-21 18:21 ` Eli Zaretskii
@ 2013-03-21 23:50   ` Stefan Monnier
  2013-03-22  7:40     ` Alternate design [Was: Re: [RFC] some reworking of struct window] Dmitry Antipov
  2013-03-22  6:13   ` [RFC] some reworking of struct window Dmitry Antipov
  1 sibling, 1 reply; 16+ messages in thread
From: Stefan Monnier @ 2013-03-21 23:50 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: Dmitry Antipov, emacs-devel

>> +enum window_type
>> +  {
>> +    WINDOW_LEAF,
>> +    WINDOW_HORIZONTAL_COMBINATION,
>> +    WINDOW_VERTICAL_COMBINATION,
>> +  };
> The test BUFFERP (w->object) already gives you the same info as
> WINDOW_LEAF type, no?

Right, we could probably replace window_type by a boolean, used only for
the "child is a window" case and indicating whether the split is
vertical or horizontal.


        Stefan



^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [RFC] some reworking of struct window
  2013-03-21 18:21 ` Eli Zaretskii
  2013-03-21 23:50   ` Stefan Monnier
@ 2013-03-22  6:13   ` Dmitry Antipov
  2013-03-22  8:47     ` Eli Zaretskii
  1 sibling, 1 reply; 16+ messages in thread
From: Dmitry Antipov @ 2013-03-22  6:13 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: emacs-devel

On 03/21/2013 10:21 PM, Eli Zaretskii wrote:

>> @@ -838,16 +838,8 @@
>>   {
>>     while (w)
>>       {
>> -      if (!NILP (w->hchild))
>> -	{
>> -	  eassert (WINDOWP (w->hchild));
>> -	  clear_window_matrices (XWINDOW (w->hchild), desired_p);
>> -	}
>> -      else if (!NILP (w->vchild))
>> -	{
>> -	  eassert (WINDOWP (w->vchild));
>> -	  clear_window_matrices (XWINDOW (w->vchild), desired_p);
>> -	}
>> +      if (WINDOWP (w->object))
>> +	clear_window_matrices (XWINDOW (w->object), desired_p);
>>         else
>>   	{
>>   	  if (desired_p)
>
> Here, you effectively lost the assertion that w->object can only be a
> window or a buffer.  With the new code, if it's neither a window nor a
> buffer, you will behave as if it were a buffer, without checking.

No, because clear_window_matrices doesn't check whether w->buffer is not
nil and call clear_glyph_matrix anyway.

I assume that the most of display-related functions should not be called
for the deleted windows. E.g. this code just silences possible error:

if (WINDOWP (w->object))
   foo (w->object);
else if (BUFFERP (w->object))
   bar (w->object);

The following is better since XBUFFER implies eassert if --enable-checking:

if (WINDOWP (w->object))
   foo (w->object);
else
   bar (XBUFFER (w->object));

Or:

if (WINDOWP (w->object))
   foo (w->object);
else if (BUFFERP (w->object))
   bar (w->object);
else
   emacs_abort ();

The latter example leaves the conditional call to emacs_abort even without
--enable-checking. I suspect that this is too paranoid, and would prefer:

eassert (!NILP (w->object));
if (WINDOWP (w->object))
   foo (w->object);
else
   bar (w->object);

>> -  eassert (NILP (w->hchild) && NILP (w->vchild));
>> +  eassert (w->type == WINDOW_LEAF);
>
> Why do you need to store the WINDOW_LEAF type explicitly, if you can
> test w->object for being a buffer?

Since sync_window_with_frame_matrix_rows assumes live window,
eassert (BUFFERP (w->object)) may be better; but...

> And if you do need this type, why
> not use it instead of WINDOWP in the various tests above and below?

this is not always the same because w->type == WINDOW_xxx_COMBINATION
may be true for the deleted window too.

>> @@ -2069,22 +2060,18 @@
>>     if (!NILP (parent) && NILP (w->combination_limit))
>>       {
>>         p = XWINDOW (parent);
>> -      if (((!NILP (p->vchild) && !NILP (w->vchild))
>> -	   || (!NILP (p->hchild) && !NILP (w->hchild))))
>> +      if (p->type == w->type && p->type > WINDOW_LEAF)
>                                     ^^^^^^^^^^^^^^^^^^^^^
> I think you are not supposed to compare enumerated types, except for
> equality.  How exactly the compiler assigns numerical values to
> enumerated types is implementation-defined, I think.

No.

"An enumerator with = defines its enumeration constant as the value of the constant
expression. If the first enumerator has no =, the value of its enumeration constant
is 0. Each subsequent enumerator with no = defines its enumeration constant as the
value of the constant expression obtained by adding 1 to the value of the previous
enumeration constant".

This is from the latest C99 draft (http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1256.pdf
6.7.2.2 "Enumeration specifiers"), but I believe it was so since long time ago.

>> -  /* P's buffer slot may change from nil to a buffer.  */
>> -  adjust_window_count (p, 1);
>
> Why did you remove this call?

Because I also remove wset_buffer (p, Qnil) few lines below, and per-buffer window counters
should be balanced.

>> +/* Window types, see the comment above.  */
>> +
>> +enum window_type
>> +  {
>> +    WINDOW_LEAF,
>> +    WINDOW_HORIZONTAL_COMBINATION,
>> +    WINDOW_VERTICAL_COMBINATION,
>> +  };
>
> The test BUFFERP (w->object) already gives you the same info as
> WINDOW_LEAF type, no?

Of course, it's possible to avoid enum window_type at all and use something like:

unsigned combination : 1;
unsigned horizontal : 1;

in struct window. Then we will have

w->type == WINDOW_LEAF equal to !w->combination;
w->type == WINDOW_VERTICAL_COMBINATION equal to w->combination && !w->horizontal;
w->type == WINDOW_HORIZONTAL_COMBINATION equal to w->combination && w->horizontal.

I'll try this design too.

Dmitry



^ permalink raw reply	[flat|nested] 16+ messages in thread

* Alternate design [Was: Re: [RFC] some reworking of struct window]
  2013-03-21 23:50   ` Stefan Monnier
@ 2013-03-22  7:40     ` Dmitry Antipov
  2013-03-22 13:34       ` Stefan Monnier
  0 siblings, 1 reply; 16+ messages in thread
From: Dmitry Antipov @ 2013-03-22  7:40 UTC (permalink / raw)
  To: Stefan Monnier; +Cc: Eli Zaretskii, emacs-devel

[-- Attachment #1: Type: text/plain, Size: 300 bytes --]

On 03/22/2013 03:50 AM, Stefan Monnier wrote:

> Right, we could probably replace window_type by a boolean, used only for
> the "child is a window" case and indicating whether the split is
> vertical or horizontal.

Since at least two people suggests such an alternate design, here is it.

Dmitry




[-- Attachment #2: window_noenum.patch --]
[-- Type: text/plain, Size: 100497 bytes --]

=== modified file 'src/alloc.c'
--- src/alloc.c	2013-03-21 20:56:22 +0000
+++ src/alloc.c	2013-03-22 06:38:27 +0000
@@ -5810,14 +5810,13 @@
 	  case PVEC_WINDOW:
 	    {
 	      struct window *w = (struct window *) ptr;
-	      bool leaf = NILP (w->hchild) && NILP (w->vchild);
 
 	      mark_vectorlike (ptr);
 
 	      /* Mark glyphs for leaf windows.  Marking window
 		 matrices is sufficient because frame matrices
 		 use the same glyph memory.  */
-	      if (leaf && w->current_matrix)
+	      if (WINDOW_LEAF (w) && w->current_matrix)
 		{
 		  mark_glyph_matrix (w->current_matrix);
 		  mark_glyph_matrix (w->desired_matrix);

=== modified file 'src/buffer.c'
--- src/buffer.c	2013-01-19 20:04:33 +0000
+++ src/buffer.c	2013-03-22 06:16:49 +0000
@@ -1769,7 +1769,7 @@
      since anything can happen within do_yes_or_no_p.  */
 
   /* Don't kill the minibuffer now current.  */
-  if (EQ (buffer, XWINDOW (minibuf_window)->buffer))
+  if (EQ (buffer, XWINDOW (minibuf_window)->payload))
     return Qnil;
 
   /* When we kill an ordinary buffer which shares it's buffer text
@@ -1820,7 +1820,7 @@
   /* If the buffer now current is shown in the minibuffer and our buffer
      is the sole other buffer give up.  */
   XSETBUFFER (tem, current_buffer);
-  if (EQ (tem, XWINDOW (minibuf_window)->buffer)
+  if (EQ (tem, XWINDOW (minibuf_window)->payload)
       && EQ (buffer, Fother_buffer (buffer, Qnil, Qnil)))
     return Qnil;
 
@@ -2394,7 +2394,7 @@
 	   BUF_MARKERS(buf) should either be for `buf' or dead.  */
 	eassert (!m->buffer);
   }
-  { /* Some of the C code expects that w->buffer == w->pointm->buffer.
+  { /* Some of the C code expects that w->payload == w->pointm->buffer.
        So since we just swapped the markers between the two buffers, we need
        to undo the effect of this swap for window markers.  */
     Lisp_Object w = Fselected_window (), ws = Qnil;
@@ -2405,12 +2405,12 @@
       {
 	ws = Fcons (w, ws);
 	if (MARKERP (XWINDOW (w)->pointm)
-	    && (EQ (XWINDOW (w)->buffer, buf1)
-		|| EQ (XWINDOW (w)->buffer, buf2)))
+	    && (EQ (XWINDOW (w)->payload, buf1)
+		|| EQ (XWINDOW (w)->payload, buf2)))
 	  Fset_marker (XWINDOW (w)->pointm,
 		       make_number
-		       (BUF_BEGV (XBUFFER (XWINDOW (w)->buffer))),
-		       XWINDOW (w)->buffer);
+		       (BUF_BEGV (XBUFFER (XWINDOW (w)->payload))),
+		       XWINDOW (w)->payload);
 	w = Fnext_window (w, Qt, Qt);
       }
   }
@@ -3893,7 +3893,7 @@
   if (buffer_window_count (buf) > 0)
     {
       /* ... it's visible in other window than selected,  */
-      if (buf != XBUFFER (XWINDOW (selected_window)->buffer))
+      if (buf != XBUFFER (XWINDOW (selected_window)->payload))
 	windows_or_buffers_changed = 1;
       /* ... or if we modify an overlay at the end of the buffer
 	 and so we cannot be sure that window end is still valid.  */

=== modified file 'src/dispextern.h'
--- src/dispextern.h	2013-03-19 04:41:53 +0000
+++ src/dispextern.h	2013-03-22 06:16:49 +0000
@@ -1412,25 +1412,24 @@
 
 /* Value is non-zero if window W wants a mode line.  */
 
-#define WINDOW_WANTS_MODELINE_P(W)					\
-     (!MINI_WINDOW_P ((W))						\
-      && !(W)->pseudo_window_p						\
-      && FRAME_WANTS_MODELINE_P (XFRAME (WINDOW_FRAME ((W))))		\
-      && BUFFERP (W->buffer)					\
-      && !NILP (BVAR (XBUFFER (W->buffer), mode_line_format))	\
-      && WINDOW_TOTAL_LINES (W) > 1)
+#define WINDOW_WANTS_MODELINE_P(W)				\
+  (!MINI_WINDOW_P ((W))						\
+   && !(W)->pseudo_window_p					\
+   && FRAME_WANTS_MODELINE_P (XFRAME (WINDOW_FRAME ((W))))	\
+   && BUFFERP (W->payload)					\
+   && !NILP (BVAR (XBUFFER (W->payload), mode_line_format))	\
+   && WINDOW_TOTAL_LINES (W) > 1)
 
 /* Value is true if window W wants a header line.  */
 
-#define WINDOW_WANTS_HEADER_LINE_P(W)					\
-     (!MINI_WINDOW_P ((W))						\
-      && !(W)->pseudo_window_p						\
-      && FRAME_WANTS_MODELINE_P (XFRAME (WINDOW_FRAME ((W))))		\
-      && BUFFERP (W->buffer)					\
-      && !NILP (BVAR (XBUFFER (W->buffer), header_line_format))	\
-      && WINDOW_TOTAL_LINES (W) > 1					\
-      + !NILP (BVAR (XBUFFER (W->buffer), mode_line_format)))
-
+#define WINDOW_WANTS_HEADER_LINE_P(W)				\
+  (!MINI_WINDOW_P ((W))						\
+   && !(W)->pseudo_window_p					\
+   && FRAME_WANTS_MODELINE_P (XFRAME (WINDOW_FRAME ((W))))	\
+   && BUFFERP (W->payload)					\
+   && !NILP (BVAR (XBUFFER (W->payload), header_line_format))	\
+   && WINDOW_TOTAL_LINES (W) > 1				\
+   + !NILP (BVAR (XBUFFER (W->payload), mode_line_format)))
 
 /* Return proper value to be used as baseline offset of font that has
    ASCENT and DESCENT to draw characters by the font at the vertical

=== modified file 'src/dispnew.c'
--- src/dispnew.c	2013-03-20 11:29:37 +0000
+++ src/dispnew.c	2013-03-22 07:19:46 +0000
@@ -223,9 +223,9 @@
 	    "%"pMu": window %p (`%s')%s\n%s",
 	    history_tick++,
 	    w,
-	    ((BUFFERP (w->buffer)
-	      && STRINGP (BVAR (XBUFFER (w->buffer), name)))
-	     ? SSDATA (BVAR (XBUFFER (w->buffer), name))
+	    ((BUFFERP (w->payload)
+	      && STRINGP (BVAR (XBUFFER (w->payload), name)))
+	     ? SSDATA (BVAR (XBUFFER (w->payload), name))
 	     : "???"),
 	    paused_p ? " ***paused***" : "",
 	    msg);
@@ -838,16 +838,8 @@
 {
   while (w)
     {
-      if (!NILP (w->hchild))
-	{
-	  eassert (WINDOWP (w->hchild));
-	  clear_window_matrices (XWINDOW (w->hchild), desired_p);
-	}
-      else if (!NILP (w->vchild))
-	{
-	  eassert (WINDOWP (w->vchild));
-	  clear_window_matrices (XWINDOW (w->vchild), desired_p);
-	}
+      if (WINDOWP (w->payload))
+	clear_window_matrices (XWINDOW (w->payload), desired_p);
       else
 	{
 	  if (desired_p)
@@ -1468,7 +1460,7 @@
   struct glyph_row *row = matrix->rows;
   struct glyph_row *last_text_row = NULL;
   struct buffer *saved = current_buffer;
-  struct buffer *buffer = XBUFFER (w->buffer);
+  struct buffer *buffer = XBUFFER (w->payload);
   int c;
 
   /* This can sometimes happen for a fresh window.  */
@@ -1632,7 +1624,7 @@
      vertically below other windows.  */
   in_horz_combination_p
     = (!NILP (XWINDOW (window)->parent)
-       && !NILP (XWINDOW (XWINDOW (window)->parent)->hchild));
+       && WINDOW_HORIZONTAL_COMBINATION (XWINDOW (XWINDOW (window)->parent)));
 
   /* For WINDOW and all windows on the same level.  */
   do
@@ -1641,12 +1633,8 @@
 
       /* Get the dimension of the window sub-matrix for W, depending
 	 on whether this is a combination or a leaf window.  */
-      if (!NILP (w->hchild))
-	dim = allocate_matrices_for_frame_redisplay (w->hchild, x, y,
-						     dim_only_p,
-						     window_change_flags);
-      else if (!NILP (w->vchild))
-	dim = allocate_matrices_for_frame_redisplay (w->vchild, x, y,
+      if (WINDOWP (w->payload))
+	dim = allocate_matrices_for_frame_redisplay (w->payload, x, y,
 						     dim_only_p,
 						     window_change_flags);
       else
@@ -1788,10 +1776,8 @@
 {
   while (w)
     {
-      if (!NILP (w->vchild))
-	allocate_matrices_for_window_redisplay (XWINDOW (w->vchild));
-      else if (!NILP (w->hchild))
-	allocate_matrices_for_window_redisplay (XWINDOW (w->hchild));
+      if (WINDOWP (w->payload))
+	allocate_matrices_for_window_redisplay (XWINDOW (w->payload));
       else
 	{
 	  /* W is a leaf window.  */
@@ -1863,18 +1849,12 @@
 {
   while (w)
     {
-      if (!NILP (w->hchild))
-	{
-	  if (showing_window_margins_p (XWINDOW (w->hchild)))
-	    return 1;
-	}
-      else if (!NILP (w->vchild))
-	{
-	  if (showing_window_margins_p (XWINDOW (w->vchild)))
-	    return 1;
-	}
-      else if (!NILP (w->left_margin_cols)
-	       || !NILP (w->right_margin_cols))
+      if (WINDOWP (w->payload))
+	{
+	  if (showing_window_margins_p (XWINDOW (w->payload)))
+	    return 1;
+	}
+      else if (!NILP (w->left_margin_cols) || !NILP (w->right_margin_cols))
 	return 1;
 
       w = NILP (w->next) ? 0 : XWINDOW (w->next);
@@ -1895,10 +1875,8 @@
     {
       w = XWINDOW (window);
 
-      if (!NILP (w->hchild))
-	fake_current_matrices (w->hchild);
-      else if (!NILP (w->vchild))
-	fake_current_matrices (w->vchild);
+      if (WINDOWP (w->payload))
+	fake_current_matrices (w->payload);
       else
 	{
 	  int i;
@@ -2236,10 +2214,8 @@
 {
   while (w)
     {
-      if (!NILP (w->hchild))
-	free_window_matrices (XWINDOW (w->hchild));
-      else if (!NILP (w->vchild))
-	free_window_matrices (XWINDOW (w->vchild));
+      if (WINDOWP (w->payload))
+	free_window_matrices (XWINDOW (w->payload));
       else
 	{
 	  /* This is a leaf window.  Free its memory and reset fields
@@ -2372,10 +2348,8 @@
 {
   while (w)
     {
-      if (!NILP (w->hchild))
-	build_frame_matrix_from_window_tree (matrix, XWINDOW (w->hchild));
-      else if (!NILP (w->vchild))
-	build_frame_matrix_from_window_tree (matrix, XWINDOW (w->vchild));
+      if (WINDOWP (w->payload))
+	build_frame_matrix_from_window_tree (matrix, XWINDOW (w->payload));
       else
 	build_frame_matrix_from_leaf_window (matrix, w);
 
@@ -2639,10 +2613,8 @@
 {
   while (w)
     {
-      if (!NILP (w->hchild))
- 	mirror_make_current (XWINDOW (w->hchild), frame_row);
-      else if (!NILP (w->vchild))
-	mirror_make_current (XWINDOW (w->vchild), frame_row);
+      if (WINDOWP (w->payload))
+ 	mirror_make_current (XWINDOW (w->payload), frame_row);
       else
 	{
 	  /* Row relative to window W.  Don't use FRAME_TO_WINDOW_VPOS
@@ -2738,8 +2710,8 @@
   struct glyph_row *window_row, *window_row_end, *frame_row;
   int left, right, x, width;
 
-  /* Preconditions: W must be a leaf window on a tty frame.  */
-  eassert (NILP (w->hchild) && NILP (w->vchild));
+  /* Preconditions: W must be a live window on a tty frame.  */
+  eassert (BUFFERP (w->payload));
   eassert (!FRAME_WINDOW_P (f));
 
   left = margin_glyphs_to_reserve (w, 1, w->left_margin_cols);
@@ -2775,10 +2747,8 @@
 
   while (w && !found)
     {
-      if (!NILP (w->hchild))
- 	found = frame_row_to_window (XWINDOW (w->hchild), row);
-      else if (!NILP (w->vchild))
-	found = frame_row_to_window (XWINDOW (w->vchild), row);
+      if (WINDOWP (w->payload))
+ 	found = frame_row_to_window (XWINDOW (w->payload), row);
       else if (row >= WINDOW_TOP_EDGE_LINE (w)
 	       && row < WINDOW_BOTTOM_EDGE_LINE (w))
 	found = w;
@@ -2806,11 +2776,8 @@
 {
   while (w)
     {
-      if (!NILP (w->hchild))
-	mirror_line_dance (XWINDOW (w->hchild), unchanged_at_top,
-			   nlines, copy_from, retained_p);
-      else if (!NILP (w->vchild))
-	mirror_line_dance (XWINDOW (w->vchild), unchanged_at_top,
+      if (WINDOWP (w->payload))
+	mirror_line_dance (XWINDOW (w->payload), unchanged_at_top,
 			   nlines, copy_from, retained_p);
       else
 	{
@@ -3186,10 +3153,8 @@
 
   while (w && !paused_p)
     {
-      if (!NILP (w->hchild))
-	paused_p |= update_window_tree (XWINDOW (w->hchild), force_p);
-      else if (!NILP (w->vchild))
-	paused_p |= update_window_tree (XWINDOW (w->vchild), force_p);
+      if (WINDOWP (w->payload))
+	paused_p |= update_window_tree (XWINDOW (w->payload), force_p);
       else if (w->must_be_updated_p)
 	paused_p |= update_window (w, force_p);
 
@@ -3967,10 +3932,8 @@
 {
   while (w)
     {
-      if (!NILP (w->hchild))
-	set_window_update_flags (XWINDOW (w->hchild), on_p);
-      else if (!NILP (w->vchild))
-	set_window_update_flags (XWINDOW (w->vchild), on_p);
+      if (WINDOWP (w->payload))
+	set_window_update_flags (XWINDOW (w->payload), on_p);
       else
 	w->must_be_updated_p = on_p;
 
@@ -5117,7 +5080,7 @@
 
   /* We used to set current_buffer directly here, but that does the
      wrong thing with `face-remapping-alist' (bug#2044).  */
-  Fset_buffer (w->buffer);
+  Fset_buffer (w->payload);
   itdata = bidi_shelve_cache ();
   SET_TEXT_POS_FROM_MARKER (startp, w->start);
   CHARPOS (startp) = min (ZV, max (BEGV, CHARPOS (startp)));
@@ -5163,7 +5126,7 @@
   *dx = x0 + it.first_visible_x - it.current_x;
   *dy = *y - it.current_y;
 
-  string =  w->buffer;
+  string = w->payload;
   if (STRINGP (it.string))
     string = it.string;
   *pos = it.current;
@@ -5181,7 +5144,7 @@
       if (STRINGP (it.string))
 	BYTEPOS (pos->pos) = string_char_to_byte (string, CHARPOS (pos->pos));
       else
-	BYTEPOS (pos->pos) = buf_charpos_to_bytepos (XBUFFER (w->buffer),
+	BYTEPOS (pos->pos) = buf_charpos_to_bytepos (XBUFFER (w->payload),
 						     CHARPOS (pos->pos));
     }
 

=== modified file 'src/editfns.c'
--- src/editfns.c	2013-03-21 20:56:22 +0000
+++ src/editfns.c	2013-03-22 06:16:49 +0000
@@ -373,7 +373,7 @@
   if (NILP (object))
     XSETBUFFER (object, current_buffer);
   else if (WINDOWP (object))
-    object = XWINDOW (object)->buffer;
+    object = XWINDOW (object)->payload;
 
   if (!BUFFERP (object))
     /* pos-property only makes sense in buffers right now, since strings
@@ -846,7 +846,7 @@
       ? Fcopy_marker (BVAR (current_buffer, mark), Qnil)
       : Qnil),
      /* Selected window if current buffer is shown in it, nil otherwise.  */
-     ((XBUFFER (XWINDOW (selected_window)->buffer) == current_buffer)
+     ((XBUFFER (XWINDOW (selected_window)->payload) == current_buffer)
       ? selected_window : Qnil),
      BVAR (current_buffer, mark_active));
 }
@@ -915,7 +915,7 @@
   tem = XSAVE_OBJECT (info, 2);
   if (WINDOWP (tem)
       && !EQ (tem, selected_window)
-      && (tem1 = XWINDOW (tem)->buffer,
+      && (tem1 = XWINDOW (tem)->payload,
 	  (/* Window is live...  */
 	   BUFFERP (tem1)
 	   /* ...and it shows the current buffer.  */

=== modified file 'src/fileio.c'
--- src/fileio.c	2013-03-21 20:56:22 +0000
+++ src/fileio.c	2013-03-22 06:16:49 +0000
@@ -3958,7 +3958,7 @@
 
 	  /* If display currently starts at beginning of line,
 	     keep it that way.  */
-	  if (XBUFFER (XWINDOW (selected_window)->buffer) == current_buffer)
+	  if (XBUFFER (XWINDOW (selected_window)->payload) == current_buffer)
 	    XWINDOW (selected_window)->start_at_line_beg = !NILP (Fbolp ());
 
 	  replace_handled = 1;
@@ -4108,7 +4108,7 @@
 
       /* If display currently starts at beginning of line,
 	 keep it that way.  */
-      if (XBUFFER (XWINDOW (selected_window)->buffer) == current_buffer)
+      if (XBUFFER (XWINDOW (selected_window)->payload) == current_buffer)
 	XWINDOW (selected_window)->start_at_line_beg = !NILP (Fbolp ());
 
       /* Replace the chars that we need to replace,

=== modified file 'src/font.c'
--- src/font.c	2013-03-20 09:56:19 +0000
+++ src/font.c	2013-03-22 06:16:49 +0000
@@ -4761,7 +4761,7 @@
 
   if (NILP (string))
     {
-      if (XBUFFER (w->buffer) != current_buffer)
+      if (XBUFFER (w->payload) != current_buffer)
 	error ("Specified window is not displaying the current buffer.");
       CHECK_NUMBER_COERCE_MARKER (position);
       if (! (BEGV <= XINT (position) && XINT (position) < ZV))

=== modified file 'src/frame.c'
--- src/frame.c	2013-03-20 11:29:37 +0000
+++ src/frame.c	2013-03-22 06:29:41 +0000
@@ -159,15 +159,15 @@
   w->total_lines -= n;
 
   /* Handle just the top child in a vertical split.  */
-  if (!NILP (w->vchild))
-    set_menu_bar_lines_1 (w->vchild, n);
-
-  /* Adjust all children in a horizontal split.  */
-  for (window = w->hchild; !NILP (window); window = w->next)
-    {
-      w = XWINDOW (window);
-      set_menu_bar_lines_1 (window, n);
-    }
+  if (WINDOW_VERTICAL_COMBINATION (w))
+    set_menu_bar_lines_1 (w->payload, n);
+  else if (WINDOW_HORIZONTAL_COMBINATION (w))
+    /* Adjust all children in a horizontal split.  */
+    for (window = w->payload; !NILP (window); window = w->next)
+      {
+	w = XWINDOW (window);
+	set_menu_bar_lines_1 (window, n);
+      }
 }
 
 void
@@ -421,7 +421,7 @@
 
   /* Make the chosen minibuffer window display the proper minibuffer,
      unless it is already showing a minibuffer.  */
-  if (NILP (Fmemq (XWINDOW (mini_window)->buffer, Vminibuffer_list)))
+  if (NILP (Fmemq (XWINDOW (mini_window)->payload, Vminibuffer_list)))
     /* Use set_window_buffer instead of Fset_window_buffer (see
        discussion of bug#11984, bug#12025, bug#12026).  */
     set_window_buffer (mini_window,
@@ -1189,7 +1189,7 @@
       /* Use set_window_buffer instead of Fset_window_buffer (see
 	 discussion of bug#11984, bug#12025, bug#12026).  */
       set_window_buffer (sf->minibuffer_window,
-			 XWINDOW (minibuf_window)->buffer, 0, 0);
+			 XWINDOW (minibuf_window)->payload, 0, 0);
       minibuf_window = sf->minibuffer_window;
 
       /* If the dying minibuffer window was selected,
@@ -1593,17 +1593,13 @@
 {
   struct window *w;
 
-  for (;!NILP (window); window = w->next)
+  for (; !NILP (window); window = w->next)
     {
       w = XWINDOW (window);
-
-      if (!NILP (w->buffer))
-	bset_display_time (XBUFFER (w->buffer), Fcurrent_time ());
-
-      if (!NILP (w->vchild))
-	make_frame_visible_1 (w->vchild);
-      if (!NILP (w->hchild))
-	make_frame_visible_1 (w->hchild);
+      if (WINDOWP (w->payload))
+	make_frame_visible_1 (w->payload);
+      else
+	bset_display_time (XBUFFER (w->payload), Fcurrent_time ());
     }
 }
 
@@ -1634,7 +1630,7 @@
       /* Use set_window_buffer instead of Fset_window_buffer (see
 	 discussion of bug#11984, bug#12025, bug#12026).  */
       set_window_buffer (sf->minibuffer_window,
-			 XWINDOW (minibuf_window)->buffer, 0, 0);
+			 XWINDOW (minibuf_window)->payload, 0, 0);
       minibuf_window = sf->minibuffer_window;
     }
 
@@ -1665,7 +1661,7 @@
       /* Use set_window_buffer instead of Fset_window_buffer (see
 	 discussion of bug#11984, bug#12025, bug#12026).  */
       set_window_buffer (sf->minibuffer_window,
-			 XWINDOW (minibuf_window)->buffer, 0, 0);
+			 XWINDOW (minibuf_window)->payload, 0, 0);
       minibuf_window = sf->minibuffer_window;
     }
 

=== modified file 'src/fringe.c'
--- src/fringe.c	2013-01-02 16:13:04 +0000
+++ src/fringe.c	2013-03-22 06:16:49 +0000
@@ -699,7 +699,7 @@
 {
   Lisp_Object cmap, bm = Qnil;
 
-  if ((cmap = BVAR (XBUFFER (w->buffer), fringe_cursor_alist)), !NILP (cmap))
+  if ((cmap = BVAR (XBUFFER (w->payload), fringe_cursor_alist)), !NILP (cmap))
     {
       bm = Fassq (cursor, cmap);
       if (CONSP (bm))
@@ -736,7 +736,7 @@
      If partial, lookup partial bitmap in default value if not found here.
      If not partial, or no partial spec is present, use non-partial bitmap.  */
 
-  if ((cmap = BVAR (XBUFFER (w->buffer), fringe_indicator_alist)), !NILP (cmap))
+  if ((cmap = BVAR (XBUFFER (w->payload), fringe_indicator_alist)), !NILP (cmap))
     {
       bm1 = Fassq (bitmap, cmap);
       if (CONSP (bm1))
@@ -963,7 +963,7 @@
     return 0;
 
   if (!MINI_WINDOW_P (w)
-      && (ind = BVAR (XBUFFER (w->buffer), indicate_buffer_boundaries), !NILP (ind)))
+      && (ind = BVAR (XBUFFER (w->payload), indicate_buffer_boundaries), !NILP (ind)))
     {
       if (EQ (ind, Qleft) || EQ (ind, Qright))
 	boundary_top = boundary_bot = arrow_top = arrow_bot = ind;
@@ -1004,7 +1004,7 @@
 	    {
 	      if (top_ind_rn < 0 && row->visible_height > 0)
 		{
-		  if (MATRIX_ROW_START_CHARPOS (row) <= BUF_BEGV (XBUFFER (w->buffer))
+		  if (MATRIX_ROW_START_CHARPOS (row) <= BUF_BEGV (XBUFFER (w->payload))
 		      && !MATRIX_ROW_PARTIALLY_VISIBLE_AT_TOP_P (w, row))
 		    row->indicate_bob_p = !NILP (boundary_top);
 		  else
@@ -1014,7 +1014,7 @@
 
 	      if (bot_ind_rn < 0)
 		{
-		  if (MATRIX_ROW_END_CHARPOS (row) >= BUF_ZV (XBUFFER (w->buffer))
+		  if (MATRIX_ROW_END_CHARPOS (row) >= BUF_ZV (XBUFFER (w->payload))
 		      && !MATRIX_ROW_PARTIALLY_VISIBLE_AT_BOTTOM_P (w, row))
 		    row->indicate_eob_p = !NILP (boundary_bot), bot_ind_rn = rn;
 		  else if (y + row->height >= yb)
@@ -1024,7 +1024,7 @@
 	}
     }
 
-  empty_pos = BVAR (XBUFFER (w->buffer), indicate_empty_lines);
+  empty_pos = BVAR (XBUFFER (w->payload), indicate_empty_lines);
   if (!NILP (empty_pos) && !EQ (empty_pos, Qright))
     empty_pos = WINDOW_LEFT_FRINGE_WIDTH (w) == 0 ? Qright : Qleft;
 

=== modified file 'src/indent.c'
--- src/indent.c	2013-03-08 09:34:35 +0000
+++ src/indent.c	2013-03-22 06:16:49 +0000
@@ -254,7 +254,7 @@
      the next property change */
   prop = Fget_char_property (position, Qinvisible,
 			     (!NILP (window)
-			      && EQ (XWINDOW (window)->buffer, buffer))
+			      && EQ (XWINDOW (window)->payload, buffer))
 			     ? window : buffer);
   inv_p = TEXT_PROP_MEANS_INVISIBLE (prop);
   /* When counting columns (window == nil), don't skip over ellipsis text.  */
@@ -1826,7 +1826,7 @@
 
   /* If the window contains this buffer, use it for getting text properties.
      Otherwise use the current buffer as arg for doing that.  */
-  if (EQ (w->buffer, Fcurrent_buffer ()))
+  if (EQ (w->payload, Fcurrent_buffer ()))
     text_prop_object = window;
   else
     text_prop_object = Fcurrent_buffer ();
@@ -1979,14 +1979,14 @@
 
   old_buffer = Qnil;
   GCPRO1 (old_buffer);
-  if (XBUFFER (w->buffer) != current_buffer)
+  if (XBUFFER (w->payload) != current_buffer)
     {
       /* Set the window's buffer temporarily to the current buffer.  */
-      old_buffer = w->buffer;
+      old_buffer = w->payload;
       old_charpos = marker_position (w->pointm);
       old_bytepos = marker_byte_position (w->pointm);
       wset_buffer (w, Fcurrent_buffer ());
-      set_marker_both (w->pointm, w->buffer,
+      set_marker_both (w->pointm, w->payload,
 		       BUF_PT (current_buffer), BUF_PT_BYTE (current_buffer));
     }
 
@@ -2139,7 +2139,7 @@
   if (BUFFERP (old_buffer))
     {
       wset_buffer (w, old_buffer);
-      set_marker_both (w->pointm, w->buffer,
+      set_marker_both (w->pointm, w->payload,
 		       old_charpos, old_bytepos);
     }
 

=== modified file 'src/insdel.c'
--- src/insdel.c	2013-03-15 16:03:54 +0000
+++ src/insdel.c	2013-03-22 06:16:49 +0000
@@ -1798,7 +1798,7 @@
 
   /* If we're modifying the buffer other than shown in a selected window,
      let redisplay consider other windows if this buffer is visible.  */
-  if (XBUFFER (XWINDOW (selected_window)->buffer) != current_buffer
+  if (XBUFFER (XWINDOW (selected_window)->payload) != current_buffer
       && buffer_window_count (current_buffer))
     ++windows_or_buffers_changed;
 

=== modified file 'src/keyboard.c'
--- src/keyboard.c	2013-03-13 07:27:34 +0000
+++ src/keyboard.c	2013-03-22 06:16:49 +0000
@@ -833,7 +833,7 @@
   update_mode_lines = 1;
 
   if (command_loop_level
-      && current_buffer != XBUFFER (XWINDOW (selected_window)->buffer))
+      && current_buffer != XBUFFER (XWINDOW (selected_window)->payload))
     buffer = Fcurrent_buffer ();
   else
     buffer = Qnil;
@@ -1395,7 +1395,7 @@
 	Fkill_emacs (Qnil);
 
       /* Make sure the current window's buffer is selected.  */
-      set_buffer_internal (XBUFFER (XWINDOW (selected_window)->buffer));
+      set_buffer_internal (XBUFFER (XWINDOW (selected_window)->payload));
 
       /* Display any malloc warning that just came out.  Use while because
 	 displaying one warning can cause another.  */
@@ -1461,7 +1461,7 @@
       /* A filter may have run while we were reading the input.  */
       if (! FRAME_LIVE_P (XFRAME (selected_frame)))
 	Fkill_emacs (Qnil);
-      set_buffer_internal (XBUFFER (XWINDOW (selected_window)->buffer));
+      set_buffer_internal (XBUFFER (XWINDOW (selected_window)->payload));
 
       ++num_input_keys;
 
@@ -1492,7 +1492,7 @@
 	{
 	  struct buffer *b;
 	  XWINDOW (selected_window)->force_start = 0;
-	  b = XBUFFER (XWINDOW (selected_window)->buffer);
+	  b = XBUFFER (XWINDOW (selected_window)->payload);
 	  BUF_BEG_UNCHANGED (b) = BUF_END_UNCHANGED (b) = 0;
 	}
 
@@ -5142,7 +5142,7 @@
 	  if (STRINGP (string))
 	    string_info = Fcons (string, make_number (charpos));
 	  textpos = (w == XWINDOW (selected_window)
-		     && current_buffer == XBUFFER (w->buffer))
+		     && current_buffer == XBUFFER (w->payload))
 	    ? PT : marker_position (w->pointm);
 
 	  xret = wx;
@@ -9146,9 +9146,9 @@
 		{
 		  if (! FRAME_LIVE_P (XFRAME (selected_frame)))
 		    Fkill_emacs (Qnil);
-		  if (XBUFFER (XWINDOW (selected_window)->buffer)
+		  if (XBUFFER (XWINDOW (selected_window)->payload)
 		      != current_buffer)
-		    Fset_buffer (XWINDOW (selected_window)->buffer);
+		    Fset_buffer (XWINDOW (selected_window)->payload);
 		}
 
 	      goto replay_sequence;
@@ -9196,9 +9196,9 @@
 		 special-event-map, ...) might have switched the current buffer
 		 or the selected window from under us in the mean time.  */
 	      if (fix_current_buffer
-		  && (XBUFFER (XWINDOW (selected_window)->buffer)
+		  && (XBUFFER (XWINDOW (selected_window)->payload)
 		      != current_buffer))
-		Fset_buffer (XWINDOW (selected_window)->buffer);
+		Fset_buffer (XWINDOW (selected_window)->payload);
 	      current_binding = active_maps (first_event);
 	    }
 
@@ -9247,8 +9247,8 @@
 		     not the current buffer.  If we're at the
 		     beginning of a key sequence, switch buffers.  */
 		  if (WINDOWP (window)
-		      && BUFFERP (XWINDOW (window)->buffer)
-		      && XBUFFER (XWINDOW (window)->buffer) != current_buffer)
+		      && BUFFERP (XWINDOW (window)->payload)
+		      && XBUFFER (XWINDOW (window)->payload) != current_buffer)
 		    {
 		      ASET (raw_keybuf, raw_keybuf_count, key);
 		      raw_keybuf_count++;
@@ -9269,7 +9269,7 @@
 
 		      if (! FRAME_LIVE_P (XFRAME (selected_frame)))
 			Fkill_emacs (Qnil);
-		      set_buffer_internal (XBUFFER (XWINDOW (window)->buffer));
+		      set_buffer_internal (XBUFFER (XWINDOW (window)->payload));
 		      goto replay_sequence;
 		    }
 		}

=== modified file 'src/keymap.c'
--- src/keymap.c	2013-03-21 20:56:22 +0000
+++ src/keymap.c	2013-03-22 06:16:49 +0000
@@ -1556,8 +1556,8 @@
       window = POSN_WINDOW (position);
 
       if (WINDOWP (window)
-	  && BUFFERP (XWINDOW (window)->buffer)
-	  && XBUFFER (XWINDOW (window)->buffer) != current_buffer)
+	  && BUFFERP (XWINDOW (window)->payload)
+	  && XBUFFER (XWINDOW (window)->payload) != current_buffer)
 	{
 	  /* Arrange to go back to the original buffer once we're done
 	     processing the key sequence.  We don't use
@@ -1567,7 +1567,7 @@
 	     things the same.
 	  */
 	  record_unwind_current_buffer ();
-	  set_buffer_internal (XBUFFER (XWINDOW (window)->buffer));
+	  set_buffer_internal (XBUFFER (XWINDOW (window)->payload));
 	}
     }
 

=== modified file 'src/minibuf.c'
--- src/minibuf.c	2013-01-02 16:13:04 +0000
+++ src/minibuf.c	2013-03-22 06:16:49 +0000
@@ -114,7 +114,7 @@
       /* Under X, we come here with minibuf_window being the
 	 minibuffer window of the unused termcap window created in
 	 init_window_once.  That window doesn't have a buffer.  */
-      buffer = XWINDOW (minibuf_window)->buffer;
+      buffer = XWINDOW (minibuf_window)->payload;
       if (BUFFERP (buffer))
 	/* Use set_window_buffer instead of Fset_window_buffer (see
 	   discussion of bug#11984, bug#12025, bug#12026).  */
@@ -844,7 +844,7 @@
   window = minibuf_window;
   /* To keep things predictable, in case it matters, let's be in the
      minibuffer when we reset the relevant variables.  */
-  Fset_buffer (XWINDOW (window)->buffer);
+  Fset_buffer (XWINDOW (window)->payload);
 
   /* Restore prompt, etc, from outer minibuffer level.  */
   minibuf_prompt = Fcar (minibuf_save_list);

=== modified file 'src/msdos.c'
--- src/msdos.c	2013-03-06 16:21:26 +0000
+++ src/msdos.c	2013-03-22 06:16:49 +0000
@@ -1261,7 +1261,7 @@
 	  /* If the mouse highlight is in the window that was deleted
 	     (e.g., if it was popped by completion), clear highlight
 	     unconditionally.  */
-	  if (NILP (w->buffer))
+	  if (NILP (w->payload))
 	    hlinfo->mouse_face_window = Qnil;
 	  else
 	    {
@@ -1271,7 +1271,7 @@
 		  break;
 	    }
 
-	  if (NILP (w->buffer) || i < w->desired_matrix->nrows)
+	  if (NILP (w->payload) || i < w->desired_matrix->nrows)
 	    clear_mouse_face (hlinfo);
 	}
     }
@@ -1321,7 +1321,7 @@
     new_cursor = frame_desired_cursor;
   else
     {
-      struct buffer *b = XBUFFER (sw->buffer);
+      struct buffer *b = XBUFFER (sw->payload);
 
       if (EQ (BVAR (b,cursor_type), Qt))
 	new_cursor = frame_desired_cursor;

=== modified file 'src/nsfns.m'
--- src/nsfns.m	2013-03-20 09:56:19 +0000
+++ src/nsfns.m	2013-03-22 06:16:49 +0000
@@ -619,7 +619,7 @@
 {
   NSView *view;
   Lisp_Object name, filename;
-  Lisp_Object buf = XWINDOW (f->selected_window)->buffer;
+  Lisp_Object buf = XWINDOW (f->selected_window)->payload;
   const char *title;
   NSAutoreleasePool *pool;
   struct gcpro gcpro1;

=== modified file 'src/nsmenu.m'
--- src/nsmenu.m	2013-02-05 12:16:35 +0000
+++ src/nsmenu.m	2013-03-22 06:16:49 +0000
@@ -191,7 +191,7 @@
 	= alloca (previous_menu_items_used * sizeof *previous_items);
 
       /* lisp preliminaries */
-      buffer = XWINDOW (FRAME_SELECTED_WINDOW (f))->buffer;
+      buffer = XWINDOW (FRAME_SELECTED_WINDOW (f))->payload;
       specbind (Qinhibit_quit, Qt);
       specbind (Qdebug_on_next_call, Qnil);
       record_unwind_save_match_data ();

=== modified file 'src/nsterm.m'
--- src/nsterm.m	2013-03-16 14:22:37 +0000
+++ src/nsterm.m	2013-03-22 06:16:49 +0000
@@ -6532,7 +6532,7 @@
 {
   Lisp_Object str = Qnil;
   struct frame *f = SELECTED_FRAME ();
-  struct buffer *curbuf = XBUFFER (XWINDOW (f->selected_window)->buffer);
+  struct buffer *curbuf = XBUFFER (XWINDOW (f->selected_window)->payload);
 
   if ([attribute isEqualToString:NSAccessibilityRoleAttribute])
     return NSAccessibilityTextFieldRole;

=== modified file 'src/print.c'
--- src/print.c	2013-03-21 20:56:22 +0000
+++ src/print.c	2013-03-22 06:16:49 +0000
@@ -1769,10 +1769,10 @@
 	  strout ("#<window ", -1, -1, printcharfun);
 	  len = sprintf (buf, "%p", XWINDOW (obj));
 	  strout (buf, len, len, printcharfun);
-	  if (!NILP (XWINDOW (obj)->buffer))
+	  if (BUFFERP (XWINDOW (obj)->payload))
 	    {
 	      strout (" on ", -1, -1, printcharfun);
-	      print_string (BVAR (XBUFFER (XWINDOW (obj)->buffer), name),
+	      print_string (BVAR (XBUFFER (XWINDOW (obj)->payload), name),
 			    printcharfun);
 	    }
 	  PRINTCHAR ('>');

=== modified file 'src/textprop.c'
--- src/textprop.c	2013-03-11 01:17:40 +0000
+++ src/textprop.c	2013-03-22 06:54:28 +0000
@@ -597,8 +597,9 @@
 
   if (WINDOWP (object))
     {
+      CHECK_LIVE_WINDOW (object);
       w = XWINDOW (object);
-      object = w->buffer;
+      object = w->payload;
     }
   if (BUFFERP (object))
     {

=== modified file 'src/w32fns.c'
--- src/w32fns.c	2013-03-20 11:29:37 +0000
+++ src/w32fns.c	2013-03-22 06:16:49 +0000
@@ -5798,7 +5798,7 @@
 
   /* Display the tooltip text in a temporary buffer.  */
   old_buffer = current_buffer;
-  set_buffer_internal_1 (XBUFFER (XWINDOW (FRAME_ROOT_WINDOW (f))->buffer));
+  set_buffer_internal_1 (XBUFFER (XWINDOW (FRAME_ROOT_WINDOW (f))->payload));
   bset_truncate_lines (current_buffer, Qnil);
   clear_glyph_matrix (w->desired_matrix);
   clear_glyph_matrix (w->current_matrix);

=== modified file 'src/w32menu.c'
--- src/w32menu.c	2013-01-02 16:13:04 +0000
+++ src/w32menu.c	2013-03-22 06:16:49 +0000
@@ -396,7 +396,7 @@
       if (! menubar_widget)
 	previous_menu_items_used = 0;
 
-      buffer = XWINDOW (FRAME_SELECTED_WINDOW (f))->buffer;
+      buffer = XWINDOW (FRAME_SELECTED_WINDOW (f))->payload;
       specbind (Qinhibit_quit, Qt);
       /* Don't let the debugger step into this code
 	 because it is not reentrant.  */

=== modified file 'src/window.c'
--- src/window.c	2013-03-20 11:29:37 +0000
+++ src/window.c	2013-03-22 07:23:16 +0000
@@ -147,11 +147,6 @@
   w->display_table = val;
 }
 static void
-wset_hchild (struct window *w, Lisp_Object val)
-{
-  w->hchild = val;
-}
-static void
 wset_left_fringe_width (struct window *w, Lisp_Object val)
 {
   w->left_fringe_width = val;
@@ -217,11 +212,6 @@
   w->temslot = val;
 }
 static void
-wset_vchild (struct window *w, Lisp_Object val)
-{
-  w->vchild = val;
-}
-static void
 wset_vertical_scroll_bar_type (struct window *w, Lisp_Object val)
 {
   w->vertical_scroll_bar_type = val;
@@ -231,6 +221,13 @@
 {
   w->window_parameters = val;
 }
+static void
+wset_combination (struct window *w, bool horflag, Lisp_Object val)
+{
+  w->combination = 1;
+  w->horizontal = horflag;
+  w->payload = val;
+}
 
 struct window *
 decode_live_window (register Lisp_Object window)
@@ -275,9 +272,9 @@
 adjust_window_count (struct window *w, int arg)
 {
   eassert (eabs (arg) == 1);
-  if (BUFFERP (w->buffer))
+  if (BUFFERP (w->payload))
     {
-      struct buffer *b = XBUFFER (w->buffer);
+      struct buffer *b = XBUFFER (w->payload);
 
       if (b->base_buffer)
 	b = b->base_buffer;
@@ -296,7 +293,7 @@
 wset_buffer (struct window *w, Lisp_Object val)
 {
   adjust_window_count (w, -1);
-  w->buffer = val;
+  w->payload = val;
   adjust_window_count (w, 1);
 }
 
@@ -394,15 +391,8 @@
       window = XFRAME (frame_or_window)->root_window;
     }
 
-  while (NILP (XWINDOW (window)->buffer))
-    {
-      if (! NILP (XWINDOW (window)->hchild))
-	window = XWINDOW (window)->hchild;
-      else if (! NILP (XWINDOW (window)->vchild))
-	window = XWINDOW (window)->vchild;
-      else
-	emacs_abort ();
-    }
+  while (WINDOWP (XWINDOW (window)->payload))
+    window = XWINDOW (window)->payload;
 
   return window;
 }
@@ -489,11 +479,11 @@
   if (NILP (norecord))
     {
       w->use_time = ++window_select_count;
-      record_buffer (w->buffer);
+      record_buffer (w->payload);
     }
 
   /* Make the selected window's buffer current.  */
-  Fset_buffer (w->buffer);
+  Fset_buffer (w->payload);
 
   if (EQ (window, selected_window) && !inhibit_point_swap)
     return window;
@@ -516,7 +506,7 @@
 
   select_window_1 (window, inhibit_point_swap);
 
-  bset_last_selected_window (XBUFFER (w->buffer), window);
+  bset_last_selected_window (XBUFFER (w->payload), window);
   windows_or_buffers_changed++;
   return window;
 }
@@ -533,10 +523,10 @@
   if (!inhibit_point_swap)
     {
       struct window *ow = XWINDOW (selected_window);
-      if (! NILP (ow->buffer))
-	set_marker_both (ow->pointm, ow->buffer,
-			 BUF_PT (XBUFFER (ow->buffer)),
-			 BUF_PT_BYTE (XBUFFER (ow->buffer)));
+      if (BUFFERP (ow->payload))
+	set_marker_both (ow->pointm, ow->payload,
+			 BUF_PT (XBUFFER (ow->payload)),
+			 BUF_PT_BYTE (XBUFFER (ow->payload)));
     }
 
   selected_window = window;
@@ -581,7 +571,8 @@
 Return nil for an internal window or a deleted window.  */)
   (Lisp_Object window)
 {
-  return decode_any_window (window)->buffer;
+  struct window *w = decode_any_window (window);
+  return WINDOW_LEAF (w) ? w->payload : Qnil;
 }
 
 DEFUN ("window-parent", Fwindow_parent, Swindow_parent, 0, 1, 0,
@@ -601,7 +592,8 @@
 horizontal combination.  */)
   (Lisp_Object window)
 {
-  return decode_valid_window (window)->vchild;
+  struct window *w = decode_valid_window (window);
+  return WINDOW_VERTICAL_COMBINATION (w) ? w->payload : Qnil;
 }
 
 DEFUN ("window-left-child", Fwindow_left_child, Swindow_left_child, 0, 1, 0,
@@ -612,7 +604,8 @@
 vertical combination.  */)
   (Lisp_Object window)
 {
-  return decode_valid_window (window)->hchild;
+  struct window *w = decode_valid_window (window);
+  return WINDOW_HORIZONTAL_COMBINATION (w) ? w->payload : Qnil;
 }
 
 DEFUN ("window-next-sibling", Fwindow_next_sibling, Swindow_next_sibling, 0, 1, 0,
@@ -645,9 +638,9 @@
 
   CHECK_VALID_WINDOW (window);
   w = XWINDOW (window);
-  if (!NILP (w->buffer))
+  if (WINDOW_LEAF (w))
     error ("Combination limit is meaningful for internal windows only");
-  return XWINDOW (window)->combination_limit;
+  return w->combination_limit;
 }
 
 DEFUN ("set-window-combination-limit", Fset_window_combination_limit, Sset_window_combination_limit, 2, 2, 0,
@@ -663,7 +656,7 @@
 
   CHECK_VALID_WINDOW (window);
   w = XWINDOW (window);
-  if (!NILP (w->buffer))
+  if (WINDOW_LEAF (w))
     error ("Combination limit is meaningful for internal windows only");
   wset_combination_limit (w, limit);
   return limit;
@@ -860,7 +853,7 @@
 
   /* Prevent redisplay shortcuts when changing the hscroll.  */
   if (w->hscroll != new_hscroll)
-    XBUFFER (w->buffer)->prevent_redisplay_optimizations_p = 1;
+    XBUFFER (w->payload)->prevent_redisplay_optimizations_p = 1;
 
   w->hscroll = new_hscroll;
   return make_number (new_hscroll);
@@ -1441,7 +1434,7 @@
   register struct window *w = decode_live_window (window);
 
   if (w == XWINDOW (selected_window))
-    return make_number (BUF_PT (XBUFFER (w->buffer)));
+    return make_number (BUF_PT (XBUFFER (w->payload)));
   else
     return Fmarker_position (w->pointm);
 }
@@ -1483,7 +1476,7 @@
   Lisp_Object buf;
   struct buffer *b;
 
-  buf = w->buffer;
+  buf = w->payload;
   CHECK_BUFFER (buf);
   b = XBUFFER (buf);
 
@@ -1546,7 +1539,7 @@
 
   if (w == XWINDOW (selected_window))
     {
-      if (XBUFFER (w->buffer) == current_buffer)
+      if (XBUFFER (w->payload) == current_buffer)
 	Fgoto_char (pos);
       else
 	{
@@ -1554,14 +1547,14 @@
 
 	  /* ... but here we want to catch type error before buffer change.  */
 	  CHECK_NUMBER_COERCE_MARKER (pos);
-	  set_buffer_internal (XBUFFER (w->buffer));
+	  set_buffer_internal (XBUFFER (w->payload));
 	  Fgoto_char (pos);
 	  set_buffer_internal (old_buffer);
 	}
     }
   else
     {
-      set_marker_restricted (w->pointm, pos, w->buffer);
+      set_marker_restricted (w->pointm, pos, w->payload);
       /* We have to make sure that redisplay updates the window to show
 	 the new value of point.  */
       ++windows_or_buffers_changed;
@@ -1579,7 +1572,7 @@
 {
   register struct window *w = decode_live_window (window);
 
-  set_marker_restricted (w->start, pos, w->buffer);
+  set_marker_restricted (w->start, pos, w->payload);
   /* This is not right, but much easier than doing what is right.  */
   w->start_at_line_beg = 0;
   if (NILP (noforce))
@@ -1623,7 +1616,7 @@
   int x, y;
 
   w = decode_live_window (window);
-  buf = XBUFFER (w->buffer);
+  buf = XBUFFER (w->payload);
   SET_TEXT_POS_FROM_MARKER (top, w->start);
 
   if (EQ (pos, Qt))
@@ -1692,8 +1685,8 @@
   if (noninteractive || w->pseudo_window_p)
     return Qnil;
 
-  CHECK_BUFFER (w->buffer);
-  b = XBUFFER (w->buffer);
+  CHECK_BUFFER (w->payload);
+  b = XBUFFER (w->payload);
 
   /* Fail if current matrix is not up-to-date.  */
   if (!w->window_end_valid
@@ -1919,9 +1912,9 @@
 
   if (DISP_TABLE_P (w->display_table))
     dp = XCHAR_TABLE (w->display_table);
-  else if (BUFFERP (w->buffer))
+  else if (BUFFERP (w->payload))
     {
-      struct buffer *b = XBUFFER (w->buffer);
+      struct buffer *b = XBUFFER (w->payload);
 
       if (DISP_TABLE_P (BVAR (b, display_table)))
 	dp = XCHAR_TABLE (BVAR (b, display_table));
@@ -1946,17 +1939,14 @@
 static void
 unshow_buffer (register struct window *w)
 {
-  Lisp_Object buf;
-  struct buffer *b;
+  Lisp_Object buf = w->payload;
+  struct buffer *b = XBUFFER (buf);
 
-  buf = w->buffer;
-  b = XBUFFER (buf);
-  if (b != XMARKER (w->pointm)->buffer)
-    emacs_abort ();
+  eassert (b == XMARKER (w->pointm)->buffer);
 
 #if 0
   if (w == XWINDOW (selected_window)
-      || ! EQ (buf, XWINDOW (selected_window)->buffer))
+      || ! EQ (buf, XWINDOW (selected_window)->payload))
     /* Do this except when the selected window's buffer
        is being removed from some other window.  */
 #endif
@@ -1972,14 +1962,14 @@
   /* Point in the selected window's buffer
      is actually stored in that buffer, and the window's pointm isn't used.
      So don't clobber point in that buffer.  */
-  if (! EQ (buf, XWINDOW (selected_window)->buffer)
+  if (! EQ (buf, XWINDOW (selected_window)->payload)
       /* Don't clobber point in current buffer either (this could be
 	 useful in connection with bug#12208).
       && XBUFFER (buf) != current_buffer  */
       /* This line helps to fix Horsley's testbug.el bug.  */
       && !(WINDOWP (BVAR (b, last_selected_window))
 	   && w != XWINDOW (BVAR (b, last_selected_window))
-	   && EQ (buf, XWINDOW (BVAR (b, last_selected_window))->buffer)))
+	   && EQ (buf, XWINDOW (BVAR (b, last_selected_window))->payload)))
     temp_set_point_both (b,
 			 clip_to_bounds (BUF_BEGV (b),
 					 marker_position (w->pointm),
@@ -2046,10 +2036,8 @@
   wset_parent (n, tem);
   if (!NILP (tem))
     {
-      if (EQ (XWINDOW (tem)->vchild, old))
-	wset_vchild (XWINDOW (tem), new);
-      if (EQ (XWINDOW (tem)->hchild, old))
-	wset_hchild (XWINDOW (tem), new);
+      if (EQ (XWINDOW (tem)->payload, old))
+	XWINDOW (tem)->payload = new;
     }
 }
 
@@ -2069,22 +2057,18 @@
   if (!NILP (parent) && NILP (w->combination_limit))
     {
       p = XWINDOW (parent);
-      if (((!NILP (p->vchild) && !NILP (w->vchild))
-	   || (!NILP (p->hchild) && !NILP (w->hchild))))
+      if (p->combination == w->combination && p->horizontal == w->horizontal)
 	/* WINDOW and PARENT are both either a vertical or a horizontal
 	   combination.  */
 	{
-	  horflag = NILP (w->vchild);
-	  child = horflag ? w->hchild : w->vchild;
+	  horflag = WINDOW_HORIZONTAL_COMBINATION (w);
+	  child = w->payload;
 	  c = XWINDOW (child);
 
 	  /* Splice WINDOW's children into its parent's children and
 	     assign new normal sizes.  */
 	  if (NILP (w->prev))
-	    if (horflag)
-	      wset_hchild (p, child);
-	    else
-	      wset_vchild (p, child);
+	    wset_combination (p, horflag, child);
 	  else
 	    {
 	      wset_prev (c, w->prev);
@@ -2122,8 +2106,8 @@
 	    }
 
 	  /* WINDOW can be deleted now.  */
-	  wset_vchild (w, Qnil);
-	  wset_hchild (w, Qnil);
+	  eassert (!WINDOW_LEAF (w));
+	  w->payload = Qnil;
 	}
     }
 }
@@ -2209,7 +2193,7 @@
   struct frame *f = XFRAME (w->frame);
   int candidate_p = 1;
 
-  if (!BUFFERP (w->buffer))
+  if (!BUFFERP (w->payload))
     candidate_p = 0;
   else if (MINI_WINDOW_P (w)
            && (EQ (minibuf, Qlambda)
@@ -2613,7 +2597,7 @@
 	switch (type)
 	  {
 	  case GET_BUFFER_WINDOW:
-	    if (EQ (w->buffer, obj)
+	    if (EQ (w->payload, obj)
 		/* Don't find any minibuffer window except the one that
 		   is currently in use.  */
 		&& (MINI_WINDOW_P (w) ? EQ (window, minibuf_window) : 1))
@@ -2637,25 +2621,25 @@
 	  case REPLACE_BUFFER_IN_WINDOWS_SAFELY:
 	    /* We could simply check whether the buffer shown by window
 	       is live, and show another buffer in case it isn't.  */
-	    if (EQ (w->buffer, obj))
+	    if (EQ (w->payload, obj))
 	      {
 		/* Undedicate WINDOW.  */
 		wset_dedicated (w, Qnil);
 		/* Make WINDOW show the buffer returned by
 		   other_buffer_safely, don't run any hooks.  */
 		set_window_buffer
-		  (window, other_buffer_safely (w->buffer), 0, 0);
+		  (window, other_buffer_safely (w->payload), 0, 0);
 		/* If WINDOW is the selected window, make its buffer
 		   current.  But do so only if the window shows the
 		   current buffer (Bug#6454).  */
 		if (EQ (window, selected_window)
-		    && XBUFFER (w->buffer) == current_buffer)
-		  Fset_buffer (w->buffer);
+		    && XBUFFER (w->payload) == current_buffer)
+		  Fset_buffer (w->payload);
 	      }
 	    break;
 
 	  case REDISPLAY_BUFFER_WINDOWS:
-	    if (EQ (w->buffer, obj))
+	    if (EQ (w->payload, obj))
 	      {
 		mark_window_display_accurate (window, 0);
 		w->update_mode_line = 1;
@@ -2667,8 +2651,7 @@
 
 	    /* Check for a window that has a killed buffer.  */
 	  case CHECK_ALL_WINDOWS:
-	    if (! NILP (w->buffer)
-		&& !BUFFER_LIVE_P (XBUFFER (w->buffer)))
+	    if (BUFFERP (w->payload) && !BUFFER_LIVE_P (XBUFFER (w->payload)))
 	      emacs_abort ();
 	    break;
 
@@ -2786,7 +2769,7 @@
   else if (MINI_WINDOW_P (w)) /* && top > 0) */
     error ("Can't expand minibuffer to full frame");
 
-  if (!NILP (w->buffer))
+  if (BUFFERP (w->payload))
     {
       startpos = marker_position (w->start);
       startbyte = marker_byte_position (w->start);
@@ -2858,7 +2841,7 @@
   FRAME_WINDOW_SIZES_CHANGED (f) = 1;
   resize_failed = 0;
 
-  if (NILP (w->buffer))
+  if (!WINDOW_LEAF (w))
     {
       /* Resize child windows vertically.  */
       XSETINT (delta, r->total_lines - w->total_lines);
@@ -2917,28 +2900,20 @@
       sibling = w->next;
       s = XWINDOW (sibling);
       wset_prev (s, Qnil);
-      if (!NILP (XWINDOW (w->parent)->vchild))
-	wset_vchild (XWINDOW (w->parent), sibling);
-      else
-	wset_hchild (XWINDOW (w->parent), sibling);
+      XWINDOW (w->parent)->payload = sibling;
     }
 
   /* Delete ROOT and all child windows of ROOT.  */
-  if (!NILP (r->vchild))
-    {
-      delete_all_child_windows (r->vchild);
-      wset_vchild (r, Qnil);
-    }
-  else if (!NILP (r->hchild))
-    {
-      delete_all_child_windows (r->hchild);
-      wset_hchild (r, Qnil);
+  if (WINDOWP (r->payload))
+    {
+      delete_all_child_windows (r->payload);
+      r->payload = Qnil;
     }
 
   replace_window (root, window, 1);
 
   /* This must become SWINDOW anyway ....... */
-  if (!NILP (w->buffer) && !resize_failed)
+  if (BUFFERP (w->payload) && !resize_failed)
     {
       /* Try to minimize scrolling, by setting the window start to the
 	 point will cause the text at the old window start to be at the
@@ -2947,18 +2922,18 @@
 	 when the display is not current, due to typeahead).  */
       new_top = WINDOW_TOP_EDGE_LINE (w) - FRAME_TOP_MARGIN (XFRAME (WINDOW_FRAME (w)));
       if (new_top != top
-	  && startpos >= BUF_BEGV (XBUFFER (w->buffer))
-	  && startpos <= BUF_ZV (XBUFFER (w->buffer)))
+	  && startpos >= BUF_BEGV (XBUFFER (w->payload))
+	  && startpos <= BUF_ZV (XBUFFER (w->payload)))
 	{
 	  struct position pos;
 	  struct buffer *obuf = current_buffer;
 
-	  Fset_buffer (w->buffer);
+	  Fset_buffer (w->payload);
 	  /* This computation used to temporarily move point, but that
 	     can have unwanted side effects due to text properties.  */
 	  pos = *vmotion (startpos, startbyte, -top, w);
 
-	  set_marker_both (w->start, w->buffer, pos.bufpos, pos.bytepos);
+	  set_marker_both (w->start, w->payload, pos.bufpos, pos.bytepos);
 	  w->window_end_valid = 0;
 	  w->start_at_line_beg = (pos.bytepos == BEGV_BYTE
 				    || FETCH_BYTE (pos.bytepos - 1) == '\n');
@@ -3158,7 +3133,7 @@
   struct window *w = XWINDOW (window);
   struct buffer *b = XBUFFER (buffer);
   ptrdiff_t count = SPECPDL_INDEX ();
-  int samebuf = EQ (buffer, w->buffer);
+  int samebuf = EQ (buffer, w->payload);
 
   wset_buffer (w, buffer);
 
@@ -3277,7 +3252,7 @@
   if (!BUFFER_LIVE_P (XBUFFER (buffer)))
     error ("Attempt to display deleted buffer");
 
-  tem = w->buffer;
+  tem = w->payload;
   if (NILP (tem))
     error ("Window is deleted");
   else
@@ -3330,8 +3305,8 @@
       struct window *w = XWINDOW (object);
       mark_window_display_accurate (object, 0);
       w->update_mode_line = 1;
-      if (BUFFERP (w->buffer))
-	XBUFFER (w->buffer)->prevent_redisplay_optimizations_p = 1;
+      if (BUFFERP (w->payload))
+	XBUFFER (w->payload)->prevent_redisplay_optimizations_p = 1;
       ++update_mode_lines;
       return Qt;
     }
@@ -3400,7 +3375,7 @@
         record_unwind_protect (Fset_buffer, prev_buffer);
         record_unwind_protect (select_window_norecord, prev_window);
         Fselect_window (window, Qt);
-        Fset_buffer (w->buffer);
+        Fset_buffer (w->payload);
         Frun_hooks (1, &Qtemp_buffer_show_hook);
         unbind_to (count, Qnil);
       }
@@ -3421,8 +3396,6 @@
   memcpy ((char *) p + sizeof (struct vectorlike_header),
 	  (char *) o + sizeof (struct vectorlike_header),
 	  word_size * VECSIZE (struct window));
-  /* P's buffer slot may change from nil to a buffer.  */
-  adjust_window_count (p, 1);
   XSETWINDOW (parent, p);
 
   replace_window (window, parent, 1);
@@ -3430,12 +3403,9 @@
   wset_next (o, Qnil);
   wset_prev (o, Qnil);
   wset_parent (o, parent);
-
-  wset_hchild (p, horflag ? window : Qnil);
-  wset_vchild (p, horflag ? Qnil : window);
+  wset_combination (p, horflag, window);
   wset_start (p, Qnil);
   wset_pointm (p, Qnil);
-  wset_buffer (p, Qnil);
   wset_combination_limit (p, Qnil);
   wset_window_parameters (p, Qnil);
 }
@@ -3524,10 +3494,10 @@
 {
   struct window *c;
 
-  if (!NILP (w->vchild))
+  if (WINDOW_VERTICAL_COMBINATION (w))
     /* W is a vertical combination.  */
     {
-      c = XWINDOW (w->vchild);
+      c = XWINDOW (w->payload);
       if (horflag)
 	/* All child windows of W must have the same width as W.  */
 	{
@@ -3555,10 +3525,10 @@
 	  return (sum_of_sizes == XINT (w->new_total));
 	}
     }
-  else if (!NILP (w->hchild))
+  else if (WINDOW_HORIZONTAL_COMBINATION (w))
     /* W is a horizontal combination.  */
     {
-      c = XWINDOW (w->hchild);
+      c = XWINDOW (w->payload);
       if (horflag)
 	/* The sum of the widths of the child windows of W must equal W's
 	   width.  */
@@ -3625,10 +3595,10 @@
       pos = w->top_line;
     }
 
-  if (!NILP (w->vchild))
+  if (WINDOW_VERTICAL_COMBINATION (w))
     /* W is a vertical combination.  */
     {
-      c = XWINDOW (w->vchild);
+      c = XWINDOW (w->payload);
       while (c)
 	{
 	  if (horflag)
@@ -3641,10 +3611,10 @@
 	  c = NILP (c->next) ? 0 : XWINDOW (c->next);
 	}
     }
-  else if (!NILP (w->hchild))
+  else if (WINDOW_HORIZONTAL_COMBINATION (w))
     /* W is a horizontal combination.  */
     {
-      c = XWINDOW (w->hchild);
+      c = XWINDOW (w->payload);
       while (c)
 	{
 	  if (horflag)
@@ -3727,7 +3697,7 @@
 			? 1 : 0)));
 
   r->top_line = FRAME_TOP_MARGIN (f);
-  if (NILP (r->vchild) && NILP (r->hchild))
+  if (WINDOW_LEAF (r))
     /* For a leaf root window just set the size.  */
     if (horflag)
       r->total_cols = new_size;
@@ -3842,9 +3812,9 @@
   combination_limit =
     EQ (Vwindow_combination_limit, Qt)
     || NILP (o->parent)
-    || NILP (horflag
-	     ? (XWINDOW (o->parent)->hchild)
-	     : (XWINDOW (o->parent)->vchild));
+    || (horflag
+	? WINDOW_VERTICAL_COMBINATION (XWINDOW (o->parent))
+	: WINDOW_HORIZONTAL_COMBINATION (XWINDOW (o->parent)));
 
   /* We need a live reference window to initialize some parameters.  */
   if (WINDOW_LIVE_P (old))
@@ -3914,17 +3884,12 @@
   n = XWINDOW (new);
   wset_frame (n, frame);
   wset_parent (n, o->parent);
-  wset_vchild (n, Qnil);
-  wset_hchild (n, Qnil);
 
   if (EQ (side, Qabove) || EQ (side, Qleft))
     {
       wset_prev (n, o->prev);
       if (NILP (n->prev))
-	if (horflag)
-	  wset_hchild (p, new);
-	else
-	  wset_vchild (p, new);
+	wset_combination (p, horflag, new);
       else
 	wset_next (XWINDOW (n->prev), new);
       wset_next (n, old);
@@ -3973,7 +3938,7 @@
   adjust_glyphs (f);
   /* Set buffer of NEW to buffer of reference window.  Don't run
      any hooks.  */
-  set_window_buffer (new, r->buffer, 0, 1);
+  set_window_buffer (new, r->payload, 0, 1);
   unblock_input ();
 
   /* Maybe we should run the scroll functions in Elisp (which already
@@ -3995,13 +3960,11 @@
   register Lisp_Object parent, sibling, frame, root;
   struct window *w, *p, *s, *r;
   struct frame *f;
-  bool horflag;
-  int before_sibling = 0;
+  bool horflag, before_sibling = 0;
 
   w = decode_any_window (window);
   XSETWINDOW (window, w);
-  if (NILP (w->buffer)
-      && NILP (w->hchild) && NILP (w->vchild))
+  if (NILP (w->payload))
     /* It's a no-op to delete an already deleted window.  */
     return Qnil;
 
@@ -4015,7 +3978,7 @@
     error ("Attempt to delete sole window of parent");
 
   p = XWINDOW (parent);
-  horflag = NILP (p->vchild);
+  horflag = WINDOW_HORIZONTAL_COMBINATION (p);
 
   frame = WINDOW_FRAME (w);
   f = XFRAME (frame);
@@ -4033,10 +3996,7 @@
       sibling = w->next;
       s = XWINDOW (sibling);
       wset_prev (s, Qnil);
-      if (horflag)
-	wset_hchild (p, sibling);
-      else
-	wset_vchild (p, sibling);
+      wset_combination (p, horflag, sibling);
     }
   else
     /* Get SIBLING above (on the left of) WINDOW.  */
@@ -4075,17 +4035,12 @@
       wset_next (w, Qnil);  /* Don't delete w->next too.  */
       free_window_matrices (w);
 
-      if (!NILP (w->vchild))
-	{
-	  delete_all_child_windows (w->vchild);
-	  wset_vchild (w, Qnil);
-	}
-      else if (!NILP (w->hchild))
-	{
-	  delete_all_child_windows (w->hchild);
-	  wset_hchild (w, Qnil);
-	}
-      else if (!NILP (w->buffer))
+      if (WINDOWP (w->payload))
+	{
+	  delete_all_child_windows (w->payload);
+	  w->payload = Qnil;
+	}
+      else
 	{
 	  unshow_buffer (w);
 	  unchain_marker (XMARKER (w->pointm));
@@ -4104,8 +4059,8 @@
 	  wset_normal_cols (s, p->normal_cols);
 	  wset_normal_lines (s, p->normal_lines);
 	  /* Mark PARENT as deleted.  */
-	  wset_vchild (p, Qnil);
-	  wset_hchild (p, Qnil);
+	  eassert (!WINDOW_LEAF (p));
+	  p->payload = Qnil;
 	  /* Try to merge SIBLING into its new parent.  */
 	  recombine_windows (sibling);
 	}
@@ -4153,10 +4108,7 @@
       if (before_sibling)
 	{
 	  wset_prev (s, window);
-	  if (horflag)
-	    wset_hchild (p, window);
-	  else
-	    wset_vchild (p, window);
+	  wset_combination (p, horflag, window);
 	}
       else
 	{
@@ -4299,10 +4251,8 @@
 {
   while (w)
     {
-      if (!NILP (w->hchild))
-	mark_window_cursors_off (XWINDOW (w->hchild));
-      else if (!NILP (w->vchild))
-	mark_window_cursors_off (XWINDOW (w->vchild));
+      if (WINDOWP (w->payload))
+	mark_window_cursors_off (XWINDOW (w->payload));
       else
 	w->phys_cursor_on_p = 0;
 
@@ -4321,8 +4271,7 @@
   if (!MINI_WINDOW_P (w))
     {
       if (!NILP (w->parent)
-	  || !NILP (w->vchild)
-	  || !NILP (w->hchild)
+	  || w->combination
 	  || !NILP (w->next)
 	  || !NILP (w->prev)
 	  || WINDOW_WANTS_MODELINE_P (w))
@@ -4461,7 +4410,7 @@
 		  else
 		    spos = min (XINT (Fline_end_position (Qnil)) + 1, ZV);
 		  set_marker_restricted (w->start, make_number (spos),
-					 w->buffer);
+					 w->payload);
 		  w->start_at_line_beg = 1;
 		  w->update_mode_line = 1;
 		  w->last_modified = 0;
@@ -4585,7 +4534,7 @@
 
       /* If control gets here, then we vscrolled.  */
 
-      XBUFFER (w->buffer)->prevent_redisplay_optimizations_p = 1;
+      XBUFFER (w->payload)->prevent_redisplay_optimizations_p = 1;
 
       /* Don't try to change the window start below.  */
       vscrolled = 1;
@@ -4605,7 +4554,7 @@
 	}
 
       /* Set the window start, and set up the window for redisplay.  */
-      set_marker_restricted_both (w->start, w->buffer, IT_CHARPOS (it),
+      set_marker_restricted_both (w->start, w->payload, IT_CHARPOS (it),
 				  IT_BYTEPOS (it));
       bytepos = marker_byte_position (w->start);
       w->start_at_line_beg = (pos == BEGV || FETCH_BYTE (bytepos - 1) == '\n');
@@ -4805,7 +4754,7 @@
       int this_scroll_margin =
 	max (0, min (scroll_margin, w->total_lines / 4));
 
-      set_marker_restricted_both (w->start, w->buffer, pos, pos_byte);
+      set_marker_restricted_both (w->start, w->payload, pos, pos_byte);
       w->start_at_line_beg = !NILP (bolp);
       w->update_mode_line = 1;
       w->last_modified = 0;
@@ -4899,10 +4848,10 @@
 
   /* If selected window's buffer isn't current, make it current for
      the moment.  But don't screw up if window_scroll gets an error.  */
-  if (XBUFFER (XWINDOW (selected_window)->buffer) != current_buffer)
+  if (XBUFFER (XWINDOW (selected_window)->payload) != current_buffer)
     {
       record_unwind_protect (save_excursion_restore, save_excursion_save ());
-      Fset_buffer (XWINDOW (selected_window)->buffer);
+      Fset_buffer (XWINDOW (selected_window)->payload);
 
       /* Make redisplay consider other windows than just selected_window.  */
       ++windows_or_buffers_changed;
@@ -5017,7 +4966,7 @@
   record_unwind_protect (save_excursion_restore, save_excursion_save ());
   ++windows_or_buffers_changed;
 
-  Fset_buffer (w->buffer);
+  Fset_buffer (w->payload);
   SET_PT_BOTH (marker_position (w->pointm), marker_byte_position (w->pointm));
 
   if (NILP (arg))
@@ -5111,10 +5060,10 @@
   int bottom_y;
   void *itdata = NULL;
 
-  if (XBUFFER (w->buffer) != current_buffer)
+  if (XBUFFER (w->payload) != current_buffer)
     {
       old_buffer = current_buffer;
-      set_buffer_internal (XBUFFER (w->buffer));
+      set_buffer_internal (XBUFFER (w->payload));
     }
   else
     old_buffer = NULL;
@@ -5176,7 +5125,7 @@
   (register Lisp_Object arg)
 {
   struct window *w = XWINDOW (selected_window);
-  struct buffer *buf = XBUFFER (w->buffer);
+  struct buffer *buf = XBUFFER (w->payload);
   struct buffer *obuf = current_buffer;
   int center_p = 0;
   ptrdiff_t charpos, bytepos;
@@ -5342,7 +5291,7 @@
     }
 
   /* Set the new window start.  */
-  set_marker_both (w->start, w->buffer, charpos, bytepos);
+  set_marker_both (w->start, w->payload, charpos, bytepos);
   w->window_end_valid = 0;
 
   w->optional_new_start = 1;
@@ -5386,9 +5335,8 @@
   int this_scroll_margin;
 #endif
 
-  if (!(BUFFERP (w->buffer)
-	&& XBUFFER (w->buffer) == current_buffer))
-    /* This test is needed to make sure PT/PT_BYTE make sense in w->buffer
+  if (!(BUFFERP (w->payload) && XBUFFER (w->payload) == current_buffer))
+    /* This test is needed to make sure PT/PT_BYTE make sense in w->payload
        when passed below to set_marker_both.  */
     error ("move-to-window-line called from unrelated buffer");
 
@@ -5398,7 +5346,7 @@
     {
       int height = window_internal_height (w);
       Fvertical_motion (make_number (- (height / 2)), window);
-      set_marker_both (w->start, w->buffer, PT, PT_BYTE);
+      set_marker_both (w->start, w->payload, PT, PT_BYTE);
       w->start_at_line_beg = !NILP (Fbolp ());
       w->force_start = 1;
     }
@@ -5548,9 +5496,9 @@
 	   window-point of the final-selected-window to the window-point of
 	   the current-selected-window.  So we have to be careful which
 	   point of the current-buffer we copy into old_point.  */
-	if (EQ (XWINDOW (data->current_window)->buffer, new_current_buffer)
+	if (EQ (XWINDOW (data->current_window)->payload, new_current_buffer)
 	    && WINDOWP (selected_window)
-	    && EQ (XWINDOW (selected_window)->buffer, new_current_buffer)
+	    && EQ (XWINDOW (selected_window)->payload, new_current_buffer)
 	    && !EQ (selected_window, data->current_window))
 	  old_point = marker_position (XWINDOW (data->current_window)->pointm);
 	else
@@ -5564,7 +5512,7 @@
 	   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 (EQ (XWINDOW (data->current_window)->payload, new_current_buffer)
 	    /* If current_window = selected_window, its point is in BUF_PT.  */
 	    && !EQ (selected_window, data->current_window))
 	  old_point = marker_position (XWINDOW (data->current_window)->pointm);
@@ -5606,8 +5554,8 @@
 	  p = SAVED_WINDOW_N (saved_windows, k);
 	  window = p->window;
 	  w = XWINDOW (window);
-	  if (!NILP (w->buffer)
-	      && !EQ (w->buffer, p->buffer)
+	  if (BUFFERP (w->payload)
+	      && !EQ (w->payload, p->buffer)
 	      && BUFFER_LIVE_P (XBUFFER (p->buffer)))
 	    /* If a window we restore gets another buffer, record the
 	       window's old buffer.  */
@@ -5640,13 +5588,13 @@
 	 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))
+      if (! NILP (XWINDOW (selected_window)->payload))
 	{
 	  w = XWINDOW (selected_window);
 	  set_marker_both (w->pointm,
-			   w->buffer,
-			   BUF_PT (XBUFFER (w->buffer)),
-			   BUF_PT_BYTE (XBUFFER (w->buffer)));
+			   w->payload,
+			   BUF_PT (XBUFFER (w->payload)),
+			   BUF_PT_BYTE (XBUFFER (w->payload)));
 	}
 
       windows_or_buffers_changed++;
@@ -5693,18 +5641,10 @@
 	    {
 	      wset_prev (w, Qnil);
 	      if (!NILP (w->parent))
-		{
-		  if (XINT (p->total_cols) == XWINDOW (w->parent)->total_cols)
-		    {
-		      wset_vchild (XWINDOW (w->parent), p->window);
-		      wset_hchild (XWINDOW (w->parent), Qnil);
-		    }
-		  else
-		    {
-		      wset_hchild (XWINDOW (w->parent), p->window);
-		      wset_vchild (XWINDOW (w->parent), Qnil);
-		    }
-		}
+		wset_combination (XWINDOW (w->parent),
+				  (XINT (p->total_cols)
+				   != XWINDOW (w->parent)->total_cols),
+				  p->window);
 	    }
 
 	  /* If we squirreled away the buffer, restore it now.  */
@@ -5753,20 +5693,16 @@
 	  w->last_modified = 0;
 	  w->last_overlay_modified = 0;
 
-	  /* Reinstall the saved buffer and pointers into it.  */
-	  if (NILP (p->buffer))
-	    /* An internal window.  */
-	    wset_buffer (w, p->buffer);
-	  else if (BUFFER_LIVE_P (XBUFFER (p->buffer)))
+	  if (BUFFERP (p->buffer) && BUFFER_LIVE_P (XBUFFER (p->buffer)))
 	    /* If saved buffer is alive, install it.  */
 	    {
 	      wset_buffer (w, p->buffer);
 	      w->start_at_line_beg = !NILP (p->start_at_line_beg);
-	      set_marker_restricted (w->start, p->start, w->buffer);
+	      set_marker_restricted (w->start, p->start, w->payload);
 	      set_marker_restricted (w->pointm, p->pointm,
-				     w->buffer);
-	      Fset_marker (BVAR (XBUFFER (w->buffer), mark),
-			   p->mark, w->buffer);
+				     w->payload);
+	      Fset_marker (BVAR (XBUFFER (w->payload), mark),
+			   p->mark, w->payload);
 
 	      /* As documented in Fcurrent_window_configuration, don't
 		 restore the location of point in the buffer which was
@@ -5775,23 +5711,21 @@
 		  && XBUFFER (p->buffer) == current_buffer)
 		Fgoto_char (w->pointm);
 	     }
-	   else if (!NILP (w->buffer)
-		    && BUFFER_LIVE_P (XBUFFER (w->buffer)))
-	     /* Keep window's old buffer; make sure the markers are
-		real.  */
-	     {
-	       /* Set window markers at start of visible range.  */
-	       if (XMARKER (w->start)->buffer == 0)
-		 set_marker_restricted_both (w->start, w->buffer, 0, 0);
-	       if (XMARKER (w->pointm)->buffer == 0)
-		 set_marker_restricted_both
-		   (w->pointm, w->buffer,
-		    BUF_PT (XBUFFER (w->buffer)),
-		    BUF_PT_BYTE (XBUFFER (w->buffer)));
-	       w->start_at_line_beg = 1;
-	     }
-	  else
-	    /* Window has no live buffer, get one.  */
+	  else if (BUFFERP (w->payload) && BUFFER_LIVE_P (XBUFFER (w->payload)))
+	    /* Keep window's old buffer; make sure the markers are real.  */
+	    {
+	      /* Set window markers at start of visible range.  */
+	      if (XMARKER (w->start)->buffer == 0)
+		set_marker_restricted_both (w->start, w->payload, 0, 0);
+	      if (XMARKER (w->pointm)->buffer == 0)
+		set_marker_restricted_both
+		  (w->pointm, w->payload,
+		   BUF_PT (XBUFFER (w->payload)),
+		   BUF_PT_BYTE (XBUFFER (w->payload)));
+	      w->start_at_line_beg = 1;
+	    }
+	  else if (WINDOW_LEAF (w))
+	    /* Leaf window has no live buffer, get one.  */
 	    {
 	      /* Get the buffer via other_buffer_safely in order to
 	      avoid showing an unimportant buffer and, if necessary, to
@@ -5800,8 +5734,8 @@
 	      wset_buffer (w, other_buffer_safely (Fcurrent_buffer ()));
 	      /* This will set the markers to beginning of visible
 		 range.  */
-	      set_marker_restricted_both (w->start, w->buffer, 0, 0);
-	      set_marker_restricted_both (w->pointm, w->buffer, 0, 0);
+	      set_marker_restricted_both (w->start, w->payload, 0, 0);
+	      set_marker_restricted_both (w->pointm, w->payload, 0, 0);
 	      w->start_at_line_beg = 1;
 	      if (!NILP (w->dedicated))
 		/* Record this window as dead.  */
@@ -5814,17 +5748,17 @@
       fset_root_window (f, data->root_window);
       /* Arrange *not* to restore point in the buffer that was
 	 current when the window configuration was saved.  */
-      if (EQ (XWINDOW (data->current_window)->buffer, new_current_buffer))
+      if (EQ (XWINDOW (data->current_window)->payload, new_current_buffer))
 	set_marker_restricted (XWINDOW (data->current_window)->pointm,
 			       make_number (old_point),
-			       XWINDOW (data->current_window)->buffer);
+			       XWINDOW (data->current_window)->payload);
 
       /* In the following call to `select-window', prevent "swapping out
 	 point" in the old selected window using the buffer that has
 	 been restored into it.  We already swapped out that point from
 	 that window's old buffer.  */
       select_window (data->current_window, Qnil, 1);
-      BVAR (XBUFFER (XWINDOW (selected_window)->buffer), last_selected_window)
+      BVAR (XBUFFER (XWINDOW (selected_window)->payload), last_selected_window)
 	= selected_window;
 
       if (NILP (data->focus_frame)
@@ -5851,14 +5785,13 @@
       /* Now, free glyph matrices in windows that were not reused.  */
       for (i = n = 0; i < n_leaf_windows; ++i)
 	{
-	  if (NILP (leaf_windows[i]->buffer))
+	  if (NILP (leaf_windows[i]->payload))
 	    {
 	      /* Assert it's not reused as a combination.  */
-	      eassert (NILP (leaf_windows[i]->hchild)
-		       && NILP (leaf_windows[i]->vchild));
+	      eassert (WINDOW_LEAF (leaf_windows[i]));
 	      free_window_matrices (leaf_windows[i]);
 	    }
-	  else if (EQ (leaf_windows[i]->buffer, new_current_buffer))
+	  else if (EQ (leaf_windows[i]->payload, new_current_buffer))
 	    ++n;
 	}
 
@@ -5889,7 +5822,7 @@
       Fset_buffer (new_current_buffer);
       /* If the new current buffer doesn't appear in the selected
 	 window, go to its old point (see bug#12208).  */
-      if (!EQ (XWINDOW (data->current_window)->buffer, new_current_buffer))
+      if (!EQ (XWINDOW (data->current_window)->payload, new_current_buffer))
 	Fgoto_char (make_number (old_point));
     }
 
@@ -5913,17 +5846,12 @@
     /* Delete WINDOW's siblings (we traverse postorderly).  */
     delete_all_child_windows (w->next);
 
-  if (!NILP (w->vchild))
-    {
-      delete_all_child_windows (w->vchild);
-      wset_vchild (w, Qnil);
-    }
-  else if (!NILP (w->hchild))
-    {
-      delete_all_child_windows (w->hchild);
-      wset_hchild (w, Qnil);
-    }
-  else if (!NILP (w->buffer))
+  if (WINDOWP (w->payload))
+    {
+      delete_all_child_windows (w->payload);
+      w->payload = Qnil;
+    }
+  else if (BUFFERP (w->payload))
     {
       unshow_buffer (w);
       unchain_marker (XMARKER (w->pointm));
@@ -5931,7 +5859,7 @@
       /* Since combination limit makes sense for an internal windows
 	 only, we use this slot to save the buffer for the sake of
 	 possible resurrection in Fset_window_configuration.  */
-      wset_combination_limit (w, w->buffer);
+      wset_combination_limit (w, w->payload);
       wset_buffer (w, Qnil);
     }
 
@@ -5944,10 +5872,8 @@
   register int count = 1;
   if (!NILP (window->next))
     count += count_windows (XWINDOW (window->next));
-  if (!NILP (window->vchild))
-    count += count_windows (XWINDOW (window->vchild));
-  if (!NILP (window->hchild))
-    count += count_windows (XWINDOW (window->hchild));
+  if (WINDOWP (window->payload))
+    count += count_windows (XWINDOW (window->payload));
   return count;
 }
 
@@ -5959,10 +5885,8 @@
 {
   while (w)
     {
-      if (!NILP (w->hchild))
-	i = get_leaf_windows (XWINDOW (w->hchild), flat, i);
-      else if (!NILP (w->vchild))
-	i = get_leaf_windows (XWINDOW (w->vchild), flat, i);
+      if (WINDOWP (w->payload))
+	i = get_leaf_windows (XWINDOW (w->payload), flat, i);
       else
 	flat[i++] = w;
 
@@ -6019,14 +5943,14 @@
   register struct window *w;
   register Lisp_Object tem, pers, par;
 
-  for (;!NILP (window); window = w->next)
+  for (; !NILP (window); window = w->next)
     {
       p = SAVED_WINDOW_N (vector, i);
       w = XWINDOW (window);
 
       wset_temslot (w, make_number (i)); i++;
       p->window = window;
-      p->buffer = w->buffer;
+      p->buffer = (WINDOW_LEAF (w) ? w->payload : Qnil);
       p->left_col = make_number (w->left_col);
       p->top_line = make_number (w->top_line);
       p->total_cols = make_number (w->total_cols);
@@ -6093,15 +6017,15 @@
 	    }
 	}
 
-      if (!NILP (w->buffer))
+      if (BUFFERP (w->payload))
 	{
 	  /* 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 = build_marker (XBUFFER (w->buffer),
-				      BUF_PT (XBUFFER (w->buffer)),
-				      BUF_PT_BYTE (XBUFFER (w->buffer)));
+	    p->pointm = build_marker (XBUFFER (w->payload),
+				      BUF_PT (XBUFFER (w->payload)),
+				      BUF_PT_BYTE (XBUFFER (w->payload)));
 	  else
 	    p->pointm = Fcopy_marker (w->pointm, Qnil);
 	  XMARKER (p->pointm)->insertion_type
@@ -6110,7 +6034,7 @@
 	  p->start = Fcopy_marker (w->start, Qnil);
 	  p->start_at_line_beg = w->start_at_line_beg ? Qt : Qnil;
 
-	  tem = BVAR (XBUFFER (w->buffer), mark);
+	  tem = BVAR (XBUFFER (w->payload), mark);
 	  p->mark = Fcopy_marker (tem, Qnil);
 	}
       else
@@ -6131,10 +6055,8 @@
       else
 	p->prev = XWINDOW (w->prev)->temslot;
 
-      if (!NILP (w->vchild))
-	i = save_window_save (w->vchild, vector, i);
-      if (!NILP (w->hchild))
-	i = save_window_save (w->hchild, vector, i);
+      if (WINDOWP (w->payload))
+	i = save_window_save (w->payload, vector, i);
     }
 
   return i;
@@ -6451,7 +6373,7 @@
 	    adjust_glyphs (f);
 
 	  /* Prevent redisplay shortcuts.  */
-	  XBUFFER (w->buffer)->prevent_redisplay_optimizations_p = 1;
+	  XBUFFER (w->payload)->prevent_redisplay_optimizations_p = 1;
 	}
     }
 
@@ -6485,10 +6407,8 @@
 
   for (cont = 1; w && cont;)
     {
-      if (!NILP (w->hchild))
- 	cont = foreach_window_1 (XWINDOW (w->hchild), fn, user_data);
-      else if (!NILP (w->vchild))
- 	cont = foreach_window_1 (XWINDOW (w->vchild), fn, user_data);
+      if (WINDOWP (w->payload))
+ 	cont = foreach_window_1 (XWINDOW (w->payload), fn, user_data);
       else
 	cont = fn (w, user_data);
 

=== modified file 'src/window.h'
--- src/window.h	2013-03-20 11:29:37 +0000
+++ src/window.h	2013-03-22 07:16:09 +0000
@@ -41,14 +41,13 @@
 this can be done implicitly).  Combination windows can be created
 and deleted at any time.
 
-A leaf window has a non-nil buffer field, and also
- has markers in its start and pointm fields.  Non-leaf windows
- have nil in these fields.
+A leaf window has a buffer stored in payload field and markers in its start
+and pointm fields.  Non-leaf windows have nil in the latter two fields.
 
 Non-leaf windows are either vertical or horizontal combinations.
 
 A vertical combination window has children that are arranged on the frame
-one above the next.  Its vchild field points to the uppermost child.
+one above the next.  Its payload field points to the uppermost child.
 The parent field of each of the children points to the vertical
 combination window.  The next field of each child points to the
 child below it, or is nil for the lowest child.  The prev field
@@ -56,7 +55,7 @@
 highest child.
 
 A horizontal combination window has children that are side by side.
-Its hchild field points to the leftmost child.  In each child
+Its payload field points to the leftmost child.  In each child
 the next field points to the child to the right and the prev field
 points to the child to the left.
 
@@ -78,7 +77,7 @@
 minibuffer-only screens, the root window and the minibuffer window are
 one and the same, so its prev and next members are nil.
 
-A dead window has its buffer, hchild, and vchild windows all nil.  */
+A dead window has its payload field set to nil.  */
 
 struct cursor_pos
 {
@@ -102,13 +101,6 @@
     Lisp_Object next;
     Lisp_Object prev;
 
-    /* First child of this window: vchild is used if this is a vertical
-       combination, hchild if this is a horizontal combination.  Of the
-       fields vchild, hchild and buffer, one and only one is non-nil
-       unless the window is dead.  */
-    Lisp_Object hchild;
-    Lisp_Object vchild;
-
     /* The window this one is a child of.  */
     Lisp_Object parent;
 
@@ -123,10 +115,8 @@
     Lisp_Object new_total;
     Lisp_Object new_normal;
 
-    /* The buffer displayed in this window.  Of the fields vchild,
-       hchild and buffer, one and only one is non-nil unless the window
-       is dead.  */
-    Lisp_Object buffer;
+    /* Payload may be buffer, window, or nil.  */
+    Lisp_Object payload;
 
     /* A marker pointing to where in the text to start displaying.
        BIDI Note: This is the _logical-order_ start, i.e. the smallest
@@ -282,6 +272,14 @@
     /* Non-zero if this window is a minibuffer window.  */
     unsigned mini : 1;
 
+    /* Non-zero if this window is internal, e.g. used in either
+       horizontal or vertical combination.  */
+    unsigned combination : 1;
+
+    /* Meaningless for the leaf window, non-zero if this internal
+       window is used in horizontal combination.  */
+    unsigned horizontal : 1;
+
     /* Non-zero means must regenerate mode line of this window.  */
     unsigned update_mode_line : 1;
 
@@ -428,6 +426,21 @@
 
 /* A handy macro.  */
 
+/* Non-zero if W is (can carry the buffer).  */
+
+#define WINDOW_LEAF(W) \
+  (!(W)->combination)
+
+/* Non-zero if W is a member of horizontal combination.  */
+
+#define WINDOW_HORIZONTAL_COMBINATION(W) \
+  ((W)->combination && (W)->horizontal)
+
+/* Non-zero if W is a member of vertical combination.  */
+
+#define WINDOW_VERTICAL_COMBINATION(W) \
+  ((W)->combination && !(W)->horizontal)
+
 #define WINDOW_XFRAME(W) \
   (XFRAME (WINDOW_FRAME ((W))))
 
@@ -926,20 +939,17 @@
 struct glyph *get_phys_cursor_glyph (struct window *w);
 
 /* Value is non-zero if WINDOW is a valid window.  */
-#define WINDOW_VALID_P(WINDOW)				\
-  (WINDOWP (WINDOW)					\
-   && (!NILP (XWINDOW (WINDOW)->buffer)			\
-       || !NILP (XWINDOW (WINDOW)->vchild)		\
-       || !NILP (XWINDOW (WINDOW)->hchild)))
+#define WINDOW_VALID_P(WINDOW)					\
+  (WINDOWP (WINDOW) && !NILP (XWINDOW (WINDOW)->payload))	\
 
-/* A window of any sort, leaf or interior, is "valid" if one
-   of its buffer, vchild, or hchild members is non-nil.  */
+/* A window of any sort, leaf or interior, is "valid" if its payload
+   slot is non-nil.  */
 #define CHECK_VALID_WINDOW(WINDOW)				\
   CHECK_TYPE (WINDOW_VALID_P (WINDOW), Qwindow_valid_p, WINDOW)
 
 /* Value is non-zero if WINDOW is a live window.  */
 #define WINDOW_LIVE_P(WINDOW)					\
-  (WINDOWP (WINDOW) && !NILP (XWINDOW (WINDOW)->buffer))
+  (WINDOWP (WINDOW) && BUFFERP (XWINDOW (WINDOW)->payload))
 
 /* A window is "live" if and only if it shows a buffer.  */
 #define CHECK_LIVE_WINDOW(WINDOW)				\

=== modified file 'src/xdisp.c'
--- src/xdisp.c	2013-03-20 11:29:37 +0000
+++ src/xdisp.c	2013-03-22 06:30:17 +0000
@@ -1283,10 +1283,10 @@
   if (FRAME_INITIAL_P (XFRAME (WINDOW_FRAME (w))))
     return visible_p;
 
-  if (XBUFFER (w->buffer) != current_buffer)
+  if (XBUFFER (w->payload) != current_buffer)
     {
       old_buffer = current_buffer;
-      set_buffer_internal_1 (XBUFFER (w->buffer));
+      set_buffer_internal_1 (XBUFFER (w->payload));
     }
 
   SET_TEXT_POS_FROM_MARKER (top, w->start);
@@ -4458,7 +4458,7 @@
      if it was a text property.  */
 
   if (!STRINGP (it->string))
-    object = it->w->buffer;
+    object = it->w->payload;
 
   display_replaced_p = handle_display_spec (it, propval, object, overlay,
 					    position, bufpos,
@@ -4866,7 +4866,7 @@
 	  it->what = IT_IMAGE;
 	  it->image_id = -1; /* no image */
 	  it->position = start_pos;
-	  it->object = NILP (object) ? it->w->buffer : object;
+	  it->object = NILP (object) ? it->w->payload : object;
 	  it->method = GET_FROM_IMAGE;
 	  it->from_overlay = Qnil;
 	  it->face_id = face_id;
@@ -5012,7 +5012,7 @@
 	  it->what = IT_IMAGE;
 	  it->image_id = lookup_image (it->f, value);
 	  it->position = start_pos;
-	  it->object = NILP (object) ? it->w->buffer : object;
+	  it->object = NILP (object) ? it->w->payload : object;
 	  it->method = GET_FROM_IMAGE;
 
 	  /* Say that we haven't consumed the characters with
@@ -5836,7 +5836,7 @@
       it->object = p->u.stretch.object;
       break;
     case GET_FROM_BUFFER:
-      it->object = it->w->buffer;
+      it->object = it->w->payload;
       break;
     case GET_FROM_STRING:
       it->object = it->string;
@@ -5849,7 +5849,7 @@
       else
 	{
 	  it->method = GET_FROM_BUFFER;
-	  it->object = it->w->buffer;
+	  it->object = it->w->payload;
 	}
     }
   it->end_charpos = p->end_charpos;
@@ -6290,7 +6290,7 @@
   IT_STRING_BYTEPOS (*it) = -1;
   it->string = Qnil;
   it->method = GET_FROM_BUFFER;
-  it->object = it->w->buffer;
+  it->object = it->w->payload;
   it->area = TEXT_AREA;
   it->multibyte_p = !NILP (BVAR (current_buffer, enable_multibyte_characters));
   it->sp = 0;
@@ -7141,7 +7141,7 @@
 	  else
 	    {
 	      it->method = GET_FROM_BUFFER;
-	      it->object = it->w->buffer;
+	      it->object = it->w->payload;
 	    }
 
 	  it->dpvec = NULL;
@@ -7714,7 +7714,7 @@
 	 setting face_before_selective_p.  */
       it->saved_face_id = it->face_id;
       it->method = GET_FROM_BUFFER;
-      it->object = it->w->buffer;
+      it->object = it->w->payload;
       reseat_at_next_visible_line_start (it, 1);
       it->face_before_selective_p = 1;
     }
@@ -7978,7 +7978,7 @@
 
       /* Record what we have and where it came from.  */
       it->what = IT_CHARACTER;
-      it->object = it->w->buffer;
+      it->object = it->w->payload;
       it->position = it->current.pos;
 
       /* Normally we return the character found above, except when we
@@ -8084,7 +8084,7 @@
 	  return 0;
 	}
       it->position = it->current.pos;
-      it->object = it->w->buffer;
+      it->object = it->w->payload;
       it->c = composition_update_it (&it->cmp_it, IT_CHARPOS (*it),
 				     IT_BYTEPOS (*it), Qnil);
     }
@@ -10003,7 +10003,7 @@
   if (w)
     {
       XSETWINDOW (tmp, w); ASET (vector, i, tmp); ++i;
-      ASET (vector, i, w->buffer); ++i;
+      ASET (vector, i, w->payload); ++i;
       ASET (vector, i, make_number (marker_position (w->pointm))); ++i;
       ASET (vector, i, make_number (marker_byte_position (w->pointm))); ++i;
     }
@@ -10255,9 +10255,9 @@
   eassert (MINI_WINDOW_P (w));
 
   /* By default, start display at the beginning.  */
-  set_marker_both (w->start, w->buffer,
-		   BUF_BEGV (XBUFFER (w->buffer)),
-		   BUF_BEGV_BYTE (XBUFFER (w->buffer)));
+  set_marker_both (w->start, w->payload,
+		   BUF_BEGV (XBUFFER (w->payload)),
+		   BUF_BEGV_BYTE (XBUFFER (w->payload)));
 
   /* Don't resize windows while redisplaying a window; it would
      confuse redisplay functions when the size of the window they are
@@ -10284,10 +10284,10 @@
       struct text_pos start;
       struct buffer *old_current_buffer = NULL;
 
-      if (current_buffer != XBUFFER (w->buffer))
+      if (current_buffer != XBUFFER (w->payload))
 	{
 	  old_current_buffer = current_buffer;
-	  set_buffer_internal (XBUFFER (w->buffer));
+	  set_buffer_internal (XBUFFER (w->payload));
 	}
 
       init_iterator (&it, w, BEGV, BEGV_BYTE, NULL, DEFAULT_FACE_ID);
@@ -10736,7 +10736,7 @@
 
 /* Nonzero if W doesn't reflect the actual state of current buffer due
    to its text or overlays change.  FIXME: this may be called when
-   XBUFFER (w->buffer) != current_buffer, which looks suspicious.  */
+   XBUFFER (w->payload) != current_buffer, which looks suspicious.  */
 
 static int
 window_outdated (struct window *w)
@@ -10751,7 +10751,7 @@
 static int
 window_buffer_changed (struct window *w)
 {
-  struct buffer *b = XBUFFER (w->buffer);
+  struct buffer *b = XBUFFER (w->payload);
 
   eassert (BUFFER_LIVE_P (b));
 
@@ -11005,7 +11005,7 @@
 
       Fselect_window (f->selected_window, Qt);
       set_buffer_internal_1
-	(XBUFFER (XWINDOW (f->selected_window)->buffer));
+	(XBUFFER (XWINDOW (f->selected_window)->payload));
       fmt = FRAME_ICONIFIED_P (f) ? Vicon_title_format : Vframe_title_format;
 
       mode_line_target = MODE_LINE_TITLE;
@@ -11124,7 +11124,7 @@
           if (windows_or_buffers_changed
 	      && FRAME_NS_P (f))
             ns_set_doc_edited
-	      (f, Fbuffer_modified_p (XWINDOW (f->selected_window)->buffer));
+	      (f, Fbuffer_modified_p (XWINDOW (f->selected_window)->payload));
 #endif
 	  UNGCPRO;
 	}
@@ -11196,7 +11196,7 @@
 
 	  specbind (Qinhibit_menubar_update, Qt);
 
-	  set_buffer_internal_1 (XBUFFER (w->buffer));
+	  set_buffer_internal_1 (XBUFFER (w->payload));
 	  if (save_match_data)
 	    record_unwind_save_match_data ();
 	  if (NILP (Voverriding_local_map_menu_flag))
@@ -11400,7 +11400,7 @@
 	  /* Set current_buffer to the buffer of the selected
 	     window of the frame, so that we get the right local
 	     keymaps.  */
-	  set_buffer_internal_1 (XBUFFER (w->buffer));
+	  set_buffer_internal_1 (XBUFFER (w->payload));
 
 	  /* Save match data, if we must.  */
 	  if (save_match_data)
@@ -12267,10 +12267,8 @@
     {
       struct window *w = XWINDOW (window);
 
-      if (WINDOWP (w->hchild))
-	hscrolled_p |= hscroll_window_tree (w->hchild);
-      else if (WINDOWP (w->vchild))
-	hscrolled_p |= hscroll_window_tree (w->vchild);
+      if (WINDOWP (w->payload))
+	hscrolled_p |= hscroll_window_tree (w->payload);
       else if (w->cursor.vpos >= 0)
 	{
 	  int h_margin;
@@ -12290,7 +12288,7 @@
 	  /* Scroll when cursor is inside this scroll margin.  */
 	  h_margin = hscroll_margin * WINDOW_FRAME_COLUMN_WIDTH (w);
 
-	  if (!NILP (Fbuffer_local_value (Qauto_hscroll_mode, w->buffer))
+	  if (!NILP (Fbuffer_local_value (Qauto_hscroll_mode, w->payload))
 	      /* For left-to-right rows, hscroll when cursor is either
 		 (i) inside the right hscroll margin, or (ii) if it is
 		 inside the left margin and the window is already
@@ -12325,7 +12323,7 @@
 
 	      /* Find point in a display of infinite width.  */
 	      saved_current_buffer = current_buffer;
-	      current_buffer = XBUFFER (w->buffer);
+	      current_buffer = XBUFFER (w->payload);
 
 	      if (w == XWINDOW (selected_window))
 		pt = PT;
@@ -12378,7 +12376,7 @@
 		 redisplay.  */
 	      if (w->hscroll != hscroll)
 		{
-		  XBUFFER (w->buffer)->prevent_redisplay_optimizations_p = 1;
+		  XBUFFER (w->payload)->prevent_redisplay_optimizations_p = 1;
 		  w->hscroll = hscroll;
 		  hscrolled_p = 1;
 		}
@@ -12467,9 +12465,9 @@
   if (trace_redisplay_p)
     fprintf (stderr, "%p (%s): %s\n",
 	     w,
-	     ((BUFFERP (w->buffer)
-	       && STRINGP (BVAR (XBUFFER (w->buffer), name)))
-	      ? SSDATA (BVAR (XBUFFER (w->buffer), name))
+	     ((BUFFERP (w->payload)
+	       && STRINGP (BVAR (XBUFFER (w->payload), name)))
+	      ? SSDATA (BVAR (XBUFFER (w->payload), name))
 	      : "no buffer"),
 	     method + len);
 }
@@ -12533,8 +12531,8 @@
 	 require to redisplay the whole paragraph.  It might be worthwhile
 	 to find the paragraph limits and widen the range of redisplayed
 	 lines to that, but for now just give up this optimization.  */
-      if (!NILP (BVAR (XBUFFER (w->buffer), bidi_display_reordering))
-	  && NILP (BVAR (XBUFFER (w->buffer), bidi_paragraph_direction)))
+      if (!NILP (BVAR (XBUFFER (w->payload), bidi_display_reordering))
+	  && NILP (BVAR (XBUFFER (w->payload), bidi_paragraph_direction)))
 	unchanged_p = 0;
     }
 
@@ -12757,7 +12755,7 @@
      we set b->clip_changed to 1 to force updating the screen.  If
      b->clip_changed has already been set to 1, we can skip this
      check.  */
-  if (!b->clip_changed && BUFFERP (w->buffer) && w->window_end_valid)
+  if (!b->clip_changed && BUFFERP (w->payload) && w->window_end_valid)
     {
       ptrdiff_t pt;
 
@@ -12766,11 +12764,11 @@
       else
 	pt = marker_position (w->pointm);
 
-      if ((w->current_matrix->buffer != XBUFFER (w->buffer)
+      if ((w->current_matrix->buffer != XBUFFER (w->payload)
 	   || pt != w->last_point)
 	  && check_point_in_composition (w->current_matrix->buffer,
 					 w->last_point,
-					 XBUFFER (w->buffer), pt))
+					 XBUFFER (w->payload), pt))
 	b->clip_changed = 1;
     }
 }
@@ -13025,11 +13023,11 @@
      the whole window.  The assignment to this_line_start_pos prevents
      the optimization directly below this if-statement.  */
   if (((!NILP (Vtransient_mark_mode)
-	&& !NILP (BVAR (XBUFFER (w->buffer), mark_active)))
+	&& !NILP (BVAR (XBUFFER (w->payload), mark_active)))
        != (w->region_showing > 0))
       || (w->region_showing
 	  && w->region_showing
-	  != XINT (Fmarker_position (BVAR (XBUFFER (w->buffer), mark)))))
+	  != XINT (Fmarker_position (BVAR (XBUFFER (w->payload), mark)))))
     CHARPOS (this_line_start_pos) = 0;
 
   /* Optimize the case that only the line containing the cursor in the
@@ -13047,7 +13045,7 @@
       && !FRAME_OBSCURED_P (XFRAME (w->frame))
       /* Make sure recorded data applies to current buffer, etc.  */
       && this_line_buffer == current_buffer
-      && current_buffer == XBUFFER (w->buffer)
+      && current_buffer == XBUFFER (w->payload)
       && !w->force_start
       && !w->optional_new_start
       /* Point must be on the line that we have info recorded about.  */
@@ -13338,7 +13336,7 @@
       Lisp_Object mini_window = FRAME_MINIBUF_WINDOW (sf);
       struct frame *mini_frame;
 
-      displayed_buffer = XBUFFER (XWINDOW (selected_window)->buffer);
+      displayed_buffer = XBUFFER (XWINDOW (selected_window)->payload);
       /* Use list_of_error, not Qerror, so that
 	 we catch only errors and don't run the debugger.  */
       internal_condition_case_1 (redisplay_window_1, selected_window,
@@ -13548,7 +13546,7 @@
 static void
 mark_window_display_accurate_1 (struct window *w, int accurate_p)
 {
-  struct buffer *b = XBUFFER (w->buffer);
+  struct buffer *b = XBUFFER (w->payload);
 
   w->last_modified = accurate_p ? BUF_MODIFF (b) : 0;
   w->last_overlay_modified = accurate_p ? BUF_OVERLAY_MODIFF (b) : 0;
@@ -13595,11 +13593,9 @@
   for (; !NILP (window); window = w->next)
     {
       w = XWINDOW (window);
-      if (!NILP (w->vchild))
-	mark_window_display_accurate (w->vchild, accurate_p);
-      else if (!NILP (w->hchild))
-	mark_window_display_accurate (w->hchild, accurate_p);
-      else if (BUFFERP (w->buffer))
+      if (WINDOWP (w->payload))
+	mark_window_display_accurate (w->payload, accurate_p);
+      else
 	mark_window_display_accurate_1 (w, accurate_p);
     }
 
@@ -13656,13 +13652,11 @@
     {
       struct window *w = XWINDOW (window);
 
-      if (!NILP (w->hchild))
-	redisplay_windows (w->hchild);
-      else if (!NILP (w->vchild))
-	redisplay_windows (w->vchild);
-      else if (!NILP (w->buffer))
+      if (WINDOWP (w->payload))
+	redisplay_windows (w->payload);
+      else
 	{
-	  displayed_buffer = XBUFFER (w->buffer);
+	  displayed_buffer = XBUFFER (w->payload);
 	  /* Use list_of_error, not Qerror, so that
 	     we catch only errors and don't run the debugger.  */
 	  internal_condition_case_1 (redisplay_window_0, window,
@@ -14309,7 +14303,7 @@
 	  && !MATRIX_ROW_CONTINUATION_LINE_P (row)
 	  && row->x == 0)
 	{
-	  this_line_buffer = XBUFFER (w->buffer);
+	  this_line_buffer = XBUFFER (w->payload);
 
 	  CHARPOS (this_line_start_pos)
 	    = MATRIX_ROW_START_CHARPOS (row) + delta;
@@ -14345,7 +14339,7 @@
   struct window *w = XWINDOW (window);
   SET_MARKER_FROM_TEXT_POS (w->start, startp);
 
-  if (current_buffer != XBUFFER (w->buffer))
+  if (current_buffer != XBUFFER (w->payload))
     emacs_abort ();
 
   if (!NILP (Vwindow_scroll_functions))
@@ -14354,7 +14348,7 @@
 			    make_number (CHARPOS (startp)));
       SET_TEXT_POS_FROM_MARKER (startp, w->start);
       /* In case the hook functions switch buffers.  */
-      set_buffer_internal (XBUFFER (w->buffer));
+      set_buffer_internal (XBUFFER (w->payload));
     }
 
   return startp;
@@ -15005,7 +14999,7 @@
 	      must_scroll = 1;
 	    }
 	  else if (rc != CURSOR_MOVEMENT_SUCCESS
-		   && !NILP (BVAR (XBUFFER (w->buffer), bidi_display_reordering)))
+		   && !NILP (BVAR (XBUFFER (w->payload), bidi_display_reordering)))
 	    {
 	      struct glyph_row *row1;
 
@@ -15068,7 +15062,7 @@
 	  else if (scroll_p)
 	    rc = CURSOR_MOVEMENT_MUST_SCROLL;
 	  else if (rc != CURSOR_MOVEMENT_SUCCESS
-		   && !NILP (BVAR (XBUFFER (w->buffer), bidi_display_reordering)))
+		   && !NILP (BVAR (XBUFFER (w->payload), bidi_display_reordering)))
 	    {
 	      /* With bidi-reordered rows, there could be more than
 		 one candidate row whose start and end positions
@@ -15175,7 +15169,7 @@
       || (w == XWINDOW (minibuf_window)
 	  && NILP (echo_area_buffer[0])))
     {
-      struct buffer *buf = XBUFFER (w->buffer);
+      struct buffer *buf = XBUFFER (w->payload);
       whole = BUF_ZV (buf) - BUF_BEGV (buf);
       start = marker_position (w->start) - BUF_BEGV (buf);
       /* I don't think this is guaranteed to be right.  For the
@@ -15209,7 +15203,7 @@
 {
   struct window *w = XWINDOW (window);
   struct frame *f = XFRAME (w->frame);
-  struct buffer *buffer = XBUFFER (w->buffer);
+  struct buffer *buffer = XBUFFER (w->payload);
   struct buffer *old = current_buffer;
   struct text_pos lpoint, opoint, startp;
   int update_mode_line;
@@ -15232,7 +15226,7 @@
   opoint = lpoint;
 
   /* W must be a leaf window here.  */
-  eassert (!NILP (w->buffer));
+  eassert (!NILP (w->payload));
 #ifdef GLYPH_DEBUG
   *w->desired_matrix->method = 0;
 #endif
@@ -15262,10 +15256,10 @@
       else if ((w != XWINDOW (minibuf_window)
 		|| minibuf_level == 0)
 	       /* When buffer is nonempty, redisplay window normally. */
-	       && BUF_Z (XBUFFER (w->buffer)) == BUF_BEG (XBUFFER (w->buffer))
+	       && BUF_Z (XBUFFER (w->payload)) == BUF_BEG (XBUFFER (w->payload))
 	       /* Quail displays non-mini buffers in minibuffer window.
 		  In that case, redisplay the window normally.  */
-	       && !NILP (Fmemq (w->buffer, Vminibuffer_list)))
+	       && !NILP (Fmemq (w->payload, Vminibuffer_list)))
 	{
 	  /* W is a mini-buffer window, but it's not active, so clear
 	     it.  */
@@ -15287,7 +15281,7 @@
      value.  */
   /* Really select the buffer, for the sake of buffer-local
      variables.  */
-  set_buffer_internal_1 (XBUFFER (w->buffer));
+  set_buffer_internal_1 (XBUFFER (w->payload));
 
   current_matrix_up_to_date_p
     = (w->window_end_valid
@@ -16578,7 +16572,7 @@
 		 bidi-reordered glyph rows.  Let set_cursor_from_row
 		 figure out where to put the cursor, and if it fails,
 		 give up.  */
-	      if (!NILP (BVAR (XBUFFER (w->buffer), bidi_display_reordering)))
+	      if (!NILP (BVAR (XBUFFER (w->payload), bidi_display_reordering)))
 		{
 		  if (!set_cursor_from_row (w, row, w->current_matrix,
 					    0, 0, 0, 0))
@@ -16829,7 +16823,7 @@
 
   /* Preconditions: W must be a leaf window and full-width.  Its frame
      must have a frame matrix.  */
-  eassert (NILP (w->hchild) && NILP (w->vchild));
+  eassert (BUFFERP (w->payload));
   eassert (WINDOW_FULL_WIDTH_P (w));
   eassert (!FRAME_WINDOW_P (f));
 
@@ -16871,7 +16865,7 @@
 {
   struct glyph_row *row = start;
   struct glyph_row *best_row = NULL;
-  ptrdiff_t mindif = BUF_ZV (XBUFFER (w->buffer)) + 1;
+  ptrdiff_t mindif = BUF_ZV (XBUFFER (w->payload)) + 1;
   int last_y;
 
   /* If we happen to start on a header-line, skip that.  */
@@ -16907,7 +16901,7 @@
 	{
 	  struct glyph *g;
 
-	  if (NILP (BVAR (XBUFFER (w->buffer), bidi_display_reordering))
+	  if (NILP (BVAR (XBUFFER (w->payload), bidi_display_reordering))
 	      || (!best_row && !row->continued_p))
 	    return row;
 	  /* In bidi-reordered rows, there could be several rows
@@ -17073,7 +17067,7 @@
      wrapped line can change the wrap position, altering the line
      above it.  It might be worthwhile to handle this more
      intelligently, but for now just redisplay from scratch.  */
-  if (!NILP (BVAR (XBUFFER (w->buffer), word_wrap)))
+  if (!NILP (BVAR (XBUFFER (w->payload), word_wrap)))
     GIVE_UP (21);
 
   /* Under bidi reordering, adding or deleting a character in the
@@ -17084,8 +17078,8 @@
      to find the paragraph limits and widen the range of redisplayed
      lines to that, but for now just give up this optimization and
      redisplay from scratch.  */
-  if (!NILP (BVAR (XBUFFER (w->buffer), bidi_display_reordering))
-      && NILP (BVAR (XBUFFER (w->buffer), bidi_paragraph_direction)))
+  if (!NILP (BVAR (XBUFFER (w->payload), bidi_display_reordering))
+      && NILP (BVAR (XBUFFER (w->payload), bidi_paragraph_direction)))
     GIVE_UP (22);
 
   /* Make sure beg_unchanged and end_unchanged are up to date.  Do it
@@ -17950,7 +17944,7 @@
   (Lisp_Object glyphs)
 {
   struct window *w = XWINDOW (selected_window);
-  struct buffer *buffer = XBUFFER (w->buffer);
+  struct buffer *buffer = XBUFFER (w->payload);
 
   fprintf (stderr, "PT = %"pI"d, BEGV = %"pI"d. ZV = %"pI"d\n",
 	   BUF_PT (buffer), BUF_BEGV (buffer), BUF_ZV (buffer));
@@ -18056,7 +18050,7 @@
 get_overlay_arrow_glyph_row (struct window *w, Lisp_Object overlay_arrow_string)
 {
   struct frame *f = XFRAME (WINDOW_FRAME (w));
-  struct buffer *buffer = XBUFFER (w->buffer);
+  struct buffer *buffer = XBUFFER (w->payload);
   struct buffer *old = current_buffer;
   const unsigned char *arrow_string = SDATA (overlay_arrow_string);
   int arrow_len = SCHARS (overlay_arrow_string);
@@ -19263,7 +19257,7 @@
 	      row->glyphs[TEXT_AREA]->charpos = -1;
 	      row->displays_text_p = 0;
 
-	      if (!NILP (BVAR (XBUFFER (it->w->buffer), indicate_empty_lines))
+	      if (!NILP (BVAR (XBUFFER (it->w->payload), indicate_empty_lines))
 		  && (!MINI_WINDOW_P (it->w)
 		      || (minibuf_level && EQ (it->window, minibuf_window))))
 		row->indicate_empty_line_p = 1;
@@ -20079,10 +20073,8 @@
     {
       struct window *w = XWINDOW (window);
 
-      if (WINDOWP (w->hchild))
-	nwindows += redisplay_mode_lines (w->hchild, force);
-      else if (WINDOWP (w->vchild))
-	nwindows += redisplay_mode_lines (w->vchild, force);
+      if (WINDOWP (w->payload))
+	nwindows += redisplay_mode_lines (w->payload, force);
       else if (force
 	       || FRAME_GARBAGED_P (XFRAME (w->frame))
 	       || !MATRIX_MODE_LINE_ROW (w->current_matrix)->enabled_p)
@@ -20092,7 +20084,7 @@
 
 	  /* Set the window's buffer for the mode line display.  */
 	  SET_TEXT_POS (lpoint, PT, PT_BYTE);
-	  set_buffer_internal_1 (XBUFFER (w->buffer));
+	  set_buffer_internal_1 (XBUFFER (w->payload));
 
 	  /* Point refers normally to the selected window.  For any
 	     other window, set up appropriate value.  */
@@ -20874,7 +20866,7 @@
   XSETWINDOW (window, w);
 
   if (NILP (buffer))
-    buffer = w->buffer;
+    buffer = w->payload;
   CHECK_BUFFER (buffer);
 
   /* Make formatting the modeline a non-op when noninteractive, otherwise
@@ -22180,7 +22172,7 @@
 	    return OK_PIXELS (WINDOW_SCROLL_BAR_AREA_WIDTH (it->w));
 	}
 
-      prop = buffer_local_value_1 (prop, it->w->buffer);
+      prop = buffer_local_value_1 (prop, it->w->payload);
       if (EQ (prop, Qunbound))
 	prop = Qnil;
     }
@@ -22232,7 +22224,7 @@
 	      return OK_PIXELS (pixels);
 	    }
 
-	  car = buffer_local_value_1 (car, it->w->buffer);
+	  car = buffer_local_value_1 (car, it->w->payload);
 	  if (EQ (car, Qunbound))
 	    car = Qnil;
 	}
@@ -24082,7 +24074,7 @@
       int n = width;
 
       if (!STRINGP (object))
-	object = it->w->buffer;
+	object = it->w->payload;
 #ifdef HAVE_WINDOW_SYSTEM
       if (FRAME_WINDOW_P (it->f))
 	append_stretch_glyph (it, object, width, height, ascent);
@@ -25478,7 +25470,7 @@
 			int *active_cursor)
 {
   struct frame *f = XFRAME (w->frame);
-  struct buffer *b = XBUFFER (w->buffer);
+  struct buffer *b = XBUFFER (w->payload);
   int cursor_type = DEFAULT_CURSOR;
   Lisp_Object alt_cursor;
   int non_selected = 0;
@@ -26029,10 +26021,8 @@
 {
   while (w)
     {
-      if (!NILP (w->hchild))
-	update_cursor_in_window_tree (XWINDOW (w->hchild), on_p);
-      else if (!NILP (w->vchild))
-	update_cursor_in_window_tree (XWINDOW (w->vchild), on_p);
+      if (WINDOWP (w->payload))
+	update_cursor_in_window_tree (XWINDOW (w->payload), on_p);
       else
 	update_window_cursor (w, on_p);
 
@@ -27278,7 +27268,7 @@
 		{
 		  help_echo_string = help;
 		  XSETWINDOW (help_echo_window, w);
-		  help_echo_object = w->buffer;
+		  help_echo_object = w->payload;
 		  help_echo_pos = charpos;
 		}
 	    }
@@ -27314,7 +27304,7 @@
 	    {
 	      Lisp_Object default_help
 		= buffer_local_value_1 (Qmode_line_default_help_echo,
-					w->buffer);
+					w->payload);
 
 	      if (STRINGP (default_help))
 		{
@@ -27589,7 +27579,7 @@
 
   /* Are we in a window whose display is up to date?
      And verify the buffer's text has not changed.  */
-  b = XBUFFER (w->buffer);
+  b = XBUFFER (w->payload);
   if (part == ON_TEXT
       && w->window_end_valid
       && w->last_modified == BUF_MODIFF (b)
@@ -27798,8 +27788,8 @@
 		  if (pos > 0)
 		    {
 		      mouse_face = get_char_property_and_overlay
-			(make_number (pos), Qmouse_face, w->buffer, &overlay);
-		      buffer = w->buffer;
+			(make_number (pos), Qmouse_face, w->payload, &overlay);
+		      buffer = w->payload;
 		      disp_string = object;
 		    }
 		}
@@ -27912,11 +27902,11 @@
 		    if (p > 0)
 		      {
 			help = Fget_char_property (make_number (p),
-						   Qhelp_echo, w->buffer);
+						   Qhelp_echo, w->payload);
 			if (!NILP (help))
 			  {
 			    charpos = p;
-			    obj = w->buffer;
+			    obj = w->payload;
 			  }
 		      }
 		  }
@@ -27967,7 +27957,7 @@
 		      ptrdiff_t p = string_buffer_position (obj, start);
 		      if (p > 0)
 			pointer = Fget_char_property (make_number (p),
-						      Qpointer, w->buffer);
+						      Qpointer, w->payload);
 		    }
 		}
 	      else if (BUFFERP (obj)
@@ -28410,12 +28400,9 @@
 
   while (w && !FRAME_GARBAGED_P (f))
     {
-      if (!NILP (w->hchild))
-	mouse_face_overwritten_p
-	  |= expose_window_tree (XWINDOW (w->hchild), r);
-      else if (!NILP (w->vchild))
-	mouse_face_overwritten_p
-	  |= expose_window_tree (XWINDOW (w->vchild), r);
+      if (WINDOWP (w->payload))
+	mouse_face_overwritten_p
+	  |= expose_window_tree (XWINDOW (w->payload), r);
       else
 	mouse_face_overwritten_p |= expose_window (w, r);
 

=== modified file 'src/xfaces.c'
--- src/xfaces.c	2013-03-20 09:56:19 +0000
+++ src/xfaces.c	2013-03-22 06:16:49 +0000
@@ -5963,7 +5963,7 @@
 
   /* W must display the current buffer.  We could write this function
      to use the frame and buffer of W, but right now it doesn't.  */
-  /* eassert (XBUFFER (w->buffer) == current_buffer); */
+  /* eassert (XBUFFER (w->payload) == current_buffer); */
 
   XSETFASTINT (position, pos);
 
@@ -5973,9 +5973,9 @@
 
   /* Get the `face' or `mouse_face' text property at POS, and
      determine the next position at which the property changes.  */
-  prop = Fget_text_property (position, propname, w->buffer);
+  prop = Fget_text_property (position, propname, w->payload);
   XSETFASTINT (limit1, (limit < endpos ? limit : endpos));
-  end = Fnext_single_property_change (position, propname, w->buffer, limit1);
+  end = Fnext_single_property_change (position, propname, w->payload, limit1);
   if (INTEGERP (end))
     endpos = XINT (end);
 
@@ -6071,7 +6071,7 @@
 
   /* W must display the current buffer.  We could write this function
      to use the frame and buffer of W, but right now it doesn't.  */
-  /* eassert (XBUFFER (w->buffer) == current_buffer); */
+  /* eassert (XBUFFER (w->payload) == current_buffer); */
 
   XSETFASTINT (position, pos);
 
@@ -6081,9 +6081,9 @@
 
   /* Get the `face' or `mouse_face' text property at POS, and
      determine the next position at which the property changes.  */
-  prop = Fget_text_property (position, propname, w->buffer);
+  prop = Fget_text_property (position, propname, w->payload);
   XSETFASTINT (limit1, (limit < endpos ? limit : endpos));
-  end = Fnext_single_property_change (position, propname, w->buffer, limit1);
+  end = Fnext_single_property_change (position, propname, w->payload, limit1);
   if (INTEGERP (end))
     endpos = XINT (end);
 

=== modified file 'src/xfns.c'
--- src/xfns.c	2013-03-20 11:29:37 +0000
+++ src/xfns.c	2013-03-22 06:16:49 +0000
@@ -5043,7 +5043,7 @@
 
   /* Display the tooltip text in a temporary buffer.  */
   old_buffer = current_buffer;
-  set_buffer_internal_1 (XBUFFER (XWINDOW (FRAME_ROOT_WINDOW (f))->buffer));
+  set_buffer_internal_1 (XBUFFER (XWINDOW (FRAME_ROOT_WINDOW (f))->payload));
   bset_truncate_lines (current_buffer, Qnil);
   clear_glyph_matrix (w->desired_matrix);
   clear_glyph_matrix (w->current_matrix);

=== modified file 'src/xmenu.c'
--- src/xmenu.c	2013-03-21 20:56:22 +0000
+++ src/xmenu.c	2013-03-22 06:16:49 +0000
@@ -976,7 +976,7 @@
       if (! menubar_widget)
 	previous_menu_items_used = 0;
 
-      buffer = XWINDOW (FRAME_SELECTED_WINDOW (f))->buffer;
+      buffer = XWINDOW (FRAME_SELECTED_WINDOW (f))->payload;
       specbind (Qinhibit_quit, Qt);
       /* Don't let the debugger step into this code
 	 because it is not reentrant.  */


^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [RFC] some reworking of struct window
  2013-03-22  6:13   ` [RFC] some reworking of struct window Dmitry Antipov
@ 2013-03-22  8:47     ` Eli Zaretskii
  0 siblings, 0 replies; 16+ messages in thread
From: Eli Zaretskii @ 2013-03-22  8:47 UTC (permalink / raw)
  To: Dmitry Antipov; +Cc: emacs-devel

> Date: Fri, 22 Mar 2013 10:13:42 +0400
> From: Dmitry Antipov <dmantipov@yandex.ru>
> CC: emacs-devel@gnu.org
> 
> On 03/21/2013 10:21 PM, Eli Zaretskii wrote:
> 
> >> @@ -838,16 +838,8 @@
> >>   {
> >>     while (w)
> >>       {
> >> -      if (!NILP (w->hchild))
> >> -	{
> >> -	  eassert (WINDOWP (w->hchild));
> >> -	  clear_window_matrices (XWINDOW (w->hchild), desired_p);
> >> -	}
> >> -      else if (!NILP (w->vchild))
> >> -	{
> >> -	  eassert (WINDOWP (w->vchild));
> >> -	  clear_window_matrices (XWINDOW (w->vchild), desired_p);
> >> -	}
> >> +      if (WINDOWP (w->object))
> >> +	clear_window_matrices (XWINDOW (w->object), desired_p);
> >>         else
> >>   	{
> >>   	  if (desired_p)
> >
> > Here, you effectively lost the assertion that w->object can only be a
> > window or a buffer.  With the new code, if it's neither a window nor a
> > buffer, you will behave as if it were a buffer, without checking.
> 
> No, because clear_window_matrices doesn't check whether w->buffer is not
> nil and call clear_glyph_matrix anyway.

Sorry, I'm not following your reasoning.

> I assume that the most of display-related functions should not be called
> for the deleted windows. E.g. this code just silences possible error:
> 
> if (WINDOWP (w->object))
>    foo (w->object);
> else if (BUFFERP (w->object))
>    bar (w->object);
> 
> The following is better since XBUFFER implies eassert if --enable-checking:
> 
> if (WINDOWP (w->object))
>    foo (w->object);
> else
>    bar (XBUFFER (w->object));
> 
> Or:
> 
> if (WINDOWP (w->object))
>    foo (w->object);
> else if (BUFFERP (w->object))
>    bar (w->object);
> else
>    emacs_abort ();
> 
> The latter example leaves the conditional call to emacs_abort even without
> --enable-checking. I suspect that this is too paranoid, and would prefer:
> 
> eassert (!NILP (w->object));
> if (WINDOWP (w->object))
>    foo (w->object);
> else
>    bar (w->object);

But the latter is only protected against nil objects, while the code
only handles windows and buffers.  Any non-nil Lisp object that is
neither a window nor a buffer will slip the assertion.

If there's an immediate XBUFFER in the 'else' branch, then indeed an
assertion is not needed.  But in many cases, this one included,
there's no such call to XBUFFER at all, or it is much later in the
control flow, which makes it harder to find such bugs.

> >> @@ -2069,22 +2060,18 @@
> >>     if (!NILP (parent) && NILP (w->combination_limit))
> >>       {
> >>         p = XWINDOW (parent);
> >> -      if (((!NILP (p->vchild) && !NILP (w->vchild))
> >> -	   || (!NILP (p->hchild) && !NILP (w->hchild))))
> >> +      if (p->type == w->type && p->type > WINDOW_LEAF)
> >                                     ^^^^^^^^^^^^^^^^^^^^^
> > I think you are not supposed to compare enumerated types, except for
> > equality.  How exactly the compiler assigns numerical values to
> > enumerated types is implementation-defined, I think.
> 
> No.
> 
> "An enumerator with = defines its enumeration constant as the value of the constant
> expression. If the first enumerator has no =, the value of its enumeration constant
> is 0. Each subsequent enumerator with no = defines its enumeration constant as the
> value of the constant expression obtained by adding 1 to the value of the previous
> enumeration constant".
> 
> This is from the latest C99 draft (http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1256.pdf
> 6.7.2.2 "Enumeration specifiers"), but I believe it was so since long time ago.

OK, so what happens if the enumeration is reshuffled at some later
point in time?  And why did you need to use > anyway, when != would do
the same, and be free of the problem altogether?

> >> -  /* P's buffer slot may change from nil to a buffer.  */
> >> -  adjust_window_count (p, 1);
> >
> > Why did you remove this call?
> 
> Because I also remove wset_buffer (p, Qnil) few lines below, and per-buffer window counters
> should be balanced.

Sorry, you lost me here.



^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: Alternate design [Was: Re: [RFC] some reworking of struct window]
  2013-03-22  7:40     ` Alternate design [Was: Re: [RFC] some reworking of struct window] Dmitry Antipov
@ 2013-03-22 13:34       ` Stefan Monnier
  2013-03-25 15:29         ` Dmitry Antipov
  0 siblings, 1 reply; 16+ messages in thread
From: Stefan Monnier @ 2013-03-22 13:34 UTC (permalink / raw)
  To: Dmitry Antipov; +Cc: Eli Zaretskii, emacs-devel

>> Right, we could probably replace window_type by a boolean, used only for
>> the "child is a window" case and indicating whether the split is
>> vertical or horizontal.
> Since at least two people suggests such an alternate design, here is it.

The main motivation, for me, is to eliminate "invalid states"
(e.g. window_type=LEAF but the content is a window).

> -    /* The buffer displayed in this window.  Of the fields vchild,
> -       hchild and buffer, one and only one is non-nil unless the window
> -       is dead.  */
> -    Lisp_Object buffer;
> +    /* Payload may be buffer, window, or nil.  */
> +    Lisp_Object payload;

For me, `payload' is associated with transport (or communication), so it
sounds a bit odd here.  But I won't oppose it (whereas I do oppose "object").

> +    /* Non-zero if this window is internal, e.g. used in either
> +       horizontal or vertical combination.  */
> +    unsigned combination : 1;

Isn't that redundant with BUFFERP (payload)?
I actually prefer the enum form than this one (which adds a fourth
state, basically, instead of removing invalid states).
But I think we can eliminate this `combination', which is better than either.

> +#define WINDOW_LEAF(W) \
> +  (!(W)->combination)

I'd call it WINDOW_LEAF_P since it's a predicate (returns a boolean).

> +#define WINDOW_HORIZONTAL_COMBINATION(W) \
> +  ((W)->combination && (W)->horizontal)

I think this should be (eassert (WINDOWP ((W)->payload)), (W)->horizontal)

> +#define WINDOW_VERTICAL_COMBINATION(W) \
> +  ((W)->combination && !(W)->horizontal)

#define WINDOW_VERTICAL_COMBINATION(W) (!WINDOW_HORIZONTAL_COMBINATION(W))

And we probably should call them both with a "_P" suffix.


        Stefan



^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: Alternate design [Was: Re: [RFC] some reworking of struct window]
  2013-03-22 13:34       ` Stefan Monnier
@ 2013-03-25 15:29         ` Dmitry Antipov
  2013-03-25 19:02           ` Stefan Monnier
  0 siblings, 1 reply; 16+ messages in thread
From: Dmitry Antipov @ 2013-03-25 15:29 UTC (permalink / raw)
  To: Stefan Monnier; +Cc: Eli Zaretskii, emacs-devel

[-- Attachment #1: Type: text/plain, Size: 1310 bytes --]

On 03/22/2013 05:34 PM, Stefan Monnier wrote:

> For me, `payload' is associated with transport (or communication), so it
> sounds a bit odd here.  But I won't oppose it (whereas I do oppose "object").

OK, what about neutral `contained'?

>> +    /* Non-zero if this window is internal, e.g. used in either
>> +       horizontal or vertical combination.  */
>> +    unsigned combination : 1;
>
> Isn't that redundant with BUFFERP (payload)?
> I actually prefer the enum form than this one (which adds a fourth
> state, basically, instead of removing invalid states).
> But I think we can eliminate this `combination', which is better than either.

Yes; this makes the 'previous' (before nil was assigned to W->payload) state
undefined, but it shouldn't be a problem.

>> +#define WINDOW_HORIZONTAL_COMBINATION(W) \
>> +  ((W)->combination && (W)->horizontal)
>
> I think this should be (eassert (WINDOWP ((W)->payload)), (W)->horizontal)

This will require a lot of explicit checking whether W->payload is a window,
for example in Fwindow_top_child and Fwindow_left_child. I believe that we
should treat dead windows as 'typeless' (that is, all of WINDOW_LEAF_P and
WINDOW_xxx_COMBINATION_P should return false for them) and add explicit
eassert where leaf or dead window can cause serious problems.

Dmitry


[-- Attachment #2: window_contained.patch --]
[-- Type: text/plain, Size: 101160 bytes --]

=== modified file 'src/alloc.c'
--- src/alloc.c	2013-03-24 12:59:45 +0000
+++ src/alloc.c	2013-03-25 14:30:42 +0000
@@ -5810,14 +5810,13 @@
 	  case PVEC_WINDOW:
 	    {
 	      struct window *w = (struct window *) ptr;
-	      bool leaf = NILP (w->hchild) && NILP (w->vchild);
 
 	      mark_vectorlike (ptr);
 
-	      /* Mark glyphs for leaf windows.  Marking window
+	      /* Mark glyph matrices, if any.  Marking window
 		 matrices is sufficient because frame matrices
 		 use the same glyph memory.  */
-	      if (leaf && w->current_matrix)
+	      if (w->current_matrix)
 		{
 		  mark_glyph_matrix (w->current_matrix);
 		  mark_glyph_matrix (w->desired_matrix);

=== modified file 'src/buffer.c'
--- src/buffer.c	2013-01-19 20:04:33 +0000
+++ src/buffer.c	2013-03-25 14:24:29 +0000
@@ -1769,7 +1769,7 @@
      since anything can happen within do_yes_or_no_p.  */
 
   /* Don't kill the minibuffer now current.  */
-  if (EQ (buffer, XWINDOW (minibuf_window)->buffer))
+  if (EQ (buffer, XWINDOW (minibuf_window)->contained))
     return Qnil;
 
   /* When we kill an ordinary buffer which shares it's buffer text
@@ -1820,7 +1820,7 @@
   /* If the buffer now current is shown in the minibuffer and our buffer
      is the sole other buffer give up.  */
   XSETBUFFER (tem, current_buffer);
-  if (EQ (tem, XWINDOW (minibuf_window)->buffer)
+  if (EQ (tem, XWINDOW (minibuf_window)->contained)
       && EQ (buffer, Fother_buffer (buffer, Qnil, Qnil)))
     return Qnil;
 
@@ -2394,7 +2394,7 @@
 	   BUF_MARKERS(buf) should either be for `buf' or dead.  */
 	eassert (!m->buffer);
   }
-  { /* Some of the C code expects that w->buffer == w->pointm->buffer.
+  { /* Some of the C code expects that w->contained == w->pointm->buffer.
        So since we just swapped the markers between the two buffers, we need
        to undo the effect of this swap for window markers.  */
     Lisp_Object w = Fselected_window (), ws = Qnil;
@@ -2405,12 +2405,12 @@
       {
 	ws = Fcons (w, ws);
 	if (MARKERP (XWINDOW (w)->pointm)
-	    && (EQ (XWINDOW (w)->buffer, buf1)
-		|| EQ (XWINDOW (w)->buffer, buf2)))
+	    && (EQ (XWINDOW (w)->contained, buf1)
+		|| EQ (XWINDOW (w)->contained, buf2)))
 	  Fset_marker (XWINDOW (w)->pointm,
 		       make_number
-		       (BUF_BEGV (XBUFFER (XWINDOW (w)->buffer))),
-		       XWINDOW (w)->buffer);
+		       (BUF_BEGV (XBUFFER (XWINDOW (w)->contained))),
+		       XWINDOW (w)->contained);
 	w = Fnext_window (w, Qt, Qt);
       }
   }
@@ -3893,7 +3893,7 @@
   if (buffer_window_count (buf) > 0)
     {
       /* ... it's visible in other window than selected,  */
-      if (buf != XBUFFER (XWINDOW (selected_window)->buffer))
+      if (buf != XBUFFER (XWINDOW (selected_window)->contained))
 	windows_or_buffers_changed = 1;
       /* ... or if we modify an overlay at the end of the buffer
 	 and so we cannot be sure that window end is still valid.  */

=== modified file 'src/dispextern.h'
--- src/dispextern.h	2013-03-19 04:41:53 +0000
+++ src/dispextern.h	2013-03-25 14:24:29 +0000
@@ -1412,25 +1412,24 @@
 
 /* Value is non-zero if window W wants a mode line.  */
 
-#define WINDOW_WANTS_MODELINE_P(W)					\
-     (!MINI_WINDOW_P ((W))						\
-      && !(W)->pseudo_window_p						\
-      && FRAME_WANTS_MODELINE_P (XFRAME (WINDOW_FRAME ((W))))		\
-      && BUFFERP (W->buffer)					\
-      && !NILP (BVAR (XBUFFER (W->buffer), mode_line_format))	\
-      && WINDOW_TOTAL_LINES (W) > 1)
+#define WINDOW_WANTS_MODELINE_P(W)				\
+  (!MINI_WINDOW_P ((W))						\
+   && !(W)->pseudo_window_p					\
+   && FRAME_WANTS_MODELINE_P (XFRAME (WINDOW_FRAME ((W))))	\
+   && BUFFERP (W->contained)					\
+   && !NILP (BVAR (XBUFFER (W->contained), mode_line_format))	\
+   && WINDOW_TOTAL_LINES (W) > 1)
 
 /* Value is true if window W wants a header line.  */
 
-#define WINDOW_WANTS_HEADER_LINE_P(W)					\
-     (!MINI_WINDOW_P ((W))						\
-      && !(W)->pseudo_window_p						\
-      && FRAME_WANTS_MODELINE_P (XFRAME (WINDOW_FRAME ((W))))		\
-      && BUFFERP (W->buffer)					\
-      && !NILP (BVAR (XBUFFER (W->buffer), header_line_format))	\
-      && WINDOW_TOTAL_LINES (W) > 1					\
-      + !NILP (BVAR (XBUFFER (W->buffer), mode_line_format)))
-
+#define WINDOW_WANTS_HEADER_LINE_P(W)				\
+  (!MINI_WINDOW_P ((W))						\
+   && !(W)->pseudo_window_p					\
+   && FRAME_WANTS_MODELINE_P (XFRAME (WINDOW_FRAME ((W))))	\
+   && BUFFERP (W->contained)					\
+   && !NILP (BVAR (XBUFFER (W->contained), header_line_format))	\
+   && WINDOW_TOTAL_LINES (W) > 1				\
+   + !NILP (BVAR (XBUFFER (W->contained), mode_line_format)))
 
 /* Return proper value to be used as baseline offset of font that has
    ASCENT and DESCENT to draw characters by the font at the vertical

=== modified file 'src/dispnew.c'
--- src/dispnew.c	2013-03-24 12:59:45 +0000
+++ src/dispnew.c	2013-03-25 14:24:29 +0000
@@ -223,9 +223,9 @@
 	    "%"pMu": window %p (`%s')%s\n%s",
 	    history_tick++,
 	    w,
-	    ((BUFFERP (w->buffer)
-	      && STRINGP (BVAR (XBUFFER (w->buffer), name)))
-	     ? SSDATA (BVAR (XBUFFER (w->buffer), name))
+	    ((BUFFERP (w->contained)
+	      && STRINGP (BVAR (XBUFFER (w->contained), name)))
+	     ? SSDATA (BVAR (XBUFFER (w->contained), name))
 	     : "???"),
 	    paused_p ? " ***paused***" : "",
 	    msg);
@@ -842,16 +842,8 @@
 {
   while (w)
     {
-      if (!NILP (w->hchild))
-	{
-	  eassert (WINDOWP (w->hchild));
-	  clear_window_matrices (XWINDOW (w->hchild), desired_p);
-	}
-      else if (!NILP (w->vchild))
-	{
-	  eassert (WINDOWP (w->vchild));
-	  clear_window_matrices (XWINDOW (w->vchild), desired_p);
-	}
+      if (WINDOWP (w->contained))
+	clear_window_matrices (XWINDOW (w->contained), desired_p);
       else
 	{
 	  if (desired_p)
@@ -1472,7 +1464,7 @@
   struct glyph_row *row = matrix->rows;
   struct glyph_row *last_text_row = NULL;
   struct buffer *saved = current_buffer;
-  struct buffer *buffer = XBUFFER (w->buffer);
+  struct buffer *buffer = XBUFFER (w->contained);
   int c;
 
   /* This can sometimes happen for a fresh window.  */
@@ -1636,7 +1628,7 @@
      vertically below other windows.  */
   in_horz_combination_p
     = (!NILP (XWINDOW (window)->parent)
-       && !NILP (XWINDOW (XWINDOW (window)->parent)->hchild));
+       && WINDOW_HORIZONTAL_COMBINATION_P (XWINDOW (XWINDOW (window)->parent)));
 
   /* For WINDOW and all windows on the same level.  */
   do
@@ -1645,12 +1637,8 @@
 
       /* Get the dimension of the window sub-matrix for W, depending
 	 on whether this is a combination or a leaf window.  */
-      if (!NILP (w->hchild))
-	dim = allocate_matrices_for_frame_redisplay (w->hchild, x, y,
-						     dim_only_p,
-						     window_change_flags);
-      else if (!NILP (w->vchild))
-	dim = allocate_matrices_for_frame_redisplay (w->vchild, x, y,
+      if (WINDOWP (w->contained))
+	dim = allocate_matrices_for_frame_redisplay (w->contained, x, y,
 						     dim_only_p,
 						     window_change_flags);
       else
@@ -1792,10 +1780,8 @@
 {
   while (w)
     {
-      if (!NILP (w->vchild))
-	allocate_matrices_for_window_redisplay (XWINDOW (w->vchild));
-      else if (!NILP (w->hchild))
-	allocate_matrices_for_window_redisplay (XWINDOW (w->hchild));
+      if (WINDOWP (w->contained))
+	allocate_matrices_for_window_redisplay (XWINDOW (w->contained));
       else
 	{
 	  /* W is a leaf window.  */
@@ -1867,18 +1853,12 @@
 {
   while (w)
     {
-      if (!NILP (w->hchild))
-	{
-	  if (showing_window_margins_p (XWINDOW (w->hchild)))
-	    return 1;
-	}
-      else if (!NILP (w->vchild))
-	{
-	  if (showing_window_margins_p (XWINDOW (w->vchild)))
-	    return 1;
-	}
-      else if (!NILP (w->left_margin_cols)
-	       || !NILP (w->right_margin_cols))
+      if (WINDOWP (w->contained))
+	{
+	  if (showing_window_margins_p (XWINDOW (w->contained)))
+	    return 1;
+	}
+      else if (!NILP (w->left_margin_cols) || !NILP (w->right_margin_cols))
 	return 1;
 
       w = NILP (w->next) ? 0 : XWINDOW (w->next);
@@ -1899,10 +1879,8 @@
     {
       w = XWINDOW (window);
 
-      if (!NILP (w->hchild))
-	fake_current_matrices (w->hchild);
-      else if (!NILP (w->vchild))
-	fake_current_matrices (w->vchild);
+      if (WINDOWP (w->contained))
+	fake_current_matrices (w->contained);
       else
 	{
 	  int i;
@@ -2242,10 +2220,8 @@
 {
   while (w)
     {
-      if (!NILP (w->hchild))
-	free_window_matrices (XWINDOW (w->hchild));
-      else if (!NILP (w->vchild))
-	free_window_matrices (XWINDOW (w->vchild));
+      if (WINDOWP (w->contained))
+	free_window_matrices (XWINDOW (w->contained));
       else
 	{
 	  /* This is a leaf window.  Free its memory and reset fields
@@ -2378,10 +2354,8 @@
 {
   while (w)
     {
-      if (!NILP (w->hchild))
-	build_frame_matrix_from_window_tree (matrix, XWINDOW (w->hchild));
-      else if (!NILP (w->vchild))
-	build_frame_matrix_from_window_tree (matrix, XWINDOW (w->vchild));
+      if (WINDOWP (w->contained))
+	build_frame_matrix_from_window_tree (matrix, XWINDOW (w->contained));
       else
 	build_frame_matrix_from_leaf_window (matrix, w);
 
@@ -2645,10 +2619,8 @@
 {
   while (w)
     {
-      if (!NILP (w->hchild))
- 	mirror_make_current (XWINDOW (w->hchild), frame_row);
-      else if (!NILP (w->vchild))
-	mirror_make_current (XWINDOW (w->vchild), frame_row);
+      if (WINDOWP (w->contained))
+ 	mirror_make_current (XWINDOW (w->contained), frame_row);
       else
 	{
 	  /* Row relative to window W.  Don't use FRAME_TO_WINDOW_VPOS
@@ -2744,8 +2716,8 @@
   struct glyph_row *window_row, *window_row_end, *frame_row;
   int left, right, x, width;
 
-  /* Preconditions: W must be a leaf window on a tty frame.  */
-  eassert (NILP (w->hchild) && NILP (w->vchild));
+  /* Preconditions: W must be a live window on a tty frame.  */
+  eassert (BUFFERP (w->contained));
   eassert (!FRAME_WINDOW_P (f));
 
   left = margin_glyphs_to_reserve (w, 1, w->left_margin_cols);
@@ -2781,10 +2753,8 @@
 
   while (w && !found)
     {
-      if (!NILP (w->hchild))
- 	found = frame_row_to_window (XWINDOW (w->hchild), row);
-      else if (!NILP (w->vchild))
-	found = frame_row_to_window (XWINDOW (w->vchild), row);
+      if (WINDOWP (w->contained))
+ 	found = frame_row_to_window (XWINDOW (w->contained), row);
       else if (row >= WINDOW_TOP_EDGE_LINE (w)
 	       && row < WINDOW_BOTTOM_EDGE_LINE (w))
 	found = w;
@@ -2812,11 +2782,8 @@
 {
   while (w)
     {
-      if (!NILP (w->hchild))
-	mirror_line_dance (XWINDOW (w->hchild), unchanged_at_top,
-			   nlines, copy_from, retained_p);
-      else if (!NILP (w->vchild))
-	mirror_line_dance (XWINDOW (w->vchild), unchanged_at_top,
+      if (WINDOWP (w->contained))
+	mirror_line_dance (XWINDOW (w->contained), unchanged_at_top,
 			   nlines, copy_from, retained_p);
       else
 	{
@@ -3194,10 +3161,8 @@
 
   while (w && !paused_p)
     {
-      if (!NILP (w->hchild))
-	paused_p |= update_window_tree (XWINDOW (w->hchild), force_p);
-      else if (!NILP (w->vchild))
-	paused_p |= update_window_tree (XWINDOW (w->vchild), force_p);
+      if (WINDOWP (w->contained))
+	paused_p |= update_window_tree (XWINDOW (w->contained), force_p);
       else if (w->must_be_updated_p)
 	paused_p |= update_window (w, force_p);
 
@@ -3975,10 +3940,8 @@
 {
   while (w)
     {
-      if (!NILP (w->hchild))
-	set_window_update_flags (XWINDOW (w->hchild), on_p);
-      else if (!NILP (w->vchild))
-	set_window_update_flags (XWINDOW (w->vchild), on_p);
+      if (WINDOWP (w->contained))
+	set_window_update_flags (XWINDOW (w->contained), on_p);
       else
 	w->must_be_updated_p = on_p;
 
@@ -5125,7 +5088,7 @@
 
   /* We used to set current_buffer directly here, but that does the
      wrong thing with `face-remapping-alist' (bug#2044).  */
-  Fset_buffer (w->buffer);
+  Fset_buffer (w->contained);
   itdata = bidi_shelve_cache ();
   SET_TEXT_POS_FROM_MARKER (startp, w->start);
   CHARPOS (startp) = min (ZV, max (BEGV, CHARPOS (startp)));
@@ -5171,7 +5134,7 @@
   *dx = x0 + it.first_visible_x - it.current_x;
   *dy = *y - it.current_y;
 
-  string =  w->buffer;
+  string = w->contained;
   if (STRINGP (it.string))
     string = it.string;
   *pos = it.current;
@@ -5189,7 +5152,7 @@
       if (STRINGP (it.string))
 	BYTEPOS (pos->pos) = string_char_to_byte (string, CHARPOS (pos->pos));
       else
-	BYTEPOS (pos->pos) = buf_charpos_to_bytepos (XBUFFER (w->buffer),
+	BYTEPOS (pos->pos) = buf_charpos_to_bytepos (XBUFFER (w->contained),
 						     CHARPOS (pos->pos));
     }
 

=== modified file 'src/editfns.c'
--- src/editfns.c	2013-03-24 12:59:45 +0000
+++ src/editfns.c	2013-03-25 14:24:29 +0000
@@ -373,7 +373,7 @@
   if (NILP (object))
     XSETBUFFER (object, current_buffer);
   else if (WINDOWP (object))
-    object = XWINDOW (object)->buffer;
+    object = XWINDOW (object)->contained;
 
   if (!BUFFERP (object))
     /* pos-property only makes sense in buffers right now, since strings
@@ -846,7 +846,7 @@
       ? Fcopy_marker (BVAR (current_buffer, mark), Qnil)
       : Qnil),
      /* Selected window if current buffer is shown in it, nil otherwise.  */
-     ((XBUFFER (XWINDOW (selected_window)->buffer) == current_buffer)
+     ((XBUFFER (XWINDOW (selected_window)->contained) == current_buffer)
       ? selected_window : Qnil),
      BVAR (current_buffer, mark_active));
 }
@@ -915,7 +915,7 @@
   tem = XSAVE_OBJECT (info, 2);
   if (WINDOWP (tem)
       && !EQ (tem, selected_window)
-      && (tem1 = XWINDOW (tem)->buffer,
+      && (tem1 = XWINDOW (tem)->contained,
 	  (/* Window is live...  */
 	   BUFFERP (tem1)
 	   /* ...and it shows the current buffer.  */

=== modified file 'src/fileio.c'
--- src/fileio.c	2013-03-24 12:59:45 +0000
+++ src/fileio.c	2013-03-25 14:24:29 +0000
@@ -3958,7 +3958,7 @@
 
 	  /* If display currently starts at beginning of line,
 	     keep it that way.  */
-	  if (XBUFFER (XWINDOW (selected_window)->buffer) == current_buffer)
+	  if (XBUFFER (XWINDOW (selected_window)->contained) == current_buffer)
 	    XWINDOW (selected_window)->start_at_line_beg = !NILP (Fbolp ());
 
 	  replace_handled = 1;
@@ -4108,7 +4108,7 @@
 
       /* If display currently starts at beginning of line,
 	 keep it that way.  */
-      if (XBUFFER (XWINDOW (selected_window)->buffer) == current_buffer)
+      if (XBUFFER (XWINDOW (selected_window)->contained) == current_buffer)
 	XWINDOW (selected_window)->start_at_line_beg = !NILP (Fbolp ());
 
       /* Replace the chars that we need to replace,

=== modified file 'src/font.c'
--- src/font.c	2013-03-24 12:59:45 +0000
+++ src/font.c	2013-03-25 14:24:29 +0000
@@ -4761,7 +4761,7 @@
 
   if (NILP (string))
     {
-      if (XBUFFER (w->buffer) != current_buffer)
+      if (XBUFFER (w->contained) != current_buffer)
 	error ("Specified window is not displaying the current buffer.");
       CHECK_NUMBER_COERCE_MARKER (position);
       if (! (BEGV <= XINT (position) && XINT (position) < ZV))

=== modified file 'src/frame.c'
--- src/frame.c	2013-03-24 12:59:45 +0000
+++ src/frame.c	2013-03-25 14:24:29 +0000
@@ -159,15 +159,15 @@
   w->total_lines -= n;
 
   /* Handle just the top child in a vertical split.  */
-  if (!NILP (w->vchild))
-    set_menu_bar_lines_1 (w->vchild, n);
-
-  /* Adjust all children in a horizontal split.  */
-  for (window = w->hchild; !NILP (window); window = w->next)
-    {
-      w = XWINDOW (window);
-      set_menu_bar_lines_1 (window, n);
-    }
+  if (WINDOW_VERTICAL_COMBINATION_P (w))
+    set_menu_bar_lines_1 (w->contained, n);
+  else if (WINDOW_HORIZONTAL_COMBINATION_P (w))
+    /* Adjust all children in a horizontal split.  */
+    for (window = w->contained; !NILP (window); window = w->next)
+      {
+	w = XWINDOW (window);
+	set_menu_bar_lines_1 (window, n);
+      }
 }
 
 void
@@ -421,7 +421,7 @@
 
   /* Make the chosen minibuffer window display the proper minibuffer,
      unless it is already showing a minibuffer.  */
-  if (NILP (Fmemq (XWINDOW (mini_window)->buffer, Vminibuffer_list)))
+  if (NILP (Fmemq (XWINDOW (mini_window)->contained, Vminibuffer_list)))
     /* Use set_window_buffer instead of Fset_window_buffer (see
        discussion of bug#11984, bug#12025, bug#12026).  */
     set_window_buffer (mini_window,
@@ -1189,7 +1189,7 @@
       /* Use set_window_buffer instead of Fset_window_buffer (see
 	 discussion of bug#11984, bug#12025, bug#12026).  */
       set_window_buffer (sf->minibuffer_window,
-			 XWINDOW (minibuf_window)->buffer, 0, 0);
+			 XWINDOW (minibuf_window)->contained, 0, 0);
       minibuf_window = sf->minibuffer_window;
 
       /* If the dying minibuffer window was selected,
@@ -1593,17 +1593,13 @@
 {
   struct window *w;
 
-  for (;!NILP (window); window = w->next)
+  for (; !NILP (window); window = w->next)
     {
       w = XWINDOW (window);
-
-      if (!NILP (w->buffer))
-	bset_display_time (XBUFFER (w->buffer), Fcurrent_time ());
-
-      if (!NILP (w->vchild))
-	make_frame_visible_1 (w->vchild);
-      if (!NILP (w->hchild))
-	make_frame_visible_1 (w->hchild);
+      if (WINDOWP (w->contained))
+	make_frame_visible_1 (w->contained);
+      else
+	bset_display_time (XBUFFER (w->contained), Fcurrent_time ());
     }
 }
 
@@ -1634,7 +1630,7 @@
       /* Use set_window_buffer instead of Fset_window_buffer (see
 	 discussion of bug#11984, bug#12025, bug#12026).  */
       set_window_buffer (sf->minibuffer_window,
-			 XWINDOW (minibuf_window)->buffer, 0, 0);
+			 XWINDOW (minibuf_window)->contained, 0, 0);
       minibuf_window = sf->minibuffer_window;
     }
 
@@ -1665,7 +1661,7 @@
       /* Use set_window_buffer instead of Fset_window_buffer (see
 	 discussion of bug#11984, bug#12025, bug#12026).  */
       set_window_buffer (sf->minibuffer_window,
-			 XWINDOW (minibuf_window)->buffer, 0, 0);
+			 XWINDOW (minibuf_window)->contained, 0, 0);
       minibuf_window = sf->minibuffer_window;
     }
 

=== modified file 'src/fringe.c'
--- src/fringe.c	2013-01-02 16:13:04 +0000
+++ src/fringe.c	2013-03-25 14:24:29 +0000
@@ -699,7 +699,7 @@
 {
   Lisp_Object cmap, bm = Qnil;
 
-  if ((cmap = BVAR (XBUFFER (w->buffer), fringe_cursor_alist)), !NILP (cmap))
+  if ((cmap = BVAR (XBUFFER (w->contained), fringe_cursor_alist)), !NILP (cmap))
     {
       bm = Fassq (cursor, cmap);
       if (CONSP (bm))
@@ -736,7 +736,7 @@
      If partial, lookup partial bitmap in default value if not found here.
      If not partial, or no partial spec is present, use non-partial bitmap.  */
 
-  if ((cmap = BVAR (XBUFFER (w->buffer), fringe_indicator_alist)), !NILP (cmap))
+  if ((cmap = BVAR (XBUFFER (w->contained), fringe_indicator_alist)), !NILP (cmap))
     {
       bm1 = Fassq (bitmap, cmap);
       if (CONSP (bm1))
@@ -963,7 +963,7 @@
     return 0;
 
   if (!MINI_WINDOW_P (w)
-      && (ind = BVAR (XBUFFER (w->buffer), indicate_buffer_boundaries), !NILP (ind)))
+      && (ind = BVAR (XBUFFER (w->contained), indicate_buffer_boundaries), !NILP (ind)))
     {
       if (EQ (ind, Qleft) || EQ (ind, Qright))
 	boundary_top = boundary_bot = arrow_top = arrow_bot = ind;
@@ -1004,7 +1004,7 @@
 	    {
 	      if (top_ind_rn < 0 && row->visible_height > 0)
 		{
-		  if (MATRIX_ROW_START_CHARPOS (row) <= BUF_BEGV (XBUFFER (w->buffer))
+		  if (MATRIX_ROW_START_CHARPOS (row) <= BUF_BEGV (XBUFFER (w->contained))
 		      && !MATRIX_ROW_PARTIALLY_VISIBLE_AT_TOP_P (w, row))
 		    row->indicate_bob_p = !NILP (boundary_top);
 		  else
@@ -1014,7 +1014,7 @@
 
 	      if (bot_ind_rn < 0)
 		{
-		  if (MATRIX_ROW_END_CHARPOS (row) >= BUF_ZV (XBUFFER (w->buffer))
+		  if (MATRIX_ROW_END_CHARPOS (row) >= BUF_ZV (XBUFFER (w->contained))
 		      && !MATRIX_ROW_PARTIALLY_VISIBLE_AT_BOTTOM_P (w, row))
 		    row->indicate_eob_p = !NILP (boundary_bot), bot_ind_rn = rn;
 		  else if (y + row->height >= yb)
@@ -1024,7 +1024,7 @@
 	}
     }
 
-  empty_pos = BVAR (XBUFFER (w->buffer), indicate_empty_lines);
+  empty_pos = BVAR (XBUFFER (w->contained), indicate_empty_lines);
   if (!NILP (empty_pos) && !EQ (empty_pos, Qright))
     empty_pos = WINDOW_LEFT_FRINGE_WIDTH (w) == 0 ? Qright : Qleft;
 

=== modified file 'src/indent.c'
--- src/indent.c	2013-03-24 12:59:45 +0000
+++ src/indent.c	2013-03-25 14:24:29 +0000
@@ -254,7 +254,7 @@
      the next property change */
   prop = Fget_char_property (position, Qinvisible,
 			     (!NILP (window)
-			      && EQ (XWINDOW (window)->buffer, buffer))
+			      && EQ (XWINDOW (window)->contained, buffer))
 			     ? window : buffer);
   inv_p = TEXT_PROP_MEANS_INVISIBLE (prop);
   /* When counting columns (window == nil), don't skip over ellipsis text.  */
@@ -1826,7 +1826,7 @@
 
   /* If the window contains this buffer, use it for getting text properties.
      Otherwise use the current buffer as arg for doing that.  */
-  if (EQ (w->buffer, Fcurrent_buffer ()))
+  if (EQ (w->contained, Fcurrent_buffer ()))
     text_prop_object = window;
   else
     text_prop_object = Fcurrent_buffer ();
@@ -1979,14 +1979,14 @@
 
   old_buffer = Qnil;
   GCPRO1 (old_buffer);
-  if (XBUFFER (w->buffer) != current_buffer)
+  if (XBUFFER (w->contained) != current_buffer)
     {
       /* Set the window's buffer temporarily to the current buffer.  */
-      old_buffer = w->buffer;
+      old_buffer = w->contained;
       old_charpos = marker_position (w->pointm);
       old_bytepos = marker_byte_position (w->pointm);
       wset_buffer (w, Fcurrent_buffer ());
-      set_marker_both (w->pointm, w->buffer,
+      set_marker_both (w->pointm, w->contained,
 		       BUF_PT (current_buffer), BUF_PT_BYTE (current_buffer));
     }
 
@@ -2139,7 +2139,7 @@
   if (BUFFERP (old_buffer))
     {
       wset_buffer (w, old_buffer);
-      set_marker_both (w->pointm, w->buffer,
+      set_marker_both (w->pointm, w->contained,
 		       old_charpos, old_bytepos);
     }
 

=== modified file 'src/insdel.c'
--- src/insdel.c	2013-03-15 16:03:54 +0000
+++ src/insdel.c	2013-03-25 14:24:29 +0000
@@ -1798,7 +1798,7 @@
 
   /* If we're modifying the buffer other than shown in a selected window,
      let redisplay consider other windows if this buffer is visible.  */
-  if (XBUFFER (XWINDOW (selected_window)->buffer) != current_buffer
+  if (XBUFFER (XWINDOW (selected_window)->contained) != current_buffer
       && buffer_window_count (current_buffer))
     ++windows_or_buffers_changed;
 

=== modified file 'src/keyboard.c'
--- src/keyboard.c	2013-03-24 12:59:45 +0000
+++ src/keyboard.c	2013-03-25 14:24:29 +0000
@@ -833,7 +833,7 @@
   update_mode_lines = 1;
 
   if (command_loop_level
-      && current_buffer != XBUFFER (XWINDOW (selected_window)->buffer))
+      && current_buffer != XBUFFER (XWINDOW (selected_window)->contained))
     buffer = Fcurrent_buffer ();
   else
     buffer = Qnil;
@@ -1395,7 +1395,7 @@
 	Fkill_emacs (Qnil);
 
       /* Make sure the current window's buffer is selected.  */
-      set_buffer_internal (XBUFFER (XWINDOW (selected_window)->buffer));
+      set_buffer_internal (XBUFFER (XWINDOW (selected_window)->contained));
 
       /* Display any malloc warning that just came out.  Use while because
 	 displaying one warning can cause another.  */
@@ -1461,7 +1461,7 @@
       /* A filter may have run while we were reading the input.  */
       if (! FRAME_LIVE_P (XFRAME (selected_frame)))
 	Fkill_emacs (Qnil);
-      set_buffer_internal (XBUFFER (XWINDOW (selected_window)->buffer));
+      set_buffer_internal (XBUFFER (XWINDOW (selected_window)->contained));
 
       ++num_input_keys;
 
@@ -1492,7 +1492,7 @@
 	{
 	  struct buffer *b;
 	  XWINDOW (selected_window)->force_start = 0;
-	  b = XBUFFER (XWINDOW (selected_window)->buffer);
+	  b = XBUFFER (XWINDOW (selected_window)->contained);
 	  BUF_BEG_UNCHANGED (b) = BUF_END_UNCHANGED (b) = 0;
 	}
 
@@ -5142,7 +5142,7 @@
 	  if (STRINGP (string))
 	    string_info = Fcons (string, make_number (charpos));
 	  textpos = (w == XWINDOW (selected_window)
-		     && current_buffer == XBUFFER (w->buffer))
+		     && current_buffer == XBUFFER (w->contained))
 	    ? PT : marker_position (w->pointm);
 
 	  xret = wx;
@@ -9145,9 +9145,9 @@
 		{
 		  if (! FRAME_LIVE_P (XFRAME (selected_frame)))
 		    Fkill_emacs (Qnil);
-		  if (XBUFFER (XWINDOW (selected_window)->buffer)
+		  if (XBUFFER (XWINDOW (selected_window)->contained)
 		      != current_buffer)
-		    Fset_buffer (XWINDOW (selected_window)->buffer);
+		    Fset_buffer (XWINDOW (selected_window)->contained);
 		}
 
 	      goto replay_sequence;
@@ -9195,9 +9195,9 @@
 		 special-event-map, ...) might have switched the current buffer
 		 or the selected window from under us in the mean time.  */
 	      if (fix_current_buffer
-		  && (XBUFFER (XWINDOW (selected_window)->buffer)
+		  && (XBUFFER (XWINDOW (selected_window)->contained)
 		      != current_buffer))
-		Fset_buffer (XWINDOW (selected_window)->buffer);
+		Fset_buffer (XWINDOW (selected_window)->contained);
 	      current_binding = active_maps (first_event);
 	    }
 
@@ -9246,8 +9246,8 @@
 		     not the current buffer.  If we're at the
 		     beginning of a key sequence, switch buffers.  */
 		  if (WINDOWP (window)
-		      && BUFFERP (XWINDOW (window)->buffer)
-		      && XBUFFER (XWINDOW (window)->buffer) != current_buffer)
+		      && BUFFERP (XWINDOW (window)->contained)
+		      && XBUFFER (XWINDOW (window)->contained) != current_buffer)
 		    {
 		      ASET (raw_keybuf, raw_keybuf_count, key);
 		      raw_keybuf_count++;
@@ -9268,7 +9268,7 @@
 
 		      if (! FRAME_LIVE_P (XFRAME (selected_frame)))
 			Fkill_emacs (Qnil);
-		      set_buffer_internal (XBUFFER (XWINDOW (window)->buffer));
+		      set_buffer_internal (XBUFFER (XWINDOW (window)->contained));
 		      goto replay_sequence;
 		    }
 		}

=== modified file 'src/keymap.c'
--- src/keymap.c	2013-03-24 12:59:45 +0000
+++ src/keymap.c	2013-03-25 14:24:29 +0000
@@ -1556,8 +1556,8 @@
       window = POSN_WINDOW (position);
 
       if (WINDOWP (window)
-	  && BUFFERP (XWINDOW (window)->buffer)
-	  && XBUFFER (XWINDOW (window)->buffer) != current_buffer)
+	  && BUFFERP (XWINDOW (window)->contained)
+	  && XBUFFER (XWINDOW (window)->contained) != current_buffer)
 	{
 	  /* Arrange to go back to the original buffer once we're done
 	     processing the key sequence.  We don't use
@@ -1567,7 +1567,7 @@
 	     things the same.
 	  */
 	  record_unwind_current_buffer ();
-	  set_buffer_internal (XBUFFER (XWINDOW (window)->buffer));
+	  set_buffer_internal (XBUFFER (XWINDOW (window)->contained));
 	}
     }
 

=== modified file 'src/minibuf.c'
--- src/minibuf.c	2013-03-24 12:59:45 +0000
+++ src/minibuf.c	2013-03-25 14:24:29 +0000
@@ -114,7 +114,7 @@
       /* Under X, we come here with minibuf_window being the
 	 minibuffer window of the unused termcap window created in
 	 init_window_once.  That window doesn't have a buffer.  */
-      buffer = XWINDOW (minibuf_window)->buffer;
+      buffer = XWINDOW (minibuf_window)->contained;
       if (BUFFERP (buffer))
 	/* Use set_window_buffer instead of Fset_window_buffer (see
 	   discussion of bug#11984, bug#12025, bug#12026).  */
@@ -844,7 +844,7 @@
   window = minibuf_window;
   /* To keep things predictable, in case it matters, let's be in the
      minibuffer when we reset the relevant variables.  */
-  Fset_buffer (XWINDOW (window)->buffer);
+  Fset_buffer (XWINDOW (window)->contained);
 
   /* Restore prompt, etc, from outer minibuffer level.  */
   minibuf_prompt = Fcar (minibuf_save_list);

=== modified file 'src/msdos.c'
--- src/msdos.c	2013-03-06 16:21:26 +0000
+++ src/msdos.c	2013-03-25 14:24:29 +0000
@@ -1261,7 +1261,7 @@
 	  /* If the mouse highlight is in the window that was deleted
 	     (e.g., if it was popped by completion), clear highlight
 	     unconditionally.  */
-	  if (NILP (w->buffer))
+	  if (NILP (w->contained))
 	    hlinfo->mouse_face_window = Qnil;
 	  else
 	    {
@@ -1271,7 +1271,7 @@
 		  break;
 	    }
 
-	  if (NILP (w->buffer) || i < w->desired_matrix->nrows)
+	  if (NILP (w->contained) || i < w->desired_matrix->nrows)
 	    clear_mouse_face (hlinfo);
 	}
     }
@@ -1321,7 +1321,7 @@
     new_cursor = frame_desired_cursor;
   else
     {
-      struct buffer *b = XBUFFER (sw->buffer);
+      struct buffer *b = XBUFFER (sw->contained);
 
       if (EQ (BVAR (b,cursor_type), Qt))
 	new_cursor = frame_desired_cursor;

=== modified file 'src/nsfns.m'
--- src/nsfns.m	2013-03-20 09:56:19 +0000
+++ src/nsfns.m	2013-03-25 14:24:29 +0000
@@ -619,7 +619,7 @@
 {
   NSView *view;
   Lisp_Object name, filename;
-  Lisp_Object buf = XWINDOW (f->selected_window)->buffer;
+  Lisp_Object buf = XWINDOW (f->selected_window)->contained;
   const char *title;
   NSAutoreleasePool *pool;
   struct gcpro gcpro1;

=== modified file 'src/nsmenu.m'
--- src/nsmenu.m	2013-02-05 12:16:35 +0000
+++ src/nsmenu.m	2013-03-25 14:24:29 +0000
@@ -191,7 +191,7 @@
 	= alloca (previous_menu_items_used * sizeof *previous_items);
 
       /* lisp preliminaries */
-      buffer = XWINDOW (FRAME_SELECTED_WINDOW (f))->buffer;
+      buffer = XWINDOW (FRAME_SELECTED_WINDOW (f))->contained;
       specbind (Qinhibit_quit, Qt);
       specbind (Qdebug_on_next_call, Qnil);
       record_unwind_save_match_data ();

=== modified file 'src/nsterm.m'
--- src/nsterm.m	2013-03-16 14:22:37 +0000
+++ src/nsterm.m	2013-03-25 14:24:29 +0000
@@ -6532,7 +6532,7 @@
 {
   Lisp_Object str = Qnil;
   struct frame *f = SELECTED_FRAME ();
-  struct buffer *curbuf = XBUFFER (XWINDOW (f->selected_window)->buffer);
+  struct buffer *curbuf = XBUFFER (XWINDOW (f->selected_window)->contained);
 
   if ([attribute isEqualToString:NSAccessibilityRoleAttribute])
     return NSAccessibilityTextFieldRole;

=== modified file 'src/print.c'
--- src/print.c	2013-03-24 12:59:45 +0000
+++ src/print.c	2013-03-25 14:24:29 +0000
@@ -1769,10 +1769,10 @@
 	  strout ("#<window ", -1, -1, printcharfun);
 	  len = sprintf (buf, "%p", XWINDOW (obj));
 	  strout (buf, len, len, printcharfun);
-	  if (!NILP (XWINDOW (obj)->buffer))
+	  if (BUFFERP (XWINDOW (obj)->contained))
 	    {
 	      strout (" on ", -1, -1, printcharfun);
-	      print_string (BVAR (XBUFFER (XWINDOW (obj)->buffer), name),
+	      print_string (BVAR (XBUFFER (XWINDOW (obj)->contained), name),
 			    printcharfun);
 	    }
 	  PRINTCHAR ('>');

=== modified file 'src/textprop.c'
--- src/textprop.c	2013-03-11 01:17:40 +0000
+++ src/textprop.c	2013-03-25 14:24:29 +0000
@@ -597,8 +597,9 @@
 
   if (WINDOWP (object))
     {
+      CHECK_LIVE_WINDOW (object);
       w = XWINDOW (object);
-      object = w->buffer;
+      object = w->contained;
     }
   if (BUFFERP (object))
     {

=== modified file 'src/w32fns.c'
--- src/w32fns.c	2013-03-24 00:48:49 +0000
+++ src/w32fns.c	2013-03-25 14:24:29 +0000
@@ -5798,7 +5798,7 @@
 
   /* Display the tooltip text in a temporary buffer.  */
   old_buffer = current_buffer;
-  set_buffer_internal_1 (XBUFFER (XWINDOW (FRAME_ROOT_WINDOW (f))->buffer));
+  set_buffer_internal_1 (XBUFFER (XWINDOW (FRAME_ROOT_WINDOW (f))->contained));
   bset_truncate_lines (current_buffer, Qnil);
   clear_glyph_matrix (w->desired_matrix);
   clear_glyph_matrix (w->current_matrix);

=== modified file 'src/w32menu.c'
--- src/w32menu.c	2013-01-02 16:13:04 +0000
+++ src/w32menu.c	2013-03-25 14:24:29 +0000
@@ -396,7 +396,7 @@
       if (! menubar_widget)
 	previous_menu_items_used = 0;
 
-      buffer = XWINDOW (FRAME_SELECTED_WINDOW (f))->buffer;
+      buffer = XWINDOW (FRAME_SELECTED_WINDOW (f))->contained;
       specbind (Qinhibit_quit, Qt);
       /* Don't let the debugger step into this code
 	 because it is not reentrant.  */

=== modified file 'src/window.c'
--- src/window.c	2013-03-24 12:59:45 +0000
+++ src/window.c	2013-03-25 14:24:29 +0000
@@ -147,11 +147,6 @@
   w->display_table = val;
 }
 static void
-wset_hchild (struct window *w, Lisp_Object val)
-{
-  w->hchild = val;
-}
-static void
 wset_left_fringe_width (struct window *w, Lisp_Object val)
 {
   w->left_fringe_width = val;
@@ -217,11 +212,6 @@
   w->temslot = val;
 }
 static void
-wset_vchild (struct window *w, Lisp_Object val)
-{
-  w->vchild = val;
-}
-static void
 wset_vertical_scroll_bar_type (struct window *w, Lisp_Object val)
 {
   w->vertical_scroll_bar_type = val;
@@ -231,6 +221,12 @@
 {
   w->window_parameters = val;
 }
+static void
+wset_combination (struct window *w, bool horflag, Lisp_Object val)
+{
+  w->horizontal = horflag;
+  w->contained = val;
+}
 
 struct window *
 decode_live_window (register Lisp_Object window)
@@ -275,9 +271,9 @@
 adjust_window_count (struct window *w, int arg)
 {
   eassert (eabs (arg) == 1);
-  if (BUFFERP (w->buffer))
+  if (BUFFERP (w->contained))
     {
-      struct buffer *b = XBUFFER (w->buffer);
+      struct buffer *b = XBUFFER (w->contained);
 
       if (b->base_buffer)
 	b = b->base_buffer;
@@ -296,7 +292,7 @@
 wset_buffer (struct window *w, Lisp_Object val)
 {
   adjust_window_count (w, -1);
-  w->buffer = val;
+  w->contained = val;
   adjust_window_count (w, 1);
 }
 
@@ -394,15 +390,8 @@
       window = XFRAME (frame_or_window)->root_window;
     }
 
-  while (NILP (XWINDOW (window)->buffer))
-    {
-      if (! NILP (XWINDOW (window)->hchild))
-	window = XWINDOW (window)->hchild;
-      else if (! NILP (XWINDOW (window)->vchild))
-	window = XWINDOW (window)->vchild;
-      else
-	emacs_abort ();
-    }
+  while (WINDOWP (XWINDOW (window)->contained))
+    window = XWINDOW (window)->contained;
 
   return window;
 }
@@ -489,11 +478,11 @@
   if (NILP (norecord))
     {
       w->use_time = ++window_select_count;
-      record_buffer (w->buffer);
+      record_buffer (w->contained);
     }
 
   /* Make the selected window's buffer current.  */
-  Fset_buffer (w->buffer);
+  Fset_buffer (w->contained);
 
   if (EQ (window, selected_window) && !inhibit_point_swap)
     return window;
@@ -516,7 +505,7 @@
 
   select_window_1 (window, inhibit_point_swap);
 
-  bset_last_selected_window (XBUFFER (w->buffer), window);
+  bset_last_selected_window (XBUFFER (w->contained), window);
   windows_or_buffers_changed++;
   return window;
 }
@@ -533,10 +522,10 @@
   if (!inhibit_point_swap)
     {
       struct window *ow = XWINDOW (selected_window);
-      if (! NILP (ow->buffer))
-	set_marker_both (ow->pointm, ow->buffer,
-			 BUF_PT (XBUFFER (ow->buffer)),
-			 BUF_PT_BYTE (XBUFFER (ow->buffer)));
+      if (BUFFERP (ow->contained))
+	set_marker_both (ow->pointm, ow->contained,
+			 BUF_PT (XBUFFER (ow->contained)),
+			 BUF_PT_BYTE (XBUFFER (ow->contained)));
     }
 
   selected_window = window;
@@ -581,7 +570,8 @@
 Return nil for an internal window or a deleted window.  */)
   (Lisp_Object window)
 {
-  return decode_any_window (window)->buffer;
+  struct window *w = decode_any_window (window);
+  return WINDOW_LEAF_P (w) ? w->contained : Qnil;
 }
 
 DEFUN ("window-parent", Fwindow_parent, Swindow_parent, 0, 1, 0,
@@ -601,7 +591,8 @@
 horizontal combination.  */)
   (Lisp_Object window)
 {
-  return decode_valid_window (window)->vchild;
+  struct window *w = decode_valid_window (window);
+  return WINDOW_VERTICAL_COMBINATION_P (w) ? w->contained : Qnil;
 }
 
 DEFUN ("window-left-child", Fwindow_left_child, Swindow_left_child, 0, 1, 0,
@@ -612,7 +603,8 @@
 vertical combination.  */)
   (Lisp_Object window)
 {
-  return decode_valid_window (window)->hchild;
+  struct window *w = decode_valid_window (window);
+  return WINDOW_HORIZONTAL_COMBINATION_P (w) ? w->contained : Qnil;
 }
 
 DEFUN ("window-next-sibling", Fwindow_next_sibling, Swindow_next_sibling, 0, 1, 0,
@@ -645,9 +637,9 @@
 
   CHECK_VALID_WINDOW (window);
   w = XWINDOW (window);
-  if (!NILP (w->buffer))
+  if (WINDOW_LEAF_P (w))
     error ("Combination limit is meaningful for internal windows only");
-  return XWINDOW (window)->combination_limit;
+  return w->combination_limit;
 }
 
 DEFUN ("set-window-combination-limit", Fset_window_combination_limit, Sset_window_combination_limit, 2, 2, 0,
@@ -663,7 +655,7 @@
 
   CHECK_VALID_WINDOW (window);
   w = XWINDOW (window);
-  if (!NILP (w->buffer))
+  if (WINDOW_LEAF_P (w))
     error ("Combination limit is meaningful for internal windows only");
   wset_combination_limit (w, limit);
   return limit;
@@ -860,7 +852,7 @@
 
   /* Prevent redisplay shortcuts when changing the hscroll.  */
   if (w->hscroll != new_hscroll)
-    XBUFFER (w->buffer)->prevent_redisplay_optimizations_p = 1;
+    XBUFFER (w->contained)->prevent_redisplay_optimizations_p = 1;
 
   w->hscroll = new_hscroll;
   return make_number (new_hscroll);
@@ -1441,7 +1433,7 @@
   register struct window *w = decode_live_window (window);
 
   if (w == XWINDOW (selected_window))
-    return make_number (BUF_PT (XBUFFER (w->buffer)));
+    return make_number (BUF_PT (XBUFFER (w->contained)));
   else
     return Fmarker_position (w->pointm);
 }
@@ -1483,7 +1475,7 @@
   Lisp_Object buf;
   struct buffer *b;
 
-  buf = w->buffer;
+  buf = w->contained;
   CHECK_BUFFER (buf);
   b = XBUFFER (buf);
 
@@ -1546,7 +1538,7 @@
 
   if (w == XWINDOW (selected_window))
     {
-      if (XBUFFER (w->buffer) == current_buffer)
+      if (XBUFFER (w->contained) == current_buffer)
 	Fgoto_char (pos);
       else
 	{
@@ -1554,14 +1546,14 @@
 
 	  /* ... but here we want to catch type error before buffer change.  */
 	  CHECK_NUMBER_COERCE_MARKER (pos);
-	  set_buffer_internal (XBUFFER (w->buffer));
+	  set_buffer_internal (XBUFFER (w->contained));
 	  Fgoto_char (pos);
 	  set_buffer_internal (old_buffer);
 	}
     }
   else
     {
-      set_marker_restricted (w->pointm, pos, w->buffer);
+      set_marker_restricted (w->pointm, pos, w->contained);
       /* We have to make sure that redisplay updates the window to show
 	 the new value of point.  */
       ++windows_or_buffers_changed;
@@ -1579,7 +1571,7 @@
 {
   register struct window *w = decode_live_window (window);
 
-  set_marker_restricted (w->start, pos, w->buffer);
+  set_marker_restricted (w->start, pos, w->contained);
   /* This is not right, but much easier than doing what is right.  */
   w->start_at_line_beg = 0;
   if (NILP (noforce))
@@ -1623,7 +1615,7 @@
   int x, y;
 
   w = decode_live_window (window);
-  buf = XBUFFER (w->buffer);
+  buf = XBUFFER (w->contained);
   SET_TEXT_POS_FROM_MARKER (top, w->start);
 
   if (EQ (pos, Qt))
@@ -1692,8 +1684,8 @@
   if (noninteractive || w->pseudo_window_p)
     return Qnil;
 
-  CHECK_BUFFER (w->buffer);
-  b = XBUFFER (w->buffer);
+  CHECK_BUFFER (w->contained);
+  b = XBUFFER (w->contained);
 
   /* Fail if current matrix is not up-to-date.  */
   if (!w->window_end_valid
@@ -1919,9 +1911,9 @@
 
   if (DISP_TABLE_P (w->display_table))
     dp = XCHAR_TABLE (w->display_table);
-  else if (BUFFERP (w->buffer))
+  else if (BUFFERP (w->contained))
     {
-      struct buffer *b = XBUFFER (w->buffer);
+      struct buffer *b = XBUFFER (w->contained);
 
       if (DISP_TABLE_P (BVAR (b, display_table)))
 	dp = XCHAR_TABLE (BVAR (b, display_table));
@@ -1946,17 +1938,14 @@
 static void
 unshow_buffer (register struct window *w)
 {
-  Lisp_Object buf;
-  struct buffer *b;
+  Lisp_Object buf = w->contained;
+  struct buffer *b = XBUFFER (buf);
 
-  buf = w->buffer;
-  b = XBUFFER (buf);
-  if (b != XMARKER (w->pointm)->buffer)
-    emacs_abort ();
+  eassert (b == XMARKER (w->pointm)->buffer);
 
 #if 0
   if (w == XWINDOW (selected_window)
-      || ! EQ (buf, XWINDOW (selected_window)->buffer))
+      || ! EQ (buf, XWINDOW (selected_window)->contained))
     /* Do this except when the selected window's buffer
        is being removed from some other window.  */
 #endif
@@ -1972,14 +1961,14 @@
   /* Point in the selected window's buffer
      is actually stored in that buffer, and the window's pointm isn't used.
      So don't clobber point in that buffer.  */
-  if (! EQ (buf, XWINDOW (selected_window)->buffer)
+  if (! EQ (buf, XWINDOW (selected_window)->contained)
       /* Don't clobber point in current buffer either (this could be
 	 useful in connection with bug#12208).
       && XBUFFER (buf) != current_buffer  */
       /* This line helps to fix Horsley's testbug.el bug.  */
       && !(WINDOWP (BVAR (b, last_selected_window))
 	   && w != XWINDOW (BVAR (b, last_selected_window))
-	   && EQ (buf, XWINDOW (BVAR (b, last_selected_window))->buffer)))
+	   && EQ (buf, XWINDOW (BVAR (b, last_selected_window))->contained)))
     temp_set_point_both (b,
 			 clip_to_bounds (BUF_BEGV (b),
 					 marker_position (w->pointm),
@@ -2046,10 +2035,8 @@
   wset_parent (n, tem);
   if (!NILP (tem))
     {
-      if (EQ (XWINDOW (tem)->vchild, old))
-	wset_vchild (XWINDOW (tem), new);
-      if (EQ (XWINDOW (tem)->hchild, old))
-	wset_hchild (XWINDOW (tem), new);
+      if (EQ (XWINDOW (tem)->contained, old))
+	XWINDOW (tem)->contained = new;
     }
 }
 
@@ -2069,22 +2056,19 @@
   if (!NILP (parent) && NILP (w->combination_limit))
     {
       p = XWINDOW (parent);
-      if (((!NILP (p->vchild) && !NILP (w->vchild))
-	   || (!NILP (p->hchild) && !NILP (w->hchild))))
+      if (WINDOWP (p->contained) && WINDOWP (w->contained)
+	  && p->horizontal == w->horizontal)
 	/* WINDOW and PARENT are both either a vertical or a horizontal
 	   combination.  */
 	{
-	  horflag = NILP (w->vchild);
-	  child = horflag ? w->hchild : w->vchild;
+	  horflag = WINDOW_HORIZONTAL_COMBINATION_P (w);
+	  child = w->contained;
 	  c = XWINDOW (child);
 
 	  /* Splice WINDOW's children into its parent's children and
 	     assign new normal sizes.  */
 	  if (NILP (w->prev))
-	    if (horflag)
-	      wset_hchild (p, child);
-	    else
-	      wset_vchild (p, child);
+	    wset_combination (p, horflag, child);
 	  else
 	    {
 	      wset_prev (c, w->prev);
@@ -2122,8 +2106,8 @@
 	    }
 
 	  /* WINDOW can be deleted now.  */
-	  wset_vchild (w, Qnil);
-	  wset_hchild (w, Qnil);
+	  eassert (!BUFFERP (w->contained));
+	  w->contained = Qnil;
 	}
     }
 }
@@ -2209,7 +2193,7 @@
   struct frame *f = XFRAME (w->frame);
   int candidate_p = 1;
 
-  if (!BUFFERP (w->buffer))
+  if (!BUFFERP (w->contained))
     candidate_p = 0;
   else if (MINI_WINDOW_P (w)
            && (EQ (minibuf, Qlambda)
@@ -2613,7 +2597,7 @@
 	switch (type)
 	  {
 	  case GET_BUFFER_WINDOW:
-	    if (EQ (w->buffer, obj)
+	    if (EQ (w->contained, obj)
 		/* Don't find any minibuffer window except the one that
 		   is currently in use.  */
 		&& (MINI_WINDOW_P (w) ? EQ (window, minibuf_window) : 1))
@@ -2637,25 +2621,25 @@
 	  case REPLACE_BUFFER_IN_WINDOWS_SAFELY:
 	    /* We could simply check whether the buffer shown by window
 	       is live, and show another buffer in case it isn't.  */
-	    if (EQ (w->buffer, obj))
+	    if (EQ (w->contained, obj))
 	      {
 		/* Undedicate WINDOW.  */
 		wset_dedicated (w, Qnil);
 		/* Make WINDOW show the buffer returned by
 		   other_buffer_safely, don't run any hooks.  */
 		set_window_buffer
-		  (window, other_buffer_safely (w->buffer), 0, 0);
+		  (window, other_buffer_safely (w->contained), 0, 0);
 		/* If WINDOW is the selected window, make its buffer
 		   current.  But do so only if the window shows the
 		   current buffer (Bug#6454).  */
 		if (EQ (window, selected_window)
-		    && XBUFFER (w->buffer) == current_buffer)
-		  Fset_buffer (w->buffer);
+		    && XBUFFER (w->contained) == current_buffer)
+		  Fset_buffer (w->contained);
 	      }
 	    break;
 
 	  case REDISPLAY_BUFFER_WINDOWS:
-	    if (EQ (w->buffer, obj))
+	    if (EQ (w->contained, obj))
 	      {
 		mark_window_display_accurate (window, 0);
 		w->update_mode_line = 1;
@@ -2667,8 +2651,7 @@
 
 	    /* Check for a window that has a killed buffer.  */
 	  case CHECK_ALL_WINDOWS:
-	    if (! NILP (w->buffer)
-		&& !BUFFER_LIVE_P (XBUFFER (w->buffer)))
+	    if (BUFFERP (w->contained) && !BUFFER_LIVE_P (XBUFFER (w->contained)))
 	      emacs_abort ();
 	    break;
 
@@ -2786,7 +2769,7 @@
   else if (MINI_WINDOW_P (w)) /* && top > 0) */
     error ("Can't expand minibuffer to full frame");
 
-  if (!NILP (w->buffer))
+  if (BUFFERP (w->contained))
     {
       startpos = marker_position (w->start);
       startbyte = marker_byte_position (w->start);
@@ -2858,7 +2841,7 @@
   FRAME_WINDOW_SIZES_CHANGED (f) = 1;
   resize_failed = 0;
 
-  if (NILP (w->buffer))
+  if (!WINDOW_LEAF_P (w))
     {
       /* Resize child windows vertically.  */
       XSETINT (delta, r->total_lines - w->total_lines);
@@ -2917,28 +2900,20 @@
       sibling = w->next;
       s = XWINDOW (sibling);
       wset_prev (s, Qnil);
-      if (!NILP (XWINDOW (w->parent)->vchild))
-	wset_vchild (XWINDOW (w->parent), sibling);
-      else
-	wset_hchild (XWINDOW (w->parent), sibling);
+      XWINDOW (w->parent)->contained = sibling;
     }
 
   /* Delete ROOT and all child windows of ROOT.  */
-  if (!NILP (r->vchild))
-    {
-      delete_all_child_windows (r->vchild);
-      wset_vchild (r, Qnil);
-    }
-  else if (!NILP (r->hchild))
-    {
-      delete_all_child_windows (r->hchild);
-      wset_hchild (r, Qnil);
+  if (WINDOWP (r->contained))
+    {
+      delete_all_child_windows (r->contained);
+      r->contained = Qnil;
     }
 
   replace_window (root, window, 1);
 
   /* This must become SWINDOW anyway ....... */
-  if (!NILP (w->buffer) && !resize_failed)
+  if (BUFFERP (w->contained) && !resize_failed)
     {
       /* Try to minimize scrolling, by setting the window start to the
 	 point will cause the text at the old window start to be at the
@@ -2947,18 +2922,18 @@
 	 when the display is not current, due to typeahead).  */
       new_top = WINDOW_TOP_EDGE_LINE (w) - FRAME_TOP_MARGIN (XFRAME (WINDOW_FRAME (w)));
       if (new_top != top
-	  && startpos >= BUF_BEGV (XBUFFER (w->buffer))
-	  && startpos <= BUF_ZV (XBUFFER (w->buffer)))
+	  && startpos >= BUF_BEGV (XBUFFER (w->contained))
+	  && startpos <= BUF_ZV (XBUFFER (w->contained)))
 	{
 	  struct position pos;
 	  struct buffer *obuf = current_buffer;
 
-	  Fset_buffer (w->buffer);
+	  Fset_buffer (w->contained);
 	  /* This computation used to temporarily move point, but that
 	     can have unwanted side effects due to text properties.  */
 	  pos = *vmotion (startpos, startbyte, -top, w);
 
-	  set_marker_both (w->start, w->buffer, pos.bufpos, pos.bytepos);
+	  set_marker_both (w->start, w->contained, pos.bufpos, pos.bytepos);
 	  w->window_end_valid = 0;
 	  w->start_at_line_beg = (pos.bytepos == BEGV_BYTE
 				    || FETCH_BYTE (pos.bytepos - 1) == '\n');
@@ -3158,7 +3133,7 @@
   struct window *w = XWINDOW (window);
   struct buffer *b = XBUFFER (buffer);
   ptrdiff_t count = SPECPDL_INDEX ();
-  int samebuf = EQ (buffer, w->buffer);
+  int samebuf = EQ (buffer, w->contained);
 
   wset_buffer (w, buffer);
 
@@ -3277,7 +3252,7 @@
   if (!BUFFER_LIVE_P (XBUFFER (buffer)))
     error ("Attempt to display deleted buffer");
 
-  tem = w->buffer;
+  tem = w->contained;
   if (NILP (tem))
     error ("Window is deleted");
   else
@@ -3330,8 +3305,8 @@
       struct window *w = XWINDOW (object);
       mark_window_display_accurate (object, 0);
       w->update_mode_line = 1;
-      if (BUFFERP (w->buffer))
-	XBUFFER (w->buffer)->prevent_redisplay_optimizations_p = 1;
+      if (BUFFERP (w->contained))
+	XBUFFER (w->contained)->prevent_redisplay_optimizations_p = 1;
       ++update_mode_lines;
       return Qt;
     }
@@ -3400,7 +3375,7 @@
         record_unwind_protect (Fset_buffer, prev_buffer);
         record_unwind_protect (select_window_norecord, prev_window);
         Fselect_window (window, Qt);
-        Fset_buffer (w->buffer);
+        Fset_buffer (w->contained);
         Frun_hooks (1, &Qtemp_buffer_show_hook);
         unbind_to (count, Qnil);
       }
@@ -3421,8 +3396,6 @@
   memcpy ((char *) p + sizeof (struct vectorlike_header),
 	  (char *) o + sizeof (struct vectorlike_header),
 	  word_size * VECSIZE (struct window));
-  /* P's buffer slot may change from nil to a buffer.  */
-  adjust_window_count (p, 1);
   XSETWINDOW (parent, p);
 
   replace_window (window, parent, 1);
@@ -3430,12 +3403,9 @@
   wset_next (o, Qnil);
   wset_prev (o, Qnil);
   wset_parent (o, parent);
-
-  wset_hchild (p, horflag ? window : Qnil);
-  wset_vchild (p, horflag ? Qnil : window);
+  wset_combination (p, horflag, window);
   wset_start (p, Qnil);
   wset_pointm (p, Qnil);
-  wset_buffer (p, Qnil);
   wset_combination_limit (p, Qnil);
   wset_window_parameters (p, Qnil);
 }
@@ -3524,10 +3494,10 @@
 {
   struct window *c;
 
-  if (!NILP (w->vchild))
+  if (WINDOW_VERTICAL_COMBINATION_P (w))
     /* W is a vertical combination.  */
     {
-      c = XWINDOW (w->vchild);
+      c = XWINDOW (w->contained);
       if (horflag)
 	/* All child windows of W must have the same width as W.  */
 	{
@@ -3555,10 +3525,10 @@
 	  return (sum_of_sizes == XINT (w->new_total));
 	}
     }
-  else if (!NILP (w->hchild))
+  else if (WINDOW_HORIZONTAL_COMBINATION_P (w))
     /* W is a horizontal combination.  */
     {
-      c = XWINDOW (w->hchild);
+      c = XWINDOW (w->contained);
       if (horflag)
 	/* The sum of the widths of the child windows of W must equal W's
 	   width.  */
@@ -3625,10 +3595,10 @@
       pos = w->top_line;
     }
 
-  if (!NILP (w->vchild))
+  if (WINDOW_VERTICAL_COMBINATION_P (w))
     /* W is a vertical combination.  */
     {
-      c = XWINDOW (w->vchild);
+      c = XWINDOW (w->contained);
       while (c)
 	{
 	  if (horflag)
@@ -3641,10 +3611,10 @@
 	  c = NILP (c->next) ? 0 : XWINDOW (c->next);
 	}
     }
-  else if (!NILP (w->hchild))
+  else if (WINDOW_HORIZONTAL_COMBINATION_P (w))
     /* W is a horizontal combination.  */
     {
-      c = XWINDOW (w->hchild);
+      c = XWINDOW (w->contained);
       while (c)
 	{
 	  if (horflag)
@@ -3727,7 +3697,7 @@
 			? 1 : 0)));
 
   r->top_line = FRAME_TOP_MARGIN (f);
-  if (NILP (r->vchild) && NILP (r->hchild))
+  if (WINDOW_LEAF_P (r))
     /* For a leaf root window just set the size.  */
     if (horflag)
       r->total_cols = new_size;
@@ -3842,9 +3812,9 @@
   combination_limit =
     EQ (Vwindow_combination_limit, Qt)
     || NILP (o->parent)
-    || NILP (horflag
-	     ? (XWINDOW (o->parent)->hchild)
-	     : (XWINDOW (o->parent)->vchild));
+    || (horflag
+	? WINDOW_VERTICAL_COMBINATION_P (XWINDOW (o->parent))
+	: WINDOW_HORIZONTAL_COMBINATION_P (XWINDOW (o->parent)));
 
   /* We need a live reference window to initialize some parameters.  */
   if (WINDOW_LIVE_P (old))
@@ -3914,17 +3884,12 @@
   n = XWINDOW (new);
   wset_frame (n, frame);
   wset_parent (n, o->parent);
-  wset_vchild (n, Qnil);
-  wset_hchild (n, Qnil);
 
   if (EQ (side, Qabove) || EQ (side, Qleft))
     {
       wset_prev (n, o->prev);
       if (NILP (n->prev))
-	if (horflag)
-	  wset_hchild (p, new);
-	else
-	  wset_vchild (p, new);
+	wset_combination (p, horflag, new);
       else
 	wset_next (XWINDOW (n->prev), new);
       wset_next (n, old);
@@ -3973,7 +3938,7 @@
   adjust_glyphs (f);
   /* Set buffer of NEW to buffer of reference window.  Don't run
      any hooks.  */
-  set_window_buffer (new, r->buffer, 0, 1);
+  set_window_buffer (new, r->contained, 0, 1);
   unblock_input ();
 
   /* Maybe we should run the scroll functions in Elisp (which already
@@ -3995,13 +3960,11 @@
   register Lisp_Object parent, sibling, frame, root;
   struct window *w, *p, *s, *r;
   struct frame *f;
-  bool horflag;
-  int before_sibling = 0;
+  bool horflag, before_sibling = 0;
 
   w = decode_any_window (window);
   XSETWINDOW (window, w);
-  if (NILP (w->buffer)
-      && NILP (w->hchild) && NILP (w->vchild))
+  if (NILP (w->contained))
     /* It's a no-op to delete an already deleted window.  */
     return Qnil;
 
@@ -4015,7 +3978,7 @@
     error ("Attempt to delete sole window of parent");
 
   p = XWINDOW (parent);
-  horflag = NILP (p->vchild);
+  horflag = WINDOW_HORIZONTAL_COMBINATION_P (p);
 
   frame = WINDOW_FRAME (w);
   f = XFRAME (frame);
@@ -4033,10 +3996,7 @@
       sibling = w->next;
       s = XWINDOW (sibling);
       wset_prev (s, Qnil);
-      if (horflag)
-	wset_hchild (p, sibling);
-      else
-	wset_vchild (p, sibling);
+      wset_combination (p, horflag, sibling);
     }
   else
     /* Get SIBLING above (on the left of) WINDOW.  */
@@ -4075,17 +4035,12 @@
       wset_next (w, Qnil);  /* Don't delete w->next too.  */
       free_window_matrices (w);
 
-      if (!NILP (w->vchild))
-	{
-	  delete_all_child_windows (w->vchild);
-	  wset_vchild (w, Qnil);
-	}
-      else if (!NILP (w->hchild))
-	{
-	  delete_all_child_windows (w->hchild);
-	  wset_hchild (w, Qnil);
-	}
-      else if (!NILP (w->buffer))
+      if (WINDOWP (w->contained))
+	{
+	  delete_all_child_windows (w->contained);
+	  w->contained = Qnil;
+	}
+      else
 	{
 	  unshow_buffer (w);
 	  unchain_marker (XMARKER (w->pointm));
@@ -4104,8 +4059,8 @@
 	  wset_normal_cols (s, p->normal_cols);
 	  wset_normal_lines (s, p->normal_lines);
 	  /* Mark PARENT as deleted.  */
-	  wset_vchild (p, Qnil);
-	  wset_hchild (p, Qnil);
+	  eassert (!BUFFERP (p->contained));
+	  p->contained = Qnil;
 	  /* Try to merge SIBLING into its new parent.  */
 	  recombine_windows (sibling);
 	}
@@ -4153,10 +4108,7 @@
       if (before_sibling)
 	{
 	  wset_prev (s, window);
-	  if (horflag)
-	    wset_hchild (p, window);
-	  else
-	    wset_vchild (p, window);
+	  wset_combination (p, horflag, window);
 	}
       else
 	{
@@ -4299,10 +4251,8 @@
 {
   while (w)
     {
-      if (!NILP (w->hchild))
-	mark_window_cursors_off (XWINDOW (w->hchild));
-      else if (!NILP (w->vchild))
-	mark_window_cursors_off (XWINDOW (w->vchild));
+      if (WINDOWP (w->contained))
+	mark_window_cursors_off (XWINDOW (w->contained));
       else
 	w->phys_cursor_on_p = 0;
 
@@ -4321,8 +4271,7 @@
   if (!MINI_WINDOW_P (w))
     {
       if (!NILP (w->parent)
-	  || !NILP (w->vchild)
-	  || !NILP (w->hchild)
+	  || WINDOWP (w->contained)
 	  || !NILP (w->next)
 	  || !NILP (w->prev)
 	  || WINDOW_WANTS_MODELINE_P (w))
@@ -4461,7 +4410,7 @@
 		  else
 		    spos = min (XINT (Fline_end_position (Qnil)) + 1, ZV);
 		  set_marker_restricted (w->start, make_number (spos),
-					 w->buffer);
+					 w->contained);
 		  w->start_at_line_beg = 1;
 		  w->update_mode_line = 1;
 		  w->last_modified = 0;
@@ -4585,7 +4534,7 @@
 
       /* If control gets here, then we vscrolled.  */
 
-      XBUFFER (w->buffer)->prevent_redisplay_optimizations_p = 1;
+      XBUFFER (w->contained)->prevent_redisplay_optimizations_p = 1;
 
       /* Don't try to change the window start below.  */
       vscrolled = 1;
@@ -4605,7 +4554,7 @@
 	}
 
       /* Set the window start, and set up the window for redisplay.  */
-      set_marker_restricted_both (w->start, w->buffer, IT_CHARPOS (it),
+      set_marker_restricted_both (w->start, w->contained, IT_CHARPOS (it),
 				  IT_BYTEPOS (it));
       bytepos = marker_byte_position (w->start);
       w->start_at_line_beg = (pos == BEGV || FETCH_BYTE (bytepos - 1) == '\n');
@@ -4805,7 +4754,7 @@
       int this_scroll_margin =
 	max (0, min (scroll_margin, w->total_lines / 4));
 
-      set_marker_restricted_both (w->start, w->buffer, pos, pos_byte);
+      set_marker_restricted_both (w->start, w->contained, pos, pos_byte);
       w->start_at_line_beg = !NILP (bolp);
       w->update_mode_line = 1;
       w->last_modified = 0;
@@ -4899,10 +4848,10 @@
 
   /* If selected window's buffer isn't current, make it current for
      the moment.  But don't screw up if window_scroll gets an error.  */
-  if (XBUFFER (XWINDOW (selected_window)->buffer) != current_buffer)
+  if (XBUFFER (XWINDOW (selected_window)->contained) != current_buffer)
     {
       record_unwind_protect (save_excursion_restore, save_excursion_save ());
-      Fset_buffer (XWINDOW (selected_window)->buffer);
+      Fset_buffer (XWINDOW (selected_window)->contained);
 
       /* Make redisplay consider other windows than just selected_window.  */
       ++windows_or_buffers_changed;
@@ -5017,7 +4966,7 @@
   record_unwind_protect (save_excursion_restore, save_excursion_save ());
   ++windows_or_buffers_changed;
 
-  Fset_buffer (w->buffer);
+  Fset_buffer (w->contained);
   SET_PT_BOTH (marker_position (w->pointm), marker_byte_position (w->pointm));
 
   if (NILP (arg))
@@ -5111,10 +5060,10 @@
   int bottom_y;
   void *itdata = NULL;
 
-  if (XBUFFER (w->buffer) != current_buffer)
+  if (XBUFFER (w->contained) != current_buffer)
     {
       old_buffer = current_buffer;
-      set_buffer_internal (XBUFFER (w->buffer));
+      set_buffer_internal (XBUFFER (w->contained));
     }
   else
     old_buffer = NULL;
@@ -5176,7 +5125,7 @@
   (register Lisp_Object arg)
 {
   struct window *w = XWINDOW (selected_window);
-  struct buffer *buf = XBUFFER (w->buffer);
+  struct buffer *buf = XBUFFER (w->contained);
   struct buffer *obuf = current_buffer;
   int center_p = 0;
   ptrdiff_t charpos, bytepos;
@@ -5342,7 +5291,7 @@
     }
 
   /* Set the new window start.  */
-  set_marker_both (w->start, w->buffer, charpos, bytepos);
+  set_marker_both (w->start, w->contained, charpos, bytepos);
   w->window_end_valid = 0;
 
   w->optional_new_start = 1;
@@ -5386,9 +5335,8 @@
   int this_scroll_margin;
 #endif
 
-  if (!(BUFFERP (w->buffer)
-	&& XBUFFER (w->buffer) == current_buffer))
-    /* This test is needed to make sure PT/PT_BYTE make sense in w->buffer
+  if (!(BUFFERP (w->contained) && XBUFFER (w->contained) == current_buffer))
+    /* This test is needed to make sure PT/PT_BYTE make sense in w->contained
        when passed below to set_marker_both.  */
     error ("move-to-window-line called from unrelated buffer");
 
@@ -5398,7 +5346,7 @@
     {
       int height = window_internal_height (w);
       Fvertical_motion (make_number (- (height / 2)), window);
-      set_marker_both (w->start, w->buffer, PT, PT_BYTE);
+      set_marker_both (w->start, w->contained, PT, PT_BYTE);
       w->start_at_line_beg = !NILP (Fbolp ());
       w->force_start = 1;
     }
@@ -5548,9 +5496,9 @@
 	   window-point of the final-selected-window to the window-point of
 	   the current-selected-window.  So we have to be careful which
 	   point of the current-buffer we copy into old_point.  */
-	if (EQ (XWINDOW (data->current_window)->buffer, new_current_buffer)
+	if (EQ (XWINDOW (data->current_window)->contained, new_current_buffer)
 	    && WINDOWP (selected_window)
-	    && EQ (XWINDOW (selected_window)->buffer, new_current_buffer)
+	    && EQ (XWINDOW (selected_window)->contained, new_current_buffer)
 	    && !EQ (selected_window, data->current_window))
 	  old_point = marker_position (XWINDOW (data->current_window)->pointm);
 	else
@@ -5564,7 +5512,7 @@
 	   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 (EQ (XWINDOW (data->current_window)->contained, new_current_buffer)
 	    /* If current_window = selected_window, its point is in BUF_PT.  */
 	    && !EQ (selected_window, data->current_window))
 	  old_point = marker_position (XWINDOW (data->current_window)->pointm);
@@ -5606,8 +5554,8 @@
 	  p = SAVED_WINDOW_N (saved_windows, k);
 	  window = p->window;
 	  w = XWINDOW (window);
-	  if (!NILP (w->buffer)
-	      && !EQ (w->buffer, p->buffer)
+	  if (BUFFERP (w->contained)
+	      && !EQ (w->contained, p->buffer)
 	      && BUFFER_LIVE_P (XBUFFER (p->buffer)))
 	    /* If a window we restore gets another buffer, record the
 	       window's old buffer.  */
@@ -5640,13 +5588,13 @@
 	 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))
+      if (! NILP (XWINDOW (selected_window)->contained))
 	{
 	  w = XWINDOW (selected_window);
 	  set_marker_both (w->pointm,
-			   w->buffer,
-			   BUF_PT (XBUFFER (w->buffer)),
-			   BUF_PT_BYTE (XBUFFER (w->buffer)));
+			   w->contained,
+			   BUF_PT (XBUFFER (w->contained)),
+			   BUF_PT_BYTE (XBUFFER (w->contained)));
 	}
 
       windows_or_buffers_changed++;
@@ -5693,18 +5641,10 @@
 	    {
 	      wset_prev (w, Qnil);
 	      if (!NILP (w->parent))
-		{
-		  if (XINT (p->total_cols) == XWINDOW (w->parent)->total_cols)
-		    {
-		      wset_vchild (XWINDOW (w->parent), p->window);
-		      wset_hchild (XWINDOW (w->parent), Qnil);
-		    }
-		  else
-		    {
-		      wset_hchild (XWINDOW (w->parent), p->window);
-		      wset_vchild (XWINDOW (w->parent), Qnil);
-		    }
-		}
+		wset_combination (XWINDOW (w->parent),
+				  (XINT (p->total_cols)
+				   != XWINDOW (w->parent)->total_cols),
+				  p->window);
 	    }
 
 	  /* If we squirreled away the buffer, restore it now.  */
@@ -5753,20 +5693,16 @@
 	  w->last_modified = 0;
 	  w->last_overlay_modified = 0;
 
-	  /* Reinstall the saved buffer and pointers into it.  */
-	  if (NILP (p->buffer))
-	    /* An internal window.  */
-	    wset_buffer (w, p->buffer);
-	  else if (BUFFER_LIVE_P (XBUFFER (p->buffer)))
+	  if (BUFFERP (p->buffer) && BUFFER_LIVE_P (XBUFFER (p->buffer)))
 	    /* If saved buffer is alive, install it.  */
 	    {
 	      wset_buffer (w, p->buffer);
 	      w->start_at_line_beg = !NILP (p->start_at_line_beg);
-	      set_marker_restricted (w->start, p->start, w->buffer);
+	      set_marker_restricted (w->start, p->start, w->contained);
 	      set_marker_restricted (w->pointm, p->pointm,
-				     w->buffer);
-	      Fset_marker (BVAR (XBUFFER (w->buffer), mark),
-			   p->mark, w->buffer);
+				     w->contained);
+	      Fset_marker (BVAR (XBUFFER (w->contained), mark),
+			   p->mark, w->contained);
 
 	      /* As documented in Fcurrent_window_configuration, don't
 		 restore the location of point in the buffer which was
@@ -5775,23 +5711,21 @@
 		  && XBUFFER (p->buffer) == current_buffer)
 		Fgoto_char (w->pointm);
 	     }
-	   else if (!NILP (w->buffer)
-		    && BUFFER_LIVE_P (XBUFFER (w->buffer)))
-	     /* Keep window's old buffer; make sure the markers are
-		real.  */
-	     {
-	       /* Set window markers at start of visible range.  */
-	       if (XMARKER (w->start)->buffer == 0)
-		 set_marker_restricted_both (w->start, w->buffer, 0, 0);
-	       if (XMARKER (w->pointm)->buffer == 0)
-		 set_marker_restricted_both
-		   (w->pointm, w->buffer,
-		    BUF_PT (XBUFFER (w->buffer)),
-		    BUF_PT_BYTE (XBUFFER (w->buffer)));
-	       w->start_at_line_beg = 1;
-	     }
-	  else
-	    /* Window has no live buffer, get one.  */
+	  else if (BUFFERP (w->contained) && BUFFER_LIVE_P (XBUFFER (w->contained)))
+	    /* Keep window's old buffer; make sure the markers are real.  */
+	    {
+	      /* Set window markers at start of visible range.  */
+	      if (XMARKER (w->start)->buffer == 0)
+		set_marker_restricted_both (w->start, w->contained, 0, 0);
+	      if (XMARKER (w->pointm)->buffer == 0)
+		set_marker_restricted_both
+		  (w->pointm, w->contained,
+		   BUF_PT (XBUFFER (w->contained)),
+		   BUF_PT_BYTE (XBUFFER (w->contained)));
+	      w->start_at_line_beg = 1;
+	    }
+	  else if (WINDOW_LEAF_P (w))
+	    /* Leaf window has no live buffer, get one.  */
 	    {
 	      /* Get the buffer via other_buffer_safely in order to
 	      avoid showing an unimportant buffer and, if necessary, to
@@ -5800,8 +5734,8 @@
 	      wset_buffer (w, other_buffer_safely (Fcurrent_buffer ()));
 	      /* This will set the markers to beginning of visible
 		 range.  */
-	      set_marker_restricted_both (w->start, w->buffer, 0, 0);
-	      set_marker_restricted_both (w->pointm, w->buffer, 0, 0);
+	      set_marker_restricted_both (w->start, w->contained, 0, 0);
+	      set_marker_restricted_both (w->pointm, w->contained, 0, 0);
 	      w->start_at_line_beg = 1;
 	      if (!NILP (w->dedicated))
 		/* Record this window as dead.  */
@@ -5814,17 +5748,17 @@
       fset_root_window (f, data->root_window);
       /* Arrange *not* to restore point in the buffer that was
 	 current when the window configuration was saved.  */
-      if (EQ (XWINDOW (data->current_window)->buffer, new_current_buffer))
+      if (EQ (XWINDOW (data->current_window)->contained, new_current_buffer))
 	set_marker_restricted (XWINDOW (data->current_window)->pointm,
 			       make_number (old_point),
-			       XWINDOW (data->current_window)->buffer);
+			       XWINDOW (data->current_window)->contained);
 
       /* In the following call to `select-window', prevent "swapping out
 	 point" in the old selected window using the buffer that has
 	 been restored into it.  We already swapped out that point from
 	 that window's old buffer.  */
       select_window (data->current_window, Qnil, 1);
-      BVAR (XBUFFER (XWINDOW (selected_window)->buffer), last_selected_window)
+      BVAR (XBUFFER (XWINDOW (selected_window)->contained), last_selected_window)
 	= selected_window;
 
       if (NILP (data->focus_frame)
@@ -5851,14 +5785,13 @@
       /* Now, free glyph matrices in windows that were not reused.  */
       for (i = n = 0; i < n_leaf_windows; ++i)
 	{
-	  if (NILP (leaf_windows[i]->buffer))
+	  if (NILP (leaf_windows[i]->contained))
 	    {
 	      /* Assert it's not reused as a combination.  */
-	      eassert (NILP (leaf_windows[i]->hchild)
-		       && NILP (leaf_windows[i]->vchild));
+	      eassert (WINDOW_LEAF_P (leaf_windows[i]));
 	      free_window_matrices (leaf_windows[i]);
 	    }
-	  else if (EQ (leaf_windows[i]->buffer, new_current_buffer))
+	  else if (EQ (leaf_windows[i]->contained, new_current_buffer))
 	    ++n;
 	}
 
@@ -5889,7 +5822,7 @@
       Fset_buffer (new_current_buffer);
       /* If the new current buffer doesn't appear in the selected
 	 window, go to its old point (see bug#12208).  */
-      if (!EQ (XWINDOW (data->current_window)->buffer, new_current_buffer))
+      if (!EQ (XWINDOW (data->current_window)->contained, new_current_buffer))
 	Fgoto_char (make_number (old_point));
     }
 
@@ -5913,17 +5846,12 @@
     /* Delete WINDOW's siblings (we traverse postorderly).  */
     delete_all_child_windows (w->next);
 
-  if (!NILP (w->vchild))
-    {
-      delete_all_child_windows (w->vchild);
-      wset_vchild (w, Qnil);
-    }
-  else if (!NILP (w->hchild))
-    {
-      delete_all_child_windows (w->hchild);
-      wset_hchild (w, Qnil);
-    }
-  else if (!NILP (w->buffer))
+  if (WINDOWP (w->contained))
+    {
+      delete_all_child_windows (w->contained);
+      w->contained = Qnil;
+    }
+  else if (BUFFERP (w->contained))
     {
       unshow_buffer (w);
       unchain_marker (XMARKER (w->pointm));
@@ -5931,7 +5859,7 @@
       /* Since combination limit makes sense for an internal windows
 	 only, we use this slot to save the buffer for the sake of
 	 possible resurrection in Fset_window_configuration.  */
-      wset_combination_limit (w, w->buffer);
+      wset_combination_limit (w, w->contained);
       wset_buffer (w, Qnil);
     }
 
@@ -5944,10 +5872,8 @@
   register int count = 1;
   if (!NILP (window->next))
     count += count_windows (XWINDOW (window->next));
-  if (!NILP (window->vchild))
-    count += count_windows (XWINDOW (window->vchild));
-  if (!NILP (window->hchild))
-    count += count_windows (XWINDOW (window->hchild));
+  if (WINDOWP (window->contained))
+    count += count_windows (XWINDOW (window->contained));
   return count;
 }
 
@@ -5959,10 +5885,8 @@
 {
   while (w)
     {
-      if (!NILP (w->hchild))
-	i = get_leaf_windows (XWINDOW (w->hchild), flat, i);
-      else if (!NILP (w->vchild))
-	i = get_leaf_windows (XWINDOW (w->vchild), flat, i);
+      if (WINDOWP (w->contained))
+	i = get_leaf_windows (XWINDOW (w->contained), flat, i);
       else
 	flat[i++] = w;
 
@@ -6018,14 +5942,14 @@
   register struct window *w;
   register Lisp_Object tem, pers, par;
 
-  for (;!NILP (window); window = w->next)
+  for (; !NILP (window); window = w->next)
     {
       p = SAVED_WINDOW_N (vector, i);
       w = XWINDOW (window);
 
       wset_temslot (w, make_number (i)); i++;
       p->window = window;
-      p->buffer = w->buffer;
+      p->buffer = (WINDOW_LEAF_P (w) ? w->contained : Qnil);
       p->left_col = make_number (w->left_col);
       p->top_line = make_number (w->top_line);
       p->total_cols = make_number (w->total_cols);
@@ -6092,15 +6016,15 @@
 	    }
 	}
 
-      if (!NILP (w->buffer))
+      if (BUFFERP (w->contained))
 	{
 	  /* 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 = build_marker (XBUFFER (w->buffer),
-				      BUF_PT (XBUFFER (w->buffer)),
-				      BUF_PT_BYTE (XBUFFER (w->buffer)));
+	    p->pointm = build_marker (XBUFFER (w->contained),
+				      BUF_PT (XBUFFER (w->contained)),
+				      BUF_PT_BYTE (XBUFFER (w->contained)));
 	  else
 	    p->pointm = Fcopy_marker (w->pointm, Qnil);
 	  XMARKER (p->pointm)->insertion_type
@@ -6109,7 +6033,7 @@
 	  p->start = Fcopy_marker (w->start, Qnil);
 	  p->start_at_line_beg = w->start_at_line_beg ? Qt : Qnil;
 
-	  tem = BVAR (XBUFFER (w->buffer), mark);
+	  tem = BVAR (XBUFFER (w->contained), mark);
 	  p->mark = Fcopy_marker (tem, Qnil);
 	}
       else
@@ -6130,10 +6054,8 @@
       else
 	p->prev = XWINDOW (w->prev)->temslot;
 
-      if (!NILP (w->vchild))
-	i = save_window_save (w->vchild, vector, i);
-      if (!NILP (w->hchild))
-	i = save_window_save (w->hchild, vector, i);
+      if (WINDOWP (w->contained))
+	i = save_window_save (w->contained, vector, i);
     }
 
   return i;
@@ -6450,7 +6372,7 @@
 	    adjust_glyphs (f);
 
 	  /* Prevent redisplay shortcuts.  */
-	  XBUFFER (w->buffer)->prevent_redisplay_optimizations_p = 1;
+	  XBUFFER (w->contained)->prevent_redisplay_optimizations_p = 1;
 	}
     }
 
@@ -6484,10 +6406,8 @@
 
   for (cont = 1; w && cont;)
     {
-      if (!NILP (w->hchild))
- 	cont = foreach_window_1 (XWINDOW (w->hchild), fn, user_data);
-      else if (!NILP (w->vchild))
- 	cont = foreach_window_1 (XWINDOW (w->vchild), fn, user_data);
+      if (WINDOWP (w->contained))
+ 	cont = foreach_window_1 (XWINDOW (w->contained), fn, user_data);
       else
 	cont = fn (w, user_data);
 

=== modified file 'src/window.h'
--- src/window.h	2013-03-22 12:41:34 +0000
+++ src/window.h	2013-03-25 14:25:57 +0000
@@ -41,14 +41,13 @@
 this can be done implicitly).  Combination windows can be created
 and deleted at any time.
 
-A leaf window has a non-nil buffer field, and also
- has markers in its start and pointm fields.  Non-leaf windows
- have nil in these fields.
+A leaf window has a buffer stored in contained field and markers in its start
+and pointm fields.  Non-leaf windows have nil in the latter two fields.
 
 Non-leaf windows are either vertical or horizontal combinations.
 
 A vertical combination window has children that are arranged on the frame
-one above the next.  Its vchild field points to the uppermost child.
+one above the next.  Its contained field points to the uppermost child.
 The parent field of each of the children points to the vertical
 combination window.  The next field of each child points to the
 child below it, or is nil for the lowest child.  The prev field
@@ -56,7 +55,7 @@
 highest child.
 
 A horizontal combination window has children that are side by side.
-Its hchild field points to the leftmost child.  In each child
+Its contained field points to the leftmost child.  In each child
 the next field points to the child to the right and the prev field
 points to the child to the left.
 
@@ -78,7 +77,7 @@
 minibuffer-only screens, the root window and the minibuffer window are
 one and the same, so its prev and next members are nil.
 
-A dead window has its buffer, hchild, and vchild windows all nil.  */
+A dead window has its contained field set to nil.  */
 
 struct cursor_pos
 {
@@ -102,13 +101,6 @@
     Lisp_Object next;
     Lisp_Object prev;
 
-    /* First child of this window: vchild is used if this is a vertical
-       combination, hchild if this is a horizontal combination.  Of the
-       fields vchild, hchild and buffer, one and only one is non-nil
-       unless the window is dead.  */
-    Lisp_Object hchild;
-    Lisp_Object vchild;
-
     /* The window this one is a child of.  */
     Lisp_Object parent;
 
@@ -123,10 +115,8 @@
     Lisp_Object new_total;
     Lisp_Object new_normal;
 
-    /* The buffer displayed in this window.  Of the fields vchild,
-       hchild and buffer, one and only one is non-nil unless the window
-       is dead.  */
-    Lisp_Object buffer;
+    /* May be buffer, window, or nil.  */
+    Lisp_Object contained;
 
     /* A marker pointing to where in the text to start displaying.
        BIDI Note: This is the _logical-order_ start, i.e. the smallest
@@ -282,6 +272,10 @@
     /* Non-zero if this window is a minibuffer window.  */
     unsigned mini : 1;
 
+    /* Meaningful only if contained is a window, non-zero if this
+       internal window is used in horizontal combination.  */
+    unsigned horizontal : 1;
+
     /* Non-zero means must regenerate mode line of this window.  */
     unsigned update_mode_line : 1;
 
@@ -428,6 +422,21 @@
 
 /* A handy macro.  */
 
+/* Non-zero if W is leaf (carry the buffer).  */
+
+#define WINDOW_LEAF_P(W) \
+  (BUFFERP ((W)->contained))
+
+/* Non-zero if W is a member of horizontal combination.  */
+
+#define WINDOW_HORIZONTAL_COMBINATION_P(W) \
+  (WINDOWP ((W)->contained) && (W)->horizontal)
+
+/* Non-zero if W is a member of vertical combination.  */
+
+#define WINDOW_VERTICAL_COMBINATION_P(W) \
+  (WINDOWP ((W)->contained) && !(W)->horizontal)
+
 #define WINDOW_XFRAME(W) \
   (XFRAME (WINDOW_FRAME ((W))))
 
@@ -931,20 +940,17 @@
 struct glyph *get_phys_cursor_glyph (struct window *w);
 
 /* Value is non-zero if WINDOW is a valid window.  */
-#define WINDOW_VALID_P(WINDOW)				\
-  (WINDOWP (WINDOW)					\
-   && (!NILP (XWINDOW (WINDOW)->buffer)			\
-       || !NILP (XWINDOW (WINDOW)->vchild)		\
-       || !NILP (XWINDOW (WINDOW)->hchild)))
+#define WINDOW_VALID_P(WINDOW)					\
+  (WINDOWP (WINDOW) && !NILP (XWINDOW (WINDOW)->contained))	\
 
-/* A window of any sort, leaf or interior, is "valid" if one
-   of its buffer, vchild, or hchild members is non-nil.  */
+/* A window of any sort, leaf or interior, is "valid" if its contained
+   slot is non-nil.  */
 #define CHECK_VALID_WINDOW(WINDOW)				\
   CHECK_TYPE (WINDOW_VALID_P (WINDOW), Qwindow_valid_p, WINDOW)
 
 /* Value is non-zero if WINDOW is a live window.  */
 #define WINDOW_LIVE_P(WINDOW)					\
-  (WINDOWP (WINDOW) && !NILP (XWINDOW (WINDOW)->buffer))
+  (WINDOWP (WINDOW) && BUFFERP (XWINDOW (WINDOW)->contained))
 
 /* A window is "live" if and only if it shows a buffer.  */
 #define CHECK_LIVE_WINDOW(WINDOW)				\

=== modified file 'src/xdisp.c'
--- src/xdisp.c	2013-03-24 12:59:45 +0000
+++ src/xdisp.c	2013-03-25 14:24:29 +0000
@@ -1283,10 +1283,10 @@
   if (FRAME_INITIAL_P (XFRAME (WINDOW_FRAME (w))))
     return visible_p;
 
-  if (XBUFFER (w->buffer) != current_buffer)
+  if (XBUFFER (w->contained) != current_buffer)
     {
       old_buffer = current_buffer;
-      set_buffer_internal_1 (XBUFFER (w->buffer));
+      set_buffer_internal_1 (XBUFFER (w->contained));
     }
 
   SET_TEXT_POS_FROM_MARKER (top, w->start);
@@ -4458,7 +4458,7 @@
      if it was a text property.  */
 
   if (!STRINGP (it->string))
-    object = it->w->buffer;
+    object = it->w->contained;
 
   display_replaced_p = handle_display_spec (it, propval, object, overlay,
 					    position, bufpos,
@@ -4866,7 +4866,7 @@
 	  it->what = IT_IMAGE;
 	  it->image_id = -1; /* no image */
 	  it->position = start_pos;
-	  it->object = NILP (object) ? it->w->buffer : object;
+	  it->object = NILP (object) ? it->w->contained : object;
 	  it->method = GET_FROM_IMAGE;
 	  it->from_overlay = Qnil;
 	  it->face_id = face_id;
@@ -5012,7 +5012,7 @@
 	  it->what = IT_IMAGE;
 	  it->image_id = lookup_image (it->f, value);
 	  it->position = start_pos;
-	  it->object = NILP (object) ? it->w->buffer : object;
+	  it->object = NILP (object) ? it->w->contained : object;
 	  it->method = GET_FROM_IMAGE;
 
 	  /* Say that we haven't consumed the characters with
@@ -5836,7 +5836,7 @@
       it->object = p->u.stretch.object;
       break;
     case GET_FROM_BUFFER:
-      it->object = it->w->buffer;
+      it->object = it->w->contained;
       break;
     case GET_FROM_STRING:
       it->object = it->string;
@@ -5849,7 +5849,7 @@
       else
 	{
 	  it->method = GET_FROM_BUFFER;
-	  it->object = it->w->buffer;
+	  it->object = it->w->contained;
 	}
     }
   it->end_charpos = p->end_charpos;
@@ -6290,7 +6290,7 @@
   IT_STRING_BYTEPOS (*it) = -1;
   it->string = Qnil;
   it->method = GET_FROM_BUFFER;
-  it->object = it->w->buffer;
+  it->object = it->w->contained;
   it->area = TEXT_AREA;
   it->multibyte_p = !NILP (BVAR (current_buffer, enable_multibyte_characters));
   it->sp = 0;
@@ -7141,7 +7141,7 @@
 	  else
 	    {
 	      it->method = GET_FROM_BUFFER;
-	      it->object = it->w->buffer;
+	      it->object = it->w->contained;
 	    }
 
 	  it->dpvec = NULL;
@@ -7714,7 +7714,7 @@
 	 setting face_before_selective_p.  */
       it->saved_face_id = it->face_id;
       it->method = GET_FROM_BUFFER;
-      it->object = it->w->buffer;
+      it->object = it->w->contained;
       reseat_at_next_visible_line_start (it, 1);
       it->face_before_selective_p = 1;
     }
@@ -7978,7 +7978,7 @@
 
       /* Record what we have and where it came from.  */
       it->what = IT_CHARACTER;
-      it->object = it->w->buffer;
+      it->object = it->w->contained;
       it->position = it->current.pos;
 
       /* Normally we return the character found above, except when we
@@ -8084,7 +8084,7 @@
 	  return 0;
 	}
       it->position = it->current.pos;
-      it->object = it->w->buffer;
+      it->object = it->w->contained;
       it->c = composition_update_it (&it->cmp_it, IT_CHARPOS (*it),
 				     IT_BYTEPOS (*it), Qnil);
     }
@@ -10003,7 +10003,7 @@
   if (w)
     {
       XSETWINDOW (tmp, w); ASET (vector, i, tmp); ++i;
-      ASET (vector, i, w->buffer); ++i;
+      ASET (vector, i, w->contained); ++i;
       ASET (vector, i, make_number (marker_position (w->pointm))); ++i;
       ASET (vector, i, make_number (marker_byte_position (w->pointm))); ++i;
     }
@@ -10255,9 +10255,9 @@
   eassert (MINI_WINDOW_P (w));
 
   /* By default, start display at the beginning.  */
-  set_marker_both (w->start, w->buffer,
-		   BUF_BEGV (XBUFFER (w->buffer)),
-		   BUF_BEGV_BYTE (XBUFFER (w->buffer)));
+  set_marker_both (w->start, w->contained,
+		   BUF_BEGV (XBUFFER (w->contained)),
+		   BUF_BEGV_BYTE (XBUFFER (w->contained)));
 
   /* Don't resize windows while redisplaying a window; it would
      confuse redisplay functions when the size of the window they are
@@ -10284,10 +10284,10 @@
       struct text_pos start;
       struct buffer *old_current_buffer = NULL;
 
-      if (current_buffer != XBUFFER (w->buffer))
+      if (current_buffer != XBUFFER (w->contained))
 	{
 	  old_current_buffer = current_buffer;
-	  set_buffer_internal (XBUFFER (w->buffer));
+	  set_buffer_internal (XBUFFER (w->contained));
 	}
 
       init_iterator (&it, w, BEGV, BEGV_BYTE, NULL, DEFAULT_FACE_ID);
@@ -10736,7 +10736,7 @@
 
 /* Nonzero if W doesn't reflect the actual state of current buffer due
    to its text or overlays change.  FIXME: this may be called when
-   XBUFFER (w->buffer) != current_buffer, which looks suspicious.  */
+   XBUFFER (w->contained) != current_buffer, which looks suspicious.  */
 
 static int
 window_outdated (struct window *w)
@@ -10751,7 +10751,7 @@
 static int
 window_buffer_changed (struct window *w)
 {
-  struct buffer *b = XBUFFER (w->buffer);
+  struct buffer *b = XBUFFER (w->contained);
 
   eassert (BUFFER_LIVE_P (b));
 
@@ -11005,7 +11005,7 @@
 
       Fselect_window (f->selected_window, Qt);
       set_buffer_internal_1
-	(XBUFFER (XWINDOW (f->selected_window)->buffer));
+	(XBUFFER (XWINDOW (f->selected_window)->contained));
       fmt = FRAME_ICONIFIED_P (f) ? Vicon_title_format : Vframe_title_format;
 
       mode_line_target = MODE_LINE_TITLE;
@@ -11124,7 +11124,7 @@
           if (windows_or_buffers_changed
 	      && FRAME_NS_P (f))
             ns_set_doc_edited
-	      (f, Fbuffer_modified_p (XWINDOW (f->selected_window)->buffer));
+	      (f, Fbuffer_modified_p (XWINDOW (f->selected_window)->contained));
 #endif
 	  UNGCPRO;
 	}
@@ -11196,7 +11196,7 @@
 
 	  specbind (Qinhibit_menubar_update, Qt);
 
-	  set_buffer_internal_1 (XBUFFER (w->buffer));
+	  set_buffer_internal_1 (XBUFFER (w->contained));
 	  if (save_match_data)
 	    record_unwind_save_match_data ();
 	  if (NILP (Voverriding_local_map_menu_flag))
@@ -11400,7 +11400,7 @@
 	  /* Set current_buffer to the buffer of the selected
 	     window of the frame, so that we get the right local
 	     keymaps.  */
-	  set_buffer_internal_1 (XBUFFER (w->buffer));
+	  set_buffer_internal_1 (XBUFFER (w->contained));
 
 	  /* Save match data, if we must.  */
 	  if (save_match_data)
@@ -12267,10 +12267,8 @@
     {
       struct window *w = XWINDOW (window);
 
-      if (WINDOWP (w->hchild))
-	hscrolled_p |= hscroll_window_tree (w->hchild);
-      else if (WINDOWP (w->vchild))
-	hscrolled_p |= hscroll_window_tree (w->vchild);
+      if (WINDOWP (w->contained))
+	hscrolled_p |= hscroll_window_tree (w->contained);
       else if (w->cursor.vpos >= 0)
 	{
 	  int h_margin;
@@ -12290,7 +12288,7 @@
 	  /* Scroll when cursor is inside this scroll margin.  */
 	  h_margin = hscroll_margin * WINDOW_FRAME_COLUMN_WIDTH (w);
 
-	  if (!NILP (Fbuffer_local_value (Qauto_hscroll_mode, w->buffer))
+	  if (!NILP (Fbuffer_local_value (Qauto_hscroll_mode, w->contained))
 	      /* For left-to-right rows, hscroll when cursor is either
 		 (i) inside the right hscroll margin, or (ii) if it is
 		 inside the left margin and the window is already
@@ -12325,7 +12323,7 @@
 
 	      /* Find point in a display of infinite width.  */
 	      saved_current_buffer = current_buffer;
-	      current_buffer = XBUFFER (w->buffer);
+	      current_buffer = XBUFFER (w->contained);
 
 	      if (w == XWINDOW (selected_window))
 		pt = PT;
@@ -12378,7 +12376,7 @@
 		 redisplay.  */
 	      if (w->hscroll != hscroll)
 		{
-		  XBUFFER (w->buffer)->prevent_redisplay_optimizations_p = 1;
+		  XBUFFER (w->contained)->prevent_redisplay_optimizations_p = 1;
 		  w->hscroll = hscroll;
 		  hscrolled_p = 1;
 		}
@@ -12467,9 +12465,9 @@
   if (trace_redisplay_p)
     fprintf (stderr, "%p (%s): %s\n",
 	     w,
-	     ((BUFFERP (w->buffer)
-	       && STRINGP (BVAR (XBUFFER (w->buffer), name)))
-	      ? SSDATA (BVAR (XBUFFER (w->buffer), name))
+	     ((BUFFERP (w->contained)
+	       && STRINGP (BVAR (XBUFFER (w->contained), name)))
+	      ? SSDATA (BVAR (XBUFFER (w->contained), name))
 	      : "no buffer"),
 	     method + len);
 }
@@ -12533,8 +12531,8 @@
 	 require to redisplay the whole paragraph.  It might be worthwhile
 	 to find the paragraph limits and widen the range of redisplayed
 	 lines to that, but for now just give up this optimization.  */
-      if (!NILP (BVAR (XBUFFER (w->buffer), bidi_display_reordering))
-	  && NILP (BVAR (XBUFFER (w->buffer), bidi_paragraph_direction)))
+      if (!NILP (BVAR (XBUFFER (w->contained), bidi_display_reordering))
+	  && NILP (BVAR (XBUFFER (w->contained), bidi_paragraph_direction)))
 	unchanged_p = 0;
     }
 
@@ -12757,7 +12755,7 @@
      we set b->clip_changed to 1 to force updating the screen.  If
      b->clip_changed has already been set to 1, we can skip this
      check.  */
-  if (!b->clip_changed && BUFFERP (w->buffer) && w->window_end_valid)
+  if (!b->clip_changed && BUFFERP (w->contained) && w->window_end_valid)
     {
       ptrdiff_t pt;
 
@@ -12766,11 +12764,11 @@
       else
 	pt = marker_position (w->pointm);
 
-      if ((w->current_matrix->buffer != XBUFFER (w->buffer)
+      if ((w->current_matrix->buffer != XBUFFER (w->contained)
 	   || pt != w->last_point)
 	  && check_point_in_composition (w->current_matrix->buffer,
 					 w->last_point,
-					 XBUFFER (w->buffer), pt))
+					 XBUFFER (w->contained), pt))
 	b->clip_changed = 1;
     }
 }
@@ -13025,11 +13023,11 @@
      the whole window.  The assignment to this_line_start_pos prevents
      the optimization directly below this if-statement.  */
   if (((!NILP (Vtransient_mark_mode)
-	&& !NILP (BVAR (XBUFFER (w->buffer), mark_active)))
+	&& !NILP (BVAR (XBUFFER (w->contained), mark_active)))
        != (w->region_showing > 0))
       || (w->region_showing
 	  && w->region_showing
-	  != XINT (Fmarker_position (BVAR (XBUFFER (w->buffer), mark)))))
+	  != XINT (Fmarker_position (BVAR (XBUFFER (w->contained), mark)))))
     CHARPOS (this_line_start_pos) = 0;
 
   /* Optimize the case that only the line containing the cursor in the
@@ -13047,7 +13045,7 @@
       && !FRAME_OBSCURED_P (XFRAME (w->frame))
       /* Make sure recorded data applies to current buffer, etc.  */
       && this_line_buffer == current_buffer
-      && current_buffer == XBUFFER (w->buffer)
+      && current_buffer == XBUFFER (w->contained)
       && !w->force_start
       && !w->optional_new_start
       /* Point must be on the line that we have info recorded about.  */
@@ -13338,7 +13336,7 @@
       Lisp_Object mini_window = FRAME_MINIBUF_WINDOW (sf);
       struct frame *mini_frame;
 
-      displayed_buffer = XBUFFER (XWINDOW (selected_window)->buffer);
+      displayed_buffer = XBUFFER (XWINDOW (selected_window)->contained);
       /* Use list_of_error, not Qerror, so that
 	 we catch only errors and don't run the debugger.  */
       internal_condition_case_1 (redisplay_window_1, selected_window,
@@ -13548,7 +13546,7 @@
 static void
 mark_window_display_accurate_1 (struct window *w, int accurate_p)
 {
-  struct buffer *b = XBUFFER (w->buffer);
+  struct buffer *b = XBUFFER (w->contained);
 
   w->last_modified = accurate_p ? BUF_MODIFF (b) : 0;
   w->last_overlay_modified = accurate_p ? BUF_OVERLAY_MODIFF (b) : 0;
@@ -13595,11 +13593,9 @@
   for (; !NILP (window); window = w->next)
     {
       w = XWINDOW (window);
-      if (!NILP (w->vchild))
-	mark_window_display_accurate (w->vchild, accurate_p);
-      else if (!NILP (w->hchild))
-	mark_window_display_accurate (w->hchild, accurate_p);
-      else if (BUFFERP (w->buffer))
+      if (WINDOWP (w->contained))
+	mark_window_display_accurate (w->contained, accurate_p);
+      else
 	mark_window_display_accurate_1 (w, accurate_p);
     }
 
@@ -13656,13 +13652,11 @@
     {
       struct window *w = XWINDOW (window);
 
-      if (!NILP (w->hchild))
-	redisplay_windows (w->hchild);
-      else if (!NILP (w->vchild))
-	redisplay_windows (w->vchild);
-      else if (!NILP (w->buffer))
+      if (WINDOWP (w->contained))
+	redisplay_windows (w->contained);
+      else
 	{
-	  displayed_buffer = XBUFFER (w->buffer);
+	  displayed_buffer = XBUFFER (w->contained);
 	  /* Use list_of_error, not Qerror, so that
 	     we catch only errors and don't run the debugger.  */
 	  internal_condition_case_1 (redisplay_window_0, window,
@@ -14309,7 +14303,7 @@
 	  && !MATRIX_ROW_CONTINUATION_LINE_P (row)
 	  && row->x == 0)
 	{
-	  this_line_buffer = XBUFFER (w->buffer);
+	  this_line_buffer = XBUFFER (w->contained);
 
 	  CHARPOS (this_line_start_pos)
 	    = MATRIX_ROW_START_CHARPOS (row) + delta;
@@ -14345,7 +14339,7 @@
   struct window *w = XWINDOW (window);
   SET_MARKER_FROM_TEXT_POS (w->start, startp);
 
-  if (current_buffer != XBUFFER (w->buffer))
+  if (current_buffer != XBUFFER (w->contained))
     emacs_abort ();
 
   if (!NILP (Vwindow_scroll_functions))
@@ -14354,7 +14348,7 @@
 			    make_number (CHARPOS (startp)));
       SET_TEXT_POS_FROM_MARKER (startp, w->start);
       /* In case the hook functions switch buffers.  */
-      set_buffer_internal (XBUFFER (w->buffer));
+      set_buffer_internal (XBUFFER (w->contained));
     }
 
   return startp;
@@ -15005,7 +14999,7 @@
 	      must_scroll = 1;
 	    }
 	  else if (rc != CURSOR_MOVEMENT_SUCCESS
-		   && !NILP (BVAR (XBUFFER (w->buffer), bidi_display_reordering)))
+		   && !NILP (BVAR (XBUFFER (w->contained), bidi_display_reordering)))
 	    {
 	      struct glyph_row *row1;
 
@@ -15068,7 +15062,7 @@
 	  else if (scroll_p)
 	    rc = CURSOR_MOVEMENT_MUST_SCROLL;
 	  else if (rc != CURSOR_MOVEMENT_SUCCESS
-		   && !NILP (BVAR (XBUFFER (w->buffer), bidi_display_reordering)))
+		   && !NILP (BVAR (XBUFFER (w->contained), bidi_display_reordering)))
 	    {
 	      /* With bidi-reordered rows, there could be more than
 		 one candidate row whose start and end positions
@@ -15175,7 +15169,7 @@
       || (w == XWINDOW (minibuf_window)
 	  && NILP (echo_area_buffer[0])))
     {
-      struct buffer *buf = XBUFFER (w->buffer);
+      struct buffer *buf = XBUFFER (w->contained);
       whole = BUF_ZV (buf) - BUF_BEGV (buf);
       start = marker_position (w->start) - BUF_BEGV (buf);
       /* I don't think this is guaranteed to be right.  For the
@@ -15209,7 +15203,7 @@
 {
   struct window *w = XWINDOW (window);
   struct frame *f = XFRAME (w->frame);
-  struct buffer *buffer = XBUFFER (w->buffer);
+  struct buffer *buffer = XBUFFER (w->contained);
   struct buffer *old = current_buffer;
   struct text_pos lpoint, opoint, startp;
   int update_mode_line;
@@ -15232,7 +15226,7 @@
   opoint = lpoint;
 
   /* W must be a leaf window here.  */
-  eassert (!NILP (w->buffer));
+  eassert (!NILP (w->contained));
 #ifdef GLYPH_DEBUG
   *w->desired_matrix->method = 0;
 #endif
@@ -15262,10 +15256,10 @@
       else if ((w != XWINDOW (minibuf_window)
 		|| minibuf_level == 0)
 	       /* When buffer is nonempty, redisplay window normally. */
-	       && BUF_Z (XBUFFER (w->buffer)) == BUF_BEG (XBUFFER (w->buffer))
+	       && BUF_Z (XBUFFER (w->contained)) == BUF_BEG (XBUFFER (w->contained))
 	       /* Quail displays non-mini buffers in minibuffer window.
 		  In that case, redisplay the window normally.  */
-	       && !NILP (Fmemq (w->buffer, Vminibuffer_list)))
+	       && !NILP (Fmemq (w->contained, Vminibuffer_list)))
 	{
 	  /* W is a mini-buffer window, but it's not active, so clear
 	     it.  */
@@ -15287,7 +15281,7 @@
      value.  */
   /* Really select the buffer, for the sake of buffer-local
      variables.  */
-  set_buffer_internal_1 (XBUFFER (w->buffer));
+  set_buffer_internal_1 (XBUFFER (w->contained));
 
   current_matrix_up_to_date_p
     = (w->window_end_valid
@@ -16578,7 +16572,7 @@
 		 bidi-reordered glyph rows.  Let set_cursor_from_row
 		 figure out where to put the cursor, and if it fails,
 		 give up.  */
-	      if (!NILP (BVAR (XBUFFER (w->buffer), bidi_display_reordering)))
+	      if (!NILP (BVAR (XBUFFER (w->contained), bidi_display_reordering)))
 		{
 		  if (!set_cursor_from_row (w, row, w->current_matrix,
 					    0, 0, 0, 0))
@@ -16829,7 +16823,7 @@
 
   /* Preconditions: W must be a leaf window and full-width.  Its frame
      must have a frame matrix.  */
-  eassert (NILP (w->hchild) && NILP (w->vchild));
+  eassert (BUFFERP (w->contained));
   eassert (WINDOW_FULL_WIDTH_P (w));
   eassert (!FRAME_WINDOW_P (f));
 
@@ -16871,7 +16865,7 @@
 {
   struct glyph_row *row = start;
   struct glyph_row *best_row = NULL;
-  ptrdiff_t mindif = BUF_ZV (XBUFFER (w->buffer)) + 1;
+  ptrdiff_t mindif = BUF_ZV (XBUFFER (w->contained)) + 1;
   int last_y;
 
   /* If we happen to start on a header-line, skip that.  */
@@ -16907,7 +16901,7 @@
 	{
 	  struct glyph *g;
 
-	  if (NILP (BVAR (XBUFFER (w->buffer), bidi_display_reordering))
+	  if (NILP (BVAR (XBUFFER (w->contained), bidi_display_reordering))
 	      || (!best_row && !row->continued_p))
 	    return row;
 	  /* In bidi-reordered rows, there could be several rows
@@ -17073,7 +17067,7 @@
      wrapped line can change the wrap position, altering the line
      above it.  It might be worthwhile to handle this more
      intelligently, but for now just redisplay from scratch.  */
-  if (!NILP (BVAR (XBUFFER (w->buffer), word_wrap)))
+  if (!NILP (BVAR (XBUFFER (w->contained), word_wrap)))
     GIVE_UP (21);
 
   /* Under bidi reordering, adding or deleting a character in the
@@ -17084,8 +17078,8 @@
      to find the paragraph limits and widen the range of redisplayed
      lines to that, but for now just give up this optimization and
      redisplay from scratch.  */
-  if (!NILP (BVAR (XBUFFER (w->buffer), bidi_display_reordering))
-      && NILP (BVAR (XBUFFER (w->buffer), bidi_paragraph_direction)))
+  if (!NILP (BVAR (XBUFFER (w->contained), bidi_display_reordering))
+      && NILP (BVAR (XBUFFER (w->contained), bidi_paragraph_direction)))
     GIVE_UP (22);
 
   /* Make sure beg_unchanged and end_unchanged are up to date.  Do it
@@ -17950,7 +17944,7 @@
   (Lisp_Object glyphs)
 {
   struct window *w = XWINDOW (selected_window);
-  struct buffer *buffer = XBUFFER (w->buffer);
+  struct buffer *buffer = XBUFFER (w->contained);
 
   fprintf (stderr, "PT = %"pI"d, BEGV = %"pI"d. ZV = %"pI"d\n",
 	   BUF_PT (buffer), BUF_BEGV (buffer), BUF_ZV (buffer));
@@ -18056,7 +18050,7 @@
 get_overlay_arrow_glyph_row (struct window *w, Lisp_Object overlay_arrow_string)
 {
   struct frame *f = XFRAME (WINDOW_FRAME (w));
-  struct buffer *buffer = XBUFFER (w->buffer);
+  struct buffer *buffer = XBUFFER (w->contained);
   struct buffer *old = current_buffer;
   const unsigned char *arrow_string = SDATA (overlay_arrow_string);
   int arrow_len = SCHARS (overlay_arrow_string);
@@ -19263,7 +19257,7 @@
 	      row->glyphs[TEXT_AREA]->charpos = -1;
 	      row->displays_text_p = 0;
 
-	      if (!NILP (BVAR (XBUFFER (it->w->buffer), indicate_empty_lines))
+	      if (!NILP (BVAR (XBUFFER (it->w->contained), indicate_empty_lines))
 		  && (!MINI_WINDOW_P (it->w)
 		      || (minibuf_level && EQ (it->window, minibuf_window))))
 		row->indicate_empty_line_p = 1;
@@ -20078,10 +20072,8 @@
     {
       struct window *w = XWINDOW (window);
 
-      if (WINDOWP (w->hchild))
-	nwindows += redisplay_mode_lines (w->hchild, force);
-      else if (WINDOWP (w->vchild))
-	nwindows += redisplay_mode_lines (w->vchild, force);
+      if (WINDOWP (w->contained))
+	nwindows += redisplay_mode_lines (w->contained, force);
       else if (force
 	       || FRAME_GARBAGED_P (XFRAME (w->frame))
 	       || !MATRIX_MODE_LINE_ROW (w->current_matrix)->enabled_p)
@@ -20091,7 +20083,7 @@
 
 	  /* Set the window's buffer for the mode line display.  */
 	  SET_TEXT_POS (lpoint, PT, PT_BYTE);
-	  set_buffer_internal_1 (XBUFFER (w->buffer));
+	  set_buffer_internal_1 (XBUFFER (w->contained));
 
 	  /* Point refers normally to the selected window.  For any
 	     other window, set up appropriate value.  */
@@ -20873,7 +20865,7 @@
   XSETWINDOW (window, w);
 
   if (NILP (buffer))
-    buffer = w->buffer;
+    buffer = w->contained;
   CHECK_BUFFER (buffer);
 
   /* Make formatting the modeline a non-op when noninteractive, otherwise
@@ -22179,7 +22171,7 @@
 	    return OK_PIXELS (WINDOW_SCROLL_BAR_AREA_WIDTH (it->w));
 	}
 
-      prop = buffer_local_value_1 (prop, it->w->buffer);
+      prop = buffer_local_value_1 (prop, it->w->contained);
       if (EQ (prop, Qunbound))
 	prop = Qnil;
     }
@@ -22231,7 +22223,7 @@
 	      return OK_PIXELS (pixels);
 	    }
 
-	  car = buffer_local_value_1 (car, it->w->buffer);
+	  car = buffer_local_value_1 (car, it->w->contained);
 	  if (EQ (car, Qunbound))
 	    car = Qnil;
 	}
@@ -24083,7 +24075,7 @@
       int n = width;
 
       if (!STRINGP (object))
-	object = it->w->buffer;
+	object = it->w->contained;
 #ifdef HAVE_WINDOW_SYSTEM
       if (FRAME_WINDOW_P (it->f))
 	append_stretch_glyph (it, object, width, height, ascent);
@@ -25479,7 +25471,7 @@
 			int *active_cursor)
 {
   struct frame *f = XFRAME (w->frame);
-  struct buffer *b = XBUFFER (w->buffer);
+  struct buffer *b = XBUFFER (w->contained);
   int cursor_type = DEFAULT_CURSOR;
   Lisp_Object alt_cursor;
   int non_selected = 0;
@@ -26030,10 +26022,8 @@
 {
   while (w)
     {
-      if (!NILP (w->hchild))
-	update_cursor_in_window_tree (XWINDOW (w->hchild), on_p);
-      else if (!NILP (w->vchild))
-	update_cursor_in_window_tree (XWINDOW (w->vchild), on_p);
+      if (WINDOWP (w->contained))
+	update_cursor_in_window_tree (XWINDOW (w->contained), on_p);
       else
 	update_window_cursor (w, on_p);
 
@@ -27279,7 +27269,7 @@
 		{
 		  help_echo_string = help;
 		  XSETWINDOW (help_echo_window, w);
-		  help_echo_object = w->buffer;
+		  help_echo_object = w->contained;
 		  help_echo_pos = charpos;
 		}
 	    }
@@ -27315,7 +27305,7 @@
 	    {
 	      Lisp_Object default_help
 		= buffer_local_value_1 (Qmode_line_default_help_echo,
-					w->buffer);
+					w->contained);
 
 	      if (STRINGP (default_help))
 		{
@@ -27590,7 +27580,7 @@
 
   /* Are we in a window whose display is up to date?
      And verify the buffer's text has not changed.  */
-  b = XBUFFER (w->buffer);
+  b = XBUFFER (w->contained);
   if (part == ON_TEXT
       && w->window_end_valid
       && w->last_modified == BUF_MODIFF (b)
@@ -27799,8 +27789,8 @@
 		  if (pos > 0)
 		    {
 		      mouse_face = get_char_property_and_overlay
-			(make_number (pos), Qmouse_face, w->buffer, &overlay);
-		      buffer = w->buffer;
+			(make_number (pos), Qmouse_face, w->contained, &overlay);
+		      buffer = w->contained;
 		      disp_string = object;
 		    }
 		}
@@ -27913,11 +27903,11 @@
 		    if (p > 0)
 		      {
 			help = Fget_char_property (make_number (p),
-						   Qhelp_echo, w->buffer);
+						   Qhelp_echo, w->contained);
 			if (!NILP (help))
 			  {
 			    charpos = p;
-			    obj = w->buffer;
+			    obj = w->contained;
 			  }
 		      }
 		  }
@@ -27968,7 +27958,7 @@
 		      ptrdiff_t p = string_buffer_position (obj, start);
 		      if (p > 0)
 			pointer = Fget_char_property (make_number (p),
-						      Qpointer, w->buffer);
+						      Qpointer, w->contained);
 		    }
 		}
 	      else if (BUFFERP (obj)
@@ -28411,12 +28401,9 @@
 
   while (w && !FRAME_GARBAGED_P (f))
     {
-      if (!NILP (w->hchild))
-	mouse_face_overwritten_p
-	  |= expose_window_tree (XWINDOW (w->hchild), r);
-      else if (!NILP (w->vchild))
-	mouse_face_overwritten_p
-	  |= expose_window_tree (XWINDOW (w->vchild), r);
+      if (WINDOWP (w->contained))
+	mouse_face_overwritten_p
+	  |= expose_window_tree (XWINDOW (w->contained), r);
       else
 	mouse_face_overwritten_p |= expose_window (w, r);
 

=== modified file 'src/xfaces.c'
--- src/xfaces.c	2013-03-24 05:29:35 +0000
+++ src/xfaces.c	2013-03-25 14:24:29 +0000
@@ -5964,7 +5964,7 @@
 
   /* W must display the current buffer.  We could write this function
      to use the frame and buffer of W, but right now it doesn't.  */
-  /* eassert (XBUFFER (w->buffer) == current_buffer); */
+  /* eassert (XBUFFER (w->contained) == current_buffer); */
 
   XSETFASTINT (position, pos);
 
@@ -5974,9 +5974,9 @@
 
   /* Get the `face' or `mouse_face' text property at POS, and
      determine the next position at which the property changes.  */
-  prop = Fget_text_property (position, propname, w->buffer);
+  prop = Fget_text_property (position, propname, w->contained);
   XSETFASTINT (limit1, (limit < endpos ? limit : endpos));
-  end = Fnext_single_property_change (position, propname, w->buffer, limit1);
+  end = Fnext_single_property_change (position, propname, w->contained, limit1);
   if (INTEGERP (end))
     endpos = XINT (end);
 
@@ -6072,7 +6072,7 @@
 
   /* W must display the current buffer.  We could write this function
      to use the frame and buffer of W, but right now it doesn't.  */
-  /* eassert (XBUFFER (w->buffer) == current_buffer); */
+  /* eassert (XBUFFER (w->contained) == current_buffer); */
 
   XSETFASTINT (position, pos);
 
@@ -6082,9 +6082,9 @@
 
   /* Get the `face' or `mouse_face' text property at POS, and
      determine the next position at which the property changes.  */
-  prop = Fget_text_property (position, propname, w->buffer);
+  prop = Fget_text_property (position, propname, w->contained);
   XSETFASTINT (limit1, (limit < endpos ? limit : endpos));
-  end = Fnext_single_property_change (position, propname, w->buffer, limit1);
+  end = Fnext_single_property_change (position, propname, w->contained, limit1);
   if (INTEGERP (end))
     endpos = XINT (end);
 

=== modified file 'src/xfns.c'
--- src/xfns.c	2013-03-24 12:59:45 +0000
+++ src/xfns.c	2013-03-25 14:24:29 +0000
@@ -5043,7 +5043,7 @@
 
   /* Display the tooltip text in a temporary buffer.  */
   old_buffer = current_buffer;
-  set_buffer_internal_1 (XBUFFER (XWINDOW (FRAME_ROOT_WINDOW (f))->buffer));
+  set_buffer_internal_1 (XBUFFER (XWINDOW (FRAME_ROOT_WINDOW (f))->contained));
   bset_truncate_lines (current_buffer, Qnil);
   clear_glyph_matrix (w->desired_matrix);
   clear_glyph_matrix (w->current_matrix);

=== modified file 'src/xmenu.c'
--- src/xmenu.c	2013-03-24 12:59:45 +0000
+++ src/xmenu.c	2013-03-25 14:24:29 +0000
@@ -976,7 +976,7 @@
       if (! menubar_widget)
 	previous_menu_items_used = 0;
 
-      buffer = XWINDOW (FRAME_SELECTED_WINDOW (f))->buffer;
+      buffer = XWINDOW (FRAME_SELECTED_WINDOW (f))->contained;
       specbind (Qinhibit_quit, Qt);
       /* Don't let the debugger step into this code
 	 because it is not reentrant.  */


^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: Alternate design [Was: Re: [RFC] some reworking of struct window]
  2013-03-25 15:29         ` Dmitry Antipov
@ 2013-03-25 19:02           ` Stefan Monnier
  0 siblings, 0 replies; 16+ messages in thread
From: Stefan Monnier @ 2013-03-25 19:02 UTC (permalink / raw)
  To: Dmitry Antipov; +Cc: Eli Zaretskii, emacs-devel

>> For me, `payload' is associated with transport (or communication), so
>> it sounds a bit odd here.  But I won't oppose it (whereas I do oppose
>> "object").
> OK, what about neutral `contained'?

That would be a boolean field (is it contained?).  The closest noun
would be "contents" I think.

>>> +#define WINDOW_HORIZONTAL_COMBINATION(W) \
>>> +  ((W)->combination && (W)->horizontal)
>> I think this should be (eassert (WINDOWP ((W)->payload)), (W)->horizontal)
> This will require a lot of explicit checking whether W->payload is a window,
> for example in Fwindow_top_child and Fwindow_left_child.

I disagree with "a lot of" and I think making those checks explicit is good.

> I believe that we should treat dead windows as 'typeless' (that is,
> all of WINDOW_LEAF_P and WINDOW_xxx_COMBINATION_P should return false
> for them)

I'm not sure it's a good idea.

> and add explicit eassert where leaf or dead window can cause
> serious problems.

But here I do agree.


        Stefan



^ permalink raw reply	[flat|nested] 16+ messages in thread

end of thread, other threads:[~2013-03-25 19:02 UTC | newest]

Thread overview: 16+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-03-21  9:39 [RFC] some reworking of struct window Dmitry Antipov
2013-03-21 11:38 ` martin rudalics
2013-03-21 18:45   ` Eli Zaretskii
2013-03-21 21:17     ` martin rudalics
2013-03-21 14:26 ` Davis Herring
2013-03-21 14:46 ` Stefan Monnier
2013-03-21 15:01   ` Dmitry Antipov
2013-03-21 17:40     ` Eli Zaretskii
2013-03-21 18:21 ` Eli Zaretskii
2013-03-21 23:50   ` Stefan Monnier
2013-03-22  7:40     ` Alternate design [Was: Re: [RFC] some reworking of struct window] Dmitry Antipov
2013-03-22 13:34       ` Stefan Monnier
2013-03-25 15:29         ` Dmitry Antipov
2013-03-25 19:02           ` Stefan Monnier
2013-03-22  6:13   ` [RFC] some reworking of struct window Dmitry Antipov
2013-03-22  8:47     ` Eli Zaretskii

Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).