From: martin rudalics <rudalics@gmx.at>
To: Pranshu Sharma <pranshu@bauherren.ovh>
Cc: Juri Linkov <juri@linkov.net>, "eliz@gnu.org" <eliz@gnu.org>,
emacs-devel <emacs-devel@gnu.org>
Subject: Re: Add function to rotate/transpose all windows
Date: Fri, 20 Dec 2024 11:03:08 +0100 [thread overview]
Message-ID: <43f74ccd-75ca-4437-894f-7a9e4b7902e0@gmx.at> (raw)
In-Reply-To: <787e1cf0-810c-4eea-8d89-03ee83f67807@gmx.at>
[-- Attachment #1: Type: text/plain, Size: 1018 bytes --]
> - Which of my changes should I install. I think the diff I posted on
> 2024-11-14 should suffice. Right? I attach a copy so you can check.
Below find a ChangeLog and attached a diff for what I intend to install.
Please have a look.
martin
Have 'split-window' optionally resurrect deleted windows
* src/window.c (Fwindow_old_buffer): Handle deleted window as
argument.
(make_parent_window): Remove function.
(Fsplit_window_internal): New argument REFER for resurrecting
deleted windows. Incorporate functionality of defunct
make_parent_window.
(Fdelete_window_internal, delete_all_child_windows): Store any
deleted window's buffer in the window's old_buffer slot.
(window_dead_windows_table): Make it a 'value' type hash table
so the sequence number cannot affect its weakness.
* lisp/window.el (split-window): New argument REFER.
* doc/lispref/windows.texi (Resurrecting Windows): New section.
(Splitting Windows): Explain new argument REFER.
(Window Hooks): Rewrite description of 'window-old-buffer'.
[-- Attachment #2: split-window.diff --]
[-- Type: text/x-patch, Size: 33041 bytes --]
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);
next prev parent reply other threads:[~2024-12-20 10:03 UTC|newest]
Thread overview: 154+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-09-24 13:45 Add function to rotate/transpose all windows pranshu sharma
2024-09-24 13:53 ` Eli Zaretskii
2024-09-25 8:05 ` martin rudalics
2024-09-25 8:34 ` pranshu sharma
2024-09-25 9:31 ` martin rudalics
2024-09-25 10:50 ` pranshu sharma
2024-09-25 13:53 ` martin rudalics
2024-09-25 15:31 ` pranshu sharma
2024-09-26 14:10 ` martin rudalics
2024-09-26 14:22 ` Eli Zaretskii
2024-09-27 17:29 ` martin rudalics
2024-09-28 7:52 ` pranshu sharma
2024-09-28 9:26 ` martin rudalics
2024-09-28 10:53 ` pranshu sharma
2024-09-28 14:48 ` martin rudalics
2024-09-29 7:36 ` pranshu sharma
2024-09-29 8:40 ` martin rudalics
2024-09-29 9:23 ` pranshu sharma
2024-09-29 14:48 ` martin rudalics
2024-09-30 6:29 ` pranshu sharma
2024-09-30 8:57 ` martin rudalics
2024-10-01 9:17 ` pranshu sharma
2024-10-02 9:04 ` martin rudalics
2024-10-03 7:06 ` pranshu sharma
2024-10-03 8:17 ` martin rudalics
2024-10-03 10:09 ` pranshu sharma
2024-10-03 14:18 ` martin rudalics
2024-10-04 5:50 ` pranshu sharma
2024-10-04 8:08 ` martin rudalics
2024-10-04 15:10 ` pranshu sharma
2024-10-05 14:43 ` martin rudalics
2024-10-06 2:54 ` pranshu sharma
2024-10-06 15:02 ` martin rudalics
2024-10-06 15:52 ` pranshu sharma
2024-10-07 8:33 ` martin rudalics
2024-10-07 9:42 ` pranshu sharma
2024-10-03 15:12 ` Eli Zaretskii
2024-10-08 18:35 ` Juri Linkov
2024-10-09 6:59 ` pranshu sharma
2024-10-09 16:21 ` Juri Linkov
2024-10-10 11:49 ` pranshu sharma
2024-10-10 16:57 ` Juri Linkov
2024-10-13 5:43 ` pranshu sharma
2024-10-13 8:17 ` martin rudalics
2024-10-14 17:36 ` Juri Linkov
2024-10-15 8:34 ` pranshu sharma
2024-10-15 16:16 ` Juri Linkov
2024-10-18 14:52 ` pranshu sharma
2024-10-18 17:48 ` martin rudalics
2024-10-18 18:37 ` Eli Zaretskii
2024-10-19 1:45 ` pranshu sharma
2024-10-19 6:45 ` Eli Zaretskii
2024-10-19 18:19 ` Juri Linkov
2024-10-19 8:33 ` martin rudalics
2024-10-20 8:19 ` martin rudalics
2024-10-20 14:11 ` Pranshu Sharma
2024-10-20 17:37 ` martin rudalics
2024-10-21 5:54 ` Pranshu Sharma
2024-10-21 8:14 ` martin rudalics
2024-10-21 9:23 ` martin rudalics
2024-10-21 13:37 ` Pranshu Sharma
2024-10-22 18:12 ` martin rudalics
2024-10-24 14:38 ` Pranshu Sharma
2024-10-24 18:39 ` martin rudalics
2024-10-25 14:24 ` Pranshu Sharma
2024-10-25 17:09 ` martin rudalics
2024-10-26 9:14 ` Pranshu Sharma
2024-10-27 8:23 ` martin rudalics
2024-11-02 14:06 ` Pranshu Sharma
2024-11-05 18:01 ` martin rudalics
2024-11-08 9:23 ` Pranshu Sharma
2024-11-08 10:06 ` Pranshu Sharma
2024-11-08 15:52 ` martin rudalics
2024-11-09 2:14 ` Pranshu Sharma
2024-11-09 8:48 ` martin rudalics
2024-11-08 15:52 ` martin rudalics
2024-11-09 2:09 ` Pranshu Sharma
2024-11-09 8:48 ` martin rudalics
2024-11-09 10:55 ` Pranshu Sharma
2024-11-09 18:06 ` martin rudalics
2024-11-10 10:09 ` Pranshu Sharma
2024-11-10 16:36 ` martin rudalics
2024-11-11 14:47 ` Pranshu Sharma
2024-11-11 16:55 ` martin rudalics
2024-11-12 13:50 ` Pranshu Sharma
2024-11-12 17:46 ` martin rudalics
2024-11-16 13:36 ` Pranshu Sharma
2024-11-16 16:54 ` martin rudalics
2024-11-17 2:45 ` Pranshu Sharma
2024-11-17 10:22 ` martin rudalics
2024-11-17 15:03 ` Pranshu Sharma
2024-11-17 16:38 ` martin rudalics
2024-11-18 0:37 ` Pranshu Sharma
2024-11-18 8:55 ` martin rudalics
2024-11-19 9:34 ` Pranshu Sharma
2024-11-19 17:48 ` martin rudalics
2024-11-21 14:04 ` Pranshu Sharma
2024-11-21 17:54 ` martin rudalics
2024-11-24 13:53 ` Pranshu Sharma
2024-11-26 9:49 ` martin rudalics
2024-11-26 14:14 ` Pranshu Sharma
2024-11-27 8:29 ` Pranshu Sharma
2024-11-27 9:18 ` martin rudalics
2024-11-27 14:37 ` Pranshu Sharma
2024-11-27 17:42 ` martin rudalics
2024-11-28 2:43 ` Pranshu Sharma
2024-11-28 9:28 ` martin rudalics
2024-11-28 15:18 ` Pranshu Sharma
2024-11-30 10:07 ` martin rudalics
2024-11-30 17:41 ` Juri Linkov
2024-11-30 19:01 ` martin rudalics
2024-12-01 4:13 ` Pranshu Sharma
2024-12-03 7:30 ` Juri Linkov
2024-12-03 8:25 ` martin rudalics
2024-12-01 6:41 ` Pranshu Sharma
2024-12-01 17:20 ` martin rudalics
2024-12-02 8:06 ` Pranshu Sharma
2024-12-03 8:23 ` martin rudalics
2024-12-04 15:20 ` Pranshu Sharma
2024-12-04 17:56 ` martin rudalics
2024-12-04 19:12 ` Juri Linkov
2024-12-05 14:16 ` Pranshu Sharma
2024-12-05 17:48 ` Juri Linkov
2024-12-06 4:51 ` Pranshu Sharma
2024-12-06 7:29 ` Juri Linkov
2024-12-05 14:23 ` Pranshu Sharma
2024-12-05 15:17 ` Pranshu Sharma
[not found] ` <87y10ecxk9.fsf@bauherren.ovh>
2024-12-17 15:04 ` martin rudalics
2024-12-17 15:36 ` Pranshu Sharma via Emacs development discussions.
2024-12-17 18:32 ` Juri Linkov
2024-12-18 1:50 ` Pranshu Sharma via Emacs development discussions.
2024-12-18 7:29 ` Juri Linkov
2024-12-18 10:09 ` Pranshu Sharma via Emacs development discussions.
2024-12-19 7:10 ` Juri Linkov
2024-12-20 10:11 ` Pranshu Sharma via Emacs development discussions.
2024-12-18 10:06 ` martin rudalics
2024-12-20 10:03 ` martin rudalics [this message]
2024-10-14 17:32 ` Juri Linkov
2024-09-28 7:58 ` pranshu sharma
2024-09-28 8:18 ` Eli Zaretskii
2024-09-28 9:40 ` martin rudalics
2024-09-28 11:35 ` Eli Zaretskii
2024-09-28 14:58 ` martin rudalics
2024-09-28 15:28 ` Eli Zaretskii
2024-10-07 8:33 ` martin rudalics
2024-09-28 13:22 ` pranshu sharma
2024-09-28 14:21 ` Eli Zaretskii
2024-09-28 14:49 ` martin rudalics
2024-09-27 10:06 ` pranshu sharma
2024-09-27 17:29 ` martin rudalics
2024-09-24 17:40 ` Petteri Hintsanen
2024-09-24 19:34 ` Charles Choi
2024-09-25 2:00 ` Emanuel Berg
2024-09-25 7:00 ` pranshu sharma
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
List information: https://www.gnu.org/software/emacs/
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=43f74ccd-75ca-4437-894f-7a9e4b7902e0@gmx.at \
--to=rudalics@gmx.at \
--cc=eliz@gnu.org \
--cc=emacs-devel@gnu.org \
--cc=juri@linkov.net \
--cc=pranshu@bauherren.ovh \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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).