diff options
| author | Martin Rudalics | 2025-10-31 09:17:38 +0100 |
|---|---|---|
| committer | Martin Rudalics | 2025-10-31 09:17:38 +0100 |
| commit | 7da7b246cfe5c9347c16eeefa03f0485afdbaf74 (patch) | |
| tree | 64ede011280cd545d2a8ac5015bc13fb12665ab8 /src | |
| parent | 55d4596dd0ef592e769d777ffb0673725bb00b1d (diff) | |
| download | emacs-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.c | 166 |
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. */ | ||
| 5156 | static void | ||
| 5157 | window_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 | |||
| 5151 | DEFUN ("combine-windows", Fcombine_windows, Scombine_windows, 2, 2, 0, | 5209 | DEFUN ("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. |
| 5153 | FIRST and LAST must be valid windows in the same combination, that is, | 5211 | FIRST and LAST must be different, valid windows in the same combination, |
| 5154 | windows with the same parent window. If neither FIRST has a previous | 5212 | that is, windows with the same parent window. If LAST is not reachable |
| 5155 | nor LAST has a next sibling, return that parent window. Otherwise, make | 5213 | from FIRST by applying `window-next-sibling' repeatedly, invert FIRST |
| 5156 | a new parent window whose first child window becomes FIRST and whose | 5214 | and LAST. |
| 5157 | last child window becomes LAST, insert that parent window in the window | 5215 | |
| 5158 | tree in lieu of the windows starting with FIRST and ending with LAST, and | 5216 | If FIRST has no previous and LAST has no next sibling, return nil. |
| 5159 | return the new parent window. */) | 5217 | Otherwise, make a new parent window whose first child window becomes |
| 5218 | FIRST and whose last child window becomes LAST, insert that parent | ||
| 5219 | window in the window tree in lieu of the windows starting with FIRST and | ||
| 5220 | ending 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 | |||
| 5278 | DEFUN ("uncombine-window", Funcombine_window, Suncombine_window, 1, 1, 0, | 5320 | DEFUN ("uncombine-window", Funcombine_window, Suncombine_window, 1, 1, 0, |
| 5279 | doc: /* Uncombine specified WINDOW. | 5321 | doc: /* Uncombine specified WINDOW. |
| 5280 | WINDOW should be an internal window whose parent window is an internal | 5322 | WINDOW 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 |