aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorMartin Rudalics2025-10-31 09:17:38 +0100
committerMartin Rudalics2025-10-31 09:17:38 +0100
commit7da7b246cfe5c9347c16eeefa03f0485afdbaf74 (patch)
tree64ede011280cd545d2a8ac5015bc13fb12665ab8 /src
parent55d4596dd0ef592e769d777ffb0673725bb00b1d (diff)
downloademacs-7da7b246cfe5c9347c16eeefa03f0485afdbaf74.tar.gz
emacs-7da7b246cfe5c9347c16eeefa03f0485afdbaf74.zip
Fix a bug in Fcombine_windows
* src/window.c (window_set_parent_and_normal_sizes): New function. (Fcombine_windows): Improve doc-string. Use wset_... functions. Call window_set_parent_and_normal_sizes to fix a bug where it failed to assign new normal sizes. (Funcombine_window): Call window_set_parent_and_normal_sizes.
Diffstat (limited to 'src')
-rw-r--r--src/window.c166
1 files changed, 105 insertions, 61 deletions
diff --git a/src/window.c b/src/window.c
index d7348fb265b..d776cd7119e 100644
--- a/src/window.c
+++ b/src/window.c
@@ -5148,15 +5148,76 @@ make_parent_window (Lisp_Object frame)
5148} 5148}
5149 5149
5150 5150
5151/** Assign parent and normal sizes to all child windows of window P.
5152 Normal sizes are calculated from the child windows' pixel widths and
5153 heights so these must be in place already. This function is called
5154 when parent/child window relationships change without resizing as in
5155 Fcombine_windows or Funcombine_window. */
5156static void
5157window_set_parent_and_normal_sizes (Lisp_Object parent)
5158{
5159 struct window *p = XWINDOW (parent);
5160 struct window *w = XWINDOW (p->contents);
5161 /* Normal size left for yet unprocessed windows. */
5162 double remainder = 1.0;
5163
5164 if (w->horizontal)
5165 {
5166 while (true)
5167 {
5168 wset_parent (w, parent);
5169 wset_normal_lines (w, make_float (1.0));
5170
5171 if (NILP (w->next))
5172 {
5173 wset_normal_cols (w, make_float (remainder));
5174 break;
5175 }
5176 else
5177 {
5178 wset_normal_cols (w, make_float ((double) w->pixel_width
5179 / (double) p->pixel_width));
5180 remainder -= XFLOAT_DATA (w->normal_cols);
5181 w = XWINDOW (w->next);
5182 }
5183 }
5184 }
5185 else
5186 {
5187 while (true)
5188 {
5189 wset_parent (w, parent);
5190 wset_normal_cols (w, make_float (1.0));
5191
5192 if (NILP (w->next))
5193 {
5194 wset_normal_lines (w, make_float (remainder));
5195 break;
5196 }
5197 else
5198 {
5199 wset_normal_lines (w, make_float ((double) w->pixel_height
5200 / (double) p->pixel_height));
5201 remainder -= XFLOAT_DATA (w->normal_lines);
5202 w = XWINDOW (w->next);
5203 }
5204 }
5205 }
5206}
5207
5208
5151DEFUN ("combine-windows", Fcombine_windows, Scombine_windows, 2, 2, 0, 5209DEFUN ("combine-windows", Fcombine_windows, Scombine_windows, 2, 2, 0,
5152 doc: /* Combine windows from FIRST to LAST. 5210 doc: /* Combine windows from FIRST to LAST inclusive.
5153FIRST and LAST must be valid windows in the same combination, that is, 5211FIRST and LAST must be different, valid windows in the same combination,
5154windows with the same parent window. If neither FIRST has a previous 5212that is, windows with the same parent window. If LAST is not reachable
5155nor LAST has a next sibling, return that parent window. Otherwise, make 5213from FIRST by applying `window-next-sibling' repeatedly, invert FIRST
5156a new parent window whose first child window becomes FIRST and whose 5214and LAST.
5157last child window becomes LAST, insert that parent window in the window 5215
5158tree in lieu of the windows starting with FIRST and ending with LAST, and 5216If FIRST has no previous and LAST has no next sibling, return nil.
5159return the new parent window. */) 5217Otherwise, make a new parent window whose first child window becomes
5218FIRST and whose last child window becomes LAST, insert that parent
5219window in the window tree in lieu of the windows starting with FIRST and
5220ending with LAST and return the new parent window. */)
5160 (Lisp_Object first, Lisp_Object last) 5221 (Lisp_Object first, Lisp_Object last)
5161{ 5222{
5162 struct window *f = decode_valid_window (first); 5223 struct window *f = decode_valid_window (first);
@@ -5165,7 +5226,7 @@ return the new parent window. */)
5165 5226
5166 if (f == l) 5227 if (f == l)
5167 /* Don't make a matryoshka window. */ 5228 /* Don't make a matryoshka window. */
5168 error ("Invalid window to parentify"); 5229 error ("Cannot combine a window with itself");
5169 5230
5170 while (w != l && !NILP (w->next)) 5231 while (w != l && !NILP (w->next))
5171 w = XWINDOW (w->next); 5232 w = XWINDOW (w->next);
@@ -5186,58 +5247,43 @@ return the new parent window. */)
5186 XSETWINDOW (last, l); 5247 XSETWINDOW (last, l);
5187 } 5248 }
5188 else 5249 else
5189 error ("Invalid window to parentify"); 5250 error ("Windows to combine must be children of same parent");
5190 } 5251 }
5191 5252
5192 if (NILP (f->prev) && NILP (l->next)) 5253 if (NILP (f->prev) && NILP (l->next))
5193 return f->parent; 5254 /* FIRST and LAST are already the first and last child of their
5255 parent. */
5256 return Qnil;
5194 5257
5195 /* Make new parent window PARENT. */ 5258 /* Make new parent window PARENT. */
5196 Lisp_Object parent = make_parent_window (f->frame); 5259 Lisp_Object parent = make_parent_window (f->frame);
5197 struct window *p = XWINDOW (parent); 5260 struct window *p = XWINDOW (parent);
5198 double normal_size = 0.0; 5261 bool horflag = XWINDOW (f->parent)->horizontal;
5199 5262
5200 /* Splice in PARENT into the window tree. */ 5263 /* Splice in PARENT into the window tree. */
5201 p->parent = f->parent; 5264 wset_parent (p, f->parent);
5202 p->horizontal = XWINDOW (p->parent)->horizontal; 5265 wset_combination (p, horflag, first);
5203 p->contents = first;
5204 5266
5205 if (NILP (f->prev)) 5267 if (NILP (f->prev))
5206 /* FIRST has no previous sibling. */ 5268 /* FIRST has no previous sibling. Make PARENT the first child of
5207 XWINDOW (p->parent)->contents = parent; 5269 FIRST's old parent. */
5270 wset_combination (XWINDOW (p->parent), horflag, parent);
5208 else 5271 else
5209 /* FIRST has a previous sibling. */ 5272 /* FIRST has a previous sibling. Make PARENT the new next sibling
5273 of FIRST's previous sibling. */
5210 { 5274 {
5211 XWINDOW (f->prev)->next = parent; 5275 wset_next (XWINDOW (f->prev), parent);
5212 p->prev = f->prev; 5276 wset_prev (p, f->prev);
5213 f->prev = Qnil; 5277 wset_prev (f, Qnil);
5214 } 5278 }
5215 5279
5216 if (!NILP (l->next)) 5280 if (!NILP (l->next))
5217 /* LAST has a next sibling. */ 5281 /* LAST has a next sibling. Make PARENT the new previous sibling of
5282 LAST's old next sibling. */
5218 { 5283 {
5219 XWINDOW (l->next)->prev = parent; 5284 wset_prev (XWINDOW (l->next), parent);
5220 p->next = l->next; 5285 wset_next (p, l->next);
5221 l->next = Qnil; 5286 wset_next (l, 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 } 5287 }
5242 5288
5243 /* Set up PARENT's positions and sizes. */ 5289 /* Set up PARENT's positions and sizes. */
@@ -5246,7 +5292,7 @@ return the new parent window. */)
5246 p->pixel_top = f->pixel_top; 5292 p->pixel_top = f->pixel_top;
5247 p->top_line = f->top_line; 5293 p->top_line = f->top_line;
5248 5294
5249 if (p->horizontal) 5295 if (horflag)
5250 { 5296 {
5251 p->pixel_width = l->pixel_left + l->pixel_width - f->pixel_left; 5297 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; 5298 p->total_cols = l->left_col + l->total_cols - f->left_col;
@@ -5261,20 +5307,16 @@ return the new parent window. */)
5261 p->total_cols = f->total_cols; 5307 p->total_cols = f->total_cols;
5262 } 5308 }
5263 5309
5264 if (p->horizontal) 5310 /* Fix parent slots for PARENT's children and assign them new normal
5265 { 5311 sizes. */
5266 p->normal_cols = make_float (normal_size); 5312 window_set_parent_and_normal_sizes (parent);
5267 p->normal_lines = f->normal_lines; 5313 /* Assign new normal sizes for PARENT and its siblings. */
5268 } 5314 window_set_parent_and_normal_sizes (p->parent);
5269 else
5270 {
5271 p->normal_cols = f->normal_cols;
5272 p->normal_lines = make_float (normal_size);
5273 }
5274 5315
5275 return parent; 5316 return parent;
5276} 5317}
5277 5318
5319
5278DEFUN ("uncombine-window", Funcombine_window, Suncombine_window, 1, 1, 0, 5320DEFUN ("uncombine-window", Funcombine_window, Suncombine_window, 1, 1, 0,
5279 doc: /* Uncombine specified WINDOW. 5321 doc: /* Uncombine specified WINDOW.
5280WINDOW should be an internal window whose parent window is an internal 5322WINDOW should be an internal window whose parent window is an internal
@@ -5286,6 +5328,8 @@ of WINDOW's frame unchanged and return nil. */)
5286 (Lisp_Object window) 5328 (Lisp_Object window)
5287{ 5329{
5288 struct window *w = decode_valid_window (window); 5330 struct window *w = decode_valid_window (window);
5331 /* PARENT is WINDOW's parent and is supposed to be a combination of
5332 the same type as WINDOW. */
5289 Lisp_Object parent = w->parent; 5333 Lisp_Object parent = w->parent;
5290 5334
5291 if (MINI_WINDOW_P (w)) 5335 if (MINI_WINDOW_P (w))
@@ -5302,13 +5346,9 @@ of WINDOW's frame unchanged and return nil. */)
5302 Lisp_Object last = Qnil; 5346 Lisp_Object last = Qnil;
5303 struct window *l = f; 5347 struct window *l = f;
5304 5348
5305 /* Make WINDOW's parent new parent of WINDOW's children. */ 5349 /* Find last child window of WINDOW. */
5306 while (!NILP (l->next)) 5350 while (!NILP (l->next))
5307 { 5351 l = XWINDOW (l->next);
5308 wset_parent (l, parent);
5309 l = XWINDOW (l->next);
5310 }
5311 wset_parent (l, parent);
5312 XSETWINDOW (last, l); 5352 XSETWINDOW (last, l);
5313 5353
5314 wset_prev (f, w->prev); 5354 wset_prev (f, w->prev);
@@ -5321,6 +5361,10 @@ of WINDOW's frame unchanged and return nil. */)
5321 if (!NILP (l->next)) 5361 if (!NILP (l->next))
5322 wset_prev (XWINDOW (w->next), last); 5362 wset_prev (XWINDOW (w->next), last);
5323 5363
5364 /* Fix parent slots for PARENT's new children and assign new normal
5365 sizes. */
5366 window_set_parent_and_normal_sizes (parent);
5367
5324 return Qt; 5368 return Qt;
5325 } 5369 }
5326 else 5370 else