diff options
Diffstat (limited to 'src/nvim/statusline.c')
-rw-r--r-- | src/nvim/statusline.c | 213 |
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. |