unofficial mirror of emacs-devel@gnu.org 
 help / color / mirror / code / Atom feed
From: martin rudalics <rudalics@gmx.at>
To: Pranshu Sharma <pranshusharma366@gmail.com>
Cc: Juri Linkov <juri@linkov.net>, Eli Zaretskii <eliz@gnu.org>,
	emacs-devel@gnu.org
Subject: Re: Add function to rotate/transpose all windows
Date: Tue, 22 Oct 2024 20:12:18 +0200	[thread overview]
Message-ID: <b562f678-852c-4f15-b2fa-b68ff10cd785@gmx.at> (raw)
In-Reply-To: <87iktld1bd.fsf@gmail.com>

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

 >> - Split *scratch* first with REFER *Messages* and then its parent with
 >>    REFER *foo*.
 >>
 >> - Split *foo* first with REFER *scratch* and then *scratch* with REFER
 >>    *Messages*.
 >>
 >
 > Here, the second option is non feesible as it relies on #<window 222 on
 > *foo*> being an actual window, not a window split.  Althouht it is
 > possible with workarounds and I'll end up implimenting the first option
 > trying to get the second to work.
 >
 > (t (0 1 148 31)
 >      (nil (0 1 148 16) #<window 182 on *scratch*> #<window 224 on
 > 	 *Messages*>)
 >      #<window 222 on *foo*>)
 >
 > When I orignally wrote the transpose-windows-1, I didn't know about
 > internal windows.
 >
 > Also I looked at your other message about window split internal, that
 > should help a lot.

OK.  I looked into this again and maybe I can help you.  Attached find a
new version of 'split-window' that accepts also a (WINDOW . PARENT)
cons as REFER where WINDOW is the buffer window to use and PARENT its
parent before WINDOW was deleted.  How to use that is documented in the
version of window-transpose.el I also attach.  It's full of debugging
code so you have to figure out yourself how to make use of it.

The three crucial aspects are:

(1) It has a function 'window-alist' that establishes before transposing
anything an association list of all live windows with their parents and
stores it in the variable 'window-alist'.

(2) It deletes windows via 'delete-other-windows-internal'.

(3) When it calls 'split-window' then in the (listp win) case I set the
cdr of the cons to the old parent of the _window to split_ (found via
'window-alist').  In the win is a window case, I set the cdr of the cons
to the old parent of the _window to make_ (again found via
'window-alist').

This survives quite a number of 'rotate-windows-clockwise' on the three
windows structure I create on the bottom of window-transpose.el.

Try it and then maybe try it with your remaining functions in an
analogous manner.  The tricky part is certainly (3) which might just
work with my simple rotation scenario.

martin

[-- Attachment #2: split-window-diff --]
[-- Type: text/plain, Size: 21794 bytes --]

diff --git a/doc/lispref/windows.texi b/doc/lispref/windows.texi
index 0b8d7d3b76d..8bf6ebc828b 100644
--- a/doc/lispref/windows.texi
+++ b/doc/lispref/windows.texi
@@ -1355,7 +1355,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
@@ -1403,10 +1403,35 @@ Splitting Windows
 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 has to
+denote either a deleted, former live window on the same frame as
+@var{window} or an arbitrary live window.  If @var{refer} is a deleted
+window, this function does not make a new window but rather resurrects
+@var{refer} 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 restored 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.  An error is thrown if @var{refer}'s buffer has been deleted
+after @var{refer} itself was deleted.
+
+If and only if @var{refer} is a deleted window and its former parent
+window (@pxref{Windows and Frames}) is a deleted window too, this
+function will also resurrect the old parent window and insert it into
+the appropriate place in the window tree.
+
+Note that in order to resurrect a deleted window, that window must not
+have been recycled by the garbage collector (@pxref{Garbage Collection})
+yet.  Hence to make sure that a deleted window can get resurrected, you
+should keep a reference to any such window in a variable until this
+function returns.
+
+If @var{refer} is a live window, the new window will inherit properties
+like buffer, start and point and some decorations from @var{refer}.  If
+@var{refer} is @code{nil} or omitted, then if @var{window} is live, any
+such properties are inherited 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
@@ -7126,13 +7151,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 b50770cbd7e..2cf2c288452 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.
@@ -5554,11 +5554,30 @@ split-window
 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."
+If the optional fifth argument REFER is non-nil, it has to denote either
+a deleted, former live window on the same frame as WINDOW or an
+arbitrary live window.  If REFER is a deleted window, 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.
+
+If and only if REFER is a deleted window and its previous parent window
+is now a deleted window too, do not make a new parent window but reuse
+the old aprent window, making it a valid window again.
+
+If REFER is a live window, the new window will inherit properties like
+buffer, start and point 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.
+
+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 +5617,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 +5663,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 +5785,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 34968ac824f..5254f96ba89 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,54 @@ 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
-    /* Use the frame's selected window as reference window.  */
-    reference = FRAME_SELECTED_WINDOW (f);
-  r = XWINDOW (reference);
+    {
+      if (CONSP (refer))
+	{
+	  parent = Fcdr (refer);
+	  p = decode_any_window (parent);
+	  refer = Fcar (refer);
+
+	  /* Note: PARENT is not necessarily REFER's parent at the time
+	     REFER was deleted but maybe some earlier parent of REFER.  */
+	  if (BUFFERP (p->old_buffer))
+	    error ("Deleted window in REFER was a live window (did show a buffer)");
+	  else if (!EQ (p->frame, frame))
+	    error ("Deleted window in REFER was not on same frame as the window to split");
+	}
+
+      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 ("Deleted window in REFER was not a live window (did not show a buffer)");
+	  else if (!BUFFER_LIVE_P (XBUFFER (r->old_buffer)))
+	    error ("The buffer formerly shown by deleted window in REFER has been deleted");
+	  else if (!EQ (r->frame, frame))
+	    error ("Deleted window in REFER was not on same frame as the window to split");
+
+	  dead = true;
+	}
+      else if (!NILP (parent))
+	error ("REFER must not contain live and dead windows");
+      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))
@@ -5178,8 +5181,31 @@ 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);
+      /* This is the crux of the old make_parent_window.  */
+      if (dead && WINDOWP (parent) && !WINDOW_VALID_P (parent))
+	/* Reuse REFER's cdr (provided by caller).  */
+	p = XWINDOW (parent);
+      else if (dead && WINDOWP (r->parent) && !WINDOW_VALID_P (r->parent))
+	/* Reuse REFER's old parent (potentially unsafe).  */
+	{
+	  parent = r->parent;
+	  p = XWINDOW (parent);
+	}
+      else
+	/* Allocate new parent (classic style).  */
+	{
+	  p = allocate_window ();
+	  XSETWINDOW (parent, p);
+	  p->sequence_number = ++sequence_number;
+	  wset_frame (p, frame);
+	}
+
+      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 +5221,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 +5253,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 +5294,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 +5302,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 +5423,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 +7769,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 +9123,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);

[-- Attachment #3: window-transpose.el --]
[-- Type: text/x-emacs-lisp, Size: 9966 bytes --]

;;; -*- lexical-binding:t -*-
(setq debug-on-error t)

(defvar old-window-alist nil)
(defvar old-window-list nil)
(defvar new-window-alist nil)
(defvar window-alist nil)

(defun window-alist (&optional window)
  (setq window-alist nil)
  (walk-window-subtree
   (lambda (w)
     (setq window-alist
	   (cons (cons w (window-parent w))
		 window-alist)))
   (or window (frame-root-window))))

(defun old-window-alist ()
  (setq old-window-list (window-list))
  (setq old-window-alist nil)
  (dolist (window old-window-list)
    (setq old-window-alist
	  (cons
	   (cons window (window-parent window))
	   old-window-alist)))

  (setq old-window-alist (nreverse old-window-alist)))

(defun new-window-alist ()
  (setq new-window-alist nil)
  (dolist (window old-window-list)
    (setq new-window-alist
	  (cons
	   (cons window (window-parent window))
	   new-window-alist)))

  (setq new-window-alist (nreverse new-window-alist)))

(defun window-tree-pixel-sizes (window &optional next)
  "Return pixel sizes of all windows rooted at WINDOW.
The return value is a list where each window is represented either by a
triple whose first element is either t for an internal window that is a
horizontal combination, nil for an internal window that is a vertical
combination, or the window itself for a live window.  The second element
is a cons of the pixel height and pixel width of the window.  The third
element is specified for internal windows only and recursively lists
that window's child windows using the same triple structure."
  (let (list)
    (while window
      (setq list
	    (cons
	     (cond
	      ((window-top-child window)
	       (cons t (cons (cons (window-pixel-height window)
				   (window-pixel-width window))
			     (window-tree-pixel-sizes
			      (window-top-child window) t))))
	      ((window-left-child window)
	       (cons nil (cons (cons (window-pixel-height window)
				     (window-pixel-width window))
			       (window-tree-pixel-sizes
				(window-left-child window) t))))
	      (t (list window (cons (window-pixel-height window)
				    (window-pixel-width window)))))
	     list))
      (setq window (when next (window-next-sibling window))))
    (nreverse list)))

(defun rotate-windows-anticlockwise (&optional subtree frame-or-window)
  "Rotate windows of FRAME-OR-WINDOW anticlockwise by 90 degrees.
FRAME-OR-WINDOW must be a live frame or window and defaults to the
selected frame.  If FRAME-OR-WINDOW is a frame, rotate the main window
of the frame, otherwise rotate FRAME-OR-WINDOW.  See
`rotate-windows-clockwise' for how to rotate windows in the opposite
direction.  If SUBTREE is non-nil, the function will act as if
FRAME-OR-WINDOW is the parent window of the selected window."
  (interactive "P")
  (let ((window (if subtree
		    (window-parent)
		  (if (windowp frame-or-window)
		      frame-or-window
		    (window-main-window frame-or-window)))))
    (window--transpose window '(right . above) nil)))

(defun rotate-windows-clockwise (&optional subtree frame-or-window)
  "Rotate windows of FRAME-OR-WINDOW clockwise by 90 degrees.
FRAME-OR-WINDOW must be a live frame or window and defaults to the
selected frame.  If FRAME-OR-WINDOW is a frame, rotate the main window
of the frame, otherwise rotate FRAME-OR-WINDOW.  See
`rotate-windows-anticlockwise' for how to rotate windows in the opposite
direction.  If SUBTREE is non-nil, the function will act as if
FRAME-OR-WINDOW is the parent window of the selected window."
  (interactive "P")
  (let ((window (cond
		 (subtree
		  (window-parent))
		 ((windowp frame-or-window)
		  frame-or-window)
		 (t
		  (window-main-window frame-or-window)))))
    (old-window-alist)
    (window-alist window)
;;     (message "%s" window-alist) (sit-for 3)
    (window--transpose window '(left . below) nil)
    (new-window-alist)
    (with-current-buffer (get-buffer-create "*foo*")
      (erase-buffer)
      (pp old-window-alist (current-buffer))
      (insert "\n")
      (pp new-window-alist (current-buffer)))))

(defun flip-windows-horizontally (&optional subtree frame-or-window)
  "Horizontally flip windows of FRAME-OR-WINDOW.
When the windows are flipped horzontally, the window layout is made to
it's reflection from the side edge.  FRAME-OR-WINDOW must be a live
frame or window and defaults to the selected frame.  If FRAME-OR-WINDOW
is a frame, flip from the main window of the frame, otherwise flip from
FRAME-OR-WINDOW.  See `flip-windows-vertically' for how to flip windows
vertically.  If SUBTREE is non-nil, the function will act as if
FRAME-OR-WINDOW is the parent window of the selected window."
  (interactive "P")
  (let ((window (cond
		 (subtree
		  (window-parent))
		 ((windowp frame-or-window)
		  frame-or-window)
		 (t
		  (window-main-window frame-or-window)))))
    (window--transpose window '(below . left) t)))

(defun flip-windows-vertically (&optional subtree frame-or-window)
  "Horizontally flip windows of FRAME-OR-WINDOW.
When the windows are flipped vertically, the window layout is made to
it's reflection from the top edge.  FRAME-OR-WINDOW must be a live frame
or window and defaults to the selected frame.  If FRAME-OR-WINDOW is a
frame, flip from the main window of the frame, otherwise flip from
FRAME-OR-WINDOW.  See `flip-windows-horizontally' for how to flip
windows horizontally."
  (interactive "P")
  (let ((window (if subtree
		    (window-parent)
		  (if (windowp frame-or-window)
		      frame-or-window
		    (window-main-window frame-or-window)))))
    (window--transpose window '(above . right) t)))

(defun transpose-windows (&optional subtree frame-or-window)
  "Transpose windows of FRAME-OR-WINDOW.
Rearrange windows such that where a horizontal split was used a vertical
one is used instead, and vice versa.  FRAME-OR-WINDOW must be a live
frame or window and defaults to the selected frame.  If FRAME-OR-WINDOW
is a frame, transpose the main window of the frame, otherwise transpose
FRAME-OR-WINDOW.  If SUBTREE is non-nil, the function will act as if
FRAME-OR-WINDOW is the parent window of the selected window."
  (interactive "P")
  (let ((window (if subtree
		    (window-parent)
		  (if (windowp frame-or-window)
		      frame-or-window
		    (window-main-window frame-or-window)))))
    (window--transpose window '(right . below) nil)))

(defun window--transpose (window conf do-not-convert-size)
  "Rearrange windows of WINDOW recursively.
CONF should be a cons cell: (HORIZONTAL-SPLIT . VERTICAL-SPLIT) where
HORIZONTAL-SPLIT will be used as the third argument of `split-window'
when splitting a window that was previously horizontally split, and
VERTICAL-SPLIT as third argument of `split-window' for a window that was
previously vertically split.  If DO-NOT-CONVERT-SIZE non-nil, the size
argument of the window-split is converted from vertical to horizontal or
vice versa, with the same proportion of the total split."
  (if (or (not window)
	  (window-live-p window))
      (message "No windows to transpose")
    (let* ((frame (window-frame window))
	   (fwin window)
	   (selwin (frame-selected-window window))
	   (win-tree (car (window-tree-pixel-sizes window))))
      (while (not (window-live-p fwin))
	(setq fwin (window-child fwin)))
      (delete-other-windows-internal
       fwin (and (window-valid-p (car win-tree)) (car win-tree)))
      (window--transpose-1 win-tree fwin conf do-not-convert-size)
      ;; Go back to previously selected window.
      (set-frame-selected-window frame selwin))))

(defun window--transpose-1 (subtree cwin conf do-not-convert-size)
  "Subroutine of `window--transpose'.
SUBTREE must be in the format of the result of
`window-tree-pixel-sizes'.  CWIN is the current window through which the
window splits are made.  The CONF and DO-NOT-CONVERT-SIZE arguments are
the same as the ones in `window--transpose'."
  ;; `ilen' is the max size a window could be of given the split type.
  ;; `flen' is max size the window could be converted to the opposite
  ;; of the given split type.
  (pcase-let ((`(,ilen . ,flen) (if (car subtree)
				    (cons (float (car (cadr subtree)))
					  (float (window-pixel-width cwin)))
				  (cons (float (cdr (cadr subtree)))
					(float (window-pixel-height cwin))))))
    (mapc
     (pcase-lambda (`(,win . ,size))
       (let ((split-size (- (if do-not-convert-size
				size
			      (round (* flen  (/ size ilen))))))
	     (split-type
	      (funcall (if (car subtree) 'car 'cdr) conf)))
	 (if (listp win)
	     (let* ((refer-car (seq-some
				(lambda (x)
				  (and (windowp x) x))
				(flatten-list win)))
		    (refer (cons refer-car
				 (cdr (assq cwin window-alist)))))
;; 	       (message "1 .. %s" (cons refer (cdr (assq refer-car window-alist)))) (sit-for 3)
	       ;; `win' is a window subtree.
	       (window--transpose-1 win (split-window cwin
						      split-size
						      split-type
						      t
						      refer)
				    conf do-not-convert-size))
	   ;; `win' is a window.
;; 	   (message "2 .. %s" (cons win (cdr (assq win window-alist)))) (sit-for 3)
	   (split-window cwin split-size
			 split-type t
			 (cons win (cdr (assq win window-alist)))))))
     (mapcar
      (lambda (e)
	(let ((window? (if (windowp (car e)) (car e) e)))
	  (cons window?
		;; The respective size of the window.
		(if (car subtree)
		    (car (cadr e))
		  (cdr (cadr e))))))
      ;; By using cdddr, we ignore window split type, sizes and the
      ;; first window (it's implicitly created).
      (nreverse (cdddr subtree))))
    ;; (caaddr subtree) is the first window.
    (unless (windowp (caaddr subtree))
      (window--transpose-1 (caddr subtree) cwin conf do-not-convert-size))))

(global-set-key [(super p)] 'transpose-windows)
(global-set-key [(super q)] 'rotate-windows-clockwise)

(let ((window (split-window)))
  (set-window-buffer window (get-buffer-create "*foo*"))
  (setq window (split-window nil nil t))
  (set-window-buffer window (get-buffer-create "*Messages*"))
  (select-window window))

  reply	other threads:[~2024-10-22 18:12 UTC|newest]

Thread overview: 144+ 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 [this message]
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
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=b562f678-852c-4f15-b2fa-b68ff10cd785@gmx.at \
    --to=rudalics@gmx.at \
    --cc=eliz@gnu.org \
    --cc=emacs-devel@gnu.org \
    --cc=juri@linkov.net \
    --cc=pranshusharma366@gmail.com \
    /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).