aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/window.c
diff options
context:
space:
mode:
authorJosh Rahm <joshuarahm@gmail.com>2025-02-05 23:09:29 +0000
committerJosh Rahm <joshuarahm@gmail.com>2025-02-05 23:09:29 +0000
commitd5f194ce780c95821a855aca3c19426576d28ae0 (patch)
treed45f461b19f9118ad2bb1f440a7a08973ad18832 /src/nvim/window.c
parentc5d770d311841ea5230426cc4c868e8db27300a8 (diff)
parent44740e561fc93afe3ebecfd3618bda2d2abeafb0 (diff)
downloadrneovim-rahm.tar.gz
rneovim-rahm.tar.bz2
rneovim-rahm.zip
Merge remote-tracking branch 'upstream/master' into mix_20240309HEADrahm
Diffstat (limited to 'src/nvim/window.c')
-rw-r--r--src/nvim/window.c358
1 files changed, 164 insertions, 194 deletions
diff --git a/src/nvim/window.c b/src/nvim/window.c
index c3f3e075f1..fa2bfec138 100644
--- a/src/nvim/window.c
+++ b/src/nvim/window.c
@@ -1,9 +1,7 @@
#include <assert.h>
-#include <ctype.h>
#include <inttypes.h>
#include <limits.h>
#include <stdbool.h>
-#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -52,7 +50,6 @@
#include "nvim/mark.h"
#include "nvim/mark_defs.h"
#include "nvim/match.h"
-#include "nvim/mbyte.h"
#include "nvim/memory.h"
#include "nvim/message.h"
#include "nvim/mouse.h"
@@ -186,13 +183,13 @@ win_T *swbuf_goto_win_with_buf(buf_T *buf)
// If 'switchbuf' contains "useopen": jump to first window in the current
// tab page containing "buf" if one exists.
- if (swb_flags & SWB_USEOPEN) {
+ if (swb_flags & kOptSwbFlagUseopen) {
wp = buf_jump_open_win(buf);
}
// If 'switchbuf' contains "usetab": jump to first window in any tab page
// containing "buf" if one exists.
- if (wp == NULL && (swb_flags & SWB_USETAB)) {
+ if (wp == NULL && (swb_flags & kOptSwbFlagUsetab)) {
wp = buf_jump_open_tab(buf);
}
@@ -583,7 +580,7 @@ wingotofile:
// If 'switchbuf' is set to 'useopen' or 'usetab' and the
// file is already opened in a window, then jump to it.
win_T *wp = NULL;
- if ((swb_flags & (SWB_USEOPEN | SWB_USETAB))
+ if ((swb_flags & (kOptSwbFlagUseopen | kOptSwbFlagUsetab))
&& cmdmod.cmod_tab == 0) {
wp = swbuf_goto_win_with_buf(buflist_findname_exp(ptr));
}
@@ -746,40 +743,28 @@ void win_set_buf(win_T *win, buf_T *buf, Error *err)
RedrawingDisabled++;
switchwin_T switchwin;
- if (switch_win_noblock(&switchwin, win, tab, true) == FAIL) {
- api_set_error(err,
- kErrorTypeException,
- "Failed to switch to window %d",
- win->handle);
- goto cleanup;
- }
-
- try_start();
-
- const int save_acd = p_acd;
- if (!switchwin.sw_same_win) {
- // Temporarily disable 'autochdir' when setting buffer in another window.
- p_acd = false;
- }
- int result = do_buffer(DOBUF_GOTO, DOBUF_FIRST, FORWARD, buf->b_fnum, 0);
+ TRY_WRAP(err, {
+ int win_result = switch_win_noblock(&switchwin, win, tab, true);
+ if (win_result != FAIL) {
+ const int save_acd = p_acd;
+ if (!switchwin.sw_same_win) {
+ // Temporarily disable 'autochdir' when setting buffer in another window.
+ p_acd = false;
+ }
- if (!switchwin.sw_same_win) {
- p_acd = save_acd;
- }
+ do_buffer(DOBUF_GOTO, DOBUF_FIRST, FORWARD, buf->b_fnum, 0);
- if (!try_end(err) && result == FAIL) {
- api_set_error(err,
- kErrorTypeException,
- "Failed to set buffer %d",
- buf->handle);
- }
+ if (!switchwin.sw_same_win) {
+ p_acd = save_acd;
+ }
+ }
+ });
// If window is not current, state logic will not validate its cursor. So do it now.
// Still needed if do_buffer returns FAIL (e.g: autocmds abort script after buffer was set).
validate_cursor(curwin);
-cleanup:
restore_win_noblock(&switchwin, true);
RedrawingDisabled--;
}
@@ -850,9 +835,19 @@ void ui_ext_win_position(win_T *wp, bool validate)
col += tcol - 1;
}
}
+ } else if (c.relative == kFloatRelativeLaststatus) {
+ row += Rows - (int)p_ch - last_stl_height(false);
+ } else if (c.relative == kFloatRelativeTabline) {
+ row += tabline_height();
}
+ bool resort = wp->w_grid_alloc.comp_index != 0
+ && wp->w_grid_alloc.zindex != wp->w_config.zindex;
+ bool raise = resort && wp->w_grid_alloc.zindex < wp->w_config.zindex;
wp->w_grid_alloc.zindex = wp->w_config.zindex;
+ if (resort) {
+ ui_comp_layers_adjust(wp->w_grid_alloc.comp_index, raise);
+ }
if (ui_has(kUIMultigrid)) {
String anchor = cstr_as_string(float_anchor_str[c.anchor]);
if (!c.hide) {
@@ -1075,6 +1070,7 @@ win_T *win_split_ins(int size, int flags, win_T *new_wp, int dir, frame_T *to_fl
return NULL;
}
need_status = STATUS_HEIGHT;
+ win_float_anchor_laststatus();
}
bool do_equal = false;
@@ -1471,7 +1467,7 @@ win_T *win_split_ins(int size, int flags, win_T *new_wp, int dir, frame_T *to_fl
frame_add_statusline(curfrp);
}
}
- frame_new_height(curfrp, new_fr_height, flags & WSP_TOP, false);
+ frame_new_height(curfrp, new_fr_height, flags & WSP_TOP, false, false);
} else {
win_new_height(oldwin, oldwin_height - (new_size + STATUS_HEIGHT));
}
@@ -2145,7 +2141,7 @@ static void win_equal_rec(win_T *next_curwin, bool current, frame_T *topfr, int
|| topfr->fr_width != width
|| topfr->fr_win->w_wincol != col) {
topfr->fr_win->w_winrow = row;
- frame_new_height(topfr, height, false, false);
+ frame_new_height(topfr, height, false, false, false);
topfr->fr_win->w_wincol = col;
frame_new_width(topfr, width, false, false);
redraw_all_later(UPD_NOT_VALID);
@@ -3163,7 +3159,7 @@ win_T *winframe_remove(win_T *win, int *dirp, tabpage_T *tp, frame_T **unflat_al
if (*dirp == 'v') {
frame_new_height(altfr, altfr->fr_height + frp_close->fr_height,
- altfr == frp_close->fr_next, false);
+ altfr == frp_close->fr_next, false, false);
} else {
assert(*dirp == 'h');
frame_new_width(altfr, altfr->fr_width + frp_close->fr_width,
@@ -3365,7 +3361,7 @@ void winframe_restore(win_T *wp, int dir, frame_T *unflat_altfr)
// adjusts window sizes to fit restored statuslines/separators, if needed.
if (dir == 'v') {
frame_new_height(unflat_altfr, unflat_altfr->fr_height - frp->fr_height,
- unflat_altfr == frp->fr_next, false);
+ unflat_altfr == frp->fr_next, false, false);
} else if (dir == 'h') {
frame_new_width(unflat_altfr, unflat_altfr->fr_width - frp->fr_width,
unflat_altfr == frp->fr_next, false);
@@ -3448,13 +3444,13 @@ static frame_T *win_altframe(win_T *win, tabpage_T *tp)
static tabpage_T *alt_tabpage(void)
{
// Use the last accessed tab page, if possible.
- if ((tcl_flags & TCL_USELAST) && valid_tabpage(lastused_tabpage)) {
+ if ((tcl_flags & kOptTclFlagUselast) && valid_tabpage(lastused_tabpage)) {
return lastused_tabpage;
}
// Use the next tab page, if possible.
bool forward = curtab->tp_next != NULL
- && ((tcl_flags & TCL_LEFT) == 0 || curtab == first_tabpage);
+ && ((tcl_flags & kOptTclFlagLeft) == 0 || curtab == first_tabpage);
tabpage_T *tp;
if (forward) {
@@ -3508,15 +3504,31 @@ static bool is_bottom_win(win_T *wp)
}
return true;
}
+
+// 'cmdheight' value explicitly set by the user: window commands are allowed to
+// resize the topframe to values higher than this minimum, but not lower.
+static OptInt min_set_ch = 1;
+
/// Set a new height for a frame. Recursively sets the height for contained
/// frames and windows. Caller must take care of positions.
///
/// @param topfirst resize topmost contained frame first.
/// @param wfh obey 'winfixheight' when there is a choice;
/// may cause the height not to be set.
-void frame_new_height(frame_T *topfrp, int height, bool topfirst, bool wfh)
+/// @param set_ch set 'cmdheight' to resize topframe.
+void frame_new_height(frame_T *topfrp, int height, bool topfirst, bool wfh, bool set_ch)
FUNC_ATTR_NONNULL_ALL
{
+ if (topfrp->fr_parent == NULL && set_ch) {
+ // topframe: update the command line height, with side effects.
+ OptInt new_ch = MAX(min_set_ch, p_ch + topfrp->fr_height - height);
+ if (new_ch != p_ch) {
+ const OptInt save_ch = min_set_ch;
+ set_option_value(kOptCmdheight, NUMBER_OPTVAL(new_ch), 0);
+ min_set_ch = save_ch;
+ }
+ height = (int)MIN(ROWS_AVAIL, height);
+ }
if (topfrp->fr_win != NULL) {
// Simple case: just one window.
win_T *wp = topfrp->fr_win;
@@ -3529,7 +3541,7 @@ void frame_new_height(frame_T *topfrp, int height, bool topfirst, bool wfh)
do {
// All frames in this row get the same new height.
FOR_ALL_FRAMES(frp, topfrp->fr_child) {
- frame_new_height(frp, height, topfirst, wfh);
+ frame_new_height(frp, height, topfirst, wfh, set_ch);
if (frp->fr_height > height) {
// Could not fit the windows, make the whole row higher.
height = frp->fr_height;
@@ -3571,10 +3583,9 @@ void frame_new_height(frame_T *topfrp, int height, bool topfirst, bool wfh)
int h = frame_minheight(frp, NULL);
if (frp->fr_height + extra_lines < h) {
extra_lines += frp->fr_height - h;
- frame_new_height(frp, h, topfirst, wfh);
+ frame_new_height(frp, h, topfirst, wfh, set_ch);
} else {
- frame_new_height(frp, frp->fr_height + extra_lines,
- topfirst, wfh);
+ frame_new_height(frp, frp->fr_height + extra_lines, topfirst, wfh, set_ch);
break;
}
if (topfirst) {
@@ -3593,7 +3604,7 @@ void frame_new_height(frame_T *topfrp, int height, bool topfirst, bool wfh)
}
} else if (extra_lines > 0) {
// increase height of bottom or top frame
- frame_new_height(frp, frp->fr_height + extra_lines, topfirst, wfh);
+ frame_new_height(frp, frp->fr_height + extra_lines, topfirst, wfh, set_ch);
}
}
topfrp->fr_height = height;
@@ -4010,6 +4021,10 @@ void unuse_tabpage(tabpage_T *tp)
tp->tp_curwin = curwin;
}
+// When switching tabpage, handle other side-effects in command_height(), but
+// avoid setting frame sizes which are still correct.
+static bool command_frame_height = true;
+
/// Set the relevant pointers to use tab page "tp". May want to call
/// unuse_tabpage() first.
void use_tabpage(tabpage_T *tp)
@@ -4411,6 +4426,16 @@ static void enter_tabpage(tabpage_T *tp, buf_T *old_curbuf, bool trigger_enter_a
use_tabpage(tp);
+ if (p_ch != curtab->tp_ch_used) {
+ // Use the stored value of p_ch, so that it can be different for each tab page.
+ // Handle other side-effects but avoid setting frame sizes, which are still correct.
+ OptInt new_ch = curtab->tp_ch_used;
+ curtab->tp_ch_used = p_ch;
+ command_frame_height = false;
+ set_option_value(kOptCmdheight, NUMBER_OPTVAL(new_ch), 0);
+ command_frame_height = true;
+ }
+
if (old_curtab != curtab) {
tabpage_check_windows(old_curtab);
}
@@ -4424,27 +4449,9 @@ static void enter_tabpage(tabpage_T *tp, buf_T *old_curbuf, bool trigger_enter_a
prevwin = next_prevwin;
last_status(false); // status line may appear or disappear
- const int row = win_comp_pos(); // recompute w_winrow for all windows
+ win_comp_pos(); // recompute w_winrow for all windows
diff_need_scrollbind = true;
- // Use the stored value of p_ch, so that it can be different for each tab page.
- if (p_ch != curtab->tp_ch_used) {
- clear_cmdline = true;
- if (msg_grid.chars && p_ch < curtab->tp_ch_used) {
- // TODO(bfredl): a bit expensive, should be enough to invalidate the
- // region between the old and the new p_ch.
- grid_invalidate(&msg_grid);
- }
- }
- p_ch = curtab->tp_ch_used;
-
- // When cmdheight is changed in a tab page with '<C-w>-', cmdline_row is
- // changed but p_ch and tp_ch_used are not changed. Thus we also need to
- // check cmdline_row.
- if (row < cmdline_row && cmdline_row <= Rows - p_ch) {
- clear_cmdline = true;
- }
-
// If there was a click in a window, it won't be usable for a following
// drag.
reset_dragwin();
@@ -5169,8 +5176,8 @@ win_T *win_alloc(win_T *after, bool hidden)
return new_wp;
}
-// Free one wininfo_T.
-void free_wininfo(wininfo_T *wip, buf_T *bp)
+// Free one WinInfo.
+void free_wininfo(WinInfo *wip, buf_T *bp)
{
if (wip->wi_optset) {
clear_winopt(&wip->wi_opt);
@@ -5235,30 +5242,27 @@ void win_free(win_T *wp, tabpage_T *tp)
// Remove the window from the b_wininfo lists, it may happen that the
// freed memory is re-used for another window.
FOR_ALL_BUFFERS(buf) {
- for (wininfo_T *wip = buf->b_wininfo; wip != NULL; wip = wip->wi_next) {
+ WinInfo *wip_wp = NULL;
+ size_t pos_wip = kv_size(buf->b_wininfo);
+ size_t pos_null = kv_size(buf->b_wininfo);
+ for (size_t i = 0; i < kv_size(buf->b_wininfo); i++) {
+ WinInfo *wip = kv_A(buf->b_wininfo, i);
if (wip->wi_win == wp) {
- wininfo_T *wip2;
-
- // If there already is an entry with "wi_win" set to NULL it
- // must be removed, it would never be used.
- // Skip "wip" itself, otherwise Coverity complains.
- for (wip2 = buf->b_wininfo; wip2 != NULL; wip2 = wip2->wi_next) {
- // `wip2 != wip` to satisfy Coverity. #14884
- if (wip2 != wip && wip2->wi_win == NULL) {
- if (wip2->wi_next != NULL) {
- wip2->wi_next->wi_prev = wip2->wi_prev;
- }
- if (wip2->wi_prev == NULL) {
- buf->b_wininfo = wip2->wi_next;
- } else {
- wip2->wi_prev->wi_next = wip2->wi_next;
- }
- free_wininfo(wip2, buf);
- break;
- }
- }
+ wip_wp = wip;
+ pos_wip = i;
+ } else if (wip->wi_win == NULL) {
+ pos_null = i;
+ }
+ }
- wip->wi_win = NULL;
+ if (wip_wp) {
+ wip_wp->wi_win = NULL;
+ // If there already is an entry with "wi_win" set to NULL, only
+ // the first entry with NULL will ever be used, delete the other one.
+ if (pos_null < kv_size(buf->b_wininfo)) {
+ size_t pos_delete = MAX(pos_null, pos_wip);
+ free_wininfo(kv_A(buf->b_wininfo, pos_delete), buf);
+ kv_shift(buf->b_wininfo, pos_delete, 1);
}
}
}
@@ -5422,9 +5426,9 @@ void win_new_screen_rows(void)
// First try setting the heights of windows with 'winfixheight'. If
// that doesn't result in the right height, forget about that option.
- frame_new_height(topframe, h, false, true);
+ frame_new_height(topframe, h, false, true, false);
if (!frame_check_height(topframe, h)) {
- frame_new_height(topframe, h, false, false);
+ frame_new_height(topframe, h, false, false, false);
}
win_comp_pos(); // recompute w_winrow and w_wincol
@@ -5859,22 +5863,7 @@ void win_setheight_win(int height, win_T *win)
frame_setheight(win->w_frame, height + win->w_hsep_height + win->w_status_height);
// recompute the window positions
- int row = win_comp_pos();
-
- // If there is extra space created between the last window and the command
- // line, clear it.
- if (full_screen && msg_scrolled == 0 && row < cmdline_row) {
- grid_clear(&default_grid, row, cmdline_row, 0, Columns, 0);
- if (msg_grid.chars) {
- clear_cmdline = true;
- }
- }
- cmdline_row = row;
- p_ch = MAX(Rows - cmdline_row, 0);
- curtab->tp_ch_used = p_ch;
- msg_row = row;
- msg_col = 0;
-
+ win_comp_pos();
win_fix_scroll(true);
redraw_all_later(UPD_NOT_VALID);
@@ -5902,14 +5891,8 @@ static void frame_setheight(frame_T *curfrp, int height)
if (curfrp->fr_parent == NULL) {
// topframe: can only change the command line height
- if (height > ROWS_AVAIL) {
- // If height is greater than the available space, try to create space for
- // the frame by reducing 'cmdheight' if possible, while making sure
- // `cmdheight` doesn't go below 1 if it wasn't set to 0 explicitly.
- height = (int)MIN(ROWS_AVAIL + p_ch - !p_ch_was_zero, height);
- }
if (height > 0) {
- frame_new_height(curfrp, height, false, false);
+ frame_new_height(curfrp, height, false, false, true);
}
} else if (curfrp->fr_parent->fr_layout == FR_ROW) {
// Row of frames: Also need to resize frames left and right of this
@@ -5988,7 +5971,7 @@ static void frame_setheight(frame_T *curfrp, int height)
}
// set the current frame to the new height
- frame_new_height(curfrp, height, false, false);
+ frame_new_height(curfrp, height, false, false, true);
// First take lines from the frames after the current frame. If
// that is not enough, takes lines from frames above the current
@@ -6010,15 +5993,15 @@ static void frame_setheight(frame_T *curfrp, int height)
room_reserved = frp->fr_height - take;
}
take -= frp->fr_height - room_reserved;
- frame_new_height(frp, room_reserved, false, false);
+ frame_new_height(frp, room_reserved, false, false, true);
room_reserved = 0;
}
} else {
if (frp->fr_height - take < h) {
take -= frp->fr_height - h;
- frame_new_height(frp, h, false, false);
+ frame_new_height(frp, h, false, false, true);
} else {
- frame_new_height(frp, frp->fr_height - take, false, false);
+ frame_new_height(frp, frp->fr_height - take, false, false, true);
take = 0;
}
}
@@ -6189,7 +6172,7 @@ const char *did_set_winminheight(optset_T *args FUNC_ATTR_UNUSED)
// loop until there is a 'winminheight' that is possible
while (p_wmh > 0) {
const int room = Rows - (int)p_ch;
- const int needed = min_rows();
+ const int needed = min_rows_for_all_tabpages();
if (room >= needed) {
break;
}
@@ -6276,7 +6259,7 @@ void win_drag_status_line(win_T *dragwin, int offset)
room = Rows - cmdline_row;
if (curfr->fr_next != NULL) {
room -= (int)p_ch + global_stl_height();
- } else if (!p_ch_was_zero) {
+ } else if (min_set_ch > 0) {
room--;
}
room = MAX(room, 0);
@@ -6296,7 +6279,7 @@ void win_drag_status_line(win_T *dragwin, int offset)
// Grow frame fr by "offset" lines.
// Doesn't happen when dragging the last status line up.
if (fr != NULL) {
- frame_new_height(fr, fr->fr_height + offset, up, false);
+ frame_new_height(fr, fr->fr_height + offset, up, false, true);
}
if (up) {
@@ -6309,9 +6292,9 @@ void win_drag_status_line(win_T *dragwin, int offset)
int n = frame_minheight(fr, NULL);
if (fr->fr_height - offset <= n) {
offset -= fr->fr_height - n;
- frame_new_height(fr, n, !up, false);
+ frame_new_height(fr, n, !up, false, true);
} else {
- frame_new_height(fr, fr->fr_height - offset, !up, false);
+ frame_new_height(fr, fr->fr_height - offset, !up, false, true);
break;
}
if (up) {
@@ -6320,15 +6303,7 @@ void win_drag_status_line(win_T *dragwin, int offset)
fr = fr->fr_next;
}
}
- int row = win_comp_pos();
- grid_clear(&default_grid, row, cmdline_row, 0, Columns, 0);
- if (msg_grid.chars) {
- clear_cmdline = true;
- }
- cmdline_row = row;
- p_ch = MAX(Rows - cmdline_row, p_ch_was_zero ? 0 : 1);
- curtab->tp_ch_used = p_ch;
-
+ win_comp_pos();
win_fix_scroll(true);
redraw_all_later(UPD_SOME_VALID);
@@ -6390,7 +6365,7 @@ void win_drag_vsep_line(win_T *dragwin, int offset)
fr = curfr; // put fr at window that grows
}
- // If not enough room thn move as far as we can
+ // If not enough room then move as far as we can
offset = MIN(offset, room);
// No room at all, quit.
@@ -6765,21 +6740,6 @@ void command_height(void)
{
int old_p_ch = (int)curtab->tp_ch_used;
- // Use the value of p_ch that we remembered. This is needed for when the
- // GUI starts up, we can't be sure in what order things happen. And when
- // p_ch was changed in another tab page.
- curtab->tp_ch_used = p_ch;
-
- // Update cmdline_row to what it should be: just below the last window.
- cmdline_row = topframe->fr_height + tabline_height() + global_stl_height();
-
- // If cmdline_row is smaller than what it is supposed to be for 'cmdheight'
- // then set old_p_ch to what it would be, so that the windows get resized
- // properly for the new value.
- if (cmdline_row < Rows - p_ch) {
- old_p_ch = Rows - cmdline_row;
- }
-
// Find bottom frame with width of screen.
frame_T *frp = lastwin_nofloating()->w_frame;
while (frp->fr_width != Columns && frp->fr_parent != NULL) {
@@ -6787,60 +6747,53 @@ void command_height(void)
}
// Avoid changing the height of a window with 'winfixheight' set.
- while (frp->fr_prev != NULL && frp->fr_layout == FR_LEAF
- && frp->fr_win->w_p_wfh) {
+ while (frp->fr_prev != NULL && frp->fr_layout == FR_LEAF && frp->fr_win->w_p_wfh) {
frp = frp->fr_prev;
}
- if (starting != NO_SCREEN) {
- cmdline_row = Rows - (int)p_ch;
-
- if (p_ch > old_p_ch) { // p_ch got bigger
- while (p_ch > old_p_ch) {
- if (frp == NULL) {
- emsg(_(e_noroom));
- p_ch = old_p_ch;
- curtab->tp_ch_used = p_ch;
- cmdline_row = Rows - (int)p_ch;
- break;
- }
- int h = frp->fr_height - frame_minheight(frp, NULL);
- h = MIN(h, (int)p_ch - old_p_ch);
- old_p_ch += h;
- frame_add_height(frp, -h);
- frp = frp->fr_prev;
- }
-
- // Recompute window positions.
- win_comp_pos();
-
- if (!need_wait_return) {
- // clear the lines added to cmdline
- if (full_screen) {
- grid_clear(&default_grid, cmdline_row, Rows, 0, Columns, 0);
- }
- msg_row = cmdline_row;
- }
- redraw_cmdline = true;
- return;
+ while (p_ch > old_p_ch && command_frame_height) {
+ if (frp == NULL) {
+ emsg(_(e_noroom));
+ p_ch = old_p_ch;
+ break;
}
-
- msg_row = MAX(msg_row, cmdline_row);
- redraw_cmdline = true;
+ int h = MIN((int)(p_ch - old_p_ch), frp->fr_height - frame_minheight(frp, NULL));
+ frame_add_height(frp, -h);
+ old_p_ch += h;
+ frp = frp->fr_prev;
+ }
+ if (p_ch < old_p_ch && command_frame_height && frp != NULL) {
+ frame_add_height(frp, (int)(old_p_ch - p_ch));
}
- frame_add_height(frp, (int)(old_p_ch - p_ch));
// Recompute window positions.
- if (frp != lastwin->w_frame) {
- win_comp_pos();
+ win_comp_pos();
+ cmdline_row = Rows - (int)p_ch;
+ redraw_cmdline = true;
+
+ // Clear the cmdheight area.
+ if (msg_scrolled == 0 && full_screen) {
+ ScreenGrid *grid = &default_grid;
+ if (!ui_has(kUIMessages)) {
+ msg_grid_validate();
+ grid = &msg_grid_adj;
+ }
+ grid_clear(grid, cmdline_row, Rows, 0, Columns, 0);
+ msg_row = cmdline_row;
}
+
+ // Use the value of p_ch that we remembered. This is needed for when the
+ // GUI starts up, we can't be sure in what order things happen. And when
+ // p_ch was changed in another tab page.
+ curtab->tp_ch_used = p_ch;
+ min_set_ch = p_ch;
}
// Resize frame "frp" to be "n" lines higher (negative for less high).
// Also resize the frames it is contained in.
static void frame_add_height(frame_T *frp, int n)
{
- frame_new_height(frp, frp->fr_height + n, false, false);
+ frame_new_height(frp, frp->fr_height + n, false, false, false);
while (true) {
frp = frp->fr_parent;
if (frp == NULL) {
@@ -6858,6 +6811,7 @@ void last_status(bool morewin)
{
// Don't make a difference between horizontal or vertical split.
last_status_rec(topframe, last_stl_height(morewin) > 0, global_stl_height() > 0);
+ win_float_anchor_laststatus();
}
// Remove status line from window, replacing it with a horizontal separator if needed.
@@ -6910,7 +6864,7 @@ static bool resize_frame_for_status(frame_T *fr)
emsg(_(e_noroom));
return false;
} else if (fp != fr) {
- frame_new_height(fp, fp->fr_height - 1, false, false);
+ frame_new_height(fp, fp->fr_height - 1, false, false, false);
frame_fix_height(wp);
win_comp_pos();
} else {
@@ -6931,7 +6885,7 @@ static bool resize_frame_for_winbar(frame_T *fr)
emsg(_(e_noroom));
return false;
}
- frame_new_height(fp, fp->fr_height - 1, false, false);
+ frame_new_height(fp, fp->fr_height - 1, false, false, false);
win_new_height(wp, wp->w_height + 1);
frame_fix_height(wp);
win_comp_pos();
@@ -7065,8 +7019,24 @@ int last_stl_height(bool morewin)
}
/// Return the minimal number of rows that is needed on the screen to display
-/// the current number of windows.
-int min_rows(void)
+/// the current number of windows for the given tab page.
+int min_rows(tabpage_T *tp) FUNC_ATTR_NONNULL_ALL
+{
+ if (firstwin == NULL) { // not initialized yet
+ return MIN_LINES;
+ }
+
+ int total = frame_minheight(tp->tp_topframe, NULL);
+ total += tabline_height() + global_stl_height();
+ if ((tp == curtab ? p_ch : tp->tp_ch_used) > 0) {
+ total++; // count the room for the command line
+ }
+ return total;
+}
+
+/// Return the minimal number of rows that is needed on the screen to display
+/// the current number of windows for all tab pages.
+int min_rows_for_all_tabpages(void)
{
if (firstwin == NULL) { // not initialized yet
return MIN_LINES;
@@ -7075,12 +7045,12 @@ int min_rows(void)
int total = 0;
FOR_ALL_TABS(tp) {
int n = frame_minheight(tp->tp_topframe, NULL);
+ if ((tp == curtab ? p_ch : tp->tp_ch_used) > 0) {
+ n++; // count the room for the command line
+ }
total = MAX(total, n);
}
total += tabline_height() + global_stl_height();
- if (p_ch > 0) {
- total += 1; // count the room for the command line
- }
return total;
}
@@ -7304,7 +7274,7 @@ static win_T *restore_snapshot_rec(frame_T *sn, frame_T *fr)
fr->fr_height = sn->fr_height;
fr->fr_width = sn->fr_width;
if (fr->fr_layout == FR_LEAF) {
- frame_new_height(fr, fr->fr_height, false, false);
+ frame_new_height(fr, fr->fr_height, false, false, false);
frame_new_width(fr, fr->fr_width, false, false);
wp = sn->fr_win;
}