mirror of
https://github.com/neovim/neovim.git
synced 2024-12-31 17:13:26 -07:00
Merge pull request #17266 from famiu/feat/ui/global-statusline
feat(statusline): add global statusline
This commit is contained in:
commit
3c7e937a89
@ -175,7 +175,7 @@ o Enable Arabic settings [short-cut]
|
||||
vertical separator like "l" or "𝖨" may be used. It may also be
|
||||
hidden by changing its color to the foreground color: >
|
||||
:set fillchars=vert:l
|
||||
:hi VertSplit ctermbg=White
|
||||
:hi WinSeparator ctermbg=White
|
||||
< Note that this is a workaround, not a proper solution.
|
||||
|
||||
If, on the other hand, you'd like to be verbose and explicit and
|
||||
|
@ -2441,7 +2441,14 @@ A jump table for the options with a short description can be found at |Q_op|.
|
||||
item default Used for ~
|
||||
stl:c ' ' or '^' statusline of the current window
|
||||
stlnc:c ' ' or '=' statusline of the non-current windows
|
||||
horiz:c '─' or '-' horizontal separators |:split|
|
||||
horizup:c '┴' or '-' upwards facing horizontal separator
|
||||
horizdown:c '┬' or '-' downwards facing horizontal separator
|
||||
vert:c '│' or '|' vertical separators |:vsplit|
|
||||
vertleft:c '┤' or '|' left facing vertical separator
|
||||
vertright:c '├' or '|' right facing vertical separator
|
||||
verthoriz:c '┼' or '+' overlapping vertical and horizontal
|
||||
separator
|
||||
fold:c '·' or '-' filling 'foldtext'
|
||||
foldopen:c '-' mark the beginning of a fold
|
||||
foldclose:c '+' show a closed fold
|
||||
@ -2454,8 +2461,13 @@ A jump table for the options with a short description can be found at |Q_op|.
|
||||
"stlnc" the space will be used when there is highlighting, '^' or '='
|
||||
otherwise.
|
||||
|
||||
If 'ambiwidth' is "double" then "vert", "foldsep" and "fold" default to
|
||||
single-byte alternatives.
|
||||
Note that "horiz", "horizup", "horizdown", "vertleft", "vertright" and
|
||||
"verthoriz" are only used when 'laststatus' is 3, since only vertical
|
||||
window separators are used otherwise.
|
||||
|
||||
If 'ambiwidth' is "double" then "horiz", "horizup", "horizdown",
|
||||
"vert", "vertleft", "vertright", "verthoriz", "foldsep" and "fold"
|
||||
default to single-byte alternatives.
|
||||
|
||||
Example: >
|
||||
:set fillchars=stl:^,stlnc:=,vert:│,fold:·,diff:-
|
||||
@ -2469,7 +2481,13 @@ A jump table for the options with a short description can be found at |Q_op|.
|
||||
item highlight group ~
|
||||
stl:c StatusLine |hl-StatusLine|
|
||||
stlnc:c StatusLineNC |hl-StatusLineNC|
|
||||
vert:c VertSplit |hl-VertSplit|
|
||||
horiz:c WinSeparator |hl-WinSeparator|
|
||||
horizup:c WinSeparator |hl-WinSeparator|
|
||||
horizdown:c WinSeparator |hl-WinSeparator|
|
||||
vert:c WinSeparator |hl-WinSeparator|
|
||||
vertleft:c WinSeparator |hl-WinSeparator|
|
||||
vertright:c WinSeparator |hl-WinSeparator|
|
||||
verthoriz:c WinSeparator |hl-WinSeparator|
|
||||
fold:c Folded |hl-Folded|
|
||||
diff:c DiffDelete |hl-DiffDelete|
|
||||
eob:c EndOfBuffer |hl-EndOfBuffer|
|
||||
@ -3652,6 +3670,8 @@ A jump table for the options with a short description can be found at |Q_op|.
|
||||
0: never
|
||||
1: only if there are at least two windows
|
||||
2: always
|
||||
3: have a global statusline at the bottom instead of one for
|
||||
each window
|
||||
The screen looks nicer with a status line if you have several
|
||||
windows, but it takes another screen line. |status-line|
|
||||
|
||||
@ -5929,7 +5949,7 @@ A jump table for the options with a short description can be found at |Q_op|.
|
||||
empty to avoid further errors. Otherwise screen updating would loop.
|
||||
|
||||
Note that the only effect of 'ruler' when this option is set (and
|
||||
'laststatus' is 2) is controlling the output of |CTRL-G|.
|
||||
'laststatus' is 2 or 3) is controlling the output of |CTRL-G|.
|
||||
|
||||
field meaning ~
|
||||
- Left justify the item. The default is right justified
|
||||
|
@ -5119,8 +5119,8 @@ TermCursor cursor in a focused terminal
|
||||
TermCursorNC cursor in an unfocused terminal
|
||||
*hl-ErrorMsg*
|
||||
ErrorMsg error messages on the command line
|
||||
*hl-VertSplit*
|
||||
VertSplit the column separating vertically split windows
|
||||
*hl-WinSeparator*
|
||||
WinSeparator separators between window splits
|
||||
*hl-Folded*
|
||||
Folded line used for closed folds
|
||||
*hl-FoldColumn*
|
||||
|
@ -482,6 +482,8 @@ statusline:
|
||||
0 never
|
||||
1 only when there are split windows (the default)
|
||||
2 always
|
||||
3 have a global statusline at the bottom instead of one for each
|
||||
window
|
||||
|
||||
Many commands that edit another file have a variant that splits the window.
|
||||
For Command-line commands this is done by prepending an "s". For example:
|
||||
|
@ -211,6 +211,7 @@ Highlight groups:
|
||||
|hl-Substitute|
|
||||
|hl-TermCursor|
|
||||
|hl-TermCursorNC|
|
||||
|hl-WinSeparator| highlights window separators
|
||||
|hl-Whitespace| highlights 'listchars' whitespace
|
||||
|
||||
Input/Mappings:
|
||||
@ -227,9 +228,11 @@ Options:
|
||||
'cpoptions' flags: |cpo-_|
|
||||
'display' flags: "msgsep" minimizes scrolling when showing messages
|
||||
'guicursor' works in the terminal
|
||||
'fillchars' flags: "msgsep" (see 'display')
|
||||
'fillchars' flags: "msgsep" (see 'display'), "horiz", "horizup",
|
||||
"horizdown", "vertleft", "vertright", "verthoriz"
|
||||
'foldcolumn' supports up to 9 dynamic/fixed columns
|
||||
'inccommand' shows interactive results for |:substitute|-like commands
|
||||
'laststatus' global statusline support
|
||||
'pumblend' pseudo-transparent popupmenu
|
||||
'scrollback'
|
||||
'signcolumn' supports up to 9 dynamic/fixed columns
|
||||
@ -348,6 +351,7 @@ Highlight groups:
|
||||
|hl-ColorColumn|, |hl-CursorColumn| are lower priority than most other
|
||||
groups
|
||||
|hl-CursorLine| is low-priority unless foreground color is set
|
||||
*hl-VertSplit* superseded by |hl-WinSeparator|
|
||||
|
||||
Macro/|recording| behavior
|
||||
Replay of a macro recorded during :lmap produces the same actions as when it
|
||||
|
@ -104,6 +104,8 @@ when the last window also has a status line:
|
||||
'laststatus' = 0 never a status line
|
||||
'laststatus' = 1 status line if there is more than one window
|
||||
'laststatus' = 2 always a status line
|
||||
'laststatus' = 3 have a global statusline at the bottom instead
|
||||
of one for each window
|
||||
|
||||
You can change the contents of the status line with the 'statusline' option.
|
||||
This option can be local to the window, so that you can have a different
|
||||
|
@ -2329,7 +2329,7 @@ Dictionary nvim_eval_statusline(String str, Dict(eval_statusline) *opts, Error *
|
||||
|
||||
maxwidth = (int)opts->maxwidth.data.integer;
|
||||
} else {
|
||||
maxwidth = use_tabline ? Columns : wp->w_width;
|
||||
maxwidth = (use_tabline || global_stl_height() > 0) ? Columns : wp->w_width;
|
||||
}
|
||||
|
||||
char buf[MAXPATHL];
|
||||
|
@ -131,7 +131,7 @@
|
||||
/// An empty string can be used to turn off a specific border, for instance,
|
||||
/// [ "", "", "", ">", "", "", "", "<" ]
|
||||
/// will only make vertical borders but not horizontal ones.
|
||||
/// By default, `FloatBorder` highlight is used, which links to `VertSplit`
|
||||
/// By default, `FloatBorder` highlight is used, which links to `WinSeparator`
|
||||
/// when not defined. It could also be specified by character:
|
||||
/// [ {"+", "MyCorner"}, {"x", "MyBorder"} ].
|
||||
/// - noautocmd: If true then no buffer-related autocommand events such as
|
||||
|
@ -4947,8 +4947,8 @@ void ex_buffer_all(exarg_T *eap)
|
||||
wpnext = wp->w_next;
|
||||
if ((wp->w_buffer->b_nwindows > 1
|
||||
|| ((cmdmod.split & WSP_VERT)
|
||||
? wp->w_height + wp->w_status_height < Rows - p_ch
|
||||
- tabline_height()
|
||||
? wp->w_height + wp->w_hsep_height + wp->w_status_height < Rows - p_ch
|
||||
- tabline_height() - global_stl_height()
|
||||
: wp->w_width != Columns)
|
||||
|| (had_tab > 0 && wp != firstwin))
|
||||
&& !ONE_WINDOW
|
||||
|
@ -1232,7 +1232,13 @@ struct window_S {
|
||||
struct {
|
||||
int stl;
|
||||
int stlnc;
|
||||
int horiz;
|
||||
int horizup;
|
||||
int horizdown;
|
||||
int vert;
|
||||
int vertleft;
|
||||
int vertright;
|
||||
int verthoriz;
|
||||
int fold;
|
||||
int foldopen; ///< when fold is open
|
||||
int foldclosed; ///< when fold is closed
|
||||
@ -1278,7 +1284,8 @@ struct window_S {
|
||||
int w_status_height; // number of status lines (0 or 1)
|
||||
int w_wincol; // Leftmost column of window in screen.
|
||||
int w_width; // Width of window, excluding separation.
|
||||
int w_vsep_width; // Number of separator columns (0 or 1).
|
||||
int w_hsep_height; // Number of horizontal separator rows (0 or 1)
|
||||
int w_vsep_width; // Number of vertical separator columns (0 or 1).
|
||||
pos_save_T w_save_cursor; // backup of cursor pos and topline
|
||||
|
||||
// inner size of window, which can be overridden by external UI
|
||||
|
@ -3745,7 +3745,7 @@ static void f_getmousepos(typval_T *argvars, typval_T *rettv, FunPtr fptr)
|
||||
|
||||
wp = mouse_find_win(&grid, &row, &col);
|
||||
if (wp != NULL) {
|
||||
int height = wp->w_height + wp->w_status_height;
|
||||
int height = wp->w_height + wp->w_hsep_height + wp->w_status_height;
|
||||
// The height is adjusted by 1 when there is a bottom border. This is not
|
||||
// necessary for a top border since `row` starts at -1 in that case.
|
||||
if (row < height + wp->w_border_adj[2]) {
|
||||
|
@ -632,7 +632,7 @@ static void may_do_incsearch_highlighting(int firstc, long count, incsearch_stat
|
||||
|
||||
validate_cursor();
|
||||
// May redraw the status line to show the cursor position.
|
||||
if (p_ru && curwin->w_status_height > 0) {
|
||||
if (p_ru && (curwin->w_status_height > 0 || global_stl_height() > 0)) {
|
||||
curwin->w_redr_status = true;
|
||||
}
|
||||
|
||||
@ -3631,7 +3631,7 @@ void compute_cmdrow(void)
|
||||
} else {
|
||||
win_T *wp = lastwin_nofloating();
|
||||
cmdline_row = wp->w_winrow + wp->w_height
|
||||
+ wp->w_status_height;
|
||||
+ wp->w_hsep_height + wp->w_status_height + global_stl_height();
|
||||
}
|
||||
lines_left = cmdline_row;
|
||||
}
|
||||
|
@ -72,7 +72,7 @@ static int ses_winsizes(FILE *fd, int restore_size, win_T *tab_firstwin)
|
||||
n++;
|
||||
|
||||
// restore height when not full height
|
||||
if (wp->w_height + wp->w_status_height < topframe->fr_height
|
||||
if (wp->w_height + wp->w_hsep_height + wp->w_status_height < topframe->fr_height
|
||||
&& (fprintf(fd,
|
||||
"exe '%dresize ' . ((&lines * %" PRId64
|
||||
" + %" PRId64 ") / %" PRId64 ")\n",
|
||||
|
@ -74,7 +74,8 @@ typedef enum {
|
||||
HLF_R, // return to continue message and yes/no questions
|
||||
HLF_S, // status lines
|
||||
HLF_SNC, // status lines of not-current windows
|
||||
HLF_C, // column to separate vertically split windows
|
||||
HLF_C, // window split separators
|
||||
HLF_VSP, // VertSplit
|
||||
HLF_T, // Titles for output from ":set all", ":autocmd" etc.
|
||||
HLF_V, // Visual mode
|
||||
HLF_VNC, // Visual mode, autoselecting and not clipboard owner
|
||||
@ -133,10 +134,11 @@ EXTERN const char *hlf_names[] INIT(= {
|
||||
[HLF_R] = "Question",
|
||||
[HLF_S] = "StatusLine",
|
||||
[HLF_SNC] = "StatusLineNC",
|
||||
[HLF_C] = "VertSplit",
|
||||
[HLF_C] = "WinSeparator",
|
||||
[HLF_T] = "Title",
|
||||
[HLF_V] = "Visual",
|
||||
[HLF_VNC] = "VisualNC",
|
||||
[HLF_VSP] = "VertSplit",
|
||||
[HLF_W] = "WarningMsg",
|
||||
[HLF_WM] = "WildMenu",
|
||||
[HLF_FL] = "Folded",
|
||||
|
@ -2910,7 +2910,7 @@ ambw_end:
|
||||
|| check_opt_strings(curbuf->b_p_bt, p_buftype_values, false) != OK) {
|
||||
errmsg = e_invarg;
|
||||
} else {
|
||||
if (curwin->w_status_height) {
|
||||
if (curwin->w_status_height || global_stl_height()) {
|
||||
curwin->w_redr_status = true;
|
||||
redraw_later(curwin, VALID);
|
||||
}
|
||||
@ -3555,7 +3555,13 @@ static char *set_chars_option(win_T *wp, char_u **varp, bool set)
|
||||
struct chars_tab fcs_tab[] = {
|
||||
{ &wp->w_p_fcs_chars.stl, "stl", ' ' },
|
||||
{ &wp->w_p_fcs_chars.stlnc, "stlnc", ' ' },
|
||||
{ &wp->w_p_fcs_chars.horiz, "horiz", 9472 }, // ─
|
||||
{ &wp->w_p_fcs_chars.horizup, "horizup", 9524 }, // ┴
|
||||
{ &wp->w_p_fcs_chars.horizdown, "horizdown", 9516 }, // ┬
|
||||
{ &wp->w_p_fcs_chars.vert, "vert", 9474 }, // │
|
||||
{ &wp->w_p_fcs_chars.vertleft, "vertleft", 9508 }, // ┤
|
||||
{ &wp->w_p_fcs_chars.vertright, "vertright", 9500 }, // ├
|
||||
{ &wp->w_p_fcs_chars.verthoriz, "verthoriz", 9532 }, // ┼
|
||||
{ &wp->w_p_fcs_chars.fold, "fold", 183 }, // ·
|
||||
{ &wp->w_p_fcs_chars.foldopen, "foldopen", '-' },
|
||||
{ &wp->w_p_fcs_chars.foldclosed, "foldclose", '+' },
|
||||
@ -3589,15 +3595,17 @@ static char *set_chars_option(win_T *wp, char_u **varp, bool set)
|
||||
varp = &p_fcs;
|
||||
}
|
||||
if (*p_ambw == 'd') {
|
||||
// XXX: If ambiwidth=double then "|" and "·" take 2 columns, which is
|
||||
// forbidden (TUI limitation?). Set old defaults.
|
||||
fcs_tab[2].def = '|';
|
||||
fcs_tab[6].def = '|';
|
||||
// XXX: If ambiwidth=double then some characters take 2 columns,
|
||||
// which is forbidden (TUI limitation?). Set old defaults.
|
||||
fcs_tab[2].def = '-';
|
||||
fcs_tab[3].def = '-';
|
||||
} else {
|
||||
fcs_tab[2].def = 9474; // │
|
||||
fcs_tab[6].def = 9474; // │
|
||||
fcs_tab[3].def = 183; // ·
|
||||
fcs_tab[4].def = '-';
|
||||
fcs_tab[5].def = '|';
|
||||
fcs_tab[6].def = '|';
|
||||
fcs_tab[7].def = '|';
|
||||
fcs_tab[8].def = '+';
|
||||
fcs_tab[9].def = '-';
|
||||
fcs_tab[12].def = '|';
|
||||
}
|
||||
}
|
||||
|
||||
@ -4475,6 +4483,20 @@ static char *set_num_option(int opt_idx, char_u *varp, long value, char *errbuf,
|
||||
// 'winminwidth'
|
||||
win_setminwidth();
|
||||
} else if (pp == &p_ls) {
|
||||
// When switching to global statusline, decrease topframe height
|
||||
// Also clear the cmdline to remove the ruler if there is one
|
||||
if (value == 3 && old_value != 3) {
|
||||
frame_new_height(topframe, topframe->fr_height - STATUS_HEIGHT, false, false);
|
||||
(void)win_comp_pos();
|
||||
clear_cmdline = true;
|
||||
}
|
||||
// When switching from global statusline, increase height of topframe by STATUS_HEIGHT
|
||||
// in order to to re-add the space that was previously taken by the global statusline
|
||||
if (old_value == 3 && value != 3) {
|
||||
frame_new_height(topframe, topframe->fr_height + STATUS_HEIGHT, false, false);
|
||||
(void)win_comp_pos();
|
||||
}
|
||||
|
||||
last_status(false); // (re)set last window status line.
|
||||
} else if (pp == &p_stal) {
|
||||
// (re)set tab page line
|
||||
@ -5646,7 +5668,7 @@ static int put_setbool(FILE *fd, char *cmd, char *name, int value)
|
||||
|
||||
void comp_col(void)
|
||||
{
|
||||
int last_has_status = (p_ls == 2 || (p_ls == 1 && !ONE_WINDOW));
|
||||
int last_has_status = (p_ls > 1 || (p_ls == 1 && !ONE_WINDOW));
|
||||
|
||||
sc_col = 0;
|
||||
ru_col = 0;
|
||||
|
@ -3635,7 +3635,7 @@ static int qf_goto_cwindow(const qf_info_T *qi, bool resize, int sz, bool vertsp
|
||||
win_setwidth(sz);
|
||||
}
|
||||
} else if (sz != win->w_height
|
||||
&& (win->w_height + win->w_status_height + tabline_height()
|
||||
&& (win->w_height + win->w_hsep_height + win->w_status_height + tabline_height()
|
||||
< cmdline_row)) {
|
||||
win_setheight(sz);
|
||||
}
|
||||
|
@ -286,7 +286,8 @@ void update_curbuf(int type)
|
||||
void redraw_buf_status_later(buf_T *buf)
|
||||
{
|
||||
FOR_ALL_WINDOWS_IN_TAB(wp, curtab) {
|
||||
if (wp->w_buffer == buf && wp->w_status_height) {
|
||||
if (wp->w_buffer == buf
|
||||
&& (wp->w_status_height || (wp == curwin && global_stl_height()))) {
|
||||
wp->w_redr_status = true;
|
||||
if (must_redraw < VALID) {
|
||||
must_redraw = VALID;
|
||||
@ -316,6 +317,7 @@ void redraw_win_signcol(win_T *wp)
|
||||
int update_screen(int type)
|
||||
{
|
||||
static bool did_intro = false;
|
||||
bool is_stl_global = global_stl_height() > 0;
|
||||
|
||||
// Don't do anything if the screen structures are (not yet) valid.
|
||||
// A VimResized autocmd can invoke redrawing in the middle of a resize,
|
||||
@ -398,10 +400,13 @@ int update_screen(int type)
|
||||
if (W_ENDROW(wp) > valid) {
|
||||
wp->w_redr_type = MAX(wp->w_redr_type, NOT_VALID);
|
||||
}
|
||||
if (W_ENDROW(wp) + wp->w_status_height > valid) {
|
||||
if (!is_stl_global && W_ENDROW(wp) + wp->w_status_height > valid) {
|
||||
wp->w_redr_status = true;
|
||||
}
|
||||
}
|
||||
if (is_stl_global && Rows - p_ch - 1 > valid) {
|
||||
curwin->w_redr_status = true;
|
||||
}
|
||||
}
|
||||
msg_grid_set_pos(Rows-p_ch, false);
|
||||
msg_grid_invalid = false;
|
||||
@ -423,13 +428,15 @@ int update_screen(int type)
|
||||
wp->w_redr_type = REDRAW_TOP;
|
||||
} else {
|
||||
wp->w_redr_type = NOT_VALID;
|
||||
if (W_ENDROW(wp) + wp->w_status_height
|
||||
<= msg_scrolled) {
|
||||
wp->w_redr_status = TRUE;
|
||||
if (!is_stl_global && W_ENDROW(wp) + wp->w_status_height <= msg_scrolled) {
|
||||
wp->w_redr_status = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (is_stl_global && Rows - p_ch - 1 <= msg_scrolled) {
|
||||
curwin->w_redr_status = true;
|
||||
}
|
||||
redraw_cmdline = true;
|
||||
redraw_tabline = true;
|
||||
}
|
||||
@ -740,8 +747,11 @@ static void win_update(win_T *wp, DecorProviders *providers)
|
||||
wp->w_lines_valid = 0;
|
||||
}
|
||||
|
||||
// Window is zero-height: nothing to draw.
|
||||
// Window is zero-height: Only need to draw the separator
|
||||
if (wp->w_grid.Rows == 0) {
|
||||
// draw the horizontal separator below this window
|
||||
draw_hsep_win(wp);
|
||||
draw_sep_connectors_win(wp);
|
||||
wp->w_redr_type = 0;
|
||||
return;
|
||||
}
|
||||
@ -749,7 +759,8 @@ static void win_update(win_T *wp, DecorProviders *providers)
|
||||
// Window is zero-width: Only need to draw the separator.
|
||||
if (wp->w_grid.Columns == 0) {
|
||||
// draw the vertical separator right of this window
|
||||
draw_vsep_win(wp, 0);
|
||||
draw_vsep_win(wp);
|
||||
draw_sep_connectors_win(wp);
|
||||
wp->w_redr_type = 0;
|
||||
return;
|
||||
}
|
||||
@ -1664,7 +1675,9 @@ static void win_update(win_T *wp, DecorProviders *providers)
|
||||
kvi_destroy(line_providers);
|
||||
|
||||
if (wp->w_redr_type >= REDRAW_TOP) {
|
||||
draw_vsep_win(wp, 0);
|
||||
draw_vsep_win(wp);
|
||||
draw_hsep_win(wp);
|
||||
draw_sep_connectors_win(wp);
|
||||
}
|
||||
syn_set_timeout(NULL);
|
||||
|
||||
@ -4881,6 +4894,10 @@ void rl_mirror(char_u *str)
|
||||
*/
|
||||
void status_redraw_all(void)
|
||||
{
|
||||
if (global_stl_height()) {
|
||||
curwin->w_redr_status = true;
|
||||
redraw_later(curwin, VALID);
|
||||
} else {
|
||||
FOR_ALL_WINDOWS_IN_TAB(wp, curtab) {
|
||||
if (wp->w_status_height) {
|
||||
wp->w_redr_status = true;
|
||||
@ -4888,6 +4905,7 @@ void status_redraw_all(void)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Marks all status lines of the current buffer for redraw.
|
||||
void status_redraw_curbuf(void)
|
||||
@ -4898,6 +4916,10 @@ void status_redraw_curbuf(void)
|
||||
/// Marks all status lines of the specified buffer for redraw.
|
||||
void status_redraw_buf(buf_T *buf)
|
||||
{
|
||||
if (global_stl_height() != 0 && curwin->w_buffer == buf) {
|
||||
curwin->w_redr_status = true;
|
||||
redraw_later(curwin, VALID);
|
||||
} else {
|
||||
FOR_ALL_WINDOWS_IN_TAB(wp, curtab) {
|
||||
if (wp->w_status_height != 0 && wp->w_buffer == buf) {
|
||||
wp->w_redr_status = true;
|
||||
@ -4905,6 +4927,7 @@ void status_redraw_buf(buf_T *buf)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Redraw all status lines that need to be redrawn.
|
||||
@ -4943,10 +4966,8 @@ void win_redraw_last_status(const frame_T *frp)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Draw the verticap separator right of window "wp" starting with line "row".
|
||||
*/
|
||||
static void draw_vsep_win(win_T *wp, int row)
|
||||
/// Draw the vertical separator right of window "wp"
|
||||
static void draw_vsep_win(win_T *wp)
|
||||
{
|
||||
int hl;
|
||||
int c;
|
||||
@ -4954,15 +4975,97 @@ static void draw_vsep_win(win_T *wp, int row)
|
||||
if (wp->w_vsep_width) {
|
||||
// draw the vertical separator right of this window
|
||||
c = fillchar_vsep(wp, &hl);
|
||||
grid_fill(&default_grid, wp->w_winrow + row, W_ENDROW(wp),
|
||||
grid_fill(&default_grid, wp->w_winrow, W_ENDROW(wp),
|
||||
W_ENDCOL(wp), W_ENDCOL(wp) + 1, c, ' ', hl);
|
||||
}
|
||||
}
|
||||
|
||||
/// Draw the horizontal separator below window "wp"
|
||||
static void draw_hsep_win(win_T *wp)
|
||||
{
|
||||
int hl;
|
||||
int c;
|
||||
|
||||
/*
|
||||
* Get the length of an item as it will be shown in the status line.
|
||||
*/
|
||||
if (wp->w_hsep_height) {
|
||||
// draw the horizontal separator below this window
|
||||
c = fillchar_hsep(wp, &hl);
|
||||
grid_fill(&default_grid, W_ENDROW(wp), W_ENDROW(wp) + 1,
|
||||
wp->w_wincol, W_ENDCOL(wp), c, c, hl);
|
||||
}
|
||||
}
|
||||
|
||||
/// Get the separator connector for specified window corner of window "wp"
|
||||
static int get_corner_sep_connector(win_T *wp, WindowCorner corner)
|
||||
{
|
||||
// It's impossible for windows to be connected neither vertically nor horizontally
|
||||
// So if they're not vertically connected, assume they're horizontally connected
|
||||
if (vsep_connected(wp, corner)) {
|
||||
if (hsep_connected(wp, corner)) {
|
||||
return wp->w_p_fcs_chars.verthoriz;
|
||||
} else if (corner == WC_TOP_LEFT || corner == WC_BOTTOM_LEFT) {
|
||||
return wp->w_p_fcs_chars.vertright;
|
||||
} else {
|
||||
return wp->w_p_fcs_chars.vertleft;
|
||||
}
|
||||
} else if (corner == WC_TOP_LEFT || corner == WC_TOP_RIGHT) {
|
||||
return wp->w_p_fcs_chars.horizdown;
|
||||
} else {
|
||||
return wp->w_p_fcs_chars.horizup;
|
||||
}
|
||||
}
|
||||
|
||||
/// Draw seperator connecting characters on the corners of window "wp"
|
||||
static void draw_sep_connectors_win(win_T *wp)
|
||||
{
|
||||
// Don't draw separator connectors unless global statusline is enabled and the window has
|
||||
// either a horizontal or vertical separator
|
||||
if (global_stl_height() == 0 || !(wp->w_hsep_height == 1 || wp->w_vsep_width == 1)) {
|
||||
return;
|
||||
}
|
||||
|
||||
int hl = win_hl_attr(wp, HLF_C);
|
||||
|
||||
// Determine which edges of the screen the window is located on so we can avoid drawing separators
|
||||
// on corners contained in those edges
|
||||
bool win_at_top;
|
||||
bool win_at_bottom = wp->w_hsep_height == 0;
|
||||
bool win_at_left;
|
||||
bool win_at_right = wp->w_vsep_width == 0;
|
||||
frame_T *frp;
|
||||
|
||||
for (frp = wp->w_frame; frp->fr_parent != NULL; frp = frp->fr_parent) {
|
||||
if (frp->fr_parent->fr_layout == FR_COL && frp->fr_prev != NULL) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
win_at_top = frp->fr_parent == NULL;
|
||||
for (frp = wp->w_frame; frp->fr_parent != NULL; frp = frp->fr_parent) {
|
||||
if (frp->fr_parent->fr_layout == FR_ROW && frp->fr_prev != NULL) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
win_at_left = frp->fr_parent == NULL;
|
||||
|
||||
// Draw the appropriate separator connector in every corner where drawing them is necessary
|
||||
if (!(win_at_top || win_at_left)) {
|
||||
grid_putchar(&default_grid, get_corner_sep_connector(wp, WC_TOP_LEFT),
|
||||
wp->w_winrow - 1, wp->w_wincol - 1, hl);
|
||||
}
|
||||
if (!(win_at_top || win_at_right)) {
|
||||
grid_putchar(&default_grid, get_corner_sep_connector(wp, WC_TOP_RIGHT),
|
||||
wp->w_winrow - 1, W_ENDCOL(wp), hl);
|
||||
}
|
||||
if (!(win_at_bottom || win_at_left)) {
|
||||
grid_putchar(&default_grid, get_corner_sep_connector(wp, WC_BOTTOM_LEFT),
|
||||
W_ENDROW(wp), wp->w_wincol - 1, hl);
|
||||
}
|
||||
if (!(win_at_bottom || win_at_right)) {
|
||||
grid_putchar(&default_grid, get_corner_sep_connector(wp, WC_BOTTOM_RIGHT),
|
||||
W_ENDROW(wp), W_ENDCOL(wp), hl);
|
||||
}
|
||||
}
|
||||
|
||||
/// Get the length of an item as it will be shown in the status line.
|
||||
static int status_match_len(expand_T *xp, char_u *s)
|
||||
{
|
||||
int len = 0;
|
||||
@ -5163,7 +5266,7 @@ void win_redr_status_matches(expand_T *xp, int num_matches, char_u **matches, in
|
||||
// Create status line if needed by setting 'laststatus' to 2.
|
||||
// Set 'winminheight' to zero to avoid that the window is
|
||||
// resized.
|
||||
if (lastwin->w_status_height == 0) {
|
||||
if (lastwin->w_status_height == 0 && global_stl_height() == 0) {
|
||||
save_p_ls = p_ls;
|
||||
save_p_wmh = p_wmh;
|
||||
p_ls = 2;
|
||||
@ -5199,12 +5302,15 @@ void win_redr_status_matches(expand_T *xp, int num_matches, char_u **matches, in
|
||||
static void win_redr_status(win_T *wp)
|
||||
{
|
||||
int row;
|
||||
int col;
|
||||
char_u *p;
|
||||
int len;
|
||||
int fillchar;
|
||||
int attr;
|
||||
int width;
|
||||
int this_ru_col;
|
||||
static int busy = FALSE;
|
||||
bool is_stl_global = global_stl_height() > 0;
|
||||
static int busy = false;
|
||||
|
||||
// May get here recursively when 'statusline' (indirectly)
|
||||
// invokes ":redrawstatus". Simply ignore the call then.
|
||||
@ -5215,9 +5321,9 @@ static void win_redr_status(win_T *wp)
|
||||
}
|
||||
busy = true;
|
||||
|
||||
wp->w_redr_status = FALSE;
|
||||
if (wp->w_status_height == 0) {
|
||||
// no status line, can only be last window
|
||||
wp->w_redr_status = false;
|
||||
if (wp->w_status_height == 0 && !(is_stl_global && wp == curwin)) {
|
||||
// no status line, either global statusline is enabled or the window is a last window
|
||||
redraw_cmdline = true;
|
||||
} else if (!redrawing()) {
|
||||
// Don't redraw right now, do it later. Don't update status line when
|
||||
@ -5228,6 +5334,7 @@ static void win_redr_status(win_T *wp)
|
||||
redraw_custom_statusline(wp);
|
||||
} else {
|
||||
fillchar = fillchar_status(&attr, wp);
|
||||
width = is_stl_global ? Columns : wp->w_width;
|
||||
|
||||
get_trans_bufname(wp->w_buffer);
|
||||
p = NameBuff;
|
||||
@ -5256,9 +5363,9 @@ static void win_redr_status(win_T *wp)
|
||||
// len += (int)STRLEN(p + len); // dead assignment
|
||||
}
|
||||
|
||||
this_ru_col = ru_col - (Columns - wp->w_width);
|
||||
if (this_ru_col < (wp->w_width + 1) / 2) {
|
||||
this_ru_col = (wp->w_width + 1) / 2;
|
||||
this_ru_col = ru_col - (Columns - width);
|
||||
if (this_ru_col < (width + 1) / 2) {
|
||||
this_ru_col = (width + 1) / 2;
|
||||
}
|
||||
if (this_ru_col <= 1) {
|
||||
p = (char_u *)"<"; // No room for file name!
|
||||
@ -5283,10 +5390,11 @@ static void win_redr_status(win_T *wp)
|
||||
}
|
||||
}
|
||||
|
||||
row = W_ENDROW(wp);
|
||||
grid_puts(&default_grid, p, row, wp->w_wincol, attr);
|
||||
grid_fill(&default_grid, row, row + 1, len + wp->w_wincol,
|
||||
this_ru_col + wp->w_wincol, fillchar, fillchar, attr);
|
||||
row = is_stl_global ? (Rows - p_ch - 1) : W_ENDROW(wp);
|
||||
col = is_stl_global ? 0 : wp->w_wincol;
|
||||
grid_puts(&default_grid, p, row, col, attr);
|
||||
grid_fill(&default_grid, row, row + 1, len + col,
|
||||
this_ru_col + col, fillchar, fillchar, attr);
|
||||
|
||||
if (get_keymap_str(wp, (char_u *)"<%s>", NameBuff, MAXPATHL)
|
||||
&& this_ru_col - len > (int)(STRLEN(NameBuff) + 1)) {
|
||||
@ -5365,6 +5473,76 @@ bool stl_connected(win_T *wp)
|
||||
return false;
|
||||
}
|
||||
|
||||
/// Check if horizontal separator of window "wp" at specified window corner is connected to the
|
||||
/// horizontal separator of another window
|
||||
/// Assumes global statusline is enabled
|
||||
static bool hsep_connected(win_T *wp, WindowCorner corner)
|
||||
{
|
||||
bool before = (corner == WC_TOP_LEFT || corner == WC_BOTTOM_LEFT);
|
||||
int sep_row = (corner == WC_TOP_LEFT || corner == WC_TOP_RIGHT)
|
||||
? wp->w_winrow - 1 : W_ENDROW(wp);
|
||||
frame_T *fr = wp->w_frame;
|
||||
|
||||
while (fr->fr_parent != NULL) {
|
||||
if (fr->fr_parent->fr_layout == FR_ROW && (before ? fr->fr_prev : fr->fr_next) != NULL) {
|
||||
fr = before ? fr->fr_prev : fr->fr_next;
|
||||
break;
|
||||
}
|
||||
fr = fr->fr_parent;
|
||||
}
|
||||
if (fr->fr_parent == NULL) {
|
||||
return false;
|
||||
}
|
||||
while (fr->fr_layout != FR_LEAF) {
|
||||
fr = fr->fr_child;
|
||||
if (fr->fr_parent->fr_layout == FR_ROW && before) {
|
||||
while (fr->fr_next != NULL) {
|
||||
fr = fr->fr_next;
|
||||
}
|
||||
} else {
|
||||
while (fr->fr_next != NULL && frame2win(fr)->w_winrow + fr->fr_height < sep_row) {
|
||||
fr = fr->fr_next;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (sep_row == fr->fr_win->w_winrow - 1 || sep_row == W_ENDROW(fr->fr_win));
|
||||
}
|
||||
|
||||
/// Check if vertical separator of window "wp" at specified window corner is connected to the
|
||||
/// vertical separator of another window
|
||||
static bool vsep_connected(win_T *wp, WindowCorner corner)
|
||||
{
|
||||
bool before = (corner == WC_TOP_LEFT || corner == WC_TOP_RIGHT);
|
||||
int sep_col = (corner == WC_TOP_LEFT || corner == WC_BOTTOM_LEFT)
|
||||
? wp->w_wincol - 1 : W_ENDCOL(wp);
|
||||
frame_T *fr = wp->w_frame;
|
||||
|
||||
while (fr->fr_parent != NULL) {
|
||||
if (fr->fr_parent->fr_layout == FR_COL && (before ? fr->fr_prev : fr->fr_next) != NULL) {
|
||||
fr = before ? fr->fr_prev : fr->fr_next;
|
||||
break;
|
||||
}
|
||||
fr = fr->fr_parent;
|
||||
}
|
||||
if (fr->fr_parent == NULL) {
|
||||
return false;
|
||||
}
|
||||
while (fr->fr_layout != FR_LEAF) {
|
||||
fr = fr->fr_child;
|
||||
if (fr->fr_parent->fr_layout == FR_COL && before) {
|
||||
while (fr->fr_next != NULL) {
|
||||
fr = fr->fr_next;
|
||||
}
|
||||
} else {
|
||||
while (fr->fr_next != NULL && frame2win(fr)->w_wincol + fr->fr_width < sep_col) {
|
||||
fr = fr->fr_next;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (sep_col == fr->fr_win->w_wincol - 1 || sep_col == W_ENDCOL(fr->fr_win));
|
||||
}
|
||||
|
||||
/// Get the value to show for the language mappings, active 'keymap'.
|
||||
///
|
||||
@ -5431,6 +5609,7 @@ static void win_redr_custom(win_T *wp, bool draw_ruler)
|
||||
int use_sandbox = false;
|
||||
win_T *ewp;
|
||||
int p_crb_save;
|
||||
bool is_stl_global = global_stl_height() > 0;
|
||||
|
||||
ScreenGrid *grid = &default_grid;
|
||||
|
||||
@ -5452,9 +5631,9 @@ static void win_redr_custom(win_T *wp, bool draw_ruler)
|
||||
maxwidth = Columns;
|
||||
use_sandbox = was_set_insecurely(wp, "tabline", 0);
|
||||
} else {
|
||||
row = W_ENDROW(wp);
|
||||
row = is_stl_global ? (Rows - p_ch - 1) : W_ENDROW(wp);
|
||||
fillchar = fillchar_status(&attr, wp);
|
||||
maxwidth = wp->w_width;
|
||||
maxwidth = is_stl_global ? Columns : wp->w_width;
|
||||
|
||||
if (draw_ruler) {
|
||||
stl = p_ruf;
|
||||
@ -5472,12 +5651,12 @@ static void win_redr_custom(win_T *wp, bool draw_ruler)
|
||||
stl = p_ruf;
|
||||
}
|
||||
}
|
||||
col = ru_col - (Columns - wp->w_width);
|
||||
if (col < (wp->w_width + 1) / 2) {
|
||||
col = (wp->w_width + 1) / 2;
|
||||
col = ru_col - (Columns - maxwidth);
|
||||
if (col < (maxwidth + 1) / 2) {
|
||||
col = (maxwidth + 1) / 2;
|
||||
}
|
||||
maxwidth = wp->w_width - col;
|
||||
if (!wp->w_status_height) {
|
||||
maxwidth = maxwidth - col;
|
||||
if (!wp->w_status_height && !is_stl_global) {
|
||||
grid = &msg_grid_adj;
|
||||
row = Rows - 1;
|
||||
maxwidth--; // writing in last column may cause scrolling
|
||||
@ -5495,7 +5674,7 @@ static void win_redr_custom(win_T *wp, bool draw_ruler)
|
||||
use_sandbox = was_set_insecurely(wp, "statusline", *wp->w_p_stl == NUL ? 0 : OPT_LOCAL);
|
||||
}
|
||||
|
||||
col += wp->w_wincol;
|
||||
col += is_stl_global ? 0 : wp->w_wincol;
|
||||
}
|
||||
|
||||
if (maxwidth <= 0) {
|
||||
@ -7077,10 +7256,10 @@ int showmode(void)
|
||||
clear_showcmd();
|
||||
}
|
||||
|
||||
// If the last window has no status line, the ruler is after the mode
|
||||
// message and must be redrawn
|
||||
// If the last window has no status line and global statusline is disabled,
|
||||
// the ruler is after the mode message and must be redrawn
|
||||
win_T *last = lastwin_nofloating();
|
||||
if (redrawing() && last->w_status_height == 0) {
|
||||
if (redrawing() && last->w_status_height == 0 && global_stl_height() == 0) {
|
||||
win_redr_ruler(last, true);
|
||||
}
|
||||
redraw_cmdline = false;
|
||||
@ -7395,16 +7574,22 @@ int fillchar_status(int *attr, win_T *wp)
|
||||
return '=';
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the character to use in a separator between vertically split windows.
|
||||
* Get its attributes in "*attr".
|
||||
*/
|
||||
/// Get the character to use in a separator between vertically split windows.
|
||||
/// Get its attributes in "*attr".
|
||||
static int fillchar_vsep(win_T *wp, int *attr)
|
||||
{
|
||||
*attr = win_hl_attr(wp, HLF_C);
|
||||
return wp->w_p_fcs_chars.vert;
|
||||
}
|
||||
|
||||
/// Get the character to use in a separator between horizontally split windows.
|
||||
/// Get its attributes in "*attr".
|
||||
static int fillchar_hsep(win_T *wp, int *attr)
|
||||
{
|
||||
*attr = win_hl_attr(wp, HLF_C);
|
||||
return wp->w_p_fcs_chars.horiz;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return TRUE if redrawing should currently be done.
|
||||
*/
|
||||
@ -7430,7 +7615,8 @@ void showruler(bool always)
|
||||
if (!always && !redrawing()) {
|
||||
return;
|
||||
}
|
||||
if ((*p_stl != NUL || *curwin->w_p_stl != NUL) && curwin->w_status_height) {
|
||||
if ((*p_stl != NUL || *curwin->w_p_stl != NUL)
|
||||
&& (curwin->w_status_height || global_stl_height())) {
|
||||
redraw_custom_statusline(curwin);
|
||||
} else {
|
||||
win_redr_ruler(curwin, always);
|
||||
@ -7449,6 +7635,7 @@ void showruler(bool always)
|
||||
|
||||
static void win_redr_ruler(win_T *wp, bool always)
|
||||
{
|
||||
bool is_stl_global = global_stl_height() > 0;
|
||||
static bool did_show_ext_ruler = false;
|
||||
|
||||
// If 'ruler' off or redrawing disabled, don't do anything
|
||||
@ -7466,7 +7653,7 @@ static void win_redr_ruler(win_T *wp, bool always)
|
||||
|
||||
// Don't draw the ruler while doing insert-completion, it might overwrite
|
||||
// the (long) mode message.
|
||||
if (wp == lastwin && lastwin->w_status_height == 0) {
|
||||
if (wp == lastwin && lastwin->w_status_height == 0 && !is_stl_global) {
|
||||
if (edit_submode != NULL) {
|
||||
return;
|
||||
}
|
||||
@ -7521,6 +7708,12 @@ static void win_redr_ruler(win_T *wp, bool always)
|
||||
off = wp->w_wincol;
|
||||
width = wp->w_width;
|
||||
part_of_status = true;
|
||||
} else if (is_stl_global) {
|
||||
row = Rows - p_ch - 1;
|
||||
fillchar = fillchar_status(&attr, wp);
|
||||
off = 0;
|
||||
width = Columns;
|
||||
part_of_status = true;
|
||||
} else {
|
||||
row = Rows - 1;
|
||||
fillchar = ' ';
|
||||
@ -7560,7 +7753,7 @@ static void win_redr_ruler(win_T *wp, bool always)
|
||||
int i = (int)STRLEN(buffer);
|
||||
get_rel_pos(wp, buffer + i + 1, RULER_BUF_LEN - i - 1);
|
||||
int o = i + vim_strsize(buffer + i + 1);
|
||||
if (wp->w_status_height == 0) { // can't use last char of screen
|
||||
if (wp->w_status_height == 0 && !is_stl_global) { // can't use last char of screen
|
||||
o++;
|
||||
}
|
||||
int this_ru_col = ru_col - (Columns - width);
|
||||
|
@ -19,6 +19,14 @@
|
||||
#define NOT_VALID 40 // buffer needs complete redraw
|
||||
#define CLEAR 50 // screen messed up, clear it
|
||||
|
||||
/// corner value flags for hsep_connected and vsep_connected
|
||||
typedef enum {
|
||||
WC_TOP_LEFT = 0,
|
||||
WC_TOP_RIGHT,
|
||||
WC_BOTTOM_LEFT,
|
||||
WC_BOTTOM_RIGHT
|
||||
} WindowCorner;
|
||||
|
||||
/// By default, all widows are draw on a single rectangular grid, represented by
|
||||
/// this ScreenGrid instance. In multigrid mode each window will have its own
|
||||
/// grid, then this is only used for global screen elements that hasn't been
|
||||
|
@ -6174,6 +6174,7 @@ static const char *highlight_init_both[] = {
|
||||
"TermCursor cterm=reverse gui=reverse",
|
||||
"VertSplit cterm=reverse gui=reverse",
|
||||
"WildMenu ctermbg=Yellow ctermfg=Black guibg=Yellow guifg=Black",
|
||||
"default link WinSeparator VertSplit",
|
||||
"default link EndOfBuffer NonText",
|
||||
"default link LineNrAbove LineNr",
|
||||
"default link LineNrBelow LineNr",
|
||||
@ -6184,7 +6185,7 @@ static const char *highlight_init_both[] = {
|
||||
"default link Whitespace NonText",
|
||||
"default link MsgSeparator StatusLine",
|
||||
"default link NormalFloat Pmenu",
|
||||
"default link FloatBorder VertSplit",
|
||||
"default link FloatBorder WinSeparator",
|
||||
"default FloatShadow blend=80 guibg=Black",
|
||||
"default FloatShadowThrough blend=100 guibg=Black",
|
||||
"RedrawDebugNormal cterm=reverse gui=reverse",
|
||||
|
@ -146,7 +146,7 @@ func Test_highlight_eol_with_cursorline_vertsplit()
|
||||
" 'abcd |abcd '
|
||||
" ^^^^ ^^^^^^^^^ no highlight
|
||||
" ^ 'Search' highlight
|
||||
" ^ 'VertSplit' highlight
|
||||
" ^ 'WinSeparator' highlight
|
||||
let attrs0 = ScreenAttrs(1, 15)[0]
|
||||
call assert_equal(repeat([attrs0[0]], 4), attrs0[0:3])
|
||||
call assert_equal(repeat([attrs0[0]], 9), attrs0[6:14])
|
||||
@ -160,7 +160,7 @@ func Test_highlight_eol_with_cursorline_vertsplit()
|
||||
" 'abcd |abcd '
|
||||
" ^^^^ underline
|
||||
" ^ 'Search' highlight with underline
|
||||
" ^ 'VertSplit' highlight
|
||||
" ^ 'WinSeparator' highlight
|
||||
" ^^^^^^^^^ no highlight
|
||||
|
||||
" underline
|
||||
|
@ -60,7 +60,7 @@
|
||||
|
||||
#define NOWIN (win_T *)-1 // non-existing window
|
||||
|
||||
#define ROWS_AVAIL (Rows - p_ch - tabline_height())
|
||||
#define ROWS_AVAIL (Rows - p_ch - tabline_height() - global_stl_height())
|
||||
|
||||
/// flags for win_enter_ext()
|
||||
typedef enum {
|
||||
@ -658,6 +658,7 @@ win_T *win_new_float(win_T *wp, FloatConfig fconfig, Error *err)
|
||||
}
|
||||
wp->w_floating = 1;
|
||||
wp->w_status_height = 0;
|
||||
wp->w_hsep_height = 0;
|
||||
wp->w_vsep_width = 0;
|
||||
|
||||
win_config_float(wp, fconfig);
|
||||
@ -967,6 +968,7 @@ int win_split_ins(int size, int flags, win_T *new_wp, int dir)
|
||||
int before;
|
||||
int minheight;
|
||||
int wmh1;
|
||||
int hsep_height;
|
||||
bool did_set_fraction = false;
|
||||
|
||||
// aucmd_win should always remain floating
|
||||
@ -1079,6 +1081,7 @@ int win_split_ins(int size, int flags, win_T *new_wp, int dir)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
hsep_height = global_stl_height() > 0 ? 1 : STATUS_HEIGHT;
|
||||
layout = FR_COL;
|
||||
|
||||
/*
|
||||
@ -1087,7 +1090,7 @@ int win_split_ins(int size, int flags, win_T *new_wp, int dir)
|
||||
*/
|
||||
// Current window requires at least 1 space.
|
||||
wmh1 = p_wmh == 0 ? 1 : p_wmh;
|
||||
needed = wmh1 + STATUS_HEIGHT;
|
||||
needed = wmh1 + hsep_height;
|
||||
if (flags & WSP_ROOM) {
|
||||
needed += p_wh - wmh1;
|
||||
}
|
||||
@ -1129,15 +1132,15 @@ int win_split_ins(int size, int flags, win_T *new_wp, int dir)
|
||||
new_size = oldwin_height / 2;
|
||||
}
|
||||
|
||||
if (new_size > available - minheight - STATUS_HEIGHT) {
|
||||
new_size = available - minheight - STATUS_HEIGHT;
|
||||
if (new_size > available - minheight - hsep_height) {
|
||||
new_size = available - minheight - hsep_height;
|
||||
}
|
||||
if (new_size < wmh1) {
|
||||
new_size = wmh1;
|
||||
}
|
||||
|
||||
// if it doesn't fit in the current window, need win_equal()
|
||||
if (oldwin_height - new_size - STATUS_HEIGHT < p_wmh) {
|
||||
if (oldwin_height - new_size - hsep_height < p_wmh) {
|
||||
do_equal = true;
|
||||
}
|
||||
|
||||
@ -1150,7 +1153,7 @@ int win_split_ins(int size, int flags, win_T *new_wp, int dir)
|
||||
set_fraction(oldwin);
|
||||
did_set_fraction = true;
|
||||
|
||||
win_setheight_win(oldwin->w_height + new_size + STATUS_HEIGHT,
|
||||
win_setheight_win(oldwin->w_height + new_size + hsep_height,
|
||||
oldwin);
|
||||
oldwin_height = oldwin->w_height;
|
||||
if (need_status) {
|
||||
@ -1167,8 +1170,7 @@ int win_split_ins(int size, int flags, win_T *new_wp, int dir)
|
||||
while (frp != NULL) {
|
||||
if (frp->fr_win != oldwin && frp->fr_win != NULL
|
||||
&& (frp->fr_win->w_height > new_size
|
||||
|| frp->fr_win->w_height > oldwin_height - new_size
|
||||
- STATUS_HEIGHT)) {
|
||||
|| frp->fr_win->w_height > oldwin_height - new_size - hsep_height)) {
|
||||
do_equal = true;
|
||||
break;
|
||||
}
|
||||
@ -1294,13 +1296,15 @@ int win_split_ins(int size, int flags, win_T *new_wp, int dir)
|
||||
if (flags & (WSP_TOP | WSP_BOT)) {
|
||||
// set height and row of new window to full height
|
||||
wp->w_winrow = tabline_height();
|
||||
win_new_height(wp, curfrp->fr_height - (p_ls > 0));
|
||||
wp->w_status_height = (p_ls > 0);
|
||||
win_new_height(wp, curfrp->fr_height - (p_ls == 1 || p_ls == 2));
|
||||
wp->w_status_height = (p_ls == 1 || p_ls == 2);
|
||||
wp->w_hsep_height = 0;
|
||||
} else {
|
||||
// height and row of new window is same as current window
|
||||
wp->w_winrow = oldwin->w_winrow;
|
||||
win_new_height(wp, oldwin->w_height);
|
||||
wp->w_status_height = oldwin->w_status_height;
|
||||
wp->w_hsep_height = oldwin->w_hsep_height;
|
||||
}
|
||||
frp->fr_height = curfrp->fr_height;
|
||||
|
||||
@ -1333,6 +1337,7 @@ int win_split_ins(int size, int flags, win_T *new_wp, int dir)
|
||||
frame_fix_width(oldwin);
|
||||
frame_fix_width(wp);
|
||||
} else {
|
||||
bool is_stl_global = global_stl_height() > 0;
|
||||
// width and column of new window is same as current window
|
||||
if (flags & (WSP_TOP | WSP_BOT)) {
|
||||
wp->w_wincol = 0;
|
||||
@ -1348,28 +1353,53 @@ int win_split_ins(int size, int flags, win_T *new_wp, int dir)
|
||||
// "new_size" of the current window goes to the new window, use
|
||||
// one row for the status line
|
||||
win_new_height(wp, new_size);
|
||||
if (before) {
|
||||
wp->w_hsep_height = is_stl_global ? 1 : 0;
|
||||
} else {
|
||||
wp->w_hsep_height = oldwin->w_hsep_height;
|
||||
oldwin->w_hsep_height = is_stl_global ? 1 : 0;
|
||||
}
|
||||
if (flags & (WSP_TOP | WSP_BOT)) {
|
||||
int new_fr_height = curfrp->fr_height - new_size;
|
||||
|
||||
if (!((flags & WSP_BOT) && p_ls == 0)) {
|
||||
if (!((flags & WSP_BOT) && p_ls == 0) && global_stl_height() == 0) {
|
||||
new_fr_height -= STATUS_HEIGHT;
|
||||
} else if (global_stl_height() > 0) {
|
||||
if (flags & WSP_BOT) {
|
||||
frame_add_hsep(curfrp);
|
||||
} else {
|
||||
new_fr_height -= 1;
|
||||
}
|
||||
}
|
||||
frame_new_height(curfrp, new_fr_height, flags & WSP_TOP, false);
|
||||
} else {
|
||||
win_new_height(oldwin, oldwin_height - (new_size + STATUS_HEIGHT));
|
||||
win_new_height(oldwin, oldwin_height - (new_size
|
||||
+ (global_stl_height() > 0 ? 1 : STATUS_HEIGHT)));
|
||||
}
|
||||
|
||||
if (before) { // new window above current one
|
||||
wp->w_winrow = oldwin->w_winrow;
|
||||
|
||||
if (is_stl_global) {
|
||||
wp->w_status_height = 0;
|
||||
oldwin->w_winrow += wp->w_height + 1;
|
||||
} else {
|
||||
wp->w_status_height = STATUS_HEIGHT;
|
||||
oldwin->w_winrow += wp->w_height + STATUS_HEIGHT;
|
||||
}
|
||||
} else { // new window below current one
|
||||
if (is_stl_global) {
|
||||
wp->w_winrow = oldwin->w_winrow + oldwin->w_height + 1;
|
||||
wp->w_status_height = 0;
|
||||
} else {
|
||||
wp->w_winrow = oldwin->w_winrow + oldwin->w_height + STATUS_HEIGHT;
|
||||
wp->w_status_height = oldwin->w_status_height;
|
||||
if (!(flags & WSP_BOT)) {
|
||||
oldwin->w_status_height = STATUS_HEIGHT;
|
||||
}
|
||||
}
|
||||
if (flags & WSP_BOT) {
|
||||
}
|
||||
if ((flags & WSP_BOT) && global_stl_height() == 0) {
|
||||
frame_add_statusline(curfrp);
|
||||
}
|
||||
frame_fix_height(wp);
|
||||
@ -1609,10 +1639,10 @@ int make_windows(int count, bool vertical)
|
||||
maxcount = (curwin->w_width + curwin->w_vsep_width
|
||||
- (p_wiw - p_wmw)) / (p_wmw + 1);
|
||||
} else {
|
||||
// Each window needs at least 'winminheight' lines and a status line.
|
||||
maxcount = (curwin->w_height
|
||||
+ curwin->w_status_height
|
||||
- (p_wh - p_wmh)) / (p_wmh + STATUS_HEIGHT);
|
||||
// Each window needs at least 'winminheight' lines
|
||||
// If statusline isn't global, each window also needs a statusline
|
||||
maxcount = (curwin->w_height + curwin->w_hsep_height + curwin->w_status_height
|
||||
- (p_wh - p_wmh)) / (p_wmh + (global_stl_height() > 0 ? 1 : STATUS_HEIGHT));
|
||||
}
|
||||
|
||||
if (maxcount < 2) {
|
||||
@ -1707,7 +1737,7 @@ static void win_exchange(long Prenum)
|
||||
* if wp != wp2
|
||||
* 3. remove wp from the list
|
||||
* 4. insert wp after wp2
|
||||
* 5. exchange the status line height and vsep width.
|
||||
* 5. exchange the status line height, hsep height and vsep width.
|
||||
*/
|
||||
wp2 = curwin->w_prev;
|
||||
frp2 = curwin->w_frame->fr_prev;
|
||||
@ -1733,6 +1763,9 @@ static void win_exchange(long Prenum)
|
||||
temp = curwin->w_vsep_width;
|
||||
curwin->w_vsep_width = wp->w_vsep_width;
|
||||
wp->w_vsep_width = temp;
|
||||
temp = curwin->w_hsep_height;
|
||||
curwin->w_hsep_height = wp->w_hsep_height;
|
||||
wp->w_hsep_height = temp;
|
||||
|
||||
frame_fix_height(curwin);
|
||||
frame_fix_height(wp);
|
||||
@ -1813,10 +1846,13 @@ static void win_rotate(bool upwards, int count)
|
||||
frame_insert(frp->fr_parent->fr_child, frp);
|
||||
}
|
||||
|
||||
// exchange status height and vsep width of old and new last window
|
||||
// exchange status height, hsep height and vsep width of old and new last window
|
||||
n = wp2->w_status_height;
|
||||
wp2->w_status_height = wp1->w_status_height;
|
||||
wp1->w_status_height = n;
|
||||
n = wp2->w_hsep_height;
|
||||
wp2->w_hsep_height = wp1->w_hsep_height;
|
||||
wp1->w_hsep_height = n;
|
||||
frame_fix_height(wp1);
|
||||
frame_fix_height(wp2);
|
||||
n = wp2->w_vsep_width;
|
||||
@ -1893,11 +1929,16 @@ void win_move_after(win_T *win1, win_T *win2)
|
||||
|
||||
// check if there is something to do
|
||||
if (win2->w_next != win1) {
|
||||
// may need move the status line/vertical separator of the last window
|
||||
// may need move the status line, horizontal or vertical separator of the last window
|
||||
if (win1 == lastwin) {
|
||||
height = win1->w_prev->w_status_height;
|
||||
win1->w_prev->w_status_height = win1->w_status_height;
|
||||
win1->w_status_height = height;
|
||||
|
||||
height = win1->w_prev->w_hsep_height;
|
||||
win1->w_prev->w_hsep_height = win1->w_hsep_height;
|
||||
win1->w_hsep_height = height;
|
||||
|
||||
if (win1->w_prev->w_vsep_width == 1) {
|
||||
// Remove the vertical separator from the last-but-one window,
|
||||
// add it to the last window. Adjust the frame widths.
|
||||
@ -1910,6 +1951,11 @@ void win_move_after(win_T *win1, win_T *win2)
|
||||
height = win1->w_status_height;
|
||||
win1->w_status_height = win2->w_status_height;
|
||||
win2->w_status_height = height;
|
||||
|
||||
height = win1->w_hsep_height;
|
||||
win1->w_hsep_height = win2->w_hsep_height;
|
||||
win2->w_hsep_height = height;
|
||||
|
||||
if (win1->w_vsep_width == 1) {
|
||||
// Remove the vertical separator from win1, add it to the last
|
||||
// window, win2. Adjust the frame widths.
|
||||
@ -1973,6 +2019,7 @@ static void win_equal_rec(win_T *next_curwin, bool current, frame_T *topfr, int
|
||||
int room = 0;
|
||||
int new_size;
|
||||
int has_next_curwin = 0;
|
||||
int hsep_height;
|
||||
bool hnc;
|
||||
|
||||
if (topfr->fr_layout == FR_LEAF) {
|
||||
@ -2118,19 +2165,22 @@ static void win_equal_rec(win_T *next_curwin, bool current, frame_T *topfr, int
|
||||
totwincount -= wincount;
|
||||
}
|
||||
} else { // topfr->fr_layout == FR_COL
|
||||
hsep_height = global_stl_height() > 0 ? 1 : STATUS_HEIGHT;
|
||||
topfr->fr_width = width;
|
||||
topfr->fr_height = height;
|
||||
|
||||
if (dir != 'h') { // equalize frame heights
|
||||
// Compute maximum number of windows vertically in this frame.
|
||||
n = frame_minheight(topfr, NOWIN);
|
||||
// add one for the bottom window if it doesn't have a statusline
|
||||
// add one for the bottom window if it doesn't have a statusline or separator
|
||||
if (row + height == cmdline_row && p_ls == 0) {
|
||||
extra_sep = STATUS_HEIGHT;
|
||||
} else if (global_stl_height() > 0) {
|
||||
extra_sep = 1;
|
||||
} else {
|
||||
extra_sep = 0;
|
||||
}
|
||||
totwincount = (n + extra_sep) / (p_wmh + 1);
|
||||
totwincount = (n + extra_sep) / (p_wmh + hsep_height);
|
||||
has_next_curwin = frame_has_win(topfr, next_curwin);
|
||||
|
||||
/*
|
||||
@ -2165,7 +2215,7 @@ static void win_equal_rec(win_T *next_curwin, bool current, frame_T *topfr, int
|
||||
} else {
|
||||
// These windows don't use up room.
|
||||
totwincount -= (n + (fr->fr_next == NULL
|
||||
? extra_sep : 0)) / (p_wmh + 1);
|
||||
? extra_sep : 0)) / (p_wmh + hsep_height);
|
||||
}
|
||||
room -= new_size - n;
|
||||
if (room < 0) {
|
||||
@ -2211,7 +2261,7 @@ static void win_equal_rec(win_T *next_curwin, bool current, frame_T *topfr, int
|
||||
// Compute the maximum number of windows vert. in "fr".
|
||||
n = frame_minheight(fr, NOWIN);
|
||||
wincount = (n + (fr->fr_next == NULL ? extra_sep : 0))
|
||||
/ (p_wmh + 1);
|
||||
/ (p_wmh + hsep_height);
|
||||
m = frame_minheight(fr, next_curwin);
|
||||
if (has_next_curwin) {
|
||||
hnc = frame_has_win(fr, next_curwin);
|
||||
@ -3167,7 +3217,7 @@ static tabpage_T *alt_tabpage(void)
|
||||
/*
|
||||
* Find the left-upper window in frame "frp".
|
||||
*/
|
||||
static win_T *frame2win(frame_T *frp)
|
||||
win_T *frame2win(frame_T *frp)
|
||||
{
|
||||
while (frp->fr_win == NULL) {
|
||||
frp = frp->fr_child;
|
||||
@ -3194,23 +3244,40 @@ static bool frame_has_win(const frame_T *frp, const win_T *wp)
|
||||
return false;
|
||||
}
|
||||
|
||||
/// Check if current window is at the bottom
|
||||
/// Returns true if there are no windows below current window
|
||||
static bool is_bottom_win(win_T *wp)
|
||||
FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ALL
|
||||
{
|
||||
frame_T *frp;
|
||||
for (frp = wp->w_frame; frp->fr_parent != NULL; frp = frp->fr_parent) {
|
||||
if (frp->fr_parent->fr_layout == FR_COL && frp->fr_next != NULL) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
/// 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.
|
||||
static void frame_new_height(frame_T *topfrp, int height, bool topfirst, bool wfh)
|
||||
void frame_new_height(frame_T *topfrp, int height, bool topfirst, bool wfh)
|
||||
FUNC_ATTR_NONNULL_ALL
|
||||
{
|
||||
frame_T *frp;
|
||||
int extra_lines;
|
||||
int h;
|
||||
win_T *wp;
|
||||
|
||||
if (topfrp->fr_win != NULL) {
|
||||
// Simple case: just one window.
|
||||
win_new_height(topfrp->fr_win,
|
||||
height - topfrp->fr_win->w_status_height);
|
||||
wp = topfrp->fr_win;
|
||||
if (is_bottom_win(wp)) {
|
||||
wp->w_hsep_height = 0;
|
||||
}
|
||||
win_new_height(wp, height - wp->w_hsep_height - wp->w_status_height);
|
||||
} else if (topfrp->fr_layout == FR_ROW) {
|
||||
do {
|
||||
// All frames in this row get the same new height.
|
||||
@ -3366,8 +3433,8 @@ static void frame_add_statusline(frame_T *frp)
|
||||
if (frp->fr_layout == FR_LEAF) {
|
||||
wp = frp->fr_win;
|
||||
if (wp->w_status_height == 0) {
|
||||
if (wp->w_height > 0) { // don't make it negative
|
||||
--wp->w_height;
|
||||
if (wp->w_height - STATUS_HEIGHT >= 0) { // don't make it negative
|
||||
wp->w_height -= STATUS_HEIGHT;
|
||||
}
|
||||
wp->w_status_height = STATUS_HEIGHT;
|
||||
}
|
||||
@ -3487,10 +3554,8 @@ static void frame_new_width(frame_T *topfrp, int width, bool leftfirst, bool wfw
|
||||
topfrp->fr_width = width;
|
||||
}
|
||||
|
||||
/*
|
||||
* Add the vertical separator to windows at the right side of "frp".
|
||||
* Note: Does not check if there is room!
|
||||
*/
|
||||
/// Add the vertical separator to windows at the right side of "frp".
|
||||
/// Note: Does not check if there is room!
|
||||
static void frame_add_vsep(const frame_T *frp)
|
||||
FUNC_ATTR_NONNULL_ARG(1)
|
||||
{
|
||||
@ -3520,6 +3585,37 @@ static void frame_add_vsep(const frame_T *frp)
|
||||
}
|
||||
}
|
||||
|
||||
/// Add the horizontal separator to windows at the bottom of "frp".
|
||||
/// Note: Does not check if there is room or whether the windows have a statusline!
|
||||
static void frame_add_hsep(const frame_T *frp)
|
||||
FUNC_ATTR_NONNULL_ARG(1)
|
||||
{
|
||||
win_T *wp;
|
||||
|
||||
if (frp->fr_layout == FR_LEAF) {
|
||||
wp = frp->fr_win;
|
||||
if (wp->w_hsep_height == 0) {
|
||||
if (wp->w_height > 0) { // don't make it negative
|
||||
wp->w_height++;
|
||||
}
|
||||
wp->w_hsep_height = 1;
|
||||
}
|
||||
} else if (frp->fr_layout == FR_ROW) {
|
||||
// Handle all the frames in the row.
|
||||
FOR_ALL_FRAMES(frp, frp->fr_child) {
|
||||
frame_add_hsep(frp);
|
||||
}
|
||||
} else {
|
||||
assert(frp->fr_layout == FR_COL);
|
||||
// Only need to handle the last frame in the column.
|
||||
frp = frp->fr_child;
|
||||
while (frp->fr_next != NULL) {
|
||||
frp = frp->fr_next;
|
||||
}
|
||||
frame_add_hsep(frp);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Set frame width from the window it contains.
|
||||
*/
|
||||
@ -3534,7 +3630,7 @@ static void frame_fix_width(win_T *wp)
|
||||
static void frame_fix_height(win_T *wp)
|
||||
FUNC_ATTR_NONNULL_ALL
|
||||
{
|
||||
wp->w_frame->fr_height = wp->w_height + wp->w_status_height;
|
||||
wp->w_frame->fr_height = wp->w_height + wp->w_hsep_height + wp->w_status_height;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -3552,10 +3648,11 @@ static int frame_minheight(frame_T *topfrp, win_T *next_curwin)
|
||||
|
||||
if (topfrp->fr_win != NULL) {
|
||||
if (topfrp->fr_win == next_curwin) {
|
||||
m = p_wh + topfrp->fr_win->w_status_height;
|
||||
m = p_wh + topfrp->fr_win->w_hsep_height + topfrp->fr_win->w_status_height;
|
||||
} else {
|
||||
// window: minimal height of the window plus status line
|
||||
m = p_wmh + topfrp->fr_win->w_status_height;
|
||||
// window: minimal height of the window plus separator column or status line
|
||||
// depending on whether global statusline is enabled
|
||||
m = p_wmh + topfrp->fr_win->w_hsep_height + topfrp->fr_win->w_status_height;
|
||||
if (topfrp->fr_win == curwin && next_curwin == NULL) {
|
||||
// Current window is minimal one line high.
|
||||
if (p_wmh == 0) {
|
||||
@ -3784,7 +3881,7 @@ static int win_alloc_firstwin(win_T *oldwin)
|
||||
new_frame(curwin);
|
||||
topframe = curwin->w_frame;
|
||||
topframe->fr_width = Columns;
|
||||
topframe->fr_height = Rows - p_ch;
|
||||
topframe->fr_height = Rows - p_ch - global_stl_height();
|
||||
|
||||
return OK;
|
||||
}
|
||||
@ -5200,11 +5297,8 @@ void win_size_restore(garray_T *gap)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Update the position for all windows, using the width and height of the
|
||||
* frames.
|
||||
* Returns the row just after the last window.
|
||||
*/
|
||||
// Update the position for all windows, using the width and height of the frames.
|
||||
// Returns the row just after the last window and global statusline (if there is one).
|
||||
int win_comp_pos(void)
|
||||
{
|
||||
int row = tabline_height();
|
||||
@ -5219,7 +5313,7 @@ int win_comp_pos(void)
|
||||
}
|
||||
}
|
||||
|
||||
return row;
|
||||
return row + global_stl_height();
|
||||
}
|
||||
|
||||
void win_reconfig_floats(void)
|
||||
@ -5253,7 +5347,7 @@ static void frame_comp_pos(frame_T *topfrp, int *row, int *col)
|
||||
wp->w_redr_status = true;
|
||||
wp->w_pos_changed = true;
|
||||
}
|
||||
const int h = wp->w_height + wp->w_status_height;
|
||||
const int h = wp->w_height + wp->w_hsep_height + wp->w_status_height;
|
||||
*row += h > topfrp->fr_height ? topfrp->fr_height : h;
|
||||
*col += wp->w_width + wp->w_vsep_width;
|
||||
} else {
|
||||
@ -5302,7 +5396,7 @@ void win_setheight_win(int height, win_T *win)
|
||||
win_config_float(win, win->w_float_config);
|
||||
redraw_later(win, NOT_VALID);
|
||||
} else {
|
||||
frame_setheight(win->w_frame, height + win->w_status_height);
|
||||
frame_setheight(win->w_frame, height + win->w_hsep_height + win->w_status_height);
|
||||
|
||||
// recompute the window positions
|
||||
int row = win_comp_pos();
|
||||
@ -5393,8 +5487,8 @@ static void frame_setheight(frame_T *curfrp, int height)
|
||||
room_cmdline = 0;
|
||||
} else {
|
||||
win_T *wp = lastwin_nofloating();
|
||||
room_cmdline = Rows - p_ch
|
||||
- (wp->w_winrow + wp->w_height + wp->w_status_height);
|
||||
room_cmdline = Rows - p_ch - global_stl_height()
|
||||
- (wp->w_winrow + wp->w_height + wp->w_hsep_height + wp->w_status_height);
|
||||
if (room_cmdline < 0) {
|
||||
room_cmdline = 0;
|
||||
}
|
||||
@ -5756,7 +5850,7 @@ void win_drag_status_line(win_T *dragwin, int offset)
|
||||
} else { // drag down
|
||||
up = false;
|
||||
// Only dragging the last status line can reduce p_ch.
|
||||
room = Rows - cmdline_row;
|
||||
room = Rows - cmdline_row - global_stl_height();
|
||||
if (curfr->fr_next == NULL) {
|
||||
room -= 1;
|
||||
} else {
|
||||
@ -6397,32 +6491,26 @@ char_u *file_name_in_line(char_u *line, int col, int options, long count, char_u
|
||||
return find_file_name_in_path(ptr, len, options, count, rel_fname);
|
||||
}
|
||||
|
||||
/// Add or remove a status line for the bottom window(s), according to the
|
||||
/// Add or remove a status line from window(s), according to the
|
||||
/// value of 'laststatus'.
|
||||
///
|
||||
/// @param morewin pretend there are two or more windows if true.
|
||||
void last_status(bool morewin)
|
||||
{
|
||||
// Don't make a difference between horizontal or vertical split.
|
||||
last_status_rec(topframe, (p_ls == 2
|
||||
|| (p_ls == 1 && (morewin || !one_window()))));
|
||||
last_status_rec(topframe, (p_ls == 2 || (p_ls == 1 && (morewin || !one_window()))),
|
||||
global_stl_height() > 0);
|
||||
}
|
||||
|
||||
static void last_status_rec(frame_T *fr, bool statusline)
|
||||
// Look for resizable frames and take lines from them to make room for the statusline
|
||||
static void resize_frame_for_status(frame_T *fr, int resize_amount)
|
||||
{
|
||||
frame_T *fp;
|
||||
win_T *wp;
|
||||
|
||||
if (fr->fr_layout == FR_LEAF) {
|
||||
wp = fr->fr_win;
|
||||
if (wp->w_status_height != 0 && !statusline) {
|
||||
// remove status line
|
||||
win_new_height(wp, wp->w_height + 1);
|
||||
wp->w_status_height = 0;
|
||||
comp_col();
|
||||
} else if (wp->w_status_height == 0 && statusline) {
|
||||
// Find a frame to take a line from.
|
||||
fp = fr;
|
||||
frame_T *fp = fr;
|
||||
win_T *wp = fr->fr_win;
|
||||
int n;
|
||||
|
||||
while (resize_amount > 0) {
|
||||
while (fp->fr_height <= frame_minheight(fp, NULL)) {
|
||||
if (fp == topframe) {
|
||||
emsg(_(e_noroom));
|
||||
@ -6436,33 +6524,71 @@ static void last_status_rec(frame_T *fr, bool statusline)
|
||||
fp = fp->fr_parent;
|
||||
}
|
||||
}
|
||||
wp->w_status_height = 1;
|
||||
n = MIN(fp->fr_height - frame_minheight(fp, NULL), resize_amount);
|
||||
resize_amount -= n;
|
||||
|
||||
if (fp != fr) {
|
||||
frame_new_height(fp, fp->fr_height - 1, false, false);
|
||||
frame_new_height(fp, fp->fr_height - n, false, false);
|
||||
frame_fix_height(wp);
|
||||
(void)win_comp_pos();
|
||||
} else {
|
||||
win_new_height(wp, wp->w_height - 1);
|
||||
win_new_height(wp, wp->w_height - n);
|
||||
}
|
||||
comp_col();
|
||||
redraw_all_later(SOME_VALID);
|
||||
}
|
||||
} else if (fr->fr_layout == FR_ROW) {
|
||||
// vertically split windows, set status line for each one
|
||||
FOR_ALL_FRAMES(fp, fr->fr_child) {
|
||||
last_status_rec(fp, statusline);
|
||||
}
|
||||
} else {
|
||||
// horizontally split window, set status line for last one
|
||||
for (fp = fr->fr_child; fp->fr_next != NULL; fp = fp->fr_next) {
|
||||
}
|
||||
last_status_rec(fp, statusline);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the number of lines used by the tab page line.
|
||||
*/
|
||||
static void last_status_rec(frame_T *fr, bool statusline, bool is_stl_global)
|
||||
{
|
||||
frame_T *fp;
|
||||
win_T *wp;
|
||||
|
||||
if (fr->fr_layout == FR_LEAF) {
|
||||
wp = fr->fr_win;
|
||||
bool is_last = is_bottom_win(wp);
|
||||
|
||||
if (is_last) {
|
||||
if (wp->w_status_height != 0 && (!statusline || is_stl_global)) {
|
||||
// Remove status line
|
||||
wp->w_status_height = 0;
|
||||
win_new_height(wp, wp->w_height + STATUS_HEIGHT);
|
||||
comp_col();
|
||||
} else if (wp->w_status_height == 0 && !is_stl_global && statusline) {
|
||||
// Add statusline to window if needed
|
||||
wp->w_status_height = STATUS_HEIGHT;
|
||||
resize_frame_for_status(fr, STATUS_HEIGHT);
|
||||
comp_col();
|
||||
}
|
||||
} else if (wp->w_status_height != 0 && is_stl_global) {
|
||||
// If statusline is global and the window has a statusline, replace it with a horizontal
|
||||
// separator
|
||||
if (STATUS_HEIGHT - 1 != 0) {
|
||||
win_new_height(wp, wp->w_height + STATUS_HEIGHT - 1);
|
||||
}
|
||||
wp->w_status_height = 0;
|
||||
wp->w_hsep_height = 1;
|
||||
comp_col();
|
||||
} else if (wp->w_status_height == 0 && !is_stl_global) {
|
||||
// If statusline isn't global and the window doesn't have a statusline, re-add it
|
||||
wp->w_status_height = STATUS_HEIGHT;
|
||||
wp->w_hsep_height = 0;
|
||||
resize_frame_for_status(fr, STATUS_HEIGHT - 1);
|
||||
comp_col();
|
||||
}
|
||||
redraw_all_later(SOME_VALID);
|
||||
} else if (fr->fr_layout == FR_COL) {
|
||||
// For a column frame, recursively call this function for all child frames
|
||||
FOR_ALL_FRAMES(fp, fr->fr_child) {
|
||||
last_status_rec(fp, statusline, is_stl_global);
|
||||
}
|
||||
} else {
|
||||
// For a row frame, recursively call this function for all child frames
|
||||
FOR_ALL_FRAMES(fp, fr->fr_child) {
|
||||
last_status_rec(fp, statusline, is_stl_global);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Return the number of lines used by the tab page line.
|
||||
int tabline_height(void)
|
||||
{
|
||||
if (ui_has(kUITabline)) {
|
||||
@ -6478,10 +6604,14 @@ int tabline_height(void)
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the minimal number of rows that is needed on the screen to display
|
||||
* the current number of windows.
|
||||
*/
|
||||
/// Return the number of lines used by the global statusline
|
||||
int global_stl_height(void)
|
||||
{
|
||||
return (p_ls == 3) ? STATUS_HEIGHT : 0;
|
||||
}
|
||||
|
||||
/// Return the minimal number of rows that is needed on the screen to display
|
||||
/// the current number of windows.
|
||||
int min_rows(void)
|
||||
{
|
||||
if (firstwin == NULL) { // not initialized yet
|
||||
@ -6495,7 +6625,7 @@ int min_rows(void)
|
||||
total = n;
|
||||
}
|
||||
}
|
||||
total += tabline_height();
|
||||
total += tabline_height() + global_stl_height();
|
||||
total += 1; // count the room for the command line
|
||||
return total;
|
||||
}
|
||||
|
@ -212,10 +212,10 @@ describe('ui/cursor', function()
|
||||
if m.blinkwait then m.blinkwait = 700 end
|
||||
end
|
||||
if m.hl_id then
|
||||
m.hl_id = 60
|
||||
m.hl_id = 61
|
||||
m.attr = {background = Screen.colors.DarkGray}
|
||||
end
|
||||
if m.id_lm then m.id_lm = 61 end
|
||||
if m.id_lm then m.id_lm = 62 end
|
||||
end
|
||||
|
||||
-- Assert the new expectation.
|
||||
|
233
test/functional/ui/global_statusline_spec.lua
Normal file
233
test/functional/ui/global_statusline_spec.lua
Normal file
@ -0,0 +1,233 @@
|
||||
local helpers = require('test.functional.helpers')(after_each)
|
||||
local Screen = require('test.functional.ui.screen')
|
||||
local clear, command, feed = helpers.clear, helpers.command, helpers.feed
|
||||
|
||||
describe('global statusline', function()
|
||||
local screen
|
||||
|
||||
before_each(function()
|
||||
clear()
|
||||
screen = Screen.new(60, 16)
|
||||
screen:attach()
|
||||
command('set laststatus=3')
|
||||
command('set ruler')
|
||||
end)
|
||||
|
||||
it('works', function()
|
||||
screen:expect{grid=[[
|
||||
^ |
|
||||
{1:~ }|
|
||||
{1:~ }|
|
||||
{1:~ }|
|
||||
{1:~ }|
|
||||
{1:~ }|
|
||||
{1:~ }|
|
||||
{1:~ }|
|
||||
{1:~ }|
|
||||
{1:~ }|
|
||||
{1:~ }|
|
||||
{1:~ }|
|
||||
{1:~ }|
|
||||
{1:~ }|
|
||||
{2:[No Name] 0,0-1 All}|
|
||||
|
|
||||
]], attr_ids={
|
||||
[1] = {bold = true, foreground = Screen.colors.Blue1};
|
||||
[2] = {bold = true, reverse = true};
|
||||
}}
|
||||
|
||||
feed('i<CR><CR>')
|
||||
screen:expect{grid=[[
|
||||
|
|
||||
|
|
||||
^ |
|
||||
{1:~ }|
|
||||
{1:~ }|
|
||||
{1:~ }|
|
||||
{1:~ }|
|
||||
{1:~ }|
|
||||
{1:~ }|
|
||||
{1:~ }|
|
||||
{1:~ }|
|
||||
{1:~ }|
|
||||
{1:~ }|
|
||||
{1:~ }|
|
||||
{2:[No Name] [+] 3,1 All}|
|
||||
{3:-- INSERT --} |
|
||||
]], attr_ids={
|
||||
[1] = {bold = true, foreground = Screen.colors.Blue};
|
||||
[2] = {bold = true, reverse = true};
|
||||
[3] = {bold = true};
|
||||
}}
|
||||
end)
|
||||
|
||||
it('works with splits', function()
|
||||
command('vsplit | split | vsplit | vsplit | wincmd l | split | 2wincmd l | split')
|
||||
screen:expect{grid=[[
|
||||
{1:│} {1:│} {1:│}^ |
|
||||
{2:~ }{1:│}{2:~ }{1:│}{2:~}{1:│}{2:~ }|
|
||||
{2:~ }{1:│}{2:~ }{1:│}{2:~}{1:│}{2:~ }|
|
||||
{2:~ }{1:│}{2:~ }{1:│}{2:~}{1:│}{2:~ }|
|
||||
{2:~ }{1:├────────────────┤}{2:~}{1:│}{2:~ }|
|
||||
{2:~ }{1:│} {1:│}{2:~}{1:│}{2:~ }|
|
||||
{2:~ }{1:│}{2:~ }{1:│}{2:~}{1:│}{2:~ }|
|
||||
{2:~ }{1:│}{2:~ }{1:│}{2:~}{1:├────────────────────}|
|
||||
{2:~ }{1:│}{2:~ }{1:│}{2:~}{1:│} |
|
||||
{1:────────────────────┴────────────────┴─┤}{2:~ }|
|
||||
{1:│}{2:~ }|
|
||||
{2:~ }{1:│}{2:~ }|
|
||||
{2:~ }{1:│}{2:~ }|
|
||||
{2:~ }{1:│}{2:~ }|
|
||||
{3:[No Name] 0,0-1 All}|
|
||||
|
|
||||
]], attr_ids={
|
||||
[1] = {reverse = true};
|
||||
[2] = {bold = true, foreground = Screen.colors.Blue1};
|
||||
[3] = {bold = true, reverse = true};
|
||||
}}
|
||||
end)
|
||||
|
||||
it('works when switching between values of laststatus', function()
|
||||
command('set laststatus=1')
|
||||
screen:expect{grid=[[
|
||||
^ |
|
||||
{1:~ }|
|
||||
{1:~ }|
|
||||
{1:~ }|
|
||||
{1:~ }|
|
||||
{1:~ }|
|
||||
{1:~ }|
|
||||
{1:~ }|
|
||||
{1:~ }|
|
||||
{1:~ }|
|
||||
{1:~ }|
|
||||
{1:~ }|
|
||||
{1:~ }|
|
||||
{1:~ }|
|
||||
{1:~ }|
|
||||
0,0-1 All |
|
||||
]], attr_ids={
|
||||
[1] = {foreground = Screen.colors.Blue, bold = true};
|
||||
}}
|
||||
|
||||
command('set laststatus=3')
|
||||
screen:expect{grid=[[
|
||||
^ |
|
||||
{1:~ }|
|
||||
{1:~ }|
|
||||
{1:~ }|
|
||||
{1:~ }|
|
||||
{1:~ }|
|
||||
{1:~ }|
|
||||
{1:~ }|
|
||||
{1:~ }|
|
||||
{1:~ }|
|
||||
{1:~ }|
|
||||
{1:~ }|
|
||||
{1:~ }|
|
||||
{1:~ }|
|
||||
{2:[No Name] 0,0-1 All}|
|
||||
|
|
||||
]], attr_ids={
|
||||
[1] = {foreground = Screen.colors.Blue, bold = true};
|
||||
[2] = {reverse = true, bold = true};
|
||||
}}
|
||||
|
||||
command('vsplit | split | vsplit | vsplit | wincmd l | split | 2wincmd l | split')
|
||||
command('set laststatus=2')
|
||||
screen:expect{grid=[[
|
||||
{1:│} {1:│} {1:│}^ |
|
||||
{2:~ }{1:│}{2:~ }{1:│}{2:~}{1:│}{2:~ }|
|
||||
{2:~ }{1:│}{2:~ }{1:│}{2:~}{1:│}{2:~ }|
|
||||
{2:~ }{1:│}{2:~ }{1:│}{2:~}{1:│}{2:~ }|
|
||||
{2:~ }{1:│< Name] 0,0-1 │}{2:~}{1:│}{2:~ }|
|
||||
{2:~ }{1:│} {1:│}{2:~}{1:│}{2:~ }|
|
||||
{2:~ }{1:│}{2:~ }{1:│}{2:~}{1:│}{2:~ }|
|
||||
{2:~ }{1:│}{2:~ }{1:│}{2:~}{1:│}{3:<No Name] 0,0-1 All}|
|
||||
{2:~ }{1:│}{2:~ }{1:│}{2:~}{1:│} |
|
||||
{1:<No Name] 0,0-1 All < Name] 0,0-1 <│}{2:~ }|
|
||||
{1:│}{2:~ }|
|
||||
{2:~ }{1:│}{2:~ }|
|
||||
{2:~ }{1:│}{2:~ }|
|
||||
{2:~ }{1:│}{2:~ }|
|
||||
{1:[No Name] 0,0-1 All <No Name] 0,0-1 All}|
|
||||
|
|
||||
]], attr_ids={
|
||||
[1] = {reverse = true};
|
||||
[2] = {foreground = Screen.colors.Blue, bold = true};
|
||||
[3] = {reverse = true, bold = true};
|
||||
}}
|
||||
|
||||
command('set laststatus=3')
|
||||
screen:expect{grid=[[
|
||||
{1:│} {1:│} {1:│}^ |
|
||||
{2:~ }{1:│}{2:~ }{1:│}{2:~}{1:│}{2:~ }|
|
||||
{2:~ }{1:│}{2:~ }{1:│}{2:~}{1:│}{2:~ }|
|
||||
{2:~ }{1:│}{2:~ }{1:│}{2:~}{1:│}{2:~ }|
|
||||
{2:~ }{1:├────────────────┤}{2:~}{1:│}{2:~ }|
|
||||
{2:~ }{1:│} {1:│}{2:~}{1:│}{2:~ }|
|
||||
{2:~ }{1:│}{2:~ }{1:│}{2:~}{1:│}{2:~ }|
|
||||
{2:~ }{1:│}{2:~ }{1:│}{2:~}{1:├────────────────────}|
|
||||
{2:~ }{1:│}{2:~ }{1:│}{2:~}{1:│} |
|
||||
{1:────────────────────┴────────────────┴─┤}{2:~ }|
|
||||
{1:│}{2:~ }|
|
||||
{2:~ }{1:│}{2:~ }|
|
||||
{2:~ }{1:│}{2:~ }|
|
||||
{2:~ }{1:│}{2:~ }|
|
||||
{3:[No Name] 0,0-1 All}|
|
||||
|
|
||||
]], attr_ids={
|
||||
[1] = {reverse = true};
|
||||
[2] = {foreground = Screen.colors.Blue, bold = true};
|
||||
[3] = {reverse = true, bold = true};
|
||||
}}
|
||||
|
||||
command('set laststatus=0')
|
||||
screen:expect{grid=[[
|
||||
{1:│} {1:│} {1:│}^ |
|
||||
{2:~ }{1:│}{2:~ }{1:│}{2:~}{1:│}{2:~ }|
|
||||
{2:~ }{1:│}{2:~ }{1:│}{2:~}{1:│}{2:~ }|
|
||||
{2:~ }{1:│}{2:~ }{1:│}{2:~}{1:│}{2:~ }|
|
||||
{2:~ }{1:│< Name] 0,0-1 │}{2:~}{1:│}{2:~ }|
|
||||
{2:~ }{1:│} {1:│}{2:~}{1:│}{2:~ }|
|
||||
{2:~ }{1:│}{2:~ }{1:│}{2:~}{1:│}{2:~ }|
|
||||
{2:~ }{1:│}{2:~ }{1:│}{2:~}{1:│}{3:<No Name] 0,0-1 All}|
|
||||
{2:~ }{1:│}{2:~ }{1:│}{2:~}{1:│} |
|
||||
{1:<No Name] 0,0-1 All < Name] 0,0-1 <│}{2:~ }|
|
||||
{1:│}{2:~ }|
|
||||
{2:~ }{1:│}{2:~ }|
|
||||
{2:~ }{1:│}{2:~ }|
|
||||
{2:~ }{1:│}{2:~ }|
|
||||
{2:~ }{1:│}{2:~ }|
|
||||
0,0-1 All |
|
||||
]], attr_ids={
|
||||
[1] = {reverse = true};
|
||||
[2] = {foreground = Screen.colors.Blue, bold = true};
|
||||
[3] = {reverse = true, bold = true};
|
||||
}}
|
||||
|
||||
command('set laststatus=3')
|
||||
screen:expect{grid=[[
|
||||
{1:│} {1:│} {1:│}^ |
|
||||
{2:~ }{1:│}{2:~ }{1:│}{2:~}{1:│}{2:~ }|
|
||||
{2:~ }{1:│}{2:~ }{1:│}{2:~}{1:│}{2:~ }|
|
||||
{2:~ }{1:│}{2:~ }{1:│}{2:~}{1:│}{2:~ }|
|
||||
{2:~ }{1:├────────────────┤}{2:~}{1:│}{2:~ }|
|
||||
{2:~ }{1:│} {1:│}{2:~}{1:│}{2:~ }|
|
||||
{2:~ }{1:│}{2:~ }{1:│}{2:~}{1:│}{2:~ }|
|
||||
{2:~ }{1:│}{2:~ }{1:│}{2:~}{1:├────────────────────}|
|
||||
{2:~ }{1:│}{2:~ }{1:│}{2:~}{1:│} |
|
||||
{1:────────────────────┴────────────────┴─┤}{2:~ }|
|
||||
{1:│}{2:~ }|
|
||||
{2:~ }{1:│}{2:~ }|
|
||||
{2:~ }{1:│}{2:~ }|
|
||||
{2:~ }{1:│}{2:~ }|
|
||||
{3:[No Name] 0,0-1 All}|
|
||||
|
|
||||
]], attr_ids={
|
||||
[1] = {reverse = true};
|
||||
[2] = {foreground = Screen.colors.Blue, bold = true};
|
||||
[3] = {reverse = true, bold = true};
|
||||
}}
|
||||
end)
|
||||
end)
|
@ -59,7 +59,7 @@ describe('ext_hlstate detailed highlights', function()
|
||||
|
||||
it('work with cleared UI highlights', function()
|
||||
screen:set_default_attr_ids({
|
||||
[1] = {{}, {{hi_name = "VertSplit", ui_name = "VertSplit", kind = "ui"}}},
|
||||
[1] = {{}, {{hi_name = "VertSplit", ui_name = "WinSeparator", kind = "ui"}}},
|
||||
[2] = {{bold = true, foreground = Screen.colors.Blue1},
|
||||
{{hi_name = "NonText", ui_name = "EndOfBuffer", kind = "ui"}}},
|
||||
[3] = {{bold = true, reverse = true},
|
||||
|
@ -48,6 +48,7 @@ local predefined_hl_defs = {
|
||||
TermCursor=true,
|
||||
VertSplit=true,
|
||||
WildMenu=true,
|
||||
WinSeparator=true,
|
||||
EndOfBuffer=true,
|
||||
QuickFixLine=true,
|
||||
Substitute=true,
|
||||
|
Loading…
Reference in New Issue
Block a user