Skip to content

Instantly share code, notes, and snippets.

@h-east
Last active January 19, 2024 12:52
Show Gist options
  • Save h-east/3158492 to your computer and use it in GitHub Desktop.
Save h-east/3158492 to your computer and use it in GitHub Desktop.
Vim multi-statusline patch
diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt
index 2e58c854e..2220cfb2c 100644
--- a/runtime/doc/eval.txt
+++ b/runtime/doc/eval.txt
@@ -9485,6 +9485,7 @@ multi_byte Compiled with support for 'encoding'
multi_byte_encoding 'encoding' is set to a multi-byte encoding.
multi_byte_ime Compiled with support for IME input method.
multi_lang Compiled with support for multiple languages.
+multi_statusline Compiled with 'statuslineheight' support.
mzscheme Compiled with MzScheme interface |mzscheme|.
netbeans_enabled Compiled with support for |netbeans| and connected.
netbeans_intg Compiled with support for |netbeans|.
diff --git a/runtime/doc/options.txt b/runtime/doc/options.txt
index 0db2d465f..932db3cfa 100644
--- a/runtime/doc/options.txt
+++ b/runtime/doc/options.txt
@@ -7553,6 +7553,9 @@ A jump table for the options with a short description can be found at |Q_op|.
The difference between User{N} and StatusLine will be applied
to StatusLineNC for the statusline of non-current windows.
The number N must be between 1 and 9. See |hl-User1..9|
+ @ - To the next line to be set.
+ This item available when compiled with the |+multi_statusline|
+ feature.
When displaying a flag, Vim removes the leading comma, if any, when
that flag comes right after plaintext. This will make a nice display
@@ -7609,6 +7612,16 @@ A jump table for the options with a short description can be found at |Q_op|.
: if exists(a:var) | return a:val | else | return '' | endif
:endfunction
<
+
+ *'statuslineheight'* *'stlh'*
+'statuslineheight' 'stlh' number (default 1)
+ global or local to window |global-local|
+ {not in Vi}
+ {not available when compiled without the
+ |+multi_statusline| feature}
+ Number of screen lines to use for the status line.
+ Also see 'statusline' and |status-line|.
+
*'suffixes'* *'su'*
'suffixes' 'su' string (default ".bak,~,.o,.h,.info,.swp,.obj")
global
diff --git a/src/buffer.c b/src/buffer.c
index cbccc7026..5b33aa5fe 100644
--- a/src/buffer.c
+++ b/src/buffer.c
@@ -3623,7 +3623,7 @@ maketitle(void)
# endif
called_emsg = FALSE;
build_stl_str_hl(curwin, title_str, sizeof(buf),
- p_titlestring, use_sandbox,
+ p_titlestring, 0, use_sandbox,
0, maxlen, NULL, NULL);
if (called_emsg)
set_string_option_direct((char_u *)"titlestring", -1,
@@ -3756,8 +3756,8 @@ maketitle(void)
# endif
called_emsg = FALSE;
build_stl_str_hl(curwin, icon_str, sizeof(buf),
- p_iconstring, use_sandbox,
- 0, 0, NULL, NULL);
+ p_iconstring, 0, use_sandbox,
+ 0, 0, NULL, NULL);
if (called_emsg)
set_string_option_direct((char_u *)"iconstring", -1,
(char_u *)"", OPT_FREE, SID_ERROR);
@@ -3864,6 +3864,7 @@ build_stl_str_hl(
char_u *out, /* buffer to write into != NameBuff */
size_t outlen, /* length of out[] */
char_u *fmt,
+ int stl_row UNUSED, /* statusline row (0~) */
int use_sandbox UNUSED, /* "fmt" was set insecurely, use sandbox */
int fillchar,
int maxwidth,
@@ -3922,6 +3923,9 @@ build_stl_str_hl(
struct stl_hlrec *sp;
int save_must_redraw = must_redraw;
int save_redr_type = curwin->w_redr_type;
+#ifdef FEAT_STL_MULTI
+ int target_stl_row = 0;
+#endif
#ifdef FEAT_EVAL
/*
@@ -3986,7 +3990,16 @@ build_stl_str_hl(
* Handle up to the next '%' or the end.
*/
while (*s != NUL && *s != '%' && p + 1 < out + outlen)
+ {
+#ifdef FEAT_STL_MULTI
+ if (target_stl_row == stl_row)
+ *p++ = *s++;
+ else
+ s++;
+#else
*p++ = *s++;
+#endif
+ }
if (*s == NUL || p + 1 >= out + outlen)
break;
@@ -3996,6 +4009,19 @@ build_stl_str_hl(
s++;
if (*s == NUL) /* ignore trailing % */
break;
+#ifdef FEAT_STL_MULTI
+ if (*s == STL_NEXT_STATUSLINE)
+ {
+ s++;
+ target_stl_row++;
+ if (target_stl_row > stl_row)
+ break;
+ else
+ continue;
+ }
+ if (target_stl_row < stl_row)
+ continue;
+#endif
if (*s == '%')
{
if (p + 1 >= out + outlen)
diff --git a/src/evalfunc.c b/src/evalfunc.c
index 82ea05af3..20035655e 100644
--- a/src/evalfunc.c
+++ b/src/evalfunc.c
@@ -6318,6 +6318,9 @@ f_has(typval_T *argvars, typval_T *rettv)
#ifdef FEAT_MULTI_LANG
"multi_lang",
#endif
+#ifdef FEAT_STL_MULTI
+ "multi_statusline",
+#endif
#ifdef FEAT_MZSCHEME
#ifndef DYNAMIC_MZSCHEME
"mzscheme",
diff --git a/src/ex_docmd.c b/src/ex_docmd.c
index d00ca5689..3113ab67f 100644
--- a/src/ex_docmd.c
+++ b/src/ex_docmd.c
@@ -8428,6 +8428,9 @@ ex_splitview(exarg_T *eap)
else
do_check_scrollbind(FALSE);
do_exedit(eap, old_curwin);
+#ifdef FEAT_STL_MULTI
+ frame_change_statusline_height();
+#endif
}
# ifdef FEAT_BROWSE
diff --git a/src/feature.h b/src/feature.h
index 6ae3ac23f..c1466d3dc 100644
--- a/src/feature.h
+++ b/src/feature.h
@@ -439,6 +439,7 @@
* +title 'title' and 'icon' options
* +statusline 'statusline', 'rulerformat' and special format of
* 'titlestring' and 'iconstring' options.
+ * +multi_statusline 'statuslineheight' options
* +byte_offset '%o' in 'statusline' and builtin functions line2byte()
* and byte2line().
* Note: Required for Macintosh.
@@ -449,6 +450,7 @@
#ifdef FEAT_NORMAL
# define FEAT_STL_OPT
+# define FEAT_STL_MULTI
# ifndef FEAT_CMDL_INFO
# define FEAT_CMDL_INFO /* 'ruler' is required for 'statusline' */
# endif
diff --git a/src/gui.c b/src/gui.c
index 1341d505d..c1a2cee3e 100644
--- a/src/gui.c
+++ b/src/gui.c
@@ -3765,7 +3765,7 @@ get_tabline_label(
curbuf = curwin->w_buffer;
/* Can't use NameBuff directly, build_stl_str_hl() uses it. */
- build_stl_str_hl(curwin, res, MAXPATHL, *opt, use_sandbox,
+ build_stl_str_hl(curwin, res, MAXPATHL, *opt, 0, use_sandbox,
0, (int)Columns, NULL, NULL);
STRCPY(NameBuff, res);
@@ -4962,13 +4962,15 @@ xy2win(int x UNUSED, int y UNUSED)
else
update_mouseshape(SHAPE_IDX_MORE);
}
- else if (row > wp->w_height) /* below status line */
+ else if (row >= wp->w_height + wp->w_status_height) // below status line
update_mouseshape(SHAPE_IDX_CLINE);
else if (!(State & CMDLINE) && wp->w_vsep_width > 0 && col == wp->w_width
- && (row != wp->w_height || !stl_connected(wp)) && msg_scrolled == 0)
+ && (!(row >= wp->w_height && row < wp->w_height
+ + wp->w_status_height) || !stl_connected(wp)) && msg_scrolled == 0)
update_mouseshape(SHAPE_IDX_VSEP);
else if (!(State & CMDLINE) && wp->w_status_height > 0
- && row == wp->w_height && msg_scrolled == 0)
+ && row >= wp->w_height && row < wp->w_height + wp->w_status_height
+ && msg_scrolled == 0)
update_mouseshape(SHAPE_IDX_STATUS);
else
update_mouseshape(-2);
diff --git a/src/hardcopy.c b/src/hardcopy.c
index 486ae7d3d..761958533 100644
--- a/src/hardcopy.c
+++ b/src/hardcopy.c
@@ -492,7 +492,7 @@ prt_header(
use_sandbox = was_set_insecurely((char_u *)"printheader", 0);
# endif
build_stl_str_hl(curwin, tbuf, (size_t)(width + IOSIZE),
- p_header, use_sandbox,
+ p_header, 0, use_sandbox,
' ', width, NULL, NULL);
/* Reset line numbers */
diff --git a/src/misc1.c b/src/misc1.c
index 820f8f994..11f0bcc1c 100644
--- a/src/misc1.c
+++ b/src/misc1.c
@@ -3383,7 +3383,7 @@ check_status(buf_T *buf)
win_T *wp;
FOR_ALL_WINDOWS(wp)
- if (wp->w_buffer == buf && wp->w_status_height)
+ if (wp->w_buffer == buf && wp->w_status_height > 0)
{
wp->w_redr_status = TRUE;
if (must_redraw < VALID)
diff --git a/src/option.c b/src/option.c
index f238abe84..ae61d22ed 100644
--- a/src/option.c
+++ b/src/option.c
@@ -244,6 +244,9 @@
#ifdef FEAT_STL_OPT
# define PV_STL OPT_BOTH(OPT_WIN(WV_STL))
#endif
+#ifdef FEAT_STL_MULTI
+# define PV_STLH OPT_BOTH(OPT_WIN(WV_STLH))
+#endif
#define PV_UL OPT_BOTH(OPT_BUF(BV_UL))
# define PV_WFH OPT_WIN(WV_WFH)
# define PV_WFW OPT_WIN(WV_WFW)
@@ -2646,6 +2649,13 @@ static struct vimoption options[] =
(char_u *)NULL, PV_NONE,
#endif
{(char_u *)"", (char_u *)0L} SCTX_INIT},
+ {"statuslineheight" ,"stlh", P_NUM|P_VI_DEF|P_RALL,
+#ifdef FEAT_STL_MULTI
+ (char_u *)&p_stlh, PV_STLH,
+#else
+ (char_u *)NULL, PV_NONE,
+#endif
+ {(char_u *)1L, (char_u *)1L} SCTX_INIT},
{"suffixes", "su", P_STRING|P_VI_DEF|P_ONECOMMA|P_NODUP,
(char_u *)&p_su, PV_NONE,
{(char_u *)".bak,~,.o,.h,.info,.swp,.obj",
@@ -3585,6 +3595,10 @@ set_init_1(int clean_arg)
curbuf->b_p_ar = -1; /* no local 'autoread' value */
curbuf->b_p_ul = NO_LOCAL_UNDOLEVEL;
check_buf_options(curbuf);
+#ifdef FEAT_STL_MULTI
+ curwin->w_p_stlh = -1; // no local 'statuslineheight' value
+ curwin->w_allbuf_opt.wo_stlh = -1;
+#endif
check_win_options(curwin);
check_options();
@@ -4775,6 +4789,20 @@ do_set(
? VI_DEFAULT : VIM_DEFAULT];
else if (nextchar == '<')
{
+#ifdef FEAT_STL_MULTI
+ // For 'statuslineheight' -1 means to use global
+ // value.
+ if ((long *)varp == &curwin->w_p_stlh)
+ {
+ if (opt_flags != OPT_LOCAL)
+ {
+ curwin->w_p_stlh = -1;
+ varp = (char_u *)&p_stlh;
+ }
+ value = p_stlh;
+ }
+ else
+#endif
/* For 'undolevels' NO_LOCAL_UNDOLEVEL means to
* use the global value. */
if ((long *)varp == &curbuf->b_p_ul
@@ -5852,6 +5880,9 @@ insecure_flag(int opt_idx, int opt_flags)
#ifdef FEAT_STL_OPT
case PV_STL: return &curwin->w_p_stl_flags;
#endif
+#ifdef FEAT_STL_MULTI
+ case PV_STLH: return &curwin->w_p_stlh_flags;
+#endif
#ifdef FEAT_EVAL
# ifdef FEAT_FOLDING
case PV_FDE: return &curwin->w_p_fde_flags;
@@ -7158,7 +7189,7 @@ did_set_string_option(
errmsg = e_invarg;
else
{
- if (curwin->w_status_height)
+ if (curwin->w_status_height > 0)
{
curwin->w_redr_status = TRUE;
redraw_later(VALID);
@@ -8020,7 +8051,11 @@ check_stl_option(char_u *s)
s++;
if (*s != '%' && *s != ')')
++itemcnt;
- if (*s == '%' || *s == STL_TRUNCMARK || *s == STL_MIDDLEMARK)
+ if (*s == '%' || *s == STL_TRUNCMARK || *s == STL_MIDDLEMARK
+#ifdef FEAT_STL_MULTI
+ || *s == STL_NEXT_STATUSLINE
+#endif
+ )
{
s++;
continue;
@@ -9210,6 +9245,45 @@ set_num_option(
command_height();
}
+#ifdef FEAT_STL_MULTI
+ /* when 'statuslineheight' changed, change the status line height */
+ else if (pp == &curwin->w_p_stlh)
+ {
+ if ((opt_flags & (OPT_LOCAL | OPT_GLOBAL)) == 0)
+ {
+ p_stlh = curwin->w_p_stlh;
+ curwin->w_p_stlh = -1;
+ if (p_stlh < 1)
+ {
+ errmsg = e_positive;
+ p_stlh = 1;
+ }
+ }
+ else
+ {
+ if (curwin->w_p_stlh < 1)
+ {
+ errmsg = e_positive;
+ curwin->w_p_stlh = 1;
+ }
+ }
+ fitting_statusline_height_value();
+ frame_change_statusline_height();
+ }
+ else if (pp == &p_stlh)
+ {
+ if (p_stlh < 1)
+ {
+ errmsg = e_positive;
+ p_stlh = 1;
+ }
+ if ((opt_flags & (OPT_LOCAL | OPT_GLOBAL)) == 0)
+ curwin->w_p_stlh = -1;
+ fitting_statusline_height_value();
+ frame_change_statusline_height();
+ }
+#endif
+
/* when 'updatecount' changes from zero to non-zero, open swap files */
else if (pp == &p_uc)
{
@@ -10755,6 +10829,9 @@ get_varp_scope(struct vimoption *p, int opt_flags)
#endif
#ifdef FEAT_STL_OPT
case PV_STL: return (char_u *)&(curwin->w_p_stl);
+#endif
+#ifdef FEAT_STL_MULTI
+ case PV_STLH: return (char_u *)&(curwin->w_p_stlh);
#endif
case PV_UL: return (char_u *)&(curbuf->b_p_ul);
#ifdef FEAT_LISP
@@ -10832,6 +10909,10 @@ get_varp(struct vimoption *p)
#ifdef FEAT_STL_OPT
case PV_STL: return *curwin->w_p_stl != NUL
? (char_u *)&(curwin->w_p_stl) : p->var;
+#endif
+#ifdef FEAT_STL_MULTI
+ case PV_STLH: return curwin->w_p_stlh >= 0
+ ? (char_u *)&(curwin->w_p_stlh) : p->var;
#endif
case PV_UL: return curbuf->b_p_ul != NO_LOCAL_UNDOLEVEL
? (char_u *)&(curbuf->b_p_ul) : p->var;
@@ -11075,6 +11156,9 @@ copy_winopt(winopt_T *from, winopt_T *to)
#endif
#ifdef FEAT_STL_OPT
to->wo_stl = vim_strsave(from->wo_stl);
+#endif
+#ifdef FEAT_STL_MULTI
+ to->wo_stlh = from->wo_stlh;
#endif
to->wo_wrap = from->wo_wrap;
#ifdef FEAT_DIFF
@@ -11212,6 +11296,9 @@ clear_winopt(winopt_T *wop UNUSED)
#ifdef FEAT_STL_OPT
clear_string_option(&wop->wo_stl);
#endif
+#ifdef FEAT_STL_MULTI
+ wop->wo_stlh = -1;
+#endif
#ifdef FEAT_SYN_HL
clear_string_option(&wop->wo_cc);
#endif
diff --git a/src/option.h b/src/option.h
index 5df7f2147..7225041c3 100644
--- a/src/option.h
+++ b/src/option.h
@@ -288,6 +288,9 @@
#define STL_TRUNCMARK '<' /* truncation mark if line is too long*/
#define STL_USER_HL '*' /* highlight from (User)1..9 or 0 */
#define STL_HIGHLIGHT '#' /* highlight name */
+#ifdef FEAT_STL_MULTI
+# define STL_NEXT_STATUSLINE '@' /* next status-line */
+#endif
#define STL_TABPAGENR 'T' /* tab page label nr */
#define STL_TABCLOSENR 'X' /* tab page close nr */
#define STL_ALL ((char_u *) "fFtcvVlLknoObBrRhHmYyWwMqpPaN{#")
@@ -791,6 +794,9 @@ EXTERN int p_ssl; /* 'shellslash' */
#ifdef FEAT_STL_OPT
EXTERN char_u *p_stl; /* 'statusline' */
#endif
+#ifdef FEAT_STL_MULTI
+EXTERN long p_stlh; /* 'statuslineheight' */
+#endif
EXTERN int p_sr; /* 'shiftround' */
EXTERN char_u *p_shm; /* 'shortmess' */
#ifdef FEAT_LINEBREAK
@@ -1189,6 +1195,9 @@ enum
#endif
#ifdef FEAT_STL_OPT
, WV_STL
+#endif
+#ifdef FEAT_STL_MULTI
+ , WV_STLH
#endif
, WV_WFH
, WV_WFW
diff --git a/src/proto/buffer.pro b/src/proto/buffer.pro
index 6820d9734..494678be5 100644
--- a/src/proto/buffer.pro
+++ b/src/proto/buffer.pro
@@ -46,7 +46,7 @@ void col_print(char_u *buf, size_t buflen, int col, int vcol);
void maketitle(void);
void resettitle(void);
void free_titles(void);
-int build_stl_str_hl(win_T *wp, char_u *out, size_t outlen, char_u *fmt, int use_sandbox, int fillchar, int maxwidth, struct stl_hlrec *hltab, struct stl_hlrec *tabtab);
+int build_stl_str_hl(win_T *wp, char_u *out, size_t outlen, char_u *fmt, int stl_row, int use_sandbox, int fillchar, int maxwidth, struct stl_hlrec *hltab, struct stl_hlrec *tabtab);
void get_rel_pos(win_T *wp, char_u *buf, int buflen);
char_u *fix_fname(char_u *fname);
void fname_expand(buf_T *buf, char_u **ffname, char_u **sfname);
diff --git a/src/proto/window.pro b/src/proto/window.pro
index 4527a37f4..d5fb3684f 100644
--- a/src/proto/window.pro
+++ b/src/proto/window.pro
@@ -64,6 +64,9 @@ void win_new_width(win_T *wp, int width);
void win_comp_scroll(win_T *wp);
void command_height(void);
void last_status(int morewin);
+void fitting_statusline_height_value(void);
+void frame_change_statusline_height(void);
+int statusline_height(win_T *wp);
int tabline_height(void);
char_u *grab_file_name(long count, linenr_T *file_lnum);
char_u *file_name_at_cursor(int options, long count, linenr_T *file_lnum);
diff --git a/src/screen.c b/src/screen.c
index 69f755844..86df97eb9 100644
--- a/src/screen.c
+++ b/src/screen.c
@@ -6899,6 +6899,7 @@ win_redr_status(win_T *wp, int ignore_pum UNUSED)
{
int row;
char_u *p;
+ int i;
int len;
int fillchar;
int attr;
@@ -7021,6 +7022,9 @@ win_redr_status(win_T *wp, int ignore_pum UNUSED)
screen_puts(p, row, wp->w_wincol, attr);
screen_fill(row, row + 1, len + wp->w_wincol,
this_ru_col + wp->w_wincol, fillchar, fillchar, attr);
+ for (i = 1; i < wp->w_status_height; i++)
+ screen_fill(row + i, row + 1 + i, wp->w_wincol,
+ this_ru_col + wp->w_wincol, fillchar, fillchar, attr);
if (get_keymap_str(wp, (char_u *)"<%s>", NameBuff, MAXPATHL)
&& (int)(this_ru_col - len) > (int)(STRLEN(NameBuff) + 1))
@@ -7035,14 +7039,15 @@ win_redr_status(win_T *wp, int ignore_pum UNUSED)
/*
* May need to draw the character below the vertical separator.
*/
- if (wp->w_vsep_width != 0 && wp->w_status_height != 0 && redrawing())
+ if (wp->w_vsep_width != 0 && wp->w_status_height > 0 && redrawing())
{
if (stl_connected(wp))
fillchar = fillchar_status(&attr, wp);
else
fillchar = fillchar_vsep(&attr);
- screen_putchar(fillchar, W_WINROW(wp) + wp->w_height, W_ENDCOL(wp),
- attr);
+ for (len=0; len < wp->w_status_height; len++)
+ screen_putchar(fillchar, W_WINROW(wp) + wp->w_height + len,
+ W_ENDCOL(wp), attr);
}
busy = FALSE;
}
@@ -7174,8 +7179,10 @@ win_redr_custom(
int col = 0;
int maxwidth;
int width;
+ int i;
int n;
int len;
+ int stlh_cnt;
int fillchar;
char_u buf[MAXPATHL];
char_u *stl;
@@ -7265,67 +7272,72 @@ win_redr_custom(
ewp = wp == NULL ? curwin : wp;
p_crb_save = ewp->w_p_crb;
ewp->w_p_crb = FALSE;
+ stlh_cnt = stl == p_tal ? 1 : wp->w_status_height;
/* Make a copy, because the statusline may include a function call that
* might change the option value and free the memory. */
stl = vim_strsave(stl);
- width = build_stl_str_hl(ewp, buf, sizeof(buf),
- stl, use_sandbox,
- fillchar, maxwidth, hltab, tabtab);
- vim_free(stl);
- ewp->w_p_crb = p_crb_save;
-
- /* Make all characters printable. */
- p = transstr(buf);
- if (p != NULL)
+ for (i = 0; i < stlh_cnt; i++)
{
- vim_strncpy(buf, p, sizeof(buf) - 1);
- vim_free(p);
- }
+ vim_memset(buf, 0, sizeof(buf));
+ width = build_stl_str_hl(ewp, buf, sizeof(buf),
+ stl, i, use_sandbox,
+ fillchar, maxwidth, hltab, tabtab);
+ ewp->w_p_crb = p_crb_save;
- /* fill up with "fillchar" */
- len = (int)STRLEN(buf);
- while (width < maxwidth && len < (int)sizeof(buf) - 1)
- {
+ /* Make all characters printable. */
+ p = transstr(buf);
+ if (p != NULL)
+ {
+ vim_strncpy(buf, p, sizeof(buf) - 1);
+ vim_free(p);
+ }
+
+ /* fill up with "fillchar" */
+ len = (int)STRLEN(buf);
+ while (width < maxwidth && len < (int)sizeof(buf) - 1)
+ {
#ifdef FEAT_MBYTE
- len += (*mb_char2bytes)(fillchar, buf + len);
+ len += (*mb_char2bytes)(fillchar, buf + len);
#else
- buf[len++] = fillchar;
+ buf[len++] = fillchar;
#endif
- ++width;
- }
- buf[len] = NUL;
+ ++width;
+ }
+ buf[len] = NUL;
- /*
- * Draw each snippet with the specified highlighting.
- */
- curattr = attr;
- p = buf;
- for (n = 0; hltab[n].start != NULL; n++)
- {
- len = (int)(hltab[n].start - p);
- screen_puts_len(p, len, row, col, curattr);
- col += vim_strnsize(p, len);
- p = hltab[n].start;
-
- if (hltab[n].userhl == 0)
- curattr = attr;
- else if (hltab[n].userhl < 0)
- curattr = syn_id2attr(-hltab[n].userhl);
+ /*
+ * Draw each snippet with the specified highlighting.
+ */
+ curattr = attr;
+ p = buf;
+ for (n = 0; hltab[n].start != NULL; n++)
+ {
+ len = (int)(hltab[n].start - p);
+ screen_puts_len(p, len, row, col, curattr);
+ col += vim_strnsize(p, len);
+ p = hltab[n].start;
+
+ if (hltab[n].userhl == 0)
+ curattr = attr;
+ else if (hltab[n].userhl < 0)
+ curattr = syn_id2attr(-hltab[n].userhl);
#ifdef FEAT_TERMINAL
- else if (wp != NULL && wp != curwin && bt_terminal(wp->w_buffer)
- && wp->w_status_height != 0)
- curattr = highlight_stltermnc[hltab[n].userhl - 1];
- else if (wp != NULL && bt_terminal(wp->w_buffer)
- && wp->w_status_height != 0)
- curattr = highlight_stlterm[hltab[n].userhl - 1];
-#endif
- else if (wp != NULL && wp != curwin && wp->w_status_height != 0)
- curattr = highlight_stlnc[hltab[n].userhl - 1];
- else
- curattr = highlight_user[hltab[n].userhl - 1];
+ else if (wp != NULL && wp != curwin && bt_terminal(wp->w_buffer)
+ && wp->w_status_height != 0)
+ curattr = highlight_stltermnc[hltab[n].userhl - 1];
+ else if (wp != NULL && bt_terminal(wp->w_buffer)
+ && wp->w_status_height != 0)
+ curattr = highlight_stlterm[hltab[n].userhl - 1];
+#endif
+ else if (wp != NULL && wp != curwin && wp->w_status_height != 0)
+ curattr = highlight_stlnc[hltab[n].userhl - 1];
+ else
+ curattr = highlight_user[hltab[n].userhl - 1];
+ }
+ screen_puts(p, row + i, col, curattr);
}
- screen_puts(p, row, col, curattr);
+ vim_free(stl);
if (wp == NULL)
{
diff --git a/src/structs.h b/src/structs.h
index a0c06b5f2..2e9524dfd 100644
--- a/src/structs.h
+++ b/src/structs.h
@@ -255,7 +255,11 @@ typedef struct
#endif
#ifdef FEAT_STL_OPT
char_u *wo_stl;
-#define w_p_stl w_onebuf_opt.wo_stl /* 'statusline' */
+# define w_p_stl w_onebuf_opt.wo_stl /* 'statusline' */
+#ifdef FEAT_STL_MULTI
+ long wo_stlh;
+# define w_p_stlh w_onebuf_opt.wo_stlh /* 'statuslineheight' */
+#endif
#endif
int wo_scb;
#define w_p_scb w_onebuf_opt.wo_scb /* 'scrollbind' */
@@ -2741,7 +2745,11 @@ struct window_S
int w_winrow; /* first row of window in screen */
int w_height; /* number of rows in window, excluding
status/command/winbar line(s) */
- int w_status_height; /* number of status lines (0 or 1) */
+ int w_status_height; // number of status lines. If
+ // 'statuslineheight' was changed, this
+ // member will be the previous value until
+ // call function
+ // frame_change_statusline_height().
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). */
@@ -2870,6 +2878,9 @@ struct window_S
#ifdef FEAT_STL_OPT
long_u w_p_stl_flags; /* flags for 'statusline' */
#endif
+#ifdef FEAT_STL_MULTI
+ long_u w_p_stlh_flags; /* flags for 'statuslineheight' */
+#endif
#ifdef FEAT_EVAL
long_u w_p_fde_flags; /* flags for 'foldexpr' */
long_u w_p_fdt_flags; /* flags for 'foldtext' */
diff --git a/src/version.c b/src/version.c
index 9d700e2ba..fc7c5fd5c 100644
--- a/src/version.c
+++ b/src/version.c
@@ -470,6 +470,11 @@ static char *(features[]) =
#else
"-multi_lang",
#endif
+#ifdef FEAT_STL_MULTI
+ "+multi_statusline",
+#else
+ "-multi_statusline",
+#endif
#ifdef FEAT_MZSCHEME
# ifdef DYNAMIC_MZSCHEME
"+mzscheme/dyn",
diff --git a/src/vim.h b/src/vim.h
index 7a66ab0e2..80d39722c 100644
--- a/src/vim.h
+++ b/src/vim.h
@@ -1485,7 +1485,8 @@ typedef UINT32_TYPEDEF UINT32_T;
*/
#define MIN_COLUMNS 12 /* minimal columns for screen */
#define MIN_LINES 2 /* minimal lines for screen */
-#define STATUS_HEIGHT 1 /* height of a status line under a window */
+#define STATUS_HEIGHT 1 // default height of a status line under a
+ // window
#ifdef FEAT_MENU /* height of a status line under a window */
# define WINBAR_HEIGHT(wp) (wp)->w_winbar_height
# define VISIBLE_HEIGHT(wp) ((wp)->w_height + (wp)->w_winbar_height)
diff --git a/src/window.c b/src/window.c
index e16570f4e..4614536a6 100644
--- a/src/window.c
+++ b/src/window.c
@@ -49,6 +49,7 @@ static void win_goto_ver(int up, long count);
static void win_goto_hor(int left, long count);
static void frame_add_height(frame_T *frp, int n);
static void last_status_rec(frame_T *fr, int statusline);
+static void frame_change_statusline_height_rec(frame_T *frp);
static void make_snapshot_rec(frame_T *fr, frame_T **frp);
static void clear_snapshot(tabpage_T *tp, int idx);
@@ -784,7 +785,7 @@ win_split_ins(
EMSG(_(e_noroom));
return FAIL;
}
- need_status = STATUS_HEIGHT;
+ need_status = statusline_height(oldwin);
}
#ifdef FEAT_GUI
@@ -890,7 +891,7 @@ win_split_ins(
*/
/* Current window requires at least 1 space. */
wmh1 = (p_wmh == 0 ? 1 : p_wmh) + WINBAR_HEIGHT(curwin);
- needed = wmh1 + STATUS_HEIGHT;
+ needed = p_wmh + statusline_height(oldwin);
if (flags & WSP_ROOM)
needed += p_wh - wmh1;
if (flags & (WSP_BOT | WSP_TOP))
@@ -930,18 +931,23 @@ win_split_ins(
oldwin_height = oldwin->w_height;
if (need_status)
{
- oldwin->w_status_height = STATUS_HEIGHT;
- oldwin_height -= STATUS_HEIGHT;
+ oldwin->w_status_height = statusline_height(oldwin);
+ oldwin_height -= oldwin->w_status_height;
}
if (new_size == 0)
- new_size = oldwin_height / 2;
- if (new_size > available - minheight - STATUS_HEIGHT)
- new_size = available - minheight - STATUS_HEIGHT;
+ {
+ if (lastwin == firstwin && p_ls == 0)
+ new_size = (oldwin_height - statusline_height(oldwin) + 1) / 2;
+ else
+ new_size = (oldwin_height - oldwin->w_status_height + 1) / 2;
+ }
+ if (new_size > available - minheight - statusline_height(oldwin))
+ new_size = available - minheight - statusline_height(oldwin);
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 - statusline_height(oldwin) < p_wmh)
do_equal = TRUE;
/* We don't like to take lines for the new window from a
@@ -954,11 +960,11 @@ win_split_ins(
set_fraction(oldwin);
did_set_fraction = TRUE;
- win_setheight_win(oldwin->w_height + new_size + STATUS_HEIGHT,
- oldwin);
+ win_setheight_win(oldwin->w_height + new_size
+ + statusline_height(oldwin), oldwin);
oldwin_height = oldwin->w_height;
if (need_status)
- oldwin_height -= STATUS_HEIGHT;
+ oldwin_height -= statusline_height(oldwin);
}
/* Only make all windows the same height if one of them (except oldwin)
@@ -972,7 +978,7 @@ win_split_ins(
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))
+ - statusline_height(oldwin)))
{
do_equal = TRUE;
break;
@@ -1093,16 +1099,16 @@ win_split_ins(
if (need_status)
{
- win_new_height(oldwin, oldwin->w_height - 1);
+ win_new_height(oldwin, oldwin->w_height - need_status);
oldwin->w_status_height = need_status;
}
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)
- - WINBAR_HEIGHT(wp));
- wp->w_status_height = (p_ls > 0);
+ win_new_height(wp, curfrp->fr_height
+ - statusline_height(curfrp->fr_win) - WINBAR_HEIGHT(wp));
+ wp->w_status_height = statusline_height(curfrp->fr_win);
}
else
{
@@ -1170,24 +1176,25 @@ win_split_ins(
+ WINBAR_HEIGHT(wp) ;
if (!((flags & WSP_BOT) && p_ls == 0))
- new_fr_height -= STATUS_HEIGHT;
+ new_fr_height -= statusline_height(curfrp->fr_win);
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
+ + statusline_height(wp)));
if (before) /* new window above current one */
{
wp->w_winrow = oldwin->w_winrow;
- wp->w_status_height = STATUS_HEIGHT;
- oldwin->w_winrow += wp->w_height + STATUS_HEIGHT;
+ wp->w_status_height = statusline_height(wp);
+ oldwin->w_winrow += wp->w_height + statusline_height(wp);
}
else /* new window below current one */
{
wp->w_winrow = oldwin->w_winrow + VISIBLE_HEIGHT(oldwin)
- + STATUS_HEIGHT;
+ + statusline_height(oldwin);
wp->w_status_height = oldwin->w_status_height;
if (!(flags & WSP_BOT))
- oldwin->w_status_height = STATUS_HEIGHT;
+ oldwin->w_status_height = statusline_height(oldwin);
}
if (flags & WSP_BOT)
frame_add_statusline(curfrp);
@@ -1295,6 +1302,7 @@ win_init(win_T *newp, win_T *oldp, int flags UNUSED)
newp->w_wrow = oldp->w_wrow;
newp->w_fraction = oldp->w_fraction;
newp->w_prev_fraction_row = oldp->w_prev_fraction_row;
+// newp->w_status_height = oldp->w_status_height;
#ifdef FEAT_JUMPLIST
copy_jumplist(oldp, newp);
#endif
@@ -1426,7 +1434,7 @@ make_windows(
{
/* Each window needs at least 'winminheight' lines and a status line. */
maxcount = (VISIBLE_HEIGHT(curwin) + curwin->w_status_height
- - (p_wh - p_wmh)) / (p_wmh + STATUS_HEIGHT);
+ - (p_wh - p_wmh)) / (p_wmh + statusline_height(curwin));
}
if (maxcount < 2)
@@ -1457,8 +1465,8 @@ make_windows(
else
{
if (win_split(curwin->w_height - (curwin->w_height - todo
- * STATUS_HEIGHT) / (todo + 1)
- - STATUS_HEIGHT, WSP_ABOVE) == FAIL)
+ * statusline_height(curwin)) / (todo + 1)
+ - statusline_height(curwin), WSP_ABOVE) == FAIL)
break;
}
@@ -1766,6 +1774,7 @@ win_equal(
win_equal_rec(next_curwin == NULL ? curwin : next_curwin, current,
topframe, dir, 0, tabline_height(),
(int)Columns, topframe->fr_height);
+ frame_change_statusline_height();
}
/*
@@ -1961,10 +1970,11 @@ win_equal_rec(
n = frame_minheight(topfr, NOWIN);
/* add one for the bottom window if it doesn't have a statusline */
if (row + height == cmdline_row && p_ls == 0)
- extra_sep = 1;
+ extra_sep = statusline_height(next_curwin);
else
extra_sep = 0;
- totwincount = (n + extra_sep) / (p_wmh + 1);
+ totwincount = (n + extra_sep) / (p_wmh
+ + next_curwin->w_status_height);
has_next_curwin = frame_has_win(topfr, next_curwin);
/*
@@ -2003,7 +2013,8 @@ win_equal_rec(
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 + next_curwin->w_status_height);
room -= new_size - n;
if (room < 0)
{
@@ -2055,7 +2066,7 @@ win_equal_rec(
/* 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 + next_curwin->w_status_height);
m = frame_minheight(fr, next_curwin);
if (has_next_curwin)
hnc = frame_has_win(fr, next_curwin);
@@ -3058,9 +3069,10 @@ frame_add_statusline(frame_T *frp)
wp = frp->fr_win;
if (wp->w_status_height == 0)
{
- if (wp->w_height > 0) /* don't make it negative */
- --wp->w_height;
- wp->w_status_height = STATUS_HEIGHT;
+ wp->w_status_height = statusline_height(wp);
+ // don't make it negative
+ if (wp->w_height >= wp->w_status_height)
+ wp->w_height -= wp->w_status_height;
}
}
else if (frp->fr_layout == FR_ROW)
@@ -3555,6 +3567,10 @@ new_frame(win_T *wp)
win_init_size(void)
{
firstwin->w_height = ROWS_AVAIL;
+ firstwin->w_status_height = 0;
+#ifdef FEAT_STL_MULTI
+ firstwin->w_onebuf_opt.wo_stlh = -1;
+#endif
topframe->fr_height = ROWS_AVAIL;
firstwin->w_width = Columns;
topframe->fr_width = Columns;
@@ -4566,6 +4582,9 @@ win_alloc(win_T *after UNUSED, int hidden UNUSED)
}
init_var_dict(new_wp->w_vars, &new_wp->w_winvar, VAR_SCOPE);
#endif
+#ifdef FEAT_STL_MULTI
+ new_wp->w_p_stlh = -1;
+#endif
/* Don't execute autocommands while the window is not properly
* initialized yet. gui_create_scrollbar() may trigger a FocusGained
@@ -4972,6 +4991,7 @@ win_comp_pos(void)
int col = 0;
frame_comp_pos(topframe, &row, &col);
+ frame_change_statusline_height();
return row;
}
@@ -5029,6 +5049,9 @@ frame_comp_pos(frame_T *topfrp, int *row, int *col)
win_setheight(int height)
{
win_setheight_win(height, curwin);
+#ifdef FEAT_STL_MULTI
+ frame_change_statusline_height();
+#endif
}
/*
@@ -6008,6 +6031,7 @@ last_status(
/* Don't make a difference between horizontal or vertical split. */
last_status_rec(topframe, (p_ls == 2
|| (p_ls == 1 && (morewin || !ONE_WINDOW))));
+ frame_change_statusline_height();
}
static void
@@ -6022,7 +6046,7 @@ last_status_rec(frame_T *fr, int statusline)
if (wp->w_status_height != 0 && !statusline)
{
/* remove status line */
- win_new_height(wp, wp->w_height + 1);
+ win_new_height(wp, wp->w_height + wp->w_status_height);
wp->w_status_height = 0;
comp_col();
}
@@ -6044,15 +6068,16 @@ last_status_rec(frame_T *fr, int statusline)
else
fp = fp->fr_parent;
}
- wp->w_status_height = 1;
+ wp->w_status_height = statusline_height(wp);
if (fp != fr)
{
- frame_new_height(fp, fp->fr_height - 1, FALSE, FALSE);
+ frame_new_height(fp, fp->fr_height - wp->w_status_height,
+ 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 - wp->w_status_height);
comp_col();
redraw_all_later(SOME_VALID);
}
@@ -6072,6 +6097,97 @@ last_status_rec(frame_T *fr, int statusline)
}
}
+#ifdef FEAT_STL_MULTI
+ void
+fitting_statusline_height_value(void)
+{
+ int height;
+
+ /* use global value */
+ if (curwin->w_p_stlh == -1)
+ {
+ win_T *wp;
+ tabpage_T *tp;
+
+ FOR_ALL_TAB_WINDOWS(tp, wp)
+ {
+ if (wp->w_p_stlh == -1)
+ {
+ height = wp->w_height + wp->w_status_height;
+ if (height - 1 < p_stlh)
+ p_stlh = height - 1;
+ }
+ }
+ }
+ else
+ {
+ /* use window-local value */
+ height = curwin->w_height + curwin->w_status_height;
+ if (height - 1 < curwin->w_p_stlh)
+ curwin->w_p_stlh = height - 1;
+ }
+
+ return;
+}
+
+/*
+ * Set a status line height to windows at the bottom of "frp".
+ * Note: Does not check if there is room!
+ */
+ void
+frame_change_statusline_height(void)
+{
+ frame_change_statusline_height_rec(topframe);
+ comp_col();
+ redraw_all_later(SOME_VALID);
+}
+
+ static void
+frame_change_statusline_height_rec(frame_T *frp)
+{
+ win_T *wp;
+
+ if (frp->fr_layout == FR_LEAF)
+ {
+ int new_w_height;
+
+ wp = frp->fr_win;
+ if (wp->w_status_height > 0)
+ {
+ wp->w_status_height = statusline_height(wp);
+ new_w_height = frp->fr_height - wp->w_status_height;
+ win_new_height(wp, new_w_height);
+ }
+ }
+ else if (frp->fr_layout == FR_ROW)
+ {
+ /* Handle all the frames in the row. */
+ for (frp = frp->fr_child; frp != NULL; frp = frp->fr_next)
+ frame_change_statusline_height_rec(frp);
+ }
+ else /* frp->fr_layout == FR_COL */
+ {
+ /* Handle all the frames in the column. */
+ for (frp = frp->fr_child; frp != NULL; frp = frp->fr_next)
+ frame_change_statusline_height_rec(frp);
+ }
+}
+#endif
+
+/*
+ * Return the number of lines used by the status line.
+ */
+ int
+statusline_height(wp)
+ win_T *wp;
+{
+#ifdef FEAT_STL_MULTI
+ return (wp != NULL && wp->w_p_stlh >= 0) ? wp->w_p_stlh : p_stlh;
+#else
+ return STATUS_HEIGHT;
+#endif
+}
+
/*
* Return the number of lines used by the tab page line.
*/
@greduan
Copy link

greduan commented Jun 17, 2013

Ah I see. Well that's a shame.

いえ いえ, おつかれさん:persevere:

http://www.romajidesu.com/hiragana/
http://www.romaji.org/
たいせつ な ともだち:wink:

@h-east
Copy link
Author

h-east commented Oct 29, 2018

Patch update for Vim 8.1.0500

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment