unofficial mirror of emacs-devel@gnu.org 
 help / color / mirror / code / Atom feed
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);

  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).