diff options
| author | bfredl <bjorn.linse@gmail.com> | 2024-01-03 13:31:39 +0100 |
|---|---|---|
| committer | bfredl <bjorn.linse@gmail.com> | 2024-01-08 14:37:55 +0100 |
| commit | aeb053907d2f27713764e345b00a6618e23220d8 (patch) | |
| tree | dd881a61c8c515600b201ed2685ec6ae591f42f9 | |
| parent | fbe40caa7cc1786dc58210a82901307417ba0654 (diff) | |
| download | rneovim-aeb053907d2f27713764e345b00a6618e23220d8.tar.gz rneovim-aeb053907d2f27713764e345b00a6618e23220d8.tar.bz2 rneovim-aeb053907d2f27713764e345b00a6618e23220d8.zip | |
refactor(options): use schar_T representation for fillchars and listchars
A bit big, but practically it was a lot simpler to change over all
fillchars and all listchars at once, to not need to maintain two
parallel implementations.
This is mostly an internal refactor, but it also removes an arbitrary
limitation: that 'fillchars' and 'listchars' values can only be
single-codepoint characters. Now any character which fits into a single
screen cell can be used.
| -rw-r--r-- | src/nvim/api/ui.c | 26 | ||||
| -rw-r--r-- | src/nvim/api/vim.c | 22 | ||||
| -rw-r--r-- | src/nvim/buffer_defs.h | 62 | ||||
| -rw-r--r-- | src/nvim/cmdexpand.c | 2 | ||||
| -rw-r--r-- | src/nvim/drawline.c | 241 | ||||
| -rw-r--r-- | src/nvim/drawscreen.c | 53 | ||||
| -rw-r--r-- | src/nvim/eval/funcs.c | 19 | ||||
| -rw-r--r-- | src/nvim/grid.c | 61 | ||||
| -rw-r--r-- | src/nvim/match.c | 4 | ||||
| -rw-r--r-- | src/nvim/message.c | 106 | ||||
| -rw-r--r-- | src/nvim/option.c | 8 | ||||
| -rw-r--r-- | src/nvim/optionstr.c | 181 | ||||
| -rw-r--r-- | src/nvim/optionstr.h | 5 | ||||
| -rw-r--r-- | src/nvim/popupmenu.c | 8 | ||||
| -rw-r--r-- | src/nvim/statusline.c | 68 | ||||
| -rw-r--r-- | src/nvim/window.c | 6 | ||||
| -rw-r--r-- | test/functional/options/chars_spec.lua | 35 | ||||
| -rw-r--r-- | test/unit/statusline_spec.lua | 24 |
18 files changed, 474 insertions, 457 deletions
diff --git a/src/nvim/api/ui.c b/src/nvim/api/ui.c index 82d42d652d..271e58b851 100644 --- a/src/nvim/api/ui.c +++ b/src/nvim/api/ui.c @@ -41,7 +41,7 @@ static PMap(uint64_t) connected_uis = MAP_INIT; -#define mpack_w(b, byte) *(*b)++ = (char)(byte); +#define mpack_w(b, byte) *(*(b))++ = (char)(byte); static void mpack_w2(char **b, uint32_t v) { *(*b)++ = (char)((v >> 8) & 0xff); @@ -98,10 +98,9 @@ static char *mpack_array_dyn16(char **buf) return pos; } -static void mpack_str(char **buf, const char *str) +static void mpack_str(char **buf, const char *str, size_t len) { assert(sizeof(schar_T) - 1 < 0x20); - size_t len = strlen(str); mpack_w(buf, 0xa0 | len); memcpy(*buf, str, len); *buf += len; @@ -566,7 +565,7 @@ static void flush_event(UIData *data) // [2, "redraw", [...]] mpack_array(buf, 3); mpack_uint(buf, 2); - mpack_str(buf, "redraw"); + mpack_str(buf, S_LEN("redraw")); data->nevents_pos = mpack_array_dyn16(buf); } } @@ -607,7 +606,7 @@ static bool prepare_call(UI *ui, const char *name) data->cur_event = name; char **buf = &data->buf_wptr; data->ncalls_pos = mpack_array_dyn16(buf); - mpack_str(buf, name); + mpack_str(buf, name, strlen(name)); data->nevents++; data->ncalls = 1; return true; @@ -640,17 +639,18 @@ static void push_call(UI *ui, const char *name, Array args) remote_ui_flush_buf(ui); } - if (data->pack_totlen > UI_BUF_SIZE - strlen(name) - 20) { + size_t name_len = strlen(name); + if (data->pack_totlen > UI_BUF_SIZE - name_len - 20) { // TODO(bfredl): manually testable by setting UI_BUF_SIZE to 1024 (mode_info_set) - data->temp_buf = xmalloc(20 + strlen(name) + data->pack_totlen); + data->temp_buf = xmalloc(20 + name_len + data->pack_totlen); data->buf_wptr = data->temp_buf; char **buf = &data->buf_wptr; mpack_array(buf, 3); mpack_uint(buf, 2); - mpack_str(buf, "redraw"); + mpack_str(buf, S_LEN("redraw")); mpack_array(buf, 1); mpack_array(buf, 2); - mpack_str(buf, name); + mpack_str(buf, name, name_len); } else { prepare_call(ui, name); } @@ -895,9 +895,9 @@ void remote_ui_raw_line(UI *ui, Integer grid, Integer row, Integer startcol, Int uint32_t csize = (repeat > 1) ? 3 : ((attrs[i] != last_hl) ? 2 : 1); nelem++; mpack_array(buf, csize); - char sc_buf[MAX_SCHAR_SIZE]; - schar_get(sc_buf, chunk[i]); - mpack_str(buf, sc_buf); + char *size_byte = (*buf)++; + size_t len = schar_get_adv(buf, chunk[i]); + *size_byte = (char)(0xa0 | len); if (csize >= 2) { mpack_uint(buf, (uint32_t)attrs[i]); if (csize >= 3) { @@ -916,7 +916,7 @@ void remote_ui_raw_line(UI *ui, Integer grid, Integer row, Integer startcol, Int nelem++; data->ncells_pending += 1; mpack_array(buf, 3); - mpack_str(buf, " "); + mpack_str(buf, S_LEN(" ")); mpack_uint(buf, (uint32_t)clearattr); mpack_uint(buf, (uint32_t)(clearcol - endcol)); } diff --git a/src/nvim/api/vim.c b/src/nvim/api/vim.c index 2bb3f0fac7..f683789945 100644 --- a/src/nvim/api/vim.c +++ b/src/nvim/api/vim.c @@ -2132,7 +2132,7 @@ Dictionary nvim_eval_statusline(String str, Dict(eval_statusline) *opts, Error * Dictionary result = ARRAY_DICT_INIT; int maxwidth; - int fillchar = 0; + schar_T fillchar = 0; int statuscol_lnum = 0; Window window = 0; @@ -2148,11 +2148,13 @@ Dictionary nvim_eval_statusline(String str, Dict(eval_statusline) *opts, Error * } if (HAS_KEY(opts, eval_statusline, fillchar)) { VALIDATE_EXP((*opts->fillchar.data != 0 - && ((size_t)utf_ptr2len(opts->fillchar.data) == opts->fillchar.size)), + && ((size_t)utfc_ptr2len(opts->fillchar.data) == opts->fillchar.size)), "fillchar", "single character", NULL, { return result; }); - fillchar = utf_ptr2char(opts->fillchar.data); + int c; + fillchar = utfc_ptr2schar(opts->fillchar.data, &c); + // TODO(bfredl): actually check c is single width } int use_bools = (int)opts->use_winbar + (int)opts->use_tabline; @@ -2181,7 +2183,7 @@ Dictionary nvim_eval_statusline(String str, Dict(eval_statusline) *opts, Error * SignTextAttrs sattrs[SIGN_SHOW_MAX] = { 0 }; if (opts->use_tabline) { - fillchar = ' '; + fillchar = schar_from_ascii(' '); } else { if (fillchar == 0) { if (opts->use_winbar) { @@ -2242,16 +2244,8 @@ Dictionary nvim_eval_statusline(String str, Dict(eval_statusline) *opts, Error * int p_crb_save = wp->w_p_crb; wp->w_p_crb = false; - int width = build_stl_str_hl(wp, - buf, - sizeof(buf), - str.data, - -1, - 0, - fillchar, - maxwidth, - opts->highlights ? &hltab : NULL, - NULL, + int width = build_stl_str_hl(wp, buf, sizeof(buf), str.data, -1, 0, fillchar, maxwidth, + opts->highlights ? &hltab : NULL, NULL, statuscol_lnum ? &statuscol : NULL); PUT(result, "width", INTEGER_OBJ(width)); diff --git a/src/nvim/buffer_defs.h b/src/nvim/buffer_defs.h index c6bd5691b1..085070fc4a 100644 --- a/src/nvim/buffer_defs.h +++ b/src/nvim/buffer_defs.h @@ -971,41 +971,41 @@ typedef struct { /// Characters from the 'listchars' option. typedef struct { - int eol; - int ext; - int prec; - int nbsp; - int space; - int tab1; ///< first tab character - int tab2; ///< second tab character - int tab3; ///< third tab character - int lead; - int trail; - int *multispace; - int *leadmultispace; - int conceal; + schar_T eol; + schar_T ext; + schar_T prec; + schar_T nbsp; + schar_T space; + schar_T tab1; ///< first tab character + schar_T tab2; ///< second tab character + schar_T tab3; ///< third tab character + schar_T lead; + schar_T trail; + schar_T *multispace; + schar_T *leadmultispace; + schar_T conceal; } lcs_chars_T; /// Characters from the 'fillchars' option. typedef struct { - int stl; - int stlnc; - int wbr; - 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 - int foldsep; ///< continuous fold marker - int diff; - int msgsep; - int eob; - int lastline; + schar_T stl; + schar_T stlnc; + schar_T wbr; + schar_T horiz; + schar_T horizup; + schar_T horizdown; + schar_T vert; + schar_T vertleft; + schar_T vertright; + schar_T verthoriz; + schar_T fold; + schar_T foldopen; ///< when fold is open + schar_T foldclosed; ///< when fold is closed + schar_T foldsep; ///< continuous fold marker + schar_T diff; + schar_T msgsep; + schar_T eob; + schar_T lastline; } fcs_chars_T; /// Structure which contains all information that belongs to a window. diff --git a/src/nvim/cmdexpand.c b/src/nvim/cmdexpand.c index 2d66526f33..968081c6ac 100644 --- a/src/nvim/cmdexpand.c +++ b/src/nvim/cmdexpand.c @@ -508,7 +508,7 @@ static void redraw_wildmenu(expand_T *xp, int num_matches, char **matches, int m } } - int fillchar = fillchar_status(&attr, curwin); + schar_T fillchar = fillchar_status(&attr, curwin); if (first_match == 0) { *buf = NUL; diff --git a/src/nvim/drawline.c b/src/nvim/drawline.c index 22eb0b9c31..dc4ef72e38 100644 --- a/src/nvim/drawline.c +++ b/src/nvim/drawline.c @@ -64,6 +64,7 @@ typedef struct { colnr_T vcol; ///< virtual column, before wrapping int col; ///< visual column on screen, after wrapping int boguscols; ///< nonexistent columns added to "col" to force wrapping + int old_boguscols; ///< bogus boguscols int vcol_off; ///< offset for concealed characters int off; ///< offset relative start of line @@ -83,10 +84,10 @@ typedef struct { int n_extra; ///< number of extra bytes int n_attr; ///< chars with special attr char *p_extra; ///< string of extra chars, plus NUL, only used - ///< when c_extra and c_final are NUL + ///< when sc_extra and sc_final are NUL int extra_attr; ///< attributes for p_extra - int c_extra; ///< extra chars, all the same - int c_final; ///< final char, mandatory if set + schar_T sc_extra; ///< extra chars, all the same + schar_T sc_final; ///< final char, mandatory if set bool extra_for_extmark; ///< n_extra set for inline virtual text @@ -409,9 +410,9 @@ void fill_foldcolumn(win_T *wp, foldinfo_T foldinfo, linenr_T lnum, int attr, in int closedcol = MIN(fdc, level); for (int i = 0; i < fdc; i++) { - int symbol = 0; + schar_T symbol = 0; if (i >= level) { - symbol = ' '; + symbol = schar_from_ascii(' '); } else if (i == closedcol - 1 && closed) { symbol = wp->w_p_fcs_chars.foldclosed; } else if (foldinfo.fi_lnum == lnum && first_level + i >= foldinfo.fi_low_level) { @@ -419,17 +420,17 @@ void fill_foldcolumn(win_T *wp, foldinfo_T foldinfo, linenr_T lnum, int attr, in } else if (first_level == 1) { symbol = wp->w_p_fcs_chars.foldsep; } else if (first_level + i <= 9) { - symbol = '0' + first_level + i; + symbol = schar_from_ascii('0' + first_level + i); } else { - symbol = '>'; + symbol = schar_from_ascii('>'); } if (out_buffer) { - out_buffer[i] = schar_from_char(symbol); + out_buffer[i] = symbol; } else { linebuf_vcol[*wlv_off] = i >= level ? -1 : (i == closedcol - 1 && closed) ? -2 : -3; linebuf_attr[*wlv_off] = attr; - linebuf_char[(*wlv_off)++] = schar_from_char(symbol); + linebuf_char[(*wlv_off)++] = symbol; } } } @@ -441,7 +442,6 @@ void fill_foldcolumn(win_T *wp, foldinfo_T foldinfo, linenr_T lnum, int attr, in static void draw_sign(bool nrcol, win_T *wp, winlinevars_T *wlv, int sign_idx, int sign_cul_attr) { SignTextAttrs sattr = wlv->sattrs[sign_idx]; - wlv->c_final = NUL; if (sattr.text[0] && wlv->row == wlv->startrow + wlv->filler_lines && wlv->filler_todo <= 0) { int attr = (use_cursor_line_highlight(wp, wlv->lnum) && sign_cul_attr) @@ -453,7 +453,6 @@ static void draw_sign(bool nrcol, win_T *wp, winlinevars_T *wlv, int sign_idx, i linebuf_char[sign_pos + 1] = sattr.text[1]; } else { assert(!nrcol); // handled in draw_lnum_col() - wlv->c_extra = ' '; int attr = win_hl_attr(wp, use_cursor_line_highlight(wp, wlv->lnum) ? HLF_CLS : HLF_SC); draw_col_fill(wlv, schar_from_ascii(' '), SIGN_WIDTH, attr); } @@ -680,8 +679,8 @@ static void handle_showbreak_and_filler(win_T *wp, winlinevars_T *wlv) draw_col_fill(wlv, schar_from_ascii(' '), remaining, 0); } else if (wlv->filler_todo > 0) { // Draw "deleted" diff line(s) - int c = (char2cells(wp->w_p_fcs_chars.diff) > 1) ? '-' : wp->w_p_fcs_chars.diff; - draw_col_fill(wlv, schar_from_char(c), remaining, win_hl_attr(wp, HLF_DED)); + schar_T c = wp->w_p_fcs_chars.diff; + draw_col_fill(wlv, c, remaining, win_hl_attr(wp, HLF_DED)); } char *const sbr = get_showbreak_value(wp); @@ -790,8 +789,8 @@ static void handle_inline_virtual_text(win_T *wp, winlinevars_T *wlv, ptrdiff_t if (wlv->n_extra == 0) { continue; } - wlv->c_extra = NUL; - wlv->c_final = NUL; + wlv->sc_extra = NUL; + wlv->sc_final = NUL; wlv->extra_attr = attr; wlv->n_attr = mb_charlen(text); // If the text didn't reach until the first window @@ -871,6 +870,16 @@ static void win_line_start(win_T *wp, winlinevars_T *wlv, bool save_extra) memset(linebuf_vcol, -1, (size_t)wp->w_grid.cols * sizeof(*linebuf_vcol)); } +static void fix_for_boguscols(winlinevars_T *wlv) +{ + wlv->n_extra += wlv->vcol_off; + wlv->vcol -= wlv->vcol_off; + wlv->vcol_off = 0; + wlv->col -= wlv->boguscols; + wlv->old_boguscols = wlv->boguscols; + wlv->boguscols = 0; +} + /// Display line "lnum" of window "wp" on the screen. /// wp->w_virtcol needs to be valid. /// @@ -932,7 +941,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool number_onl int multi_attr = 0; // attributes desired by multibyte int mb_l = 1; // multi-byte byte length int mb_c = 0; // decoded multi-byte character - schar_T mb_schar; // complete screen char + schar_T mb_schar = 0; // complete screen char int change_start = MAXCOL; // first col of changed area int change_end = -1; // last col of changed area bool in_multispace = false; // in multiple consecutive spaces @@ -971,17 +980,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool number_onl int conceal_attr = win_hl_attr(wp, HLF_CONCEAL); bool is_concealing = false; bool did_wcol = false; - int old_boguscols = 0; #define vcol_hlc(wlv) ((wlv).vcol - (wlv).vcol_off) -#define FIX_FOR_BOGUSCOLS \ - { \ - wlv.n_extra += wlv.vcol_off; \ - wlv.vcol -= wlv.vcol_off; \ - wlv.vcol_off = 0; \ - wlv.col -= wlv.boguscols; \ - old_boguscols = wlv.boguscols; \ - wlv.boguscols = 0; \ - } assert(startrow < endrow); @@ -994,6 +993,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool number_onl wlv.fromcol = -10; wlv.tocol = MAXCOL; wlv.vcol_sbr = -1; + wlv.old_boguscols = 0; buf_T *buf = wp->w_buffer; const bool end_fill = (lnum == buf->b_ml.ml_line_count + 1); @@ -1276,8 +1276,9 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool number_onl colnr_T trailcol = MAXCOL; // start of trailing spaces colnr_T leadcol = 0; // start of leading spaces - int lcs_eol_one = wp->w_p_lcs_chars.eol; // 'eol' until it's been used - int lcs_prec_todo = wp->w_p_lcs_chars.prec; // 'prec' until it's been used + bool lcs_eol_todo = true; // need to keep track of this even if lcs_eol is NUL + const schar_T lcs_eol = wp->w_p_lcs_chars.eol; // 'eol' value + schar_T lcs_prec_todo = wp->w_p_lcs_chars.prec; // 'prec' until it's been used, then NUL if (wp->w_p_list && !has_fold && !end_fill) { if (wp->w_p_lcs_chars.space @@ -1644,7 +1645,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool number_onl // When another match, have to check for start again. v = ptr - line; search_attr = update_search_hl(wp, lnum, (colnr_T)v, &line, &screen_search_hl, - &has_match_conc, &match_conc, lcs_eol_one, + &has_match_conc, &match_conc, lcs_eol_todo, &on_last_col, &search_attr_from_match); ptr = line + v; // "line" may have been changed @@ -1715,8 +1716,8 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool number_onl if (wlv.p_extra != buf_fold) { foldtext_free = wlv.p_extra; } - wlv.c_extra = NUL; - wlv.c_final = NUL; + wlv.sc_extra = NUL; + wlv.sc_final = NUL; wlv.p_extra[wlv.n_extra] = NUL; // Get the line again as evaluating 'foldtext' may free it. @@ -1726,8 +1727,8 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool number_onl if (draw_folded && wlv.n_extra == 0 && wlv.col < grid->cols) { // Fill rest of line with 'fold'. - wlv.c_extra = wp->w_p_fcs_chars.fold; - wlv.c_final = NUL; + wlv.sc_extra = wp->w_p_fcs_chars.fold; + wlv.sc_final = NUL; wlv.n_extra = grid->cols - wlv.col; } @@ -1740,15 +1741,15 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool number_onl // // The "p_extra" points to the extra stuff that is inserted to // represent special characters (non-printable stuff) and other - // things. When all characters are the same, c_extra is used. - // If c_final is set, it will compulsorily be used at the end. + // things. When all characters are the same, sc_extra is used. + // If sc_final is set, it will compulsorily be used at the end. // "p_extra" must end in a NUL to avoid utfc_ptr2len() reads past // "p_extra[n_extra]". // For the '$' of the 'list' option, n_extra == 1, p_extra == "". if (wlv.n_extra > 0) { - if (wlv.c_extra != NUL || (wlv.n_extra == 1 && wlv.c_final != NUL)) { - mb_c = (wlv.n_extra == 1 && wlv.c_final != NUL) ? wlv.c_final : wlv.c_extra; - mb_schar = schar_from_char(mb_c); + if (wlv.sc_extra != NUL || (wlv.n_extra == 1 && wlv.sc_final != NUL)) { + mb_schar = (wlv.n_extra == 1 && wlv.sc_final != NUL) ? wlv.sc_final : wlv.sc_extra; + mb_c = schar_get_first_codepoint(mb_schar); wlv.n_extra--; } else { assert(wlv.p_extra != NULL); @@ -1809,7 +1810,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool number_onl mb_schar = schar_from_ascii(' '); } else if (has_fold) { // skip writing the buffer line itself - mb_c = NUL; + mb_schar = NUL; } else { char *prev_ptr = ptr; @@ -1844,8 +1845,8 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool number_onl mb_c = mb_ptr2char_adv((const char **)&wlv.p_extra); mb_schar = schar_from_char(mb_c); wlv.n_extra = (int)strlen(wlv.p_extra); - wlv.c_extra = NUL; - wlv.c_final = NUL; + wlv.sc_extra = NUL; + wlv.sc_final = NUL; if (area_attr == 0 && search_attr == 0) { wlv.n_attr = wlv.n_extra + 1; wlv.extra_attr = win_hl_attr(wp, HLF_8); @@ -1858,9 +1859,9 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool number_onl // last column; the character is displayed at the start of the // next line. if (wlv.col >= grid->cols - 1 && utf_char2cells(mb_c) == 2) { + mb_schar = schar_from_ascii('>'); mb_c = '>'; mb_l = 1; - mb_schar = schar_from_ascii(mb_c); multi_attr = win_hl_attr(wp, HLF_AT); // Put pointer back so that the character will be // displayed at the start of the next line. @@ -1874,11 +1875,11 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool number_onl // the first column. Don't do this for unprintable characters. if (wlv.skip_cells > 0 && mb_l > 1 && wlv.n_extra == 0) { wlv.n_extra = 1; - wlv.c_extra = MB_FILLER_CHAR; - wlv.c_final = NUL; + wlv.sc_extra = schar_from_ascii(MB_FILLER_CHAR); + wlv.sc_final = NUL; + mb_schar = schar_from_ascii(' '); mb_c = ' '; mb_l = 1; - mb_schar = schar_from_ascii(mb_c); if (area_attr == 0 && search_attr == 0) { wlv.n_attr = wlv.n_extra + 1; wlv.extra_attr = win_hl_attr(wp, HLF_AT); @@ -1922,7 +1923,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool number_onl // no concealing past the end of the line, it interferes // with line highlighting. - syntax_flags = (mb_c == 0) ? 0 : get_syntax_info(&syntax_seqnr); + syntax_flags = (mb_schar == 0) ? 0 : get_syntax_info(&syntax_seqnr); } if (has_decor && v > 0) { @@ -1957,7 +1958,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool number_onl spell_attr = 0; // do not calculate cap_col at the end of the line or when // only white space is following - if (mb_c != 0 && (*skipwhite(prev_ptr) != NUL) && can_spell) { + if (mb_schar != 0 && (*skipwhite(prev_ptr) != NUL) && can_spell) { char *p; hlf_T spell_hlf = HLF_COUNT; v -= mb_l - 1; @@ -2031,7 +2032,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool number_onl // // So only allow to linebreak, once we have found chars not in // 'breakat' in the line. - if (wp->w_p_lbr && !wlv.need_lbr && mb_c != NUL + if (wp->w_p_lbr && !wlv.need_lbr && mb_schar != NUL && !vim_isbreak((uint8_t)(*ptr))) { wlv.need_lbr = true; } @@ -2059,12 +2060,12 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool number_onl wlv.n_extra = tabstop_padding(wlv.vcol, wp->w_buffer->b_p_ts, wp->w_buffer->b_p_vts_array) - 1; } - wlv.c_extra = mb_off > 0 ? MB_FILLER_CHAR : ' '; - wlv.c_final = NUL; + wlv.sc_extra = schar_from_ascii(mb_off > 0 ? MB_FILLER_CHAR : ' '); + wlv.sc_final = NUL; if (mb_c < 128 && ascii_iswhite(mb_c)) { if (mb_c == TAB) { // See "Tab alignment" below. - FIX_FOR_BOGUSCOLS; + fix_for_boguscols(&wlv); } if (!wp->w_p_list) { mb_c = ' '; @@ -2093,39 +2094,39 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool number_onl && ptr - line >= leadcol && ptr - line <= trailcol))) { if (in_multispace && wp->w_p_lcs_chars.multispace != NULL) { - mb_c = wp->w_p_lcs_chars.multispace[multispace_pos++]; + mb_schar = wp->w_p_lcs_chars.multispace[multispace_pos++]; if (wp->w_p_lcs_chars.multispace[multispace_pos] == NUL) { multispace_pos = 0; } } else { - mb_c = (mb_c == ' ') ? wp->w_p_lcs_chars.space : wp->w_p_lcs_chars.nbsp; + mb_schar = (mb_c == ' ') ? wp->w_p_lcs_chars.space : wp->w_p_lcs_chars.nbsp; } wlv.n_attr = 1; wlv.extra_attr = win_hl_attr(wp, HLF_0); saved_attr2 = wlv.char_attr; // save current attr - mb_schar = schar_from_char(mb_c); + mb_c = schar_get_first_codepoint(mb_schar); } if (mb_c == ' ' && mb_l == 1 && ((trailcol != MAXCOL && ptr > line + trailcol) || (leadcol != 0 && ptr < line + leadcol))) { if (leadcol != 0 && in_multispace && ptr < line + leadcol && wp->w_p_lcs_chars.leadmultispace != NULL) { - mb_c = wp->w_p_lcs_chars.leadmultispace[multispace_pos++]; + mb_schar = wp->w_p_lcs_chars.leadmultispace[multispace_pos++]; if (wp->w_p_lcs_chars.leadmultispace[multispace_pos] == NUL) { multispace_pos = 0; } } else if (ptr > line + trailcol && wp->w_p_lcs_chars.trail) { - mb_c = wp->w_p_lcs_chars.trail; + mb_schar = wp->w_p_lcs_chars.trail; } else if (ptr < line + leadcol && wp->w_p_lcs_chars.lead) { - mb_c = wp->w_p_lcs_chars.lead; + mb_schar = wp->w_p_lcs_chars.lead; } else if (leadcol != 0 && wp->w_p_lcs_chars.space) { - mb_c = wp->w_p_lcs_chars.space; + mb_schar = wp->w_p_lcs_chars.space; } wlv.n_attr = 1; wlv.extra_attr = win_hl_attr(wp, HLF_0); saved_attr2 = wlv.char_attr; // save current attr - mb_schar = schar_from_char(mb_c); + mb_c = schar_get_first_codepoint(mb_schar); } } @@ -2157,8 +2158,8 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool number_onl // there are characters to conceal tab_len += wlv.vcol_off; } - // boguscols before FIX_FOR_BOGUSCOLS macro from above. - if (wp->w_p_lcs_chars.tab1 && old_boguscols > 0 + // boguscols before fix_for_boguscols() from above. + if (wp->w_p_lcs_chars.tab1 && wlv.old_boguscols > 0 && wlv.n_extra > tab_len) { tab_len += wlv.n_extra - tab_len; } @@ -2167,35 +2168,35 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool number_onl // If wlv.n_extra > 0, it gives the number of chars // to use for a tab, else we need to calculate the // width for a tab. - int tab2_len = utf_char2len(wp->w_p_lcs_chars.tab2); - int len = tab_len * tab2_len; + size_t tab2_len = schar_len(wp->w_p_lcs_chars.tab2); + size_t len = (size_t)tab_len * tab2_len; if (wp->w_p_lcs_chars.tab3) { - len += utf_char2len(wp->w_p_lcs_chars.tab3) - tab2_len; + len += schar_len(wp->w_p_lcs_chars.tab3) - tab2_len; } if (wlv.n_extra > 0) { - len += wlv.n_extra - tab_len; + len += (size_t)(wlv.n_extra - tab_len); } - mb_c = wp->w_p_lcs_chars.tab1; - char *p = get_extra_buf((size_t)len + 1); - memset(p, ' ', (size_t)len); - p[len] = NUL; + mb_schar = wp->w_p_lcs_chars.tab1; + mb_c = schar_get_first_codepoint(mb_schar); + char *p = get_extra_buf(len + 1); + memset(p, ' ', len); wlv.p_extra = p; for (int i = 0; i < tab_len; i++) { if (*p == NUL) { tab_len = i; break; } - int lcs = wp->w_p_lcs_chars.tab2; + schar_T lcs = wp->w_p_lcs_chars.tab2; // if tab3 is given, use it for the last char if (wp->w_p_lcs_chars.tab3 && i == tab_len - 1) { lcs = wp->w_p_lcs_chars.tab3; } - p += utf_char2bytes(lcs, p); - wlv.n_extra += utf_char2len(lcs) - (saved_nextra > 0 ? 1 : 0); + size_t slen = schar_get_adv(&p, lcs); + wlv.n_extra += (int)slen - (saved_nextra > 0 ? 1 : 0); } - // n_extra will be increased by FIX_FOX_BOGUSCOLS + // n_extra will be increased by fix_for_boguscols() // macro below, so need to adjust for that here if (wlv.vcol_off > 0) { wlv.n_extra -= wlv.vcol_off; @@ -2212,7 +2213,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool number_onl // vcol_off and boguscols accumulated so far in the // line. Note that the tab can be longer than // 'tabstop' when there are concealed characters. - FIX_FOR_BOGUSCOLS; + fix_for_boguscols(&wlv); // Make sure, the highlighting for the tab char will be // correctly set further below (effectively reverts the @@ -2224,24 +2225,24 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool number_onl } if (wp->w_p_list) { - mb_c = (wlv.n_extra == 0 && wp->w_p_lcs_chars.tab3) - ? wp->w_p_lcs_chars.tab3 : wp->w_p_lcs_chars.tab1; + mb_schar = (wlv.n_extra == 0 && wp->w_p_lcs_chars.tab3) + ? wp->w_p_lcs_chars.tab3 : wp->w_p_lcs_chars.tab1; if (wp->w_p_lbr && wlv.p_extra != NULL && *wlv.p_extra != NUL) { - wlv.c_extra = NUL; // using p_extra from above + wlv.sc_extra = NUL; // using p_extra from above } else { - wlv.c_extra = wp->w_p_lcs_chars.tab2; + wlv.sc_extra = wp->w_p_lcs_chars.tab2; } - wlv.c_final = wp->w_p_lcs_chars.tab3; + wlv.sc_final = wp->w_p_lcs_chars.tab3; wlv.n_attr = tab_len + 1; wlv.extra_attr = win_hl_attr(wp, HLF_0); saved_attr2 = wlv.char_attr; // save current attr } else { - wlv.c_final = NUL; - wlv.c_extra = ' '; - mb_c = ' '; + wlv.sc_final = NUL; + wlv.sc_extra = schar_from_ascii(' '); + mb_schar = schar_from_ascii(' '); } - mb_schar = schar_from_char(mb_c); - } else if (mb_c == NUL + mb_c = schar_get_first_codepoint(mb_schar); + } else if (mb_schar == NUL && (wp->w_p_list || ((wlv.fromcol >= 0 || fromcol_prev >= 0) && wlv.tocol > wlv.vcol @@ -2250,7 +2251,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool number_onl && !(noinvcur && lnum == wp->w_cursor.lnum && wlv.vcol == wp->w_virtcol))) - && lcs_eol_one > 0) { + && lcs_eol_todo && lcs_eol != NUL) { // Display a '$' after the line or highlight an extra // character if the line break is included. // For a diff line the highlighting continues after the "$". @@ -2265,16 +2266,16 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool number_onl wlv.n_extra = 0; } if (wp->w_p_list && wp->w_p_lcs_chars.eol > 0) { - mb_c = wp->w_p_lcs_chars.eol; + mb_schar = wp->w_p_lcs_chars.eol; } else { - mb_c = ' '; + mb_schar = schar_from_ascii(' '); } - lcs_eol_one = -1; + lcs_eol_todo = false; ptr--; // put it back at the NUL wlv.extra_attr = win_hl_attr(wp, HLF_AT); wlv.n_attr = 1; - mb_schar = schar_from_char(mb_c); - } else if (mb_c != NUL) { + mb_c = schar_get_first_codepoint(mb_schar); + } else if (mb_schar != NUL) { wlv.p_extra = transchar_buf(wp->w_buffer, mb_c); if (wlv.n_extra == 0) { wlv.n_extra = byte2cells(mb_c) - 1; @@ -2282,8 +2283,8 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool number_onl if ((dy_flags & DY_UHEX) && wp->w_p_rl) { rl_mirror_ascii(wlv.p_extra, NULL); // reverse "<12>" } - wlv.c_extra = NUL; - wlv.c_final = NUL; + wlv.sc_extra = NUL; + wlv.sc_final = NUL; if (wp->w_p_lbr) { mb_c = (uint8_t)(*wlv.p_extra); char *p = get_extra_buf((size_t)wlv.n_extra + 1); @@ -2316,7 +2317,6 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool number_onl && ((syntax_flags & HL_CONCEAL) != 0 || has_match_conc > 0 || decor_conceal > 0) && !(lnum_in_visual_area && vim_strchr(wp->w_p_cocu, 'v') == NULL)) { wlv.char_attr = conceal_attr; - bool is_conceal_char = false; if (((prev_syntax_id != syntax_seqnr && (syntax_flags & HL_CONCEAL) != 0) || has_match_conc > 1 || decor_conceal > 1) && (syn_get_sub_char() != NUL @@ -2327,21 +2327,20 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool number_onl // First time at this concealed item: display one // character. if (has_match_conc && match_conc) { - mb_c = match_conc; + mb_schar = schar_from_char(match_conc); } else if (decor_conceal && decor_state.conceal_char) { mb_schar = decor_state.conceal_char; - mb_c = schar_get_first_codepoint(mb_schar); - is_conceal_char = true; if (decor_state.conceal_attr) { wlv.char_attr = decor_state.conceal_attr; } } else if (syn_get_sub_char() != NUL) { - mb_c = syn_get_sub_char(); + mb_schar = schar_from_char(syn_get_sub_char()); } else if (wp->w_p_lcs_chars.conceal != NUL) { - mb_c = wp->w_p_lcs_chars.conceal; + |