diff --git a/doc/lispref/windows.texi b/doc/lispref/windows.texi index adc294e4c99..a981bb89ed0 100644 --- a/doc/lispref/windows.texi +++ b/doc/lispref/windows.texi @@ -22,6 +22,7 @@ Windows * Deleting Windows:: Removing a window from its frame. * Recombining Windows:: Preserving the frame layout when splitting and deleting windows. +* Resurrecting Windows:: Restoring deleted windows. * Cyclic Window Ordering:: Moving around the existing windows. * Buffers and Windows:: Each window displays the contents of a buffer. * Switching Buffers:: Higher-level functions for switching to a buffer. @@ -1355,7 +1356,7 @@ Splitting Windows Examples of such windows are side windows (@pxref{Side Windows}) and atomic windows (@pxref{Atomic Windows}). -@defun split-window &optional window size side pixelwise +@defun split-window &optional window size side pixelwise refer This function creates a new live window next to the window @var{window}. If @var{window} is omitted or @code{nil}, it defaults to the selected window. That window is split, and reduced in @@ -1399,14 +1400,62 @@ Splitting Windows window is placed on the left of @var{window}. In both these cases, @var{size} specifies a total window width, in columns. +As a rule, if @var{window} already forms a combination (@pxref{Windows +and Frames}) that matches @var{side} (a horizontal combination matches +@var{side} if it is @code{left} or @code{right}, a vertical combination +matches @var{side} if it is @code{above} or @code{below}) and +@code{window-combination-limit} (@pxref{Recombining Windows}) is +@code{nil}, this function reuses @var{window}'s parent in the window +tree as parent of the new window. + +However, if @var{window} is in a combination that does not match +@var{side} or if @code{window-combination-limit} is non-@code{nil}, this +function makes a new parent window that replaces @var{window} in the +window tree and makes @var{window} and the new window its sole child +windows. This standard behavior can be overridden via the @var{refer} +argument. + The optional fourth argument @var{pixelwise}, if non-@code{nil}, means to interpret @var{size} in units of pixels, instead of lines and columns. -If @var{window} is a live window, the new window inherits various -properties from it, including margins and scroll bars. If -@var{window} is an internal window, the new window inherits the -properties of the window selected within @var{window}'s frame. +If the optional fifth argument @var{refer} is non-@code{nil}, it +specifies a reference window used for setting up properties of the new +window. If non-@code{nil}, @var{refer} can be either a window or a cons +cell of two windows. + +If @var{refer} is a cons cell, its @sc{car} has to specify a deleted, +former live window - a window that has shown a buffer before - on the +same frame as @var{window}. That buffer must be still live. The +@sc{cdr} has to specify a deleted window that was, before its deletion, +a parent window on the same frame as @var{window}. In this case, rather +then making new windows, this function replaces @var{window} with the +@sc{cdr} of @var{refer} in the window tree and makes @var{window} and +@var{refer}'s @sc{car} its new child windows. Buffer, start and point +positions of @var{refer}'s @sc{car} are set to the values they had +immediately before @var{refer}'s @sc{car} was deleted the last time. +Decorations and parameters remain unaltered from their values before +@var{refer}'s @sc{car} and @sc{cdr} were deleted. + +Alternatively, @var{refer} may specify a deleted, former live window - a +window that has shown a buffer before - on the same frame as +@var{window}. That buffer must be still live. In this case, this +function do not make a new window but rather makes @var{refer} live +again and inserts it into the window tree at the position and with the +sizes the new window would have been given. Buffer, start and point +positions of @var{refer} are set to the values they had immediately +before @var{refer} was deleted the last time. Decorations and +parameters remain unaltered from their values before @var{refer} was +deleted. The parent of @var{refer} is then determined as if it were a +window created anew. + +In any other case, @var{refer} must specify a live window. Then the new +window will inherit properties like buffer, start and point positions +and some decorations from @var{refer}. If @var{refer} is @code{nil} or +omitted, then if @var{window} is live, the new window inherits these +properties from @var{window}. If, however, @var{window} is an internal +window, the new window will inherit these properties from the window +selected on @var{window}'s frame. The behavior of this function may be altered by the window parameters of @var{window}, so long as the variable @@ -2048,6 +2097,131 @@ Recombining Windows windows. +@node Resurrecting windows +@section Resurrecting Windows +@cindex resurrecting deleted windows +@cindex restoring deleted windows + +After a window has been deleted (@pxref{Deleting Windows}) it cannot be +used any more by functions that require a valid window as their argument +even if some Lisp variable still references that window. When the last +reference to a window has ceased to exist, the window's Lisp object will +be eventually recycled by the garbage collector. + +There are two ways to resurrect a deleted window whose object has not +been yet recycled by the collector: The first is to keep a reference to +that window in a saved window configuration (@pxref{Window +Configurations}) and then call @code{set-window-configuration} with that +configuration as argument. The second one is to keep a reference to +that window in a variable or let-bind it and then use that reference as +@var{refer} argument in @code{split-window} (@pxref{Splitting Windows}). + +The major difference between these two is that +@code{set-window-configuration} restores the frame layout as it existed +before deleting the window. The @code{split-window} approach, on the +other hand, allows for arbitrary variations of the layout. + +Consider the following example starting with a frame containing a single +window showing the buffer @file{*scratch*}: + +@example +@group +(let* ((old (selected-window)) + (new (split-window old nil 'right)) + overlay) + (with-current-buffer (get-buffer-create "*Messages*") + (set-window-buffer new (current-buffer)) + (setq overlay (make-overlay (point-min) (point-max))) + (overlay-put overlay 'face 'highlight) + (overlay-put overlay 'window new) + (message "new %s parent %s" new (window-parent new)) + (sit-for 3)) + (delete-window new) + (setq new (split-window old nil 'left)) + (set-window-buffer new (get-buffer-create "*Messages*")) + (format "new %s parent %s" new (window-parent new))) +@end group +@end example + +When you run that code in @file{*scratch*} it will first split the +window showing @file{*scratch*} to display @file{*Messages*} in a new +window on the right. It also sets up an overlay with a window property +to highlight the text of @file{*Messages*} in the new window and +displays a message showing the new window and its parent in the window +tree. It then deletes the new window and resurrects it on the left of +the @file{*scratch*} window again displaying a message showing the new +window and its parent in the window tree. + +Note that both, new window and its parent have changed after moving the +@file{*Messages*} window to the left. Also, the highlighting disappears +because any properties set up for the new window on the right are lost +when the new window is re-created on the left. + +The following code uses the @var{refer} argument of @code{split-window} +instead. + +@example +@group +(let* ((old (selected-window)) + (new (split-window old nil 'right)) + overlay) + (with-current-buffer (get-buffer-create "*Messages*") + (set-window-buffer new (current-buffer)) + (setq overlay (make-overlay (point-min) (point-max))) + (overlay-put overlay 'face 'highlight) + (overlay-put overlay 'window new) + (message "new %s parent %s" new (window-parent new)) + (sit-for 3)) + (delete-window new) + (split-window old nil 'left nil new) + (format "new %s parent %s" new (window-parent new))) +@end group +@end example + +Note that all properties of the resurrected window like its decorations, +parameters as well as any overlays with a window property are preserved +as if that window had never been deleted. The only things that changed +are its position in the window tree and consequently the values returned +by @code{window-left-child} of its parent window as well as the values +returned by @code{window-prev-sibling} and @code{window-next-sibling} of +the window and its sibling. + +The following code passes both, the new window on the right and its +parent, via the @var{refer} argument to @code{split-window}: instead. + +@example +@group +(let* ((old (selected-window)) + (new (split-window old nil 'right)) + (parent (window-parent new)) + overlay) + (with-current-buffer (get-buffer-create "*Messages*") + (set-window-buffer new (current-buffer)) + (setq overlay (make-overlay (point-min) (point-max))) + (overlay-put overlay 'face 'highlight) + (overlay-put overlay 'window new) + (message "new %s parent %s" new (window-parent new)) + (sit-for 3)) + (delete-window new) + (split-window old nil 'left nil (cons new parent)) + (format "new %s parent %s" new (window-parent new))) +@end group +@end example + +Note that the parent window has been resurrected along with the new +window. + +Resurrecting dead windows is useful to preserve the identity of windows +in actions that are supposed to do that like moving windows around on a +frame or hiding them temporarily. Any properties of such a window like +its decorations, the buffer it has shown previously, that buffer's start +and point position in the window, the window's dedicated status or its +cursor type are left untouched and there's no need to recreate them from +scratch. For internal windows, the value of that window's combination +limit is preserved which means that the window can be recombined +(@pxref{Recombining Windows}) as before. + + @node Cyclic Window Ordering @section Cyclic Ordering of Windows @cindex cyclic ordering of windows @@ -7133,13 +7307,16 @@ Window Hooks window. @defun window-old-buffer &optional window -This function returns the buffer shown in @var{window} at the last -time window change functions were run for @var{window}'s frame. If it -returns @code{nil}, @var{window} has been created after that. If it -returns @code{t}, @var{window} was not shown at that time but has been -restored from a previously saved window configuration afterwards. -Otherwise, the return value is the buffer shown by @var{window} at -that time. +This function returns the buffer shown in @var{window} at the last time +window change functions were run for @var{window}'s frame. If it +returns @code{nil}, @var{window} is either an internal window or has +been created after that. If it returns @code{t}, @var{window} was not +shown at that time but has been restored from a previously saved window +configuration afterwards. Otherwise, the return value is the buffer +shown by @var{window} at that time. As a special case, if @var{window} +has been deleted, this function returns the last buffer @var{window} had +shown at that time. @var{window} can be any window and defaults to the +selected one. @end defun @defun window-old-pixel-width &optional window diff --git a/lisp/window.el b/lisp/window.el index e9d57652ec6..3829b2b441f 100644 --- a/lisp/window.el +++ b/lisp/window.el @@ -5511,7 +5511,7 @@ window--combination-resizable (setq sibling (window-next-sibling sibling))) (/ size (1+ number)))) -(defun split-window (&optional window size side pixelwise) +(defun split-window (&optional window size side pixelwise refer) "Make a new window adjacent to WINDOW. WINDOW must be a valid window and defaults to the selected one. Return the new window which is always a live window. @@ -5542,23 +5542,63 @@ split-window as `above' and `below'. Any other non-nil value for SIDE is currently handled like t (or `right'). +As a rule, if WINDOW already forms a combination that matches the SIDE +parameter and `window-combination-limit' is nil, reuse WINDOW's parent +in the window tree as parent of the new window. If WINDOW is in a +combination that is orthogonal to the SIDE parameter or if +`window-combination-limit' is non-nil, make a new parent window that +replaces WINDOW in the window tree and make WINDOW and the new window +its sole child windows. This standard behavior can be overridden via +the REFER argument. + PIXELWISE, if non-nil, means to interpret SIZE pixelwise. +If the optional fifth argument REFER is non-nil, it specifies a +reference window used for setting up properties of the new window. +REFER can be either a window or a cons cell of two windows. + +If REFER is a cons cell, its car has to specify a deleted, former live +window - a window that has shown a buffer before - on the same frame as +WINDOW. That buffer must be still live. The cdr has to specify a +deleted window that was a parent window on the same frame as WINDOW +before it was deleted. In this case, rather then making new windows, +replace WINDOW with the cdr of REFER in the window tree and make WINDOW +and REFER's car its new child windows. Buffer, start and point +positions of REFER's car are set to the values they had immediately +before REFER's car was deleted the last time. Decorations and +parameters remain unaltered from their values before REFER's car and cdr +were deleted. + +Alternatively REFER may specify a deleted, former live window - a window +that has shown a buffer before - on the same frame as WINDOW. In this +case do not make a new window but rather make REFER live again and +insert it into the window tree at the position and with the sizes the +new window would have been given. Buffer, start and point positions of +REFER are set to the values they had immediately before REFER was +deleted the last time. Decorations and parameters remain unaltered from +their values before REFER was deleted. Throw an error if REFER's buffer +has been deleted after REFER itself was deleted. + +Otherwise REFER must specify a live window. In this case, the new +window will inherit properties like buffer, start and point position and +some decorations from REFER. If REFER is nil or omitted, then if WINDOW +is live, any such properties are inherited from WINDOW. If, however, +WINDOW is an internal window, the new window will inherit these +properties from the window selected on WINDOW's frame. + If the variable `ignore-window-parameters' is non-nil or the `split-window' parameter of WINDOW equals t, do not process any -parameters of WINDOW. Otherwise, if the `split-window' parameter -of WINDOW specifies a function, call that function with all three -arguments and return the value returned by that function. - -Otherwise, if WINDOW is part of an atomic window, \"split\" the -root of that atomic window. The new window does not become a -member of that atomic window. - -If WINDOW is live, properties of the new window like margins and -scrollbars are inherited from WINDOW. If WINDOW is an internal -window, these properties as well as the buffer displayed in the -new window are inherited from the window selected on WINDOW's -frame. The selected window is not changed by this function." +parameters of WINDOW. Otherwise, if the `split-window' parameter of +WINDOW specifies a function, call that function with the three first +arguments WINDOW, SIZE and SIDE and return the value returned by that +function. + +Otherwise, if WINDOW is part of an atomic window, \"split\" the root of +that atomic window. The new window does not become a member of that +atomic window. + +The selected window and the selected window on WINDOW's frame are not +changed by this function." (setq window (window-normalize-window window)) (let* ((side (cond ((not side) 'below) @@ -5598,14 +5638,14 @@ split-window ((and (window-parameter window 'window-atom) (setq atom-root (window-atom-root window)) (not (eq atom-root window))) - (throw 'done (split-window atom-root size side pixelwise))) + (throw 'done (split-window atom-root size side pixelwise refer))) ;; If WINDOW's frame has a side window and WINDOW specifies the ;; frame's root window, split the frame's main window instead ;; (Bug#73627). ((and (eq window (frame-root-window frame)) (window-with-parameter 'window-side nil frame)) (throw 'done (split-window (window-main-window frame) - size side pixelwise))) + size side pixelwise refer))) ;; If WINDOW is a side window or its first or last child is a ;; side window, throw an error unless `window-combination-resize' ;; equals 'side. @@ -5644,8 +5684,8 @@ split-window (window-combined-p window horizontal))) ;; 'old-pixel-size' is the current pixel size of WINDOW. (old-pixel-size (window-size window horizontal t)) - ;; 'new-size' is the specified or calculated size of the - ;; new window. + ;; 'new-pixel-size' is the specified or calculated size + ;; of the new window. new-pixel-size new-parent new-normal) (cond ((not pixel-size) @@ -5766,8 +5806,9 @@ split-window window (- (if new-parent 1.0 (window-normal-size window horizontal)) new-normal))) - (let* ((new (split-window-internal window new-pixel-size side new-normal))) - (window--pixel-to-total frame horizontal) + (let ((new (split-window-internal + window new-pixel-size side new-normal refer))) + (window--pixel-to-total frame horizontal) ;; Assign window-side parameters, if any. (cond ((eq window-combination-resize 'side) diff --git a/src/window.c b/src/window.c index 7f157911685..d533904a550 100644 --- a/src/window.c +++ b/src/window.c @@ -652,15 +652,16 @@ DEFUN ("window-buffer", Fwindow_buffer, Swindow_buffer, 0, 1, 0, DEFUN ("window-old-buffer", Fwindow_old_buffer, Swindow_old_buffer, 0, 1, 0, doc: /* Return the old buffer displayed by WINDOW. -WINDOW must be a live window and defaults to the selected one. +WINDOW can be any window and defaults to the selected one. The return value is the buffer shown in WINDOW at the last time window -change functions were run. It is nil if WINDOW was created after -that. It is t if WINDOW has been restored from a window configuration -after that. */) +change functions were run or WINDOW is a former live window that was +deleted. It is nil if WINDOW was created after that. It is t if WINDOW +has been restored from a window configuration after that. It is always +nil if WINDOW is an internal window. */) (Lisp_Object window) { - struct window *w = decode_live_window (window); + struct window *w = decode_any_window (window); return (NILP (w->old_buffer) /* A new window. */ @@ -668,8 +669,8 @@ DEFUN ("window-old-buffer", Fwindow_old_buffer, Swindow_old_buffer, 0, 1, 0, : (w->change_stamp != WINDOW_XFRAME (w)->change_stamp) /* A window restored from a configuration. */ ? Qt - /* A window that was live the last time seen by window - change functions. */ + /* A window that was live the last time seen by window change + functions or was deleted. */ : w->old_buffer); } @@ -4491,45 +4492,6 @@ allocate_window (void) PVEC_WINDOW); } -/* Make new window, have it replace WINDOW in window-tree, and make - WINDOW its only vertical child (HORFLAG means make WINDOW its only - horizontal child). */ -static void -make_parent_window (Lisp_Object window, bool horflag) -{ - Lisp_Object parent; - register struct window *o, *p; - - o = XWINDOW (window); - p = allocate_window (); - memcpy ((char *) p + sizeof (union vectorlike_header), - (char *) o + sizeof (union 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); - - p->sequence_number = ++sequence_number; - - replace_window (window, parent, true); - - wset_next (o, Qnil); - wset_prev (o, Qnil); - wset_parent (o, parent); - /* ...but now P becomes an internal window. */ - wset_start (p, Qnil); - wset_pointm (p, Qnil); - wset_old_pointm (p, Qnil); - wset_buffer (p, Qnil); - wset_combination (p, horflag, window); - wset_combination_limit (p, Qnil); - /* Reset any previous and next buffers of p which have been installed - by the memcpy above. */ - wset_prev_buffers (p, Qnil); - wset_next_buffers (p, Qnil); - wset_window_parameters (p, Qnil); -} - /* Make new window from scratch. */ Lisp_Object make_window (void) @@ -5073,7 +5035,7 @@ resize_frame_windows (struct frame *f, int size, bool horflag) } -DEFUN ("split-window-internal", Fsplit_window_internal, Ssplit_window_internal, 4, 4, 0, +DEFUN ("split-window-internal", Fsplit_window_internal, Ssplit_window_internal, 4, 5, 0, doc: /* Split window OLD. Second argument PIXEL-SIZE specifies the number of pixels of the new window. It must be a positive integer. @@ -5088,32 +5050,33 @@ DEFUN ("split-window-internal", Fsplit_window_internal, Ssplit_window_internal, the right side of WINDOW. SIDE `left' means the new window shall be located on the left of WINDOW. In both cases PIXEL-SIZE specifies the width of the new window including space reserved for fringes and the -scrollbar or a divider column. +scroll bar or a divider column. Fourth argument NORMAL-SIZE specifies the normal size of the new window -according to the SIDE argument. +according to the SIDE argument. Optional fifth argument REFER is as for +'split-window'. The new pixel and normal sizes of all involved windows must have been set correctly. See the code of `split-window' for how this is done. */) - (Lisp_Object old, Lisp_Object pixel_size, Lisp_Object side, Lisp_Object normal_size) -{ - /* OLD (*o) is the window we have to split. (*p) is either OLD's - parent window or an internal window we have to install as OLD's new - parent. REFERENCE (*r) must denote a live window, or is set to OLD - provided OLD is a leaf window, or to the frame's selected window. - NEW (*n) is the new window created with some parameters taken from - REFERENCE (*r). */ - Lisp_Object new, frame, reference; - struct window *o, *p, *n, *r, *c; - struct frame *f; + (Lisp_Object old, Lisp_Object pixel_size, Lisp_Object side, + Lisp_Object normal_size, Lisp_Object refer) +{ + /* OLD (*o) is the window to split. REFER (*r) is a reference window, + either an arbitrary live window or a former live, now deleted + window on the same frame as OLD. NEW (*n) is the new window + created anew or resurrected from REFER (*r), if specified. *p + refers either to OLD's parent window that will become NEW's parent + window too or to a new internal window that becomes OLD's and NEW's + new parent. */ + struct window *o = decode_valid_window (old); + Lisp_Object frame = WINDOW_FRAME (o); + struct frame *f = XFRAME (frame); + struct window *p, *n, *r, *c; bool horflag /* HORFLAG is true when we split side-by-side, false otherwise. */ = EQ (side, Qt) || EQ (side, Qleft) || EQ (side, Qright); - - CHECK_WINDOW (old); - o = XWINDOW (old); - frame = WINDOW_FRAME (o); - f = XFRAME (frame); + Lisp_Object new, parent = Qnil; + bool dead = false; CHECK_FIXNUM (pixel_size); EMACS_INT total_size @@ -5131,14 +5094,74 @@ DEFUN ("split-window-internal", Fsplit_window_internal, Ssplit_window_internal, ? 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)) - /* OLD is live, use it as reference window. */ - reference = old; + /* Set up reference window. */ + if (NILP (refer)) + { + if (WINDOW_LIVE_P (old)) + /* OLD is live, use it as reference window. */ + refer = old; + else + /* Use the frame's selected window as reference window. */ + refer = FRAME_SELECTED_WINDOW (f); + + r = XWINDOW (refer); + } + else if (CONSP (refer)) + { + /* If REFER is a cons, then its car must be a deleted, former live + window and its cdr must be a deleted former parent window. Set + PARENT to the cdr of REFER and REFER to its car. WINDOW and + REFER end up as the sole children of PARENT which replaces + WINDOW in the window tree. As a special case, if REFER's cdr + is t, reuse REFER's car's old parent as new parent provided it + is a deleted fromer parent window. */ + parent = Fcdr (refer); + refer = Fcar (refer); + r = decode_any_window (refer); + + if (!NILP (r->contents) || !BUFFERP (r->old_buffer)) + error ("REFER's car must specify a deleted, former live window"); + else if (!BUFFER_LIVE_P (XBUFFER (r->old_buffer))) + error ("The buffer formerly shown by REFER's car has been killed"); + else if (!EQ (r->frame, frame)) + error ("REFER's car must specify a window on same frame as WINDOW"); + + if (EQ (parent, Qt)) + /* If REFER's cdr is t, use the old parent of REFER's car as new + parent. */ + parent = r->parent; + + p = decode_any_window (parent); + + if (!NILP (p->contents) || BUFFERP (p->old_buffer)) + error ("REFER's cdr must specify a deleted, former parent window"); + else if (!EQ (p->frame, frame)) + error ("REFER's cdr must specify window on same frame as WINDOW"); + + dead = true; + } else - /* Use the frame's selected window as reference window. */ - reference = FRAME_SELECTED_WINDOW (f); - r = XWINDOW (reference); + { + r = decode_any_window (refer); + + if (NILP (r->contents)) + /* Presumably a deleted, former live window. Check whether its + contents can be used. */ + { + if (!BUFFERP (r->old_buffer)) + error ("REFER must specify a former live window (must have shown a buffer)"); + else if (!BUFFER_LIVE_P (XBUFFER (r->old_buffer))) + error ("The buffer formerly shown by REFER has been killed"); + else if (!EQ (r->frame, frame)) + error ("REFER must specify a window on same frame as WINDOW"); + + dead = true; + } + else if (!NILP (parent)) + error ("If REFER is a cons, its car must not specify a live window"); + else if (!WINDOW_LIVE_P (refer)) + error ("REFER is not a live window (does not show a buffer)"); + } /* The following bugs are caught by `split-window'. */ if (MINI_WINDOW_P (o)) @@ -5149,16 +5172,18 @@ DEFUN ("split-window-internal", Fsplit_window_internal, Ssplit_window_internal, /* `window-combination-resize' non-nil means try to resize OLD's siblings proportionally. */ { - p = XWINDOW (o->parent); + struct window *op = XWINDOW (o->parent); + /* Temporarily pretend we split the parent window. */ wset_new_pixel - (p, make_fixnum ((horflag ? p->pixel_width : p->pixel_height) + (op, make_fixnum ((horflag ? op->pixel_width : op->pixel_height) - XFIXNUM (pixel_size))); - if (!window_resize_check (p, horflag)) + if (!window_resize_check (op, horflag)) error ("Window sizes don't fit"); else /* Undo the temporary pretension. */ - wset_new_pixel (p, make_fixnum (horflag ? p->pixel_width : p->pixel_height)); + wset_new_pixel + (op, make_fixnum (horflag ? op->pixel_width : op->pixel_height)); } else { @@ -5178,8 +5203,24 @@ DEFUN ("split-window-internal", Fsplit_window_internal, Ssplit_window_internal, Lisp_Object new_normal = horflag ? o->normal_cols : o->normal_lines; - make_parent_window (old, horflag); - p = XWINDOW (o->parent); + if (NILP (parent)) + /* This is the crux of the old make_parent_window. */ + { + p = allocate_window (); + XSETWINDOW (parent, p); + p->sequence_number = ++sequence_number; + wset_frame (p, frame); + } + else + /* Pacify GCC. */ + p = XWINDOW (parent); + + replace_window (old, parent, true); + wset_next (o, Qnil); + wset_prev (o, Qnil); + wset_parent (o, parent); + wset_combination (p, horflag, old); + if (EQ (Vwindow_combination_limit, Qt)) /* Store t in the new parent's combination_limit slot to avoid that its children get merged into another window. */ @@ -5195,7 +5236,12 @@ DEFUN ("split-window-internal", Fsplit_window_internal, Ssplit_window_internal, p = XWINDOW (o->parent); fset_redisplay (f); - new = make_window (); + + if (dead) + new = refer; + else + new = make_window (); + n = XWINDOW (new); wset_frame (n, frame); wset_parent (n, o->parent); @@ -5222,16 +5268,19 @@ DEFUN ("split-window-internal", Fsplit_window_internal, Ssplit_window_internal, n->window_end_valid = false; n->last_cursor_vpos = 0; - /* Get special geometry settings from reference window. */ - n->left_margin_cols = r->left_margin_cols; - n->right_margin_cols = r->right_margin_cols; - n->left_fringe_width = r->left_fringe_width; - n->right_fringe_width = r->right_fringe_width; - n->fringes_outside_margins = r->fringes_outside_margins; - n->scroll_bar_width = r->scroll_bar_width; - n->scroll_bar_height = r->scroll_bar_height; - wset_vertical_scroll_bar_type (n, r->vertical_scroll_bar_type); - wset_horizontal_scroll_bar_type (n, r->horizontal_scroll_bar_type); + if (!dead) + { + /* Get special geometry settings from reference window. */ + n->left_margin_cols = r->left_margin_cols; + n->right_margin_cols = r->right_margin_cols; + n->left_fringe_width = r->left_fringe_width; + n->right_fringe_width = r->right_fringe_width; + n->fringes_outside_margins = r->fringes_outside_margins; + n->scroll_bar_width = r->scroll_bar_width; + n->scroll_bar_height = r->scroll_bar_height; + wset_vertical_scroll_bar_type (n, r->vertical_scroll_bar_type); + wset_horizontal_scroll_bar_type (n, r->horizontal_scroll_bar_type); + } /* Directly assign orthogonal coordinates and sizes. */ if (horflag) @@ -5260,6 +5309,7 @@ DEFUN ("split-window-internal", Fsplit_window_internal, Ssplit_window_internal, sum = sum + XFIXNUM (c->new_total); c = NILP (c->next) ? 0 : XWINDOW (c->next); } + wset_new_total (n, make_fixnum ((horflag ? p->total_cols : p->total_lines) @@ -5267,10 +5317,30 @@ DEFUN ("split-window-internal", Fsplit_window_internal, Ssplit_window_internal, wset_new_normal (n, normal_size); block_input (); + + if (dead) + { + /* Get dead window back its old buffer and markers. */ + wset_buffer (n, n->old_buffer); + set_marker_restricted + (n->start, make_fixnum (XMARKER (n->start)->charpos), n->contents); + set_marker_restricted + (n->pointm, make_fixnum (XMARKER (n->pointm)->charpos), n->contents); + set_marker_restricted + (n->old_pointm, make_fixnum (XMARKER (n->old_pointm)->charpos), + n->contents); + + Vwindow_list = Qnil; + /* Remove window from the table of dead windows. */ + Fremhash (make_fixnum (n->sequence_number), + window_dead_windows_table); + } + window_resize_apply (p, horflag); adjust_frame_glyphs (f); - /* Set buffer of NEW to buffer of reference window. */ + set_window_buffer (new, r->contents, true, true); + FRAME_WINDOW_CHANGE (f) = true; unblock_input (); @@ -5368,6 +5438,8 @@ DEFUN ("delete-window-internal", Fdelete_window_internal, Sdelete_window_interna } else { + /* Store WINDOW's buffer in old_buffer. */ + wset_old_buffer (w, w->contents); unshow_buffer (w); unchain_marker (XMARKER (w->pointm)); unchain_marker (XMARKER (w->old_pointm)); @@ -7712,6 +7784,8 @@ delete_all_child_windows (Lisp_Object window) } else if (BUFFERP (w->contents)) { + /* Store WINDOW's buffer in old_buffer. */ + wset_old_buffer (w, w->contents); unshow_buffer (w); unchain_marker (XMARKER (w->pointm)); unchain_marker (XMARKER (w->old_pointm)); @@ -9064,12 +9138,9 @@ syms_of_window (void) doc: /* Hash table of dead windows. Each entry in this table maps a window number to a window object. Entries are added by `delete-window-internal' and are removed by the -garbage collector. - -This table is maintained by code in window.c and is made visible in -Elisp for testing purposes only. */); +garbage collector. */); window_dead_windows_table - = CALLN (Fmake_hash_table, QCweakness, Qt); + = CALLN (Fmake_hash_table, QCweakness, Qvalue); defsubr (&Sselected_window); defsubr (&Sold_selected_window);