aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorMartin Rudalics2025-10-18 10:33:10 +0200
committerMartin Rudalics2025-10-18 10:33:10 +0200
commitef2b0325677286373980f7d641576253b4f1cf41 (patch)
treeb7c9f0c1d75f84a5f740dfe83d145df1cd525dfb /src
parent81bc83c1a57999a1ff0584c605e7e13b4a9f7cbb (diff)
downloademacs-ef2b0325677286373980f7d641576253b4f1cf41.tar.gz
emacs-ef2b0325677286373980f7d641576253b4f1cf41.zip
Add functions 'combine-windows' and 'uncombine-window'
* src/window.c (make_parent_window, Fcombine_windows) (Funcombine_window): New functions. (Fsplit_window_internal): Use make_parent_window. * doc/lispref/windows.texi (Recombining Windows): Describe new functions 'combine-windows' and 'uncombine-window'. (Window Configurations): Explain "window clones". * etc/NEWS: Mention new functions 'combine-windows' and 'uncombine-window'.
Diffstat (limited to 'src')
-rw-r--r--src/window.c203
1 files changed, 198 insertions, 5 deletions
diff --git a/src/window.c b/src/window.c
index dee17ae445a..f19f2041c77 100644
--- a/src/window.c
+++ b/src/window.c
@@ -5133,6 +5133,200 @@ resize_frame_windows (struct frame *f, int size, bool horflag)
5133} 5133}
5134 5134
5135 5135
5136/** Make parent window on FRAME and return its object. */
5137static Lisp_Object
5138make_parent_window (Lisp_Object frame)
5139{
5140 Lisp_Object parent;
5141 struct window *p = allocate_window ();
5142
5143 p->sequence_number = ++sequence_number;
5144 wset_frame (p, frame);
5145 XSETWINDOW (parent, p);
5146
5147 return parent;
5148}
5149
5150
5151DEFUN ("combine-windows", Fcombine_windows, Scombine_windows, 2, 2, 0,
5152 doc: /* Combine windows from FIRST to LAST.
5153FIRST and LAST must be valid windows in the same combination, that is,
5154windows with the same parent window. If neither FIRST has a previous
5155nor LAST has a next sibling, return that parent window. Otherwise, make
5156a new parent window whose first child window becomes FIRST and whose
5157last child window becomes LAST, insert that parent window in the window
5158tree in lieu of the windows starting with FIRST and ending with LAST and
5159return the new parent window. */)
5160 (Lisp_Object first, Lisp_Object last)
5161{
5162 struct window *f = decode_valid_window (first);
5163 struct window *l = decode_valid_window (last);
5164 struct window *w = f;
5165
5166 if (f == l)
5167 /* Don't make a matryoshka window. */
5168 error ("Invalid window to parentify");
5169
5170 while (w != l && !NILP (w->next))
5171 w = XWINDOW (w->next);
5172
5173 if (w != l)
5174 {
5175 w = l;
5176
5177 while (w != f && !NILP (w->next))
5178 w = XWINDOW (w->next);
5179
5180 if (w == f)
5181 /* Invert FIRST and LAST. */
5182 {
5183 f = l;
5184 l = w;
5185 XSETWINDOW (first, f);
5186 XSETWINDOW (last, l);
5187 }
5188 else
5189 error ("Invalid window to parentify");
5190 }
5191
5192 if (NILP (f->prev) && NILP (l->next))
5193 return f->parent;
5194
5195 /* Make new parent window PARENT. */
5196 Lisp_Object parent = make_parent_window (f->frame);
5197 struct window *p = XWINDOW (parent);
5198 double normal_size = 0.0;
5199
5200 /* Splice in PARENT into the window tree. */
5201 p->parent = f->parent;
5202 p->horizontal = XWINDOW (p->parent)->horizontal;
5203 p->contents = first;
5204
5205 if (NILP (f->prev))
5206 /* FIRST has no previous sibling. */
5207 XWINDOW (p->parent)->contents = parent;
5208 else
5209 /* FIRST has a previous sibling. */
5210 {
5211 XWINDOW (f->prev)->next = parent;
5212 p->prev = f->prev;
5213 f->prev = Qnil;
5214 }
5215
5216 if (!NILP (l->next))
5217 /* LAST has a next sibling. */
5218 {
5219 XWINDOW (l->next)->prev = parent;
5220 p->next = l->next;
5221 l->next = Qnil;
5222 }
5223
5224 /* Fix parent slots for PARENT's new children. */
5225 w = f;
5226
5227 while (w)
5228 {
5229 w->parent = parent;
5230 if (w == l)
5231 break;
5232 else
5233 {
5234 if (p->horizontal)
5235 normal_size = normal_size + XFLOAT_DATA (f->normal_cols);
5236 else
5237 normal_size = normal_size + XFLOAT_DATA (f->normal_lines);
5238
5239 w = XWINDOW (w->next);
5240 }
5241 }
5242
5243 /* Set up PARENT's positions and sizes. */
5244 p->pixel_left = f->pixel_left;
5245 p->left_col = f->left_col;
5246 p->pixel_top = f->pixel_top;
5247 p->top_line = f->top_line;
5248
5249 if (p->horizontal)
5250 {
5251 p->pixel_width = l->pixel_left + l->pixel_width - f->pixel_left;
5252 p->total_cols = l->left_col + l->total_cols - f->left_col;
5253 p->pixel_height = f->pixel_height;
5254 p->total_lines = f->total_lines;
5255 }
5256 else
5257 {
5258 p->pixel_height = l->pixel_top + l->pixel_height - f->pixel_top;
5259 p->total_lines = l->top_line + l->total_lines - f->top_line;
5260 p->pixel_width = f->pixel_width;
5261 p->total_cols = f->total_cols;
5262 }
5263
5264 if (p->horizontal)
5265 {
5266 p->normal_cols = make_float (normal_size);
5267 p->normal_lines = f->normal_lines;
5268 }
5269 else
5270 {
5271 p->normal_cols = f->normal_cols;
5272 p->normal_lines = make_float (normal_size);
5273 }
5274
5275 return parent;
5276}
5277
5278DEFUN ("uncombine-window", Funcombine_window, Suncombine_window, 1, 1, 0,
5279 doc: /* Uncombine specified WINDOW.
5280WINDOW should be an internal window whose parent window is an internal
5281window of the same type. This means, that WINDOW and its parent should
5282be either both horizontal or both vertical window combinations. If this
5283is the case, make the child windows of WINDOW child windows of WINDOW's
5284parent and return t. Otherwise, leave the current configuration of
5285WINDOW's frame unchanged and return nil. */)
5286 (Lisp_Object window)
5287{
5288 struct window *w = decode_valid_window (window);
5289 Lisp_Object parent = w->parent;
5290
5291 if (MINI_WINDOW_P (w))
5292 error ("Cannot uncombine a mini window");
5293
5294 if (WINDOW_INTERNAL_P (w) && !NILP (parent)
5295 && w->horizontal == XWINDOW (parent)->horizontal)
5296 {
5297 struct window *p = XWINDOW (w->parent);
5298 /* WINDOW's first child. */
5299 Lisp_Object first = w->contents;
5300 struct window *f = XWINDOW (first);
5301 /* WINDOW's last child. */
5302 Lisp_Object last = Qnil;
5303 struct window *l = f;
5304
5305 /* Make WINDOW's parent new parent of WINDOW's children. */
5306 while (!NILP (l->next))
5307 {
5308 wset_parent (l, parent);
5309 l = XWINDOW (l->next);
5310 }
5311 wset_parent (l, parent);
5312 XSETWINDOW (last, l);
5313
5314 wset_prev (f, w->prev);
5315 if (NILP (f->prev))
5316 wset_combination (p, p->horizontal, first);
5317 else
5318 wset_next (XWINDOW (f->prev), first);
5319
5320 wset_next (l, w->next);
5321 if (!NILP (l->next))
5322 wset_prev (XWINDOW (w->next), last);
5323
5324 return Qt;
5325 }
5326 else
5327 return Qnil;
5328}
5329
5136DEFUN ("split-window-internal", Fsplit_window_internal, Ssplit_window_internal, 4, 5, 0, 5330DEFUN ("split-window-internal", Fsplit_window_internal, Ssplit_window_internal, 4, 5, 0,
5137 doc: /* Split window OLD. 5331 doc: /* Split window OLD.
5138Second argument PIXEL-SIZE specifies the number of pixels of the 5332Second argument PIXEL-SIZE specifies the number of pixels of the
@@ -5302,12 +5496,9 @@ set correctly. See the code of `split-window' for how this is done. */)
5302 = horflag ? o->normal_cols : o->normal_lines; 5496 = horflag ? o->normal_cols : o->normal_lines;
5303 5497
5304 if (NILP (parent)) 5498 if (NILP (parent))
5305 /* This is the crux of the old make_parent_window. */
5306 { 5499 {
5307 p = allocate_window (); 5500 parent = make_parent_window (frame);
5308 XSETWINDOW (parent, p); 5501 p = XWINDOW (parent);
5309 p->sequence_number = ++sequence_number;
5310 wset_frame (p, frame);
5311 } 5502 }
5312 else 5503 else
5313 /* Pacify GCC. */ 5504 /* Pacify GCC. */
@@ -9345,6 +9536,8 @@ name to `'ignore'. */);
9345 defsubr (&Sselect_window); 9536 defsubr (&Sselect_window);
9346 defsubr (&Sforce_window_update); 9537 defsubr (&Sforce_window_update);
9347 defsubr (&Ssplit_window_internal); 9538 defsubr (&Ssplit_window_internal);
9539 defsubr (&Scombine_windows);
9540 defsubr (&Suncombine_window);
9348 defsubr (&Sscroll_up); 9541 defsubr (&Sscroll_up);
9349 defsubr (&Sscroll_down); 9542 defsubr (&Sscroll_down);
9350 defsubr (&Sscroll_left); 9543 defsubr (&Sscroll_left);