aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/statusline.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/nvim/statusline.c')
-rw-r--r--src/nvim/statusline.c213
1 files changed, 111 insertions, 102 deletions
diff --git a/src/nvim/statusline.c b/src/nvim/statusline.c
index 4dac1b1451..b403f840ca 100644
--- a/src/nvim/statusline.c
+++ b/src/nvim/statusline.c
@@ -18,29 +18,37 @@
#include "nvim/eval.h"
#include "nvim/eval/typval_defs.h"
#include "nvim/eval/vars.h"
-#include "nvim/gettext.h"
+#include "nvim/gettext_defs.h"
#include "nvim/globals.h"
#include "nvim/grid.h"
+#include "nvim/grid_defs.h"
#include "nvim/highlight.h"
+#include "nvim/highlight_defs.h"
#include "nvim/highlight_group.h"
#include "nvim/macros_defs.h"
#include "nvim/mbyte.h"
#include "nvim/memline.h"
+#include "nvim/memline_defs.h"
#include "nvim/memory.h"
+#include "nvim/memory_defs.h"
#include "nvim/message.h"
#include "nvim/normal.h"
#include "nvim/option.h"
#include "nvim/option_vars.h"
#include "nvim/optionstr.h"
#include "nvim/os/os.h"
+#include "nvim/os/os_defs.h"
#include "nvim/path.h"
#include "nvim/plines.h"
#include "nvim/pos_defs.h"
#include "nvim/sign.h"
+#include "nvim/sign_defs.h"
#include "nvim/state_defs.h"
#include "nvim/statusline.h"
#include "nvim/strings.h"
+#include "nvim/types_defs.h"
#include "nvim/ui.h"
+#include "nvim/ui_defs.h"
#include "nvim/undo.h"
#include "nvim/window.h"
@@ -59,7 +67,6 @@ typedef enum {
/// If inversion is possible we use it. Else '=' characters are used.
void win_redr_status(win_T *wp)
{
- int fillchar;
int attr;
bool is_stl_global = global_stl_height() > 0;
static bool busy = false;
@@ -85,7 +92,7 @@ void win_redr_status(win_T *wp)
// redraw custom status line
redraw_custom_statusline(wp);
} else {
- fillchar = fillchar_status(&attr, wp);
+ schar_T fillchar = fillchar_status(&attr, wp);
const int stl_width = is_stl_global ? Columns : wp->w_width;
get_trans_bufname(wp->w_buffer);
@@ -144,14 +151,14 @@ void win_redr_status(win_T *wp)
}
grid_line_start(&default_grid, is_stl_global ? (Rows - (int)p_ch - 1) : W_ENDROW(wp));
- int col = is_stl_global ? 0 : wp->w_wincol;
+ const int off = is_stl_global ? 0 : wp->w_wincol;
- int width = grid_line_puts(col, p, -1, attr);
- grid_line_fill(width + col, this_ru_col + col, fillchar, attr);
+ int width = grid_line_puts(off, p, -1, attr);
+ grid_line_fill(off + width, off + this_ru_col, fillchar, attr);
if (get_keymap_str(wp, "<%s>", NameBuff, MAXPATHL)
- && this_ru_col - len > (int)(strlen(NameBuff) + 1)) {
- grid_line_puts((int)((size_t)this_ru_col - strlen(NameBuff) - 1), NameBuff, -1, attr);
+ && this_ru_col - len > (int)strlen(NameBuff) + 1) {
+ grid_line_puts(off + this_ru_col - (int)strlen(NameBuff) - 1, NameBuff, -1, attr);
}
win_redr_ruler(wp);
@@ -161,7 +168,7 @@ void win_redr_status(win_T *wp)
const int sc_width = MIN(10, this_ru_col - len - 2);
if (sc_width > 0) {
- grid_line_puts(wp->w_wincol + this_ru_col - sc_width - 1, showcmd_buf, sc_width, attr);
+ grid_line_puts(off + this_ru_col - sc_width - 1, showcmd_buf, sc_width, attr);
}
}
@@ -170,6 +177,7 @@ void win_redr_status(win_T *wp)
// May need to draw the character below the vertical separator.
if (wp->w_vsep_width != 0 && wp->w_status_height != 0 && redrawing()) {
+ schar_T fillchar;
if (stl_connected(wp)) {
fillchar = fillchar_status(&attr, wp);
} else {
@@ -177,7 +185,7 @@ void win_redr_status(win_T *wp)
fillchar = wp->w_p_fcs_chars.vert;
}
grid_line_start(&default_grid, W_ENDROW(wp));
- grid_line_put_schar(W_ENDCOL(wp), schar_from_char(fillchar), attr);
+ grid_line_put_schar(W_ENDCOL(wp), fillchar, attr);
grid_line_flush();
}
busy = false;
@@ -292,11 +300,11 @@ static void win_redr_custom(win_T *wp, bool draw_winbar, bool draw_ruler)
int row;
int col = 0;
int maxwidth;
- int fillchar;
+ schar_T fillchar;
char buf[MAXPATHL];
char transbuf[MAXPATHL];
char *stl;
- char *opt_name;
+ OptIndex opt_idx = kOptInvalid;
int opt_scope = 0;
stl_hlrec_t *hltab;
StlClickRecord *tabtab;
@@ -317,12 +325,12 @@ static void win_redr_custom(win_T *wp, bool draw_winbar, bool draw_ruler)
// Use 'tabline'. Always at the first line of the screen.
stl = p_tal;
row = 0;
- fillchar = ' ';
+ fillchar = schar_from_ascii(' ');
attr = HL_ATTR(HLF_TPF);
maxwidth = Columns;
- opt_name = "tabline";
+ opt_idx = kOptTabline;
} else if (draw_winbar) {
- opt_name = "winbar";
+ opt_idx = kOptWinbar;
stl = ((*wp->w_p_wbr != NUL) ? wp->w_p_wbr : p_wbr);
opt_scope = ((*wp->w_p_wbr != NUL) ? OPT_LOCAL : 0);
row = -1; // row zero is first row of text
@@ -351,7 +359,7 @@ static void win_redr_custom(win_T *wp, bool draw_winbar, bool draw_ruler)
if (draw_ruler) {
stl = p_ruf;
- opt_name = "rulerformat";
+ opt_idx = kOptRulerformat;
// advance past any leading group spec - implicit in ru_col
if (*stl == '%') {
if (*++stl == '-') {
@@ -375,11 +383,11 @@ static void win_redr_custom(win_T *wp, bool draw_winbar, bool draw_ruler)
grid = &msg_grid_adj;
row = Rows - 1;
maxwidth--; // writing in last column may cause scrolling
- fillchar = ' ';
+ fillchar = schar_from_ascii(' ');
attr = HL_ATTR(HLF_MSG);
}
} else {
- opt_name = "statusline";
+ opt_idx = kOptStatusline;
stl = ((*wp->w_p_stl != NUL) ? wp->w_p_stl : p_stl);
opt_scope = ((*wp->w_p_stl != NUL) ? OPT_LOCAL : 0);
}
@@ -402,8 +410,8 @@ static void win_redr_custom(win_T *wp, bool draw_winbar, bool draw_ruler)
// Make a copy, because the statusline may include a function call that
// might change the option value and free the memory.
stl = xstrdup(stl);
- build_stl_str_hl(ewp, buf, sizeof(buf), stl, opt_name, opt_scope,
- fillchar, maxwidth, &hltab, &tabtab, NULL);
+ build_stl_str_hl(ewp, buf, sizeof(buf), stl, opt_idx, opt_scope,
+ fillchar, maxwidth, &hltab, NULL, &tabtab, NULL);
xfree(stl);
ewp->w_p_crb = p_crb_save;
@@ -514,7 +522,7 @@ void win_redr_ruler(win_T *wp)
&& *ml_get_buf(wp->w_buffer, wp->w_cursor.lnum) == NUL;
int width;
- int fillchar;
+ schar_T fillchar;
int attr;
int off;
bool part_of_status = false;
@@ -530,7 +538,7 @@ void win_redr_ruler(win_T *wp)
width = Columns;
part_of_status = true;
} else {
- fillchar = ' ';
+ fillchar = schar_from_ascii(' ');
attr = HL_ATTR(HLF_MSG);
width = Columns;
off = 0;
@@ -578,7 +586,7 @@ void win_redr_ruler(win_T *wp)
if (this_ru_col + o < width) {
// Need at least 3 chars left for get_rel_pos() + NUL.
while (this_ru_col + o < width && RULER_BUF_LEN > i + 4) {
- i += utf_char2bytes(fillchar, buffer + i);
+ i += (int)schar_get(buffer + i, fillchar);
o++;
}
get_rel_pos(wp, buffer + i, RULER_BUF_LEN - i);
@@ -607,24 +615,21 @@ void win_redr_ruler(win_T *wp)
}
}
- int w = grid_line_puts(this_ru_col + off, buffer, -1, attr);
- grid_line_fill(this_ru_col + off + w, off + width, fillchar, attr);
+ int w = grid_line_puts(off + this_ru_col, buffer, -1, attr);
+ grid_line_fill(off + this_ru_col + w, off + width, fillchar, attr);
}
}
/// Get the character to use in a status line. Get its attributes in "*attr".
-int fillchar_status(int *attr, win_T *wp)
+schar_T fillchar_status(int *attr, win_T *wp)
{
- int fill;
- bool is_curwin = (wp == curwin);
- if (is_curwin) {
+ if (wp == curwin) {
*attr = win_hl_attr(wp, HLF_S);
- fill = wp->w_p_fcs_chars.stl;
+ return wp->w_p_fcs_chars.stl;
} else {
*attr = win_hl_attr(wp, HLF_SNC);
- fill = wp->w_p_fcs_chars.stlnc;
+ return wp->w_p_fcs_chars.stlnc;
}
- return fill;
}
/// Redraw the status line according to 'statusline' and take care of any
@@ -660,7 +665,7 @@ static void ui_ext_tabline_update(void)
win_T *cwp = (tp == curtab) ? curwin : tp->tp_curwin;
get_trans_bufname(cwp->w_buffer);
- PUT_C(tab_info, "name", STRING_OBJ(arena_string(&arena, cstr_as_string(NameBuff))));
+ PUT_C(tab_info, "name", CSTR_TO_ARENA_OBJ(&arena, NameBuff));
ADD_C(tabs, DICTIONARY_OBJ(tab_info));
}
@@ -681,7 +686,7 @@ static void ui_ext_tabline_update(void)
PUT_C(buffer_info, "buffer", BUFFER_OBJ(buf->handle));
get_trans_bufname(buf);
- PUT_C(buffer_info, "name", STRING_OBJ(arena_string(&arena, cstr_as_string(NameBuff))));
+ PUT_C(buffer_info, "name", CSTR_TO_ARENA_OBJ(&arena, NameBuff));
ADD_C(buffers, DICTIONARY_OBJ(buffer_info));
}
@@ -696,7 +701,7 @@ void draw_tabline(void)
win_T *wp;
int attr_nosel = HL_ATTR(HLF_TP);
int attr_fill = HL_ATTR(HLF_TPF);
- int use_sep_chars = (t_colors < 8);
+ bool use_sep_chars = (t_colors < 8);
if (default_grid.chars == NULL) {
return;
@@ -725,9 +730,6 @@ void draw_tabline(void)
int col = 0;
win_T *cwp;
int wincount;
- int c;
- int len;
- char *p;
grid_line_start(&default_grid, 0);
FOR_ALL_TABS(tp) {
tabcount++;
@@ -772,7 +774,7 @@ void draw_tabline(void)
grid_line_put_schar(col++, schar_from_ascii(' '), attr);
- int modified = false;
+ bool modified = false;
for (wincount = 0; wp != NULL; wp = wp->w_next, wincount++) {
if (bufIsChanged(wp->w_buffer)) {
@@ -783,7 +785,7 @@ void draw_tabline(void)
if (modified || wincount > 1) {
if (wincount > 1) {
vim_snprintf(NameBuff, MAXPATHL, "%d", wincount);
- len = (int)strlen(NameBuff);
+ int len = (int)strlen(NameBuff);
if (col + len >= Columns - 3) {
break;
}
@@ -802,8 +804,8 @@ void draw_tabline(void)
// Get buffer name in NameBuff[]
get_trans_bufname(cwp->w_buffer);
shorten_dir(NameBuff);
- len = vim_strsize(NameBuff);
- p = NameBuff;
+ int len = vim_strsize(NameBuff);
+ char *p = NameBuff;
while (len > room) {
len -= ptr2cells(p);
MB_PTR_ADV(p);
@@ -829,12 +831,8 @@ void draw_tabline(void)
}
}
- if (use_sep_chars) {
- c = '_';
- } else {
- c = ' ';
- }
- grid_line_fill(col, Columns, c, attr_fill);
+ char c = use_sep_chars ? '_' : ' ';
+ grid_line_fill(col, Columns, schar_from_ascii(c), attr_fill);
// Draw the 'showcmd' information if 'showcmdloc' == "tabline".
if (p_sc && *p_sloc == 't') {
@@ -868,7 +866,7 @@ void draw_tabline(void)
/// the v:lnum and v:relnum variables don't have to be updated.
///
/// @return The width of the built status column string for line "lnum"
-int build_statuscol_str(win_T *wp, linenr_T lnum, linenr_T relnum, statuscol_T *stcp)
+int build_statuscol_str(win_T *wp, linenr_T lnum, linenr_T relnum, char *buf, statuscol_T *stcp)
{
// Only update click definitions once per window per redraw.
// Don't update when current width is 0, since it will be redrawn again if not empty.
@@ -881,15 +879,15 @@ int build_statuscol_str(win_T *wp, linenr_T lnum, linenr_T relnum, statuscol_T *
StlClickRecord *clickrec;
char *stc = xstrdup(wp->w_p_stc);
- int width = build_stl_str_hl(wp, stcp->text, MAXPATHL, stc, "statuscolumn", OPT_LOCAL, ' ',
- stcp->width, &stcp->hlrec, fillclick ? &clickrec : NULL, stcp);
+ int width = build_stl_str_hl(wp, buf, MAXPATHL, stc, kOptStatuscolumn, OPT_LOCAL, 0,
+ stcp->width, &stcp->hlrec, NULL, fillclick ? &clickrec : NULL, stcp);
xfree(stc);
if (fillclick) {
stl_clear_click_defs(wp->w_statuscol_click_defs, wp->w_statuscol_click_defs_size);
- wp->w_statuscol_click_defs = stl_alloc_click_defs(wp->w_statuscol_click_defs, stcp->width,
+ wp->w_statuscol_click_defs = stl_alloc_click_defs(wp->w_statuscol_click_defs, width,
&wp->w_statuscol_click_defs_size);
- stl_fill_click_defs(wp->w_statuscol_click_defs, clickrec, stcp->text, stcp->width, false);
+ stl_fill_click_defs(wp->w_statuscol_click_defs, clickrec, buf, width, false);
}
return width;
@@ -913,8 +911,8 @@ int build_statuscol_str(win_T *wp, linenr_T lnum, linenr_T relnum, statuscol_T *
/// Note: This should not be NameBuff
/// @param outlen The length of the output buffer
/// @param fmt The statusline format string
-/// @param opt_name The option name corresponding to "fmt"
-/// @param opt_scope The scope corresponding to "opt_name"
+/// @param opt_idx Index of the option corresponding to "fmt"
+/// @param opt_scope The scope corresponding to "opt_idx"
/// @param fillchar Character to use when filling empty space in the statusline
/// @param maxwidth The maximum width to make the statusline
/// @param hltab HL attributes (can be NULL)
@@ -922,9 +920,9 @@ int build_statuscol_str(win_T *wp, linenr_T lnum, linenr_T relnum, statuscol_T *
/// @param stcp Status column attributes (can be NULL)
///
/// @return The final width of the statusline
-int build_stl_str_hl(win_T *wp, char *out, size_t outlen, char *fmt, char *opt_name, int opt_scope,
- int fillchar, int maxwidth, stl_hlrec_t **hltab, StlClickRecord **tabtab,
- statuscol_T *stcp)
+int build_stl_str_hl(win_T *wp, char *out, size_t outlen, char *fmt, OptIndex opt_idx,
+ int opt_scope, schar_T fillchar, int maxwidth, stl_hlrec_t **hltab,
+ size_t *hltab_len, StlClickRecord **tabtab, statuscol_T *stcp)
{
static size_t stl_items_len = 20; // Initial value, grows as needed.
static stl_item_t *stl_items = NULL;
@@ -937,14 +935,20 @@ int build_stl_str_hl(win_T *wp, char *out, size_t outlen, char *fmt, char *opt_n
char buf_tmp[TMPLEN];
char win_tmp[TMPLEN];
char *usefmt = fmt;
- const int save_must_redraw = must_redraw;
- const int save_redr_type = curwin->w_redr_type;
+ const bool save_redraw_not_allowed = redraw_not_allowed;
const bool save_KeyTyped = KeyTyped;
// TODO(Bram): find out why using called_emsg_before makes tests fail, does it
// matter?
// const int called_emsg_before = called_emsg;
const int did_emsg_before = did_emsg;
+ // When inside update_screen() we do not want redrawing a statusline,
+ // ruler, title, etc. to trigger another redraw, it may cause an endless
+ // loop.
+ if (updating_screen) {
+ redraw_not_allowed = true;
+ }
+
if (stl_items == NULL) {
stl_items = xmalloc(sizeof(stl_item_t) * stl_items_len);
stl_groupitems = xmalloc(sizeof(int) * stl_items_len);
@@ -957,10 +961,10 @@ int build_stl_str_hl(win_T *wp, char *out, size_t outlen, char *fmt, char *opt_n
stl_separator_locations = xmalloc(sizeof(int) * stl_items_len);
}
- // if "fmt" was set insecurely it needs to be evaluated in the sandbox
- // "opt_name" will be NULL when caller is nvim_eval_statusline()
- const int use_sandbox = opt_name ? was_set_insecurely(wp, opt_name, opt_scope)
- : false;
+ // If "fmt" was set insecurely it needs to be evaluated in the sandbox.
+ // "opt_idx" will be kOptInvalid when caller is nvim_eval_statusline().
+ const bool use_sandbox = (opt_idx != kOptInvalid) ? was_set_insecurely(wp, opt_idx, opt_scope)
+ : false;
// When the format starts with "%!" then evaluate it as an expression and
// use the result as the actual format string.
@@ -980,7 +984,7 @@ int build_stl_str_hl(win_T *wp, char *out, size_t outlen, char *fmt, char *opt_n
}
if (fillchar == 0) {
- fillchar = ' ';
+ fillchar = schar_from_ascii(' ');
}
// The cursor in windows other than the current one isn't always
@@ -1178,7 +1182,7 @@ int build_stl_str_hl(win_T *wp, char *out, size_t outlen, char *fmt, char *opt_n
out_p = out_p - n + 1;
// Fill up space left over by half a double-wide char.
while (++group_len < stl_items[stl_groupitems[groupdepth]].minwid) {
- MB_CHAR2BYTES(fillchar, out_p);
+ schar_get_adv(&out_p, fillchar);
}
// }
@@ -1201,13 +1205,13 @@ int build_stl_str_hl(win_T *wp, char *out, size_t outlen, char *fmt, char *opt_n
if (min_group_width < 0) {
min_group_width = 0 - min_group_width;
while (group_len++ < min_group_width && out_p < out_end_p) {
- MB_CHAR2BYTES(fillchar, out_p);
+ schar_get_adv(&out_p, fillchar);
}
// If the group is right-aligned, shift everything to the right and
// prepend with filler characters.
} else {
// { Move the group to the right
- group_len = (min_group_width - group_len) * utf_char2len(fillchar);
+ group_len = (min_group_width - group_len) * (int)schar_len(fillchar);
memmove(t + group_len, t, (size_t)(out_p - t));
if (out_p + group_len >= (out_end_p + 1)) {
group_len = out_end_p - out_p;
@@ -1222,7 +1226,7 @@ int build_stl_str_hl(win_T *wp, char *out, size_t outlen, char *fmt, char *opt_n
// Prepend the fill characters
for (; group_len > 0; group_len--) {
- MB_CHAR2BYTES(fillchar, t);
+ schar_get_adv(&t, fillchar);
}
}
}
@@ -1400,7 +1404,7 @@ int build_stl_str_hl(win_T *wp, char *out, size_t outlen, char *fmt, char *opt_n
case STL_VIM_EXPR: // '{'
{
char *block_start = fmt_p - 1;
- int reevaluate = (*fmt_p == '%');
+ bool reevaluate = (*fmt_p == '%');
itemisflag = true;
if (reevaluate) {
@@ -1545,7 +1549,7 @@ int build_stl_str_hl(win_T *wp, char *out, size_t outlen, char *fmt, char *opt_n
break;
case STL_SHOWCMD:
- if (p_sc && (opt_name == NULL || strcmp(opt_name, p_sloc) == 0)) {
+ if (p_sc && (opt_idx == kOptInvalid || find_option(p_sloc) == opt_idx)) {
str = showcmd_buf;
}
break;
@@ -1632,29 +1636,41 @@ int build_stl_str_hl(win_T *wp, char *out, size_t outlen, char *fmt, char *opt_n
break;
}
bool fold = opt == STL_FOLDCOL;
- int width = fold ? (compute_foldcolumn(wp, 0) > 0) : wp->w_scwidth;
+ int fdc = fold ? compute_foldcolumn(wp, 0) : 0;
+ int width = fold ? fdc > 0 : wp->w_scwidth;
- if (width == 0) {
+ if (width <= 0) {
break;
}
foldsignitem = curitem;
char *p = NULL;
if (fold) {
- size_t n = fill_foldcolumn(out_p, wp, stcp->foldinfo,
- (linenr_T)get_vim_var_nr(VV_LNUM), NULL);
+ schar_T fold_buf[10];
+ fill_foldcolumn(wp, stcp->foldinfo, (linenr_T)get_vim_var_nr(VV_LNUM),
+ 0, fdc, NULL, fold_buf);
stl_items[curitem].minwid = -((stcp->use_cul ? HLF_CLF : HLF_FC) + 1);
+ size_t buflen = 0;
+ // TODO(bfredl): this is very backwards. we must support schar_T
+ // being used directly in 'statuscolumn'
+ for (int i = 0; i < fdc; i++) {
+ buflen += schar_get(out_p + buflen, fold_buf[i]);
+ }
p = out_p;
- p[n] = NUL;
}
+ char buf[SIGN_WIDTH * MAX_SCHAR_SIZE];
size_t buflen = 0;
varnumber_T virtnum = get_vim_var_nr(VV_VIRTNUM);
for (int i = 0; i < width; i++) {
if (!fold) {
SignTextAttrs *sattr = virtnum ? NULL : &stcp->sattrs[i];
- p = sattr && sattr->text ? sattr->text : " ";
- stl_items[curitem].minwid = -(sattr && sattr->text
+ p = " ";
+ if (sattr && sattr->text[0]) {
+ describe_sign_text(buf, sattr->text);
+ p = buf;
+ }
+ stl_items[curitem].minwid = -(sattr && sattr->text[0]
? (stcp->sign_cul_id ? stcp->sign_cul_id : sattr->hl_id)
: (stcp->use_cul ? HLF_CLS : HLF_SC) + 1);
}
@@ -1803,7 +1819,7 @@ int build_stl_str_hl(win_T *wp, char *out, size_t outlen, char *fmt, char *opt_n
if (l + 1 == minwid && fillchar == '-' && ascii_isdigit(*t)) {
*out_p++ = ' ';
} else {
- MB_CHAR2BYTES(fillchar, out_p);
+ schar_get_adv(&out_p, fillchar);
}
}
minwid = 0;
@@ -1826,7 +1842,7 @@ int build_stl_str_hl(win_T *wp, char *out, size_t outlen, char *fmt, char *opt_n
// digit follows.
if (fillable && *t == ' '
&& (!ascii_isdigit(*(t + 1)) || fillchar != '-')) {
- MB_CHAR2BYTES(fillchar, out_p);
+ schar_get_adv(&out_p, fillchar);
} else {
*out_p++ = *t;
}
@@ -1843,7 +1859,7 @@ int build_stl_str_hl(win_T *wp, char *out, size_t outlen, char *fmt, char *opt_n
// For left-aligned items, fill any remaining space with the fillchar
for (; l < minwid && out_p < out_end_p; l++) {
- MB_CHAR2BYTES(fillchar, out_p);
+ schar_get_adv(&out_p, fillchar);
}
// Otherwise if the item is a number, copy that to the output buffer.
@@ -1928,16 +1944,16 @@ int build_stl_str_hl(win_T *wp, char *out, size_t outlen, char *fmt, char *opt_n
stl_items[curitem].type = Empty;
}
+ if (num >= 0 || (!itemisflag && str && *str)) {
+ prevchar_isflag = false; // Item not NULL, but not a flag
+ }
+
// Only free the string buffer if we allocated it.
// Note: This is not needed if `str` is pointing at `tmp`
if (opt == STL_VIM_EXPR) {
XFREE_CLEAR(str);
}
- if (num >= 0 || (!itemisflag && str && *str)) {
- prevchar_isflag = false; // Item not NULL, but not a flag
- }
-
// Item processed, move to the next
curitem++;
}
@@ -1954,11 +1970,7 @@ int build_stl_str_hl(win_T *wp, char *out, size_t outlen, char *fmt, char *opt_n
// What follows is post-processing to handle alignment and highlighting.
int width = vim_strsize(out);
- // Return truncated width for 'statuscolumn'
- if (stcp != NULL && width > stcp->width) {
- stcp->truncate = width - stcp->width;
- }
- if (maxwidth > 0 && width > maxwidth) {
+ if (maxwidth > 0 && width > maxwidth && (!stcp || width > MAX_STCWIDTH)) {
// Result is too long, must truncate somewhere.
int item_idx = 0;
char *trunc_p;
@@ -2064,8 +2076,7 @@ int build_stl_str_hl(win_T *wp, char *out, size_t outlen, char *fmt, char *opt_n
// Fill up for half a double-wide character.
while (++width < maxwidth) {
- MB_CHAR2BYTES(fillchar, trunc_p);
- *trunc_p = NUL;
+ schar_get_adv(&trunc_p, fillchar);
}
}
width = maxwidth;
@@ -2094,12 +2105,12 @@ int build_stl_str_hl(win_T *wp, char *out, size_t outlen, char *fmt, char *opt_n
for (int l = 0; l < num_separators; l++) {
int dislocation = (l == (num_separators - 1)) ? final_spaces : standard_spaces;
- dislocation *= utf_char2len(fillchar);
+ dislocation *= (int)schar_len(fillchar);
char *start = stl_items[stl_separator_locations[l]].start;
char *seploc = start + dislocation;
STRMOVE(seploc, start);
for (char *s = start; s < seploc;) {
- MB_CHAR2BYTES(fillchar, s);
+ schar_get_adv(&s, fillchar);
}
for (int item_idx = stl_separator_locations[l] + 1;
@@ -2127,6 +2138,9 @@ int build_stl_str_hl(win_T *wp, char *out, size_t outlen, char *fmt, char *opt_n
sp->start = NULL;
sp->userhl = 0;
}
+ if (hltab_len) {
+ *hltab_len = (size_t)itemcnt;
+ }
// Store the info about tab pages labels.
if (tabtab != NULL) {
@@ -2164,12 +2178,7 @@ int build_stl_str_hl(win_T *wp, char *out, size_t outlen, char *fmt, char *opt_n
cur_tab_rec->def.func = NULL;
}
- // When inside update_screen we do not want redrawing a statusline, ruler,
- // title, etc. to trigger another redraw, it may cause an endless loop.
- if (updating_screen) {
- must_redraw = save_must_redraw;
- curwin->w_redr_type = save_redr_type;
- }
+ redraw_not_allowed = save_redraw_not_allowed;
// Check for an error. If there is one the display will be messed up and
// might loop redrawing. Avoid that by making the corresponding option
@@ -2177,8 +2186,8 @@ int build_stl_str_hl(win_T *wp, char *out, size_t outlen, char *fmt, char *opt_n
// TODO(Bram): find out why using called_emsg_before makes tests fail, does it
// matter?
// if (called_emsg > called_emsg_before)
- if (opt_name && did_emsg > did_emsg_before) {
- set_string_option_direct(opt_name, -1, "", OPT_FREE | opt_scope, SID_ERROR);
+ if (opt_idx != kOptInvalid && did_emsg > did_emsg_before) {
+ set_string_option_direct(opt_idx, "", opt_scope, SID_ERROR);
}
// A user function may reset KeyTyped, restore it.