diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/nvim/drawline.c | 1294 |
1 files changed, 651 insertions, 643 deletions
diff --git a/src/nvim/drawline.c b/src/nvim/drawline.c index e9ff299d68..9a56477d83 100644 --- a/src/nvim/drawline.c +++ b/src/nvim/drawline.c @@ -68,6 +68,43 @@ typedef enum { WL_LINE, // text in the line } LineDrawState; +/// structure with variables passed between win_line() and other functions +typedef struct { + LineDrawState draw_state; ///< what to draw next + + linenr_T lnum; ///< line number to be drawn + + int startrow; ///< first row in the window to be drawn + int row; ///< row in the window, excl w_winrow + + 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 vcol_off; ///< offset for concealed characters + + int off; ///< offset relative start of line + + int cul_attr; ///< set when 'cursorline' active + int line_attr; ///< attribute for the whole line + int line_attr_lowprio; ///< low-priority attribute for the line + + int char_attr; ///< attributes for next character + + int n_extra; ///< number of extra bytes + char *p_extra; ///< string of extra chars, plus NUL, only used + ///< when c_extra and c_final are NUL + char *p_extra_free; ///< p_extra buffer that needs to be freed + int extra_attr; ///< attributes for p_extra + int c_extra; ///< extra chars, all the same + int c_final; ///< final char, mandatory if set + + char extra[57]; ///< sign, line number and 'fdc' must fit in here + + int filler_lines; ///< nr of filler lines to be drawn + int filler_todo; ///< nr of filler lines still to do + 1 + SignTextAttrs sattrs[SIGN_SHOW_MAX]; ///< sign attributes for the sign column +} winlinevars_T; + /// for line_putchar. Contains the state that needs to be remembered from /// putting one character to the next. typedef struct { @@ -307,93 +344,87 @@ static bool use_cursor_line_sign(win_T *wp, linenr_T lnum) && (wp->w_p_culopt_flags & CULOPT_NBR); } -// Get information needed to display the sign in line 'lnum' in window 'wp'. -// If 'nrcol' is true, the sign is going to be displayed in the number column. -// Otherwise the sign is going to be displayed in the sign column. -// -// @param count max number of signs -// @param[out] n_extrap number of characters from pp_extra to display -// @param sign_idxp Index of the displayed sign -static void get_sign_display_info(bool nrcol, win_T *wp, linenr_T lnum, SignTextAttrs sattrs[], - int row, int startrow, int filler_lines, int filler_todo, - int *c_extrap, int *c_finalp, char *extra, size_t extra_size, - char **pp_extra, int *n_extrap, int *char_attrp, int sign_idx, - int cul_attr) +/// Get information needed to display the sign in line "wlv->lnum" in window "wp". +/// If "nrcol" is true, the sign is going to be displayed in the number column. +/// Otherwise the sign is going to be displayed in the sign column. +static void get_sign_display_info(bool nrcol, win_T *wp, winlinevars_T *wlv, int sign_idx, + int sign_cul_attr) { // Draw cells with the sign value or blank. - *c_extrap = ' '; - *c_finalp = NUL; + wlv->c_extra = ' '; + wlv->c_final = NUL; if (nrcol) { - *n_extrap = number_width(wp) + 1; + wlv->n_extra = number_width(wp) + 1; } else { - if (use_cursor_line_sign(wp, lnum)) { - *char_attrp = win_hl_attr(wp, HLF_CLS); + if (use_cursor_line_sign(wp, wlv->lnum)) { + wlv->char_attr = win_hl_attr(wp, HLF_CLS); } else { - *char_attrp = win_hl_attr(wp, HLF_SC); + wlv->char_attr = win_hl_attr(wp, HLF_SC); } - *n_extrap = win_signcol_width(wp); + wlv->n_extra = win_signcol_width(wp); } - if (row == startrow + filler_lines && filler_todo <= 0) { - SignTextAttrs *sattr = sign_get_attr(sign_idx, sattrs, wp->w_scwidth); + if (wlv->row == wlv->startrow + wlv->filler_lines && wlv->filler_todo <= 0) { + SignTextAttrs *sattr = sign_get_attr(sign_idx, wlv->sattrs, wp->w_scwidth); if (sattr != NULL) { - *pp_extra = sattr->text; - if (*pp_extra != NULL) { - *c_extrap = NUL; - *c_finalp = NUL; + wlv->p_extra = sattr->text; + if (wlv->p_extra != NULL) { + wlv->c_extra = NUL; + wlv->c_final = NUL; if (nrcol) { int n, width = number_width(wp) - 2; for (n = 0; n < width; n++) { - extra[n] = ' '; + wlv->extra[n] = ' '; } - extra[n] = NUL; - STRCAT(extra, *pp_extra); - STRCAT(extra, " "); - *pp_extra = extra; - *n_extrap = (int)strlen(*pp_extra); + wlv->extra[n] = NUL; + STRCAT(wlv->extra, wlv->p_extra); + STRCAT(wlv->extra, " "); + wlv->p_extra = wlv->extra; + wlv->n_extra = (int)strlen(wlv->p_extra); } else { - size_t symbol_blen = strlen(*pp_extra); + size_t symbol_blen = strlen(wlv->p_extra); // TODO(oni-link): Is sign text already extended to // full cell width? - assert((size_t)win_signcol_width(wp) >= mb_string2cells((char *)(*pp_extra))); + assert((size_t)win_signcol_width(wp) >= mb_string2cells(wlv->p_extra)); // symbol(s) bytes + (filling spaces) (one byte each) - *n_extrap = (int)symbol_blen + win_signcol_width(wp) - - (int)mb_string2cells(*pp_extra); + wlv->n_extra = (int)symbol_blen + win_signcol_width(wp) - + (int)mb_string2cells(wlv->p_extra); - assert(extra_size > symbol_blen); - memset(extra, ' ', extra_size); - memcpy(extra, *pp_extra, symbol_blen); + assert(sizeof(wlv->extra) > symbol_blen); + memset(wlv->extra, ' ', sizeof(wlv->extra)); + memcpy(wlv->extra, wlv->p_extra, symbol_blen); - *pp_extra = extra; - (*pp_extra)[*n_extrap] = NUL; + wlv->p_extra = wlv->extra; + wlv->p_extra[wlv->n_extra] = NUL; } } - if (use_cursor_line_sign(wp, lnum) && cul_attr > 0) { - *char_attrp = cul_attr; + if (use_cursor_line_sign(wp, wlv->lnum) && sign_cul_attr > 0) { + wlv->char_attr = sign_cul_attr; } else { - *char_attrp = sattr->hl_attr_id; + wlv->char_attr = sattr->hl_attr_id; } } } } -static int get_sign_attrs(buf_T *buf, linenr_T lnum, SignTextAttrs *sattrs, int *line_attr, - int *num_attr, int *cul_attr) +static int get_sign_attrs(buf_T *buf, winlinevars_T *wlv, int *sign_num_attrp, int *sign_cul_attrp) { - HlPriAttr line_attrs = { *line_attr, 0 }; - HlPriAttr num_attrs = { *num_attr, 0 }; - HlPriAttr cul_attrs = { *cul_attr, 0 }; + HlPriAttr line_attrs = { wlv->line_attr, 0 }; + HlPriAttr num_attrs = { *sign_num_attrp, 0 }; + HlPriAttr cul_attrs = { *sign_cul_attrp, 0 }; // TODO(bfredl, vigoux): line_attr should not take priority over decoration! - int num_signs = buf_get_signattrs(buf, lnum, sattrs, &num_attrs, &line_attrs, &cul_attrs); - decor_redraw_signs(buf, lnum - 1, &num_signs, sattrs, &num_attrs, &line_attrs, &cul_attrs); + int num_signs = buf_get_signattrs(buf, wlv->lnum, wlv->sattrs, &num_attrs, &line_attrs, + &cul_attrs); + decor_redraw_signs(buf, wlv->lnum - 1, &num_signs, wlv->sattrs, &num_attrs, &line_attrs, + &cul_attrs); - *line_attr = line_attrs.attr_id; - *num_attr = num_attrs.attr_id; - *cul_attr = cul_attrs.attr_id; + wlv->line_attr = line_attrs.attr_id; + *sign_num_attrp = num_attrs.attr_id; + *sign_cul_attrp = cul_attrs.attr_id; return num_signs; } @@ -449,30 +480,30 @@ static void get_statuscol_str(win_T *wp, linenr_T lnum, int virtnum, statuscol_T } /// Get information needed to display the next segment in the 'statuscolumn'. -/// If not yet at the end, prepare for next segment and decrement "draw_state". +/// If not yet at the end, prepare for next segment and decrement "wlv->draw_state". /// /// @param stcp Status column attributes -/// @param[out] draw_state Current draw state in win_line() -static void get_statuscol_display_info(statuscol_T *stcp, LineDrawState *draw_state, int *char_attr, - int *n_extrap, int *c_extrap, int *c_finalp, char **pp_extra) +/// @param[in,out] wlv +static void get_statuscol_display_info(statuscol_T *stcp, winlinevars_T *wlv) { - *c_extrap = NUL; - *c_finalp = NUL; + wlv->c_extra = NUL; + wlv->c_final = NUL; do { - *draw_state = WL_STC; - *char_attr = stcp->cur_attr; - *pp_extra = stcp->textp; - *n_extrap = (int)((stcp->hlrecp->start ? stcp->hlrecp->start : stcp->text_end) - stcp->textp); + wlv->draw_state = WL_STC; + wlv->char_attr = stcp->cur_attr; + wlv->p_extra = stcp->textp; + wlv->n_extra = + (int)((stcp->hlrecp->start ? stcp->hlrecp->start : stcp->text_end) - stcp->textp); // Prepare for next highlight section if not yet at the end - if (stcp->textp + *n_extrap < stcp->text_end) { + if (stcp->textp + wlv->n_extra < stcp->text_end) { int hl = stcp->hlrecp->userhl; stcp->textp = stcp->hlrecp->start; stcp->cur_attr = hl < 0 ? syn_id2attr(-hl) : hl > 0 ? hl : stcp->num_attr; stcp->hlrecp++; - *draw_state = WL_STC - 1; + wlv->draw_state = WL_STC - 1; } // Skip over empty highlight sections - } while (*n_extrap == 0 && stcp->textp < stcp->text_end); + } while (wlv->n_extra == 0 && stcp->textp < stcp->text_end); } /// Return true if CursorLineNr highlight is to be used for the number column. @@ -484,13 +515,13 @@ static void get_statuscol_display_info(statuscol_T *stcp, LineDrawState *draw_st /// - When line is wrapped and 'cursorlineopt' does not have "line", only highlight the line number /// itself on the first screenline of the wrapped line, otherwise highlight the number column of /// all screenlines of the wrapped line. -static bool use_cursor_line_nr(win_T *wp, linenr_T lnum, int row, int startrow, int filler_lines) +static bool use_cursor_line_nr(win_T *wp, winlinevars_T *wlv) { return wp->w_p_cul - && lnum == wp->w_cursorline + && wlv->lnum == wp->w_cursorline && (wp->w_p_culopt_flags & CULOPT_NBR) - && (row == startrow + filler_lines - || (row > startrow + filler_lines + && (wlv->row == wlv->startrow + wlv->filler_lines + || (wlv->row > wlv->startrow + wlv->filler_lines && (wp->w_p_culopt_flags & CULOPT_LINE))); } @@ -515,20 +546,20 @@ static inline void get_line_number_str(win_T *wp, linenr_T lnum, char *buf, size snprintf(buf, buf_len, fmt, number_width(wp), num); } -static int get_line_number_attr(win_T *wp, linenr_T lnum, int row, int startrow, int filler_lines) +static int get_line_number_attr(win_T *wp, winlinevars_T *wlv) { - if (use_cursor_line_nr(wp, lnum, row, startrow, filler_lines)) { + if (use_cursor_line_nr(wp, wlv)) { // TODO(vim): Can we use CursorLine instead of CursorLineNr // when CursorLineNr isn't set? return win_hl_attr(wp, HLF_CLN); } if (wp->w_p_rnu) { - if (lnum < wp->w_cursor.lnum) { + if (wlv->lnum < wp->w_cursor.lnum) { // Use LineNrAbove return win_hl_attr(wp, HLF_LNA); } - if (lnum > wp->w_cursor.lnum) { + if (wlv->lnum > wp->w_cursor.lnum) { // Use LineNrBelow return win_hl_attr(wp, HLF_LNB); } @@ -537,22 +568,21 @@ static int get_line_number_attr(win_T *wp, linenr_T lnum, int row, int startrow, return win_hl_attr(wp, HLF_N); } -static void apply_cursorline_highlight(win_T *wp, linenr_T lnum, int *line_attr, int *cul_attr, - int *line_attr_lowprio) +static void apply_cursorline_highlight(win_T *wp, winlinevars_T *wlv) { - *cul_attr = win_hl_attr(wp, HLF_CUL); - HlAttrs ae = syn_attr2entry(*cul_attr); + wlv->cul_attr = win_hl_attr(wp, HLF_CUL); + HlAttrs ae = syn_attr2entry(wlv->cul_attr); // We make a compromise here (#7383): // * low-priority CursorLine if fg is not set // * high-priority ("same as Vim" priority) CursorLine if fg is set if (ae.rgb_fg_color == -1 && ae.cterm_fg_color == 0) { - *line_attr_lowprio = *cul_attr; + wlv->line_attr_lowprio = wlv->cul_attr; } else { if (!(State & MODE_INSERT) && bt_quickfix(wp->w_buffer) - && qf_current_entry(wp) == lnum) { - *line_attr = hl_combine_attr(*cul_attr, *line_attr); + && qf_current_entry(wp) == wlv->lnum) { + wlv->line_attr = hl_combine_attr(wlv->cul_attr, wlv->line_attr); } else { - *line_attr = *cul_attr; + wlv->line_attr = wlv->cul_attr; } } } @@ -604,6 +634,20 @@ static colnr_T get_leadcol(win_T *wp, const char *ptr, const char *line) return leadcol; } +/// Start a screen line at column zero. +static void win_line_start(win_T *wp, winlinevars_T *wlv) +{ + wlv->col = 0; + wlv->off = 0; + if (wp->w_p_rl) { + // Rightleft window: process the text in the normal direction, but put + // it in linebuf_char[wlv.off] from right to left. Start at the + // rightmost column of the window. + wlv->col = wp->w_grid.cols - 1; + wlv->off += wlv->col; + } +} + /// Display line "lnum" of window 'wp' on the screen. /// wp->w_virtcol needs to be valid. /// @@ -621,23 +665,15 @@ static colnr_T get_leadcol(win_T *wp, const char *ptr, const char *line) int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, bool number_only, foldinfo_T foldinfo, DecorProviders *providers, char **provider_err) { + winlinevars_T wlv; // variables passed between functions + int c = 0; // init for GCC - colnr_T vcol = 0; // virtual column (for tabs) long vcol_sbr = -1; // virtual column after showbreak - long vcol_prev = -1; // "vcol" of previous character + long vcol_prev = -1; // "wlv.vcol" of previous character char *line; // current line char *ptr; // current position in "line" - int row; // row in the window, excl w_winrow ScreenGrid *grid = &wp->w_grid; // grid specific to the window - char extra[57]; // sign, line number and 'fdc' must - // fit in here - int n_extra = 0; // number of extra chars - char *p_extra = NULL; // string of extra chars, plus NUL - char *p_extra_free = NULL; // p_extra needs to be freed - int c_extra = NUL; // extra chars, all the same - int c_final = NUL; // final char, mandatory if set - int extra_attr = 0; // attributes when n_extra != 0 static char *at_end_str = ""; // used for p_extra when displaying curwin->w_p_lcs_chars.eol // at end-of-line bool has_fold = foldinfo.fi_level != 0 && foldinfo.fi_lines > 0; @@ -664,7 +700,6 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, pos_T pos; ptrdiff_t v; - int char_attr = 0; // attributes for next character bool attr_pri = false; // char_attr has priority bool area_highlighting = false; // Visual or incsearch highlighting in this line int vi_attr = 0; // attributes for Visual and incsearch highlighting @@ -697,17 +732,13 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, int mb_c = 0; // decoded multi-byte character bool mb_utf8 = false; // screen char is UTF-8 char int u8cc[MAX_MCO]; // composing UTF-8 chars - int filler_lines; // nr of filler lines to be drawn - int filler_todo; // nr of filler lines still to do + 1 hlf_T diff_hlf = (hlf_T)0; // type of diff highlighting 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 int multispace_pos = 0; // position in lcs-multispace string bool need_showbreak = false; // overlong line, skip first x chars - int line_attr = 0; // attribute for the whole line int line_attr_save; - int line_attr_lowprio = 0; // low-priority attribute for the line int line_attr_lowprio_save; int prev_c = 0; // previous Arabic character int prev_c1 = 0; // first composing char for prev_c @@ -720,7 +751,6 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, bool area_active = false; - int cul_attr = 0; // set when 'cursorline' active // 'cursorlineopt' has "screenline" and cursor is in this line bool cul_screenline = false; // margin columns for the screen line, needed for when 'cursorlineopt' @@ -728,8 +758,6 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, int left_curline_col = 0; int right_curline_col = 0; - LineDrawState draw_state = WL_START; // what to draw next - int match_conc = 0; ///< cchar for match functions bool on_last_col = false; int syntax_flags = 0; @@ -737,27 +765,28 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, int prev_syntax_id = 0; int conceal_attr = win_hl_attr(wp, HLF_CONCEAL); bool is_concealing = false; - int boguscols = 0; ///< nonexistent columns added to - ///< force wrapping - int vcol_off = 0; ///< offset for concealed characters int did_wcol = false; int old_boguscols = 0; -#define VCOL_HLC (vcol - vcol_off) +#define VCOL_HLC (wlv.vcol - wlv.vcol_off) #define FIX_FOR_BOGUSCOLS \ { \ - n_extra += vcol_off; \ - vcol -= vcol_off; \ - vcol_off = 0; \ - col -= boguscols; \ - old_boguscols = boguscols; \ - boguscols = 0; \ + 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; \ } if (startrow > endrow) { // past the end already! return startrow; } - row = startrow; + CLEAR_FIELD(wlv); + + wlv.lnum = lnum; + wlv.startrow = startrow; + wlv.row = startrow; buf_T *buf = wp->w_buffer; bool end_fill = (lnum == buf->b_ml.ml_line_count + 1); @@ -935,9 +964,9 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, int bg_attr = win_bg_attr(wp); int linestatus = 0; - filler_lines = diff_check_with_linestatus(wp, lnum, &linestatus); - if (filler_lines < 0 || linestatus < 0) { - if (filler_lines == -1 || linestatus == -1) { + wlv.filler_lines = diff_check_with_linestatus(wp, lnum, &linestatus); + if (wlv.filler_lines < 0 || linestatus < 0) { + if (wlv.filler_lines == -1 || linestatus == -1) { if (diff_find_change(wp, lnum, &change_start, &change_end)) { diff_hlf = HLF_ADD; // added line } else if (change_start == 0) { @@ -949,18 +978,18 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, diff_hlf = HLF_ADD; // added line } if (linestatus == 0) { - filler_lines = 0; + wlv.filler_lines = 0; } area_highlighting = true; } VirtLines virt_lines = KV_INITIAL_VALUE; int n_virt_lines = decor_virt_lines(wp, lnum, &virt_lines, has_fold); - filler_lines += n_virt_lines; + wlv.filler_lines += n_virt_lines; if (lnum == wp->w_topline) { - filler_lines = wp->w_topfill; - n_virt_lines = MIN(n_virt_lines, filler_lines); + wlv.filler_lines = wp->w_topfill; + n_virt_lines = MIN(n_virt_lines, wlv.filler_lines); } - filler_todo = filler_lines; + wlv.filler_todo = wlv.filler_lines; // Cursor line highlighting for 'cursorline' in the current window. if (wp->w_p_cul && wp->w_p_culopt_flags != CULOPT_NBR && lnum == wp->w_cursorline @@ -969,31 +998,29 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, && !(wp == curwin && VIsual_active)) { cul_screenline = (wp->w_p_wrap && (wp->w_p_culopt_flags & CULOPT_SCRLINE)); if (!cul_screenline) { - apply_cursorline_highlight(wp, lnum, &line_attr, &cul_attr, &line_attr_lowprio); + apply_cursorline_highlight(wp, &wlv); } else { margin_columns_win(wp, &left_curline_col, &right_curline_col); } area_highlighting = true; } - SignTextAttrs sattrs[SIGN_SHOW_MAX]; // sign attributes for the sign column int sign_num_attr = 0; // sign attribute for the number column int sign_cul_attr = 0; // sign attribute for cursorline - CLEAR_FIELD(sattrs); - int num_signs = get_sign_attrs(buf, lnum, sattrs, &line_attr, &sign_num_attr, &sign_cul_attr); + int num_signs = get_sign_attrs(buf, &wlv, &sign_num_attr, &sign_cul_attr); // Highlight the current line in the quickfix window. if (bt_quickfix(wp->w_buffer) && qf_current_entry(wp) == lnum) { - line_attr = win_hl_attr(wp, HLF_QFL); + wlv.line_attr = win_hl_attr(wp, HLF_QFL); } - if (line_attr_lowprio || line_attr) { + if (wlv.line_attr_lowprio || wlv.line_attr) { area_highlighting = true; } if (cul_screenline) { - line_attr_save = line_attr; - line_attr_lowprio_save = line_attr_lowprio; + line_attr_save = wlv.line_attr; + line_attr_lowprio_save = wlv.line_attr_lowprio; } line = end_fill ? "" : ml_get_buf(wp->w_buffer, lnum, false); @@ -1061,14 +1088,14 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, chartabsize_T cts; int charsize; - init_chartabsize_arg(&cts, wp, lnum, vcol, line, ptr); + init_chartabsize_arg(&cts, wp, lnum, wlv.vcol, line, ptr); while (cts.cts_vcol < v && *cts.cts_ptr != NUL) { charsize = win_lbr_chartabsize(&cts, NULL); cts.cts_vcol += charsize; prev_ptr = cts.cts_ptr; MB_PTR_ADV(cts.cts_ptr); } - vcol = cts.cts_vcol; + wlv.vcol = cts.cts_vcol; ptr = cts.cts_ptr; clear_chartabsize_arg(&cts); @@ -1078,31 +1105,31 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, // - 'virtualedit' is set, or // - the visual mode is active, // the end of the line may be before the start of the displayed part. - if (vcol < v && (wp->w_p_cuc - || draw_color_col - || virtual_active() - || (VIsual_active && wp->w_buffer == curwin->w_buffer))) { - vcol = (colnr_T)v; + if (wlv.vcol < v && (wp->w_p_cuc + || draw_color_col + || virtual_active() + || (VIsual_active && wp->w_buffer == curwin->w_buffer))) { + wlv.vcol = (colnr_T)v; } // Handle a character that's not completely on the screen: Put ptr at // that character but skip the first few screen characters. - if (vcol > v) { - vcol -= charsize; + if (wlv.vcol > v) { + wlv.vcol -= charsize; ptr = prev_ptr; // If the character fits on the screen, don't need to skip it. // Except for a TAB. if (utf_ptr2cells(ptr) >= charsize || *ptr == TAB) { - n_skip = (int)(v - vcol); + n_skip = (int)(v - wlv.vcol); } } // Adjust for when the inverted text is before the screen, // and when the start of the inverted text is before the screen. - if (tocol <= vcol) { + if (tocol <= wlv.vcol) { fromcol = 0; - } else if (fromcol >= 0 && fromcol < vcol) { - fromcol = vcol; + } else if (fromcol >= 0 && fromcol < wlv.vcol) { + fromcol = wlv.vcol; } // When w_skipcol is non-zero, first line needs 'showbreak' @@ -1176,15 +1203,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, ptr = line + v; // "line" may have been updated } - int off = 0; // Offset relative start of line - int col = 0; // Visual column on screen. - if (wp->w_p_rl) { - // Rightleft window: process the text in the normal direction, but put - // it in linebuf_char[off] from right to left. Start at the - // rightmost column of the window. - col = grid->cols - 1; - off += col; - } + win_line_start(wp, &wlv); // won't highlight after TERM_ATTRS_MAX columns int term_attrs[TERM_ATTRS_MAX] = { 0 }; @@ -1197,13 +1216,12 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, if (*wp->w_p_stc != NUL) { // Draw the 'statuscolumn' if option is set. statuscol.draw = true; - statuscol.sattrs = sattrs; + statuscol.sattrs = wlv.sattrs; statuscol.foldinfo = foldinfo; statuscol.width = win_col_off(wp) - (cmdwin_type != 0 && wp == curwin); statuscol.use_cul = use_cursor_line_sign(wp, lnum); statuscol.sign_cul_attr = statuscol.use_cul ? sign_cul_attr : 0; - statuscol.num_attr = sign_num_attr ? sign_num_attr - : get_line_number_attr(wp, lnum, row, startrow, filler_lines); + statuscol.num_attr = sign_num_attr ? sign_num_attr : get_line_number_attr(wp, &wlv); } int sign_idx = 0; @@ -1217,27 +1235,27 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, bool did_decrement_ptr = false; // Skip this quickly when working on the text. - if (draw_state != WL_LINE) { + if (wlv.draw_state != WL_LINE) { if (cul_screenline) { - cul_attr = 0; - line_attr = line_attr_save; - line_attr_lowprio = line_attr_lowprio_save; + wlv.cul_attr = 0; + wlv.line_attr = line_attr_save; + wlv.line_attr_lowprio = line_attr_lowprio_save; } - if (draw_state == WL_CMDLINE - 1 && n_extra == 0) { - draw_state = WL_CMDLINE; + if (wlv.draw_state == WL_CMDLINE - 1 && wlv.n_extra == 0) { + wlv.draw_state = WL_CMDLINE; if (cmdwin_type != 0 && wp == curwin) { // Draw the cmdline character. - n_extra = 1; - c_extra = cmdwin_type; - c_final = NUL; - char_attr = win_hl_attr(wp, HLF_AT); + wlv.n_extra = 1; + wlv.c_extra = cmdwin_type; + wlv.c_final = NUL; + wlv.char_attr = win_hl_attr(wp, HLF_AT); } } - if (draw_state == WL_FOLD - 1 && n_extra == 0) { - if (filler_todo > 0) { - int index = filler_todo - (filler_lines - n_virt_lines); + if (wlv.draw_state == WL_FOLD - 1 && wlv.n_extra == 0) { + if (wlv.filler_todo > 0) { + int index = wlv.filler_todo - (wlv.filler_lines - n_virt_lines); if (index > 0) { virt_line_index = (int)kv_size(virt_lines) - index; assert(virt_line_index >= 0); @@ -1246,152 +1264,143 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, } if (!virt_line_offset) { // Skip the column states if there is a "virt_left_col" line. - draw_state = WL_BRI - 1; + wlv.draw_state = WL_BRI - 1; } else if (statuscol.draw) { // Skip fold, sign and number states if 'statuscolumn' is set. - draw_state = WL_STC - 1; + wlv.draw_state = WL_STC - 1; } } - if (draw_state == WL_FOLD - 1 && n_extra == 0) { + if (wlv.draw_state == WL_FOLD - 1 && wlv.n_extra == 0) { int fdc = compute_foldcolumn(wp, 0); - draw_state = WL_FOLD; + wlv.draw_state = WL_FOLD; if (fdc > 0) { - // Draw the 'foldcolumn'. Allocate a buffer, "extra" may - // already be in use. - xfree(p_extra_free); - p_extra_free = xmalloc(MAX_MCO * (size_t)fdc + 1); - n_extra = (int)fill_foldcolumn(p_extra_free, wp, foldinfo, lnum); - p_extra_free[n_extra] = NUL; - p_extra = p_extra_free; - c_extra = NUL; - c_final = NUL; + // Draw the 'foldcolumn'. + // Allocate a buffer, "wlv->extra[]" may already be in use. + xfree(wlv.p_extra_free); + wlv.p_extra_free = xmalloc(MAX_MCO * (size_t)fdc + 1); + wlv.n_extra = (int)fill_foldcolumn(wlv.p_extra_free, wp, foldinfo, lnum); + wlv.p_extra_free[wlv.n_extra] = NUL; + wlv.p_extra = wlv.p_extra_free; + wlv.c_extra = NUL; + wlv.c_final = NUL; if (use_cursor_line_sign(wp, lnum)) { - char_attr = win_hl_attr(wp, HLF_CLF); + wlv.char_attr = win_hl_attr(wp, HLF_CLF); } else { - char_attr = win_hl_attr(wp, HLF_FC); + wlv.char_attr = win_hl_attr(wp, HLF_FC); } } } // sign column, this is hit until sign_idx reaches count - if (draw_state == WL_SIGN - 1 && n_extra == 0) { - draw_state = WL_SIGN; + if (wlv.draw_state == WL_SIGN - 1 && wlv.n_extra == 0) { + wlv.draw_state = WL_SIGN; // Show the sign column when there are any signs in this buffer if (wp->w_scwidth > 0) { - get_sign_display_info(false, wp, lnum, sattrs, row, - startrow, filler_lines, filler_todo, - &c_extra, &c_final, extra, sizeof(extra), - &p_extra, &n_extra, &char_attr, sign_idx, - sign_cul_attr); + get_sign_display_info(false, wp, &wlv, sign_idx, sign_cul_attr); sign_idx++; if (sign_idx < wp->w_scwidth) { - draw_state = WL_SIGN - 1; + wlv.draw_state = WL_SIGN - 1; } else { sign_idx = 0; } } } - if (draw_state == WL_NR - 1 && n_extra == 0) { - draw_state = WL_NR; + if (wlv.draw_state == WL_NR - 1 && wlv.n_extra == 0) { + wlv.draw_state = WL_NR; // Display the absolute or relative line number. After the // first fill with blanks when the 'n' flag isn't in 'cpo' if ((wp->w_p_nu || wp->w_p_rnu) - && (row == startrow + filler_lines + && (wlv.row == startrow + wlv.filler_lines || vim_strchr(p_cpo, CPO_NUMCOL) == NULL)) { // If 'signcolumn' is set to 'number' and a sign is present // in 'lnum', then display the sign instead of the line // number. if (*wp->w_p_scl == 'n' && *(wp->w_p_scl + 1) == 'u' && num_signs > 0) { - get_sign_display_info(true, wp, lnum, sattrs, row, - startrow, filler_lines, filler_todo, - &c_extra, &c_final, extra, sizeof(extra), - &p_extra, &n_extra, &char_attr, sign_idx, - sign_cul_attr); + get_sign_display_info(true, wp, &wlv, sign_idx, sign_cul_attr); } else { // Draw the line number (empty space after wrapping). - if (row == startrow + filler_lines) { - get_line_number_str(wp, lnum, extra, sizeof(extra)); + if (wlv.row == startrow + wlv.filler_lines) { + get_line_number_str(wp, lnum, wlv.extra, sizeof(wlv.extra)); if (wp->w_skipcol > 0) { - for (p_extra = extra; *p_extra == ' '; p_extra++) { - *p_extra = '-'; + for (wlv.p_extra = wlv.extra; *wlv.p_extra == ' '; wlv.p_extra++) { + *wlv.p_extra = '-'; } } if (wp->w_p_rl) { // reverse line numbers // like rl_mirror(), but keep the space at the end - char *p2 = skipwhite(extra); + char *p2 = skipwhite(wlv.extra); p2 = skiptowhite(p2) - 1; - for (char *p1 = skipwhite(extra); p1 < p2; p1++, p2--) { + for (char *p1 = skipwhite(wlv.extra); p1 < p2; p1++, p2--) { const char t = *p1; *p1 = *p2; *p2 = t; } } - p_extra = extra; - c_extra = NUL; + wlv.p_extra = wlv.extra; + wlv.c_extra = NUL; } else { - c_extra = ' '; + wlv.c_extra = ' '; } - c_final = NUL; - n_extra = number_width(wp) + 1; + wlv.c_final = NUL; + wlv.n_extra = number_width(wp) + 1; if (sign_num_attr > 0) { - char_attr = sign_num_attr; + wlv.char_attr = sign_num_attr; } else { - char_attr = get_line_number_attr(wp, lnum, row, startrow, filler_lines); + wlv.char_attr = get_line_number_attr(wp, &wlv); } } } } - if (draw_state == WL_STC - 1 && n_extra == 0) { - draw_state = WL_STC; + if (wlv.draw_state == WL_STC - 1 && wlv.n_extra == 0) { + wlv.draw_state = WL_STC; // Draw the 'statuscolumn' if option is set. if (statuscol.draw) { if (statuscol.textp == NULL) { - get_statuscol_str(wp, lnum, row - startrow - filler_lines, &statuscol); + get_statuscol_str(wp, lnum, wlv.row - startrow - wlv.filler_lines, &statuscol); if (wp->w_redr_statuscol) { break; } } - get_statuscol_display_info(&statuscol, &draw_state, &char_attr, - &n_extra, &c_extra, &c_final, &p_extra); + get_statuscol_display_info(&statuscol, &wlv); } } - if (draw_state == WL_STC && n_extra == 0) { - win_col_offset = off; + if (wlv.draw_state == WL_STC && wlv.n_extra == 0) { + win_col_offset = wlv.off; } - if (wp->w_briopt_sbr && draw_state == WL_BRI - 1 - && n_extra == 0 && *get_showbreak_value(wp) != NUL) { + if (wp->w_briopt_sbr && wlv.draw_state == WL_BRI - 1 + && wlv.n_extra == 0 && *get_showbreak_value(wp) != NUL) { // draw indent after showbreak value - draw_state = WL_BRI; - } else if (wp->w_briopt_sbr && draw_state == WL_SBR && n_extra == 0) { + wlv.draw_state = WL_BRI; + } else if (wp->w_briopt_sbr && wlv.draw_state == WL_SBR && wlv.n_extra == 0) { // after the showbreak, draw the breakindent - draw_state = WL_BRI - 1; + wlv.draw_state = WL_BRI - 1; } // draw 'breakindent': indent wrapped text accordingly - if (draw_state == WL_BRI - 1 && n_extra == 0) { - draw_state = WL_BRI; + if (wlv.draw_state == WL_BRI - 1 && wlv.n_extra == 0) { + wlv.draw_state = WL_BRI; // if need_showbreak is set, breakindent also applies - if (wp->w_p_bri && (row != startrow || need_showbreak) - && filler_lines == 0) { - char_attr = 0; + if (wp->w_p_bri && (wlv.row != startrow || need_showbreak) + && wlv.filler_lines == 0) { + wlv.char_attr = 0; if (diff_hlf != (hlf_T)0) { - char_attr = win_hl_attr(wp, (int)diff_hlf); + wlv.char_attr = win_hl_attr(wp, (int)diff_hlf); } - p_extra = NULL; - c_extra = ' '; - c_final = NUL; - n_extra = + wlv.p_extra = NULL; + wlv.c_extra = ' '; + wlv.c_final = NUL; + wlv.n_extra = get_breakindent_win(wp, ml_get_buf(wp->w_buffer, lnum, false)); - if (row == startrow) { - n_extra -= win_col_off2(wp); - if (n_extra < 0) { - n_extra = 0; + if (wlv.row == startrow) { + wlv.n_extra -= win_col_off2(wp); + if (wlv.n_extra < 0) { + wlv.n_extra = 0; } } if (wp->w_skipcol > 0 && wp->w_p_wrap && wp->w_briopt_sbr) { @@ -1399,174 +1408,174 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, } // Correct end of highlighted area for 'breakindent', // required wen 'linebreak' is also set. - if (tocol == vcol) { - tocol += n_extra; + if (tocol == wlv.vcol) { + tocol += wlv.n_extra; } } } - if (draw_state == WL_SBR - 1 && n_extra == 0) { - draw_state = WL_SBR; - if (filler_todo > filler_lines - n_virt_lines) { + if (wlv.draw_state == WL_SBR - 1 && wlv.n_extra == 0) { + wlv.draw_state = WL_SBR; + if (wlv.filler_todo > wlv.filler_lines - n_virt_lines) { // TODO(bfredl): check this doesn't inhibit TUI-style // clear-to-end-of-line. - c_extra = ' '; - c_final = NUL; + wlv.c_extra = ' '; + wlv.c_final = NUL; if (wp->w_p_rl) { - n_extra = col + 1; + wlv.n_extra = wlv.col + 1; } else { - n_extra = grid->cols - col; + wlv.n_extra = grid->cols - wlv.col; } - char_attr = 0; - } else if (filler_todo > 0) { + wlv.char_attr = 0; + } else if (wlv.filler_todo > 0) { // Draw "deleted" diff line(s) if (char2cells(wp->w_p_fcs_chars.diff) > 1) { - c_extra = '-'; - c_final = NUL; + wlv.c_extra = '-'; + wlv.c_final = NUL; } else { - c_extra = wp->w_p_fcs_chars.diff; - c_final = NUL; + wlv.c_extra = wp->w_p_fcs_chars.diff; + wlv.c_final = NUL; } if (wp->w_p_rl) { - n_extra = col + 1; + wlv.n_extra = wlv.col + 1; } else { - n_extra = grid->cols - col; + wlv.n_extra = grid->cols - wlv.col; } - char_attr = win_hl_attr(wp, HLF_DED); + wlv.char_attr = win_hl_attr(wp, HLF_DED); } char *const sbr = get_showbreak_value(wp); if (*sbr != NUL && need_showbreak) { // Draw 'showbreak' at the start of each broken line. - p_extra = sbr; - c_extra = NUL; - c_final = NUL; - n_extra = (int)strlen(sbr); - char_attr = win_hl_attr(wp, HLF_AT); + wlv.p_extra = sbr; + wlv.c_extra = NUL; + wlv.c_final = NUL; + wlv.n_extra = (int)strlen(sbr); + wlv.char_attr = win_hl_attr(wp, HLF_AT); if (wp->w_skipcol == 0 || !wp->w_p_wrap) { need_showbreak = false; } - vcol_sbr = vcol + mb_charlen(sbr); + vcol_sbr = wlv.vcol + mb_charlen(sbr); // Correct end of highlighted area for 'showbreak', // required when 'linebreak' is also set. - if (tocol == vcol) { - tocol += n_extra; + if (tocol == wlv.vcol) { + tocol += wlv.n_extra; } // Combine 'showbreak' with 'cursorline', prioritizing 'showbreak'. - if (cul_attr) { - char_attr = hl_combine_attr(cul_attr, char_attr); + if (wlv.cul_attr) { + wlv.char_attr = hl_combine_attr(wlv.cul_attr, wlv.char_attr); } } } - if (draw_state == WL_LINE - 1 && n_extra == 0) { + if (wlv.draw_state == WL_LINE - 1 && wlv.n_extra == 0) { sign_idx = 0; - draw_state = WL_LINE; + wlv.draw_state = WL_LINE; - if (has_decor && row == startrow + filler_lines) { + if (has_decor && wlv.row == startrow + wlv.filler_lines) { // hide virt_text on text hidden by 'nowrap' - decor_redraw_col(wp->w_buffer, vcol, off, true, &decor_state); + decor_redraw_col(wp->w_buffer, wlv.vcol, wlv.off, true, &decor_state); } if (saved_n_extra) { // Continue item from end of wrapped line. - n_extra = saved_n_extra; - c_extra = saved_c_extra; - c_final = saved_c_final; - p_extra = saved_p_extra; - char_attr = saved_char_attr; + wlv.n_extra = saved_n_extra; + wlv.c_extra = saved_c_extra; + wlv.c_final = saved_c_final; + wlv.p_extra = saved_p_extra; + wlv.char_attr = saved_char_attr; } else { - char_attr = 0; + wlv.char_attr = 0; } } } - if (cul_screenline && draw_state == WL_LINE - && vcol >= left_curline_col - && vcol < right_curline_col) { - apply_cursorline_highlight(wp, lnum, &line_attr, &cul_attr, &line_attr_lowprio); + if (cul_screenline && wlv.draw_state == WL_LINE + && wlv.vcol >= left_curline_col + && wlv.vcol < right_curline_col) { + apply_cursorline_highlight(wp, &wlv); } // When still displaying '$' of change command, stop at cursor if (((dollar_vcol >= 0 && wp == curwin && lnum == wp->w_cursor.lnum - && vcol >= (long)wp->w_virtcol) - || (number_only && draw_state > WL_STC)) - && filler_todo <= 0) { - draw_virt_text(wp, buf, win_col_offset, &col, grid->cols, row); - grid_put_linebuf(grid, row, 0, col, -grid->cols, wp->w_p_rl, wp, bg_attr, false); + && wlv.vcol >= (long)wp->w_virtcol) + || (number_only && wlv.draw_state > WL_STC)) + && wlv.filler_todo <= 0) { + draw_virt_text(wp, buf, win_col_offset, &wlv.col, grid->cols, wlv.row); + grid_put_linebuf(grid, wlv.row, 0, wlv.col, -grid->cols, wp->w_p_rl, wp, bg_attr, false); // Pretend we have finished updating the window. Except when // 'cursorcolumn' is set. if (wp->w_p_cuc) { - row = wp->w_cline_row + wp->w_cline_height; + wlv.row = wp->w_cline_row + wp->w_cline_height; } else { - row = grid->rows; + wlv.row = grid->rows; } break; } - if (draw_state == WL_LINE + if (wlv.draw_state == WL_LINE && has_fold - && col == win_col_offset - && n_extra == 0 - && row == startrow + filler_lines) { - char_attr = win_hl_attr(wp, HLF_FL); + && wlv.col == win_col_offset + && wlv.n_extra == 0 + && wlv.row == startrow + wlv.filler_lines) { + wlv.char_attr = win_hl_attr(wp, HLF_FL); linenr_T lnume = lnum + foldinfo.fi_lines - 1; memset(buf_fold, ' ', FOLD_TEXT_LEN); - p_extra = get_foldtext(wp, lnum, lnume, foldinfo, buf_fold); - n_extra = (int)strlen(p_extra); + wlv.p_extra = get_foldtext(wp, lnum, lnume, foldinfo, buf_fold); + wlv.n_extra = (int)strlen(wlv.p_extra); - if (p_extra != buf_fold) { - xfree(p_extra_free); - p_extra_free = p_extra; + if (wlv.p_extra != buf_fold) { + xfree(wlv.p_extra_free); + wlv.p_extra_free = wlv.p_extra; } - c_extra = NUL; - c_final = NUL; - p_extra[n_extra] = NUL; + wlv.c_extra = NUL; + wlv.c_final = NUL; + wlv.p_extra[wlv.n_extra] = NUL; } - if (draw_state == WL_LINE + if (wlv.draw_state == WL_LINE && has_fold - && col < grid->cols - && n_extra == 0 - && row == startrow + filler_lines) { + && wlv.col < grid->cols + && wlv.n_extra == 0 + && wlv.row == startrow + wlv.filler_lines) { // fill rest of line with 'fold' - c_extra = wp->w_p_fcs_chars.fold; - c_final = NUL; + wlv.c_extra = wp->w_p_fcs_chars.fold; + wlv.c_final = NUL; - n_extra = wp->w_p_rl ? (col + 1) : (grid->cols - col); + wlv.n_extra = wp->w_p_rl ? (wlv.col + 1) : (grid->cols - wlv.col); } - if (draw_state == WL_LINE + if (wlv.draw_state == WL_LINE && has_fold - && col >= grid->cols - && n_extra != 0 - && row == startrow + filler_lines) { + && wlv.col >= grid->cols + && wlv.n_extra != 0 + && wlv.row == startrow + wlv.filler_lines) { // Truncate the folding. - n_extra = 0; + wlv.n_extra = 0; } - if (draw_state == WL_LINE && (area_highlighting || has_spell)) { + if (wlv.draw_state == WL_LINE && (area_highlighting || has_spell)) { // handle Visual or match highlighting in this line - if (vcol == fromcol - || (vcol + 1 == fromcol && n_extra == 0 + if (wlv.vcol == fromcol + || (wlv.vcol + 1 == fromcol && wlv.n_extra == 0 && utf_ptr2cells(ptr) > 1) || ((int)vcol_prev == fromcol_prev - && vcol_prev < vcol // not at margin - && vcol < tocol)) { + && vcol_prev < wlv.vcol // not at margin + && wlv.vcol < tocol)) { area_attr = vi_attr; // start highlighting if (area_highlighting) { area_active = true; } - } else if (area_attr != 0 && (vcol == tocol + } else if (area_attr != 0 && (wlv.vcol == tocol || (noinvcur - && vcol == wp->w_virtcol))) { + && wlv.vcol == wp->w_virtcol))) { area_attr = 0; // stop highlighting area_active = false; } - if (!n_extra) { + if (!wlv.n_extra) { // Check for start/end of 'hlsearch' and other matches. // After end, check for start/end of next match. // When another match, have to check for start again. @@ -1585,20 +1594,20 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, if (diff_hlf != (hlf_T)0) { if (diff_hlf == HLF_CHD && ptr - line >= change_start - && n_extra == 0) { + && wlv.n_extra == 0) { diff_hlf = HLF_TXD; // changed text } if (diff_hlf == HLF_TXD && ptr - line > change_end - && n_extra == 0) { + && wlv.n_extra == 0) { diff_hlf = HLF_CHD; // changed line } - line_attr = win_hl_attr(wp, (int)diff_hlf); + wlv.line_attr = win_hl_attr(wp, (int)diff_hlf); // Overlay CursorLine onto diff-mode highlight. - if (cul_attr) { - line_attr = 0 != line_attr_lowprio // Low-priority CursorLine - ? hl_combine_attr(hl_combine_attr(cul_attr, line_attr), + if (wlv.cul_attr) { + wlv.line_attr = 0 != wlv.line_attr_lowprio // Low-priority CursorLine + ? hl_combine_attr(hl_combine_attr(wlv.cul_attr, wlv.line_attr), hl_get_underline()) - : hl_combine_attr(line_attr, cul_attr); + : hl_combine_attr(wlv.line_attr, wlv.cul_attr); } } @@ -1606,25 +1615,25 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, attr_pri = true; if (area_attr != 0) { - char_attr = hl_combine_attr(line_attr, area_attr); + wlv.char_attr = hl_combine_attr(wlv.line_attr, area_attr); if (!highlight_match) { // let search highlight show in Visual area if possible - char_attr = hl_combine_attr(search_attr, char_attr); + wlv.char_attr = hl_combine_attr(search_attr, wlv.char_attr); } } else if (search_attr != 0) { - char_attr = hl_combine_attr(line_attr, search_attr); - } else if (line_attr != 0 && ((fromcol == -10 && tocol == MAXCOL) - || vcol < fromcol || vcol_prev < fromcol_prev - || vcol >= tocol)) { - // Use line_attr when not in the Visual or 'incsearch' area + wlv.char_attr = hl_combine_attr(wlv.line_attr, search_attr); + } else if (wlv.line_attr != 0 && ((fromcol == -10 && tocol == MAXCOL) + || wlv.vcol < fromcol || vcol_prev < fromcol_prev + || wlv.vcol >= tocol)) { + // Use wlv.line_attr when not in the Visual or 'incsearch' area // (area_attr may be 0 when "noinvcur" is set). - char_attr = line_attr; + wlv.char_attr = wlv.line_attr; } else { attr_pri = false; if (has_syntax) { - char_attr = syntax_attr; + wlv.char_attr = syntax_attr; } else { - char_attr = 0; + wlv.char_attr = 0; } } } @@ -1638,23 +1647,23 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, // "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 (n_extra > 0) { - if (c_extra != NUL || (n_extra == 1 && c_final != NUL)) { - c = (n_extra == 1 && c_final != NUL) ? c_final : c_extra; + if (wlv.n_extra > 0) { + if (wlv.c_extra != NUL || (wlv.n_extra == 1 && wlv.c_final != NUL)) { + c = (wlv.n_extra == 1 && wlv.c_final != NUL) ? wlv.c_final : wlv.c_extra; mb_c = c; // doesn't handle non-utf-8 multi-byte! mb_utf8 = check_mb_utf8(&c, u8cc); } else { - assert(p_extra != NULL); - c = (uint8_t)(*p_extra); + assert(wlv.p_extra != NULL); + c = (uint8_t)(*wlv.p_extra); mb_c = c; // If the UTF-8 character is more than one byte: // Decode it into "mb_c". - mb_l = utfc_ptr2len(p_extra); + mb_l = utfc_ptr2len(wlv.p_extra); mb_utf8 = false; - if (mb_l > n_extra) { + if (mb_l > wlv.n_extra) { mb_l = 1; } else if (mb_l > 1) { - mb_c = utfc_ptr2char(p_extra, u8cc); + mb_c = utfc_ptr2char(wlv.p_extra, u8cc); mb_utf8 = true; c = 0xc0; } @@ -1663,7 +1672,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, } // If a double-width char doesn't fit display a '>' in the last column. - if ((wp->w_p_rl ? (col <= 0) : (col >= grid->cols - 1)) + if ((wp->w_p_rl ? (wlv.col <= 0) : (wlv.col >= grid->cols - 1)) && utf_char2cells(mb_c) == 2) { c = '>'; mb_c = c; @@ -1671,23 +1680,23 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, (void)mb_l; multi_attr = win_hl_attr(wp, HLF_AT); - if (cul_attr) { - multi_attr = 0 != line_attr_lowprio - ? hl_combine_attr(cul_attr, multi_attr) - : hl_combine_attr(multi_attr, cul_attr); + if (wlv.cul_attr) { + multi_attr = 0 != wlv.line_attr_lowprio + ? hl_combine_attr(wlv.cul_attr, multi_attr) + : hl_combine_attr(multi_attr, wlv.cul_attr); } // put the pointer back to output the double-width // character at the start of the next line. - n_extra++; - p_extra--; + wlv.n_extra++; + wlv.p_extra--; } else { - n_extra -= mb_l - 1; - p_extra += mb_l - 1; + wlv.n_extra -= mb_l - 1; + wlv.p_extra += mb_l - 1; } - p_extra++; + wlv.p_extra++; } - n_extra--; + wlv.n_extra--; } else if (foldinfo.fi_lines > 0) { // skip writing the buffer line itself c = NUL; @@ -1726,22 +1735,22 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, || (mb_l > 1 && (!vim_isprintc(mb_c)))) { // Illegal UTF-8 byte: display as <xx>. // Non-BMP character : display as ? or fullwidth ?. - transchar_hex(extra, mb_c); + transchar_hex(wlv.extra, mb_c); if (wp->w_p_rl) { // reverse - rl_mirror(extra); + rl_mirror(wlv.extra); } - p_extra = extra; - c = (uint8_t)(*p_extra); - mb_c = mb_ptr2char_adv((const char **)&p_extra); + wlv.p_extra = wlv.extra; + c = (uint8_t)(*wlv.p_extra); + mb_c = mb_ptr2char_adv((const char **)&wlv.p_extra); mb_utf8 = (c >= 0x80); - n_extra = (int)strlen(p_extra); - c_extra = NUL; - c_final = NUL; + wlv.n_extra = (int)strlen(wlv.p_extra); + wlv.c_extra = NUL; + wlv.c_final = NUL; if (area_attr == 0 && search_attr == 0) { - n_attr = n_extra + 1; - extra_attr = win_hl_attr(wp, HLF_8); - saved_attr2 = char_attr; // save current attr + n_attr = wlv.n_extra + 1; + wlv.extra_attr = win_hl_attr(wp, HLF_8); + saved_attr2 = wlv.char_attr; // save current attr } } else if (mb_l == 0) { // at the NUL at end-of-line mb_l = 1; @@ -1771,8 +1780,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, // If a double-width char doesn't fit display a '>' in the // last column; the character is displayed at the start of the // next line. - if ((wp->w_p_rl ? (col <= 0) : - (col >= grid->cols - 1)) + if ((wp->w_p_rl ? (wlv.col <= 0) : (wlv.col >= grid->cols - 1)) && utf_char2cells(mb_c) == 2) { c = '>'; mb_c = c; @@ -1789,15 +1797,15 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, // If a double-width char doesn't fit at the left side display a '<' in // the first column. Don't do this for unprintable characters. - if (n_skip > 0 && mb_l > 1 && n_extra == 0) { - n_extra = 1; - c_extra = MB_FILLER_CHAR; - c_final = NUL; + if (n_skip > 0 && mb_l > 1 && wlv.n_extra == 0) { + wlv.n_extra = 1; + wlv.c_extra = MB_FILLER_CHAR; + wlv.c_final = NUL; c = ' '; if (area_attr == 0 && search_attr == 0) { - n_attr = n_extra + 1; - extra_attr = win_hl_attr(wp, HLF_AT); - saved_attr2 = char_attr; // save current attr + n_attr = wlv.n_extra + 1; + wlv.extra_attr = win_hl_attr(wp, HLF_AT); + saved_attr2 = wlv.char_attr; // save current attr } mb_c = c; mb_utf8 = false; @@ -1838,15 +1846,15 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, ptr = line + v; if (!attr_pri) { - if (cul_attr) { - char_attr = 0 != line_attr_lowprio - ? hl_combine_attr(cul_attr, syntax_attr) - : hl_combine_attr(syntax_attr, cul_attr); + if (wlv.cul_attr) { + wlv.char_attr = 0 != wlv.line_attr_lowprio + ? hl_combine_attr(wlv.cul_attr, syntax_attr) + : hl_combine_attr(syntax_attr, wlv.cul_attr); } else { - char_attr = syntax_attr; + wlv.char_attr = syntax_attr; } } else { - char_attr = hl_combine_attr(syntax_attr, char_attr); + wlv.char_attr = hl_combine_attr(syntax_attr, wlv.char_attr); } // no concealing past the end of the line, it interferes // with line highlighting. @@ -1856,19 +1864,19 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, syntax_flags = get_syntax_info(&syntax_seqnr); } } else if (!attr_pri) { - char_attr = 0; + wlv.char_attr = 0; } if (has_decor && v > 0) { bool selected = (area_active || (area_highlighting && noinvcur - && vcol == wp->w_virtcol)); - int extmark_attr = decor_redraw_col(wp->w_buffer, (colnr_T)v - 1, off, + && wlv.vcol == wp->w_virtcol)); + int extmark_attr = decor_redraw_col(wp->w_buffer, (colnr_T)v - 1, wlv.off, selected, &decor_state); if (extmark_attr != 0) { if (!attr_pri) { - char_attr = hl_combine_attr(char_attr, extmark_attr); + wlv.char_attr = hl_combine_attr(wlv.char_attr, extmark_attr); } else { - char_attr = hl_combine_attr(extmark_attr, char_attr); + wlv.char_attr = hl_combine_attr(extmark_attr, wlv.char_attr); } } @@ -1888,7 +1896,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, if (has_spell && v >= word_end && v > cur_checked_col) { spell_attr = 0; if (!attr_pri) { - char_attr = hl_combine_attr(char_attr, syntax_attr); + wlv.char_attr = hl_combine_attr(wlv.char_attr, syntax_attr); } if (c != 0 && ((!has_syntax && !no_plain_buffer) || can_spell)) { char *prev_ptr; @@ -1953,14 +1961,14 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, } if (spell_attr != 0) { if (!attr_pri) { - char_attr = hl_combine_attr(char_attr, spell_attr); + wlv.char_attr = hl_combine_attr(wlv.char_attr, spell_attr); } else { - char_attr = hl_combine_attr(spell_attr, char_attr); + wlv.char_attr = hl_combine_attr(spell_attr, wlv.char_attr); } } if (wp->w_buffer->terminal) { - char_attr = hl_combine_attr(term_attrs[vcol], char_attr); + wlv.char_attr = hl_combine_attr(term_attrs[wlv.vcol], wlv.char_attr); } // Found last space before word: check for line break. @@ -1970,15 +1978,15 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, char *p = ptr - (mb_off + 1); chartabsize_T cts; - init_chartabsize_arg(&cts, wp, lnum, vcol, line, p); - n_extra = win_lbr_chartabsize(&cts, NULL) - 1; + init_chartabsize_arg(&cts, wp, lnum, wlv.vcol, line, p); + wlv.n_extra = win_lbr_chartabsize(&cts, NULL) - 1; // We have just drawn the showbreak value, no need to add // space for it again. - if (vcol == vcol_sbr) { - n_extra -= mb_charlen(get_showbreak_value(wp)); - if (n_extra < 0) { - n_extra = 0; + if (wlv.vcol == vcol_sbr) { + wlv.n_extra -= mb_charlen(get_showbreak_value(wp)); + if (wlv.n_extra < 0) { + wlv.n_extra = 0; } } if (on_last_col && c != TAB) { @@ -1988,12 +1996,12 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, search_attr = 0; } - if (c == TAB && n_extra + col > grid->cols) { - n_extra = tabstop_padding(vcol, wp->w_buffer->b_p_ts, - wp->w_buffer->b_p_vts_array) - 1; + if (c == TAB && wlv.n_extra + wlv.col > grid->cols) { + wlv.n_extra = tabstop_padding(wlv.vcol, wp->w_buffer->b_p_ts, + wp->w_buffer->b_p_vts_array) - 1; } - c_extra = mb_off > 0 ? MB_FILLER_CHAR : ' '; - c_final = NUL; + wlv.c_extra = mb_off > 0 ? MB_FILLER_CHAR : ' '; + wlv.c_final = NUL; if (ascii_iswhite(c)) { if (c == TAB) { // See "Tab alignment" below. @@ -2035,8 +2043,8 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, c = (c == ' ') ? wp->w_p_lcs_chars.space : wp->w_p_lcs_chars.nbsp; } n_attr = 1; - extra_attr = win_hl_attr(wp, HLF_0); - saved_attr2 = char_attr; // save current attr + wlv.extra_attr = win_hl_attr(wp, HLF_0); + saved_attr2 = wlv.char_attr; // save current attr mb_c = c; mb_utf8 = check_mb_utf8(&c, u8cc); } @@ -2058,8 +2066,8 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, } n_attr = 1; - extra_attr = win_hl_attr(wp, HLF_0); - saved_attr2 = char_attr; // save current attr + wlv.extra_attr = win_hl_attr(wp, HLF_0); + saved_attr2 = wlv.char_attr; // save current attr mb_c = c; mb_utf8 = check_mb_utf8(&c, u8cc); } @@ -2071,13 +2079,13 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, // turn it into something else on the way to putting it on the screen. if (c == TAB && (!wp->w_p_list || wp->w_p_lcs_chars.tab1)) { int tab_len = 0; - long vcol_adjusted = vcol; // removed showbreak length + long vcol_adjusted = wlv.vcol; // removed showbreak length char *const sbr = get_showbreak_value(wp); // Only adjust the tab_len, when at the first column after the // showbreak value was drawn. - if (*sbr != NUL && vcol == vcol_sbr && wp->w_p_wrap) { - vcol_adjusted = vcol - mb_charlen(sbr); + if (*sbr != NUL && wlv.vcol == vcol_sbr && wp->w_p_wrap) { + vcol_adjusted = wlv.vcol - mb_charlen(sbr); } // tab amount depends on current column tab_len = tabstop_padding((colnr_T)vcol_adjusted, @@ -2085,23 +2093,23 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, wp->w_buffer->b_p_vts_array) - 1; if (!wp->w_p_lbr || !wp->w_p_list) { - n_extra = tab_len; + wlv.n_extra = tab_len; } else { char *p; - int saved_nextra = n_extra; + int saved_nextra = wlv.n_extra; - if (vcol_off > 0) { + if (wlv.vcol_off > 0) { // there are characters to conceal - tab_len += vcol_off; + tab_len += wlv.vcol_off; } // boguscols before FIX_FOR_BOGUSCOLS macro from above. if (wp->w_p_lcs_chars.tab1 && old_boguscols > 0 - && n_extra > tab_len) { - tab_len += n_extra - tab_len; + && wlv.n_extra > tab_len) { + tab_len += wlv.n_extra - tab_len; } if (tab_len > 0) { - // If n_extra > 0, it gives the number of chars + // 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); @@ -2109,15 +2117,15 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, if (wp->w_p_lcs_chars.tab3) { len += utf_char2len(wp->w_p_lcs_chars.tab3) - tab2_len; } - if (n_extra > 0) { - len += n_extra - tab_len; + if (wlv.n_extra > 0) { + len += wlv.n_extra - tab_len; } c = wp->w_p_lcs_chars.tab1; p = xmalloc((size_t)len + 1); memset(p, ' ', (size_t)len); p[len] = NUL; - xfree(p_extra_free); - p_extra_free = p; + xfree(wlv.p_extra_free); + wlv.p_extra_free = p; for (int i = 0; i < tab_len; i++) { if (*p == NUL) { tab_len = i; @@ -2130,20 +2138,20 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, lcs = wp->w_p_lcs_chars.tab3; } p += utf_char2bytes(lcs, p); - n_extra += utf_char2len(lcs) - (saved_nextra > 0 ? 1 : 0); + wlv.n_extra += utf_char2len(lcs) - (saved_nextra > 0 ? 1 : 0); } - p_extra = p_extra_free; + wlv.p_extra = wlv.p_extra_free; // n_extra will be increased by FIX_FOX_BOGUSCOLS // macro below, so need to adjust for that here - if (vcol_off > 0) { - n_extra -= vcol_off; + if (wlv.vcol_off > 0) { + wlv.n_extra -= wlv.vcol_off; } } } { - int vc_saved = vcol_off; + int vc_saved = wlv.vcol_off; // Tab alignment should be identical regardless of // 'conceallevel' value. So tab compensates of all @@ -2156,7 +2164,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, // Make sure, the highlighting for the tab char will be // correctly set further below (effectively reverts the // FIX_FOR_BOGSUCOLS macro). - if (n_extra == tab_len + vc_saved && wp->w_p_list + if (wlv.n_extra == tab_len + vc_saved && wp->w_p_list && wp->w_p_lcs_chars.tab1) { tab_len += vc_saved; } @@ -2164,50 +2172,50 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, mb_utf8 = false; // don't draw as UTF-8 if (wp->w_p_list) { - c = (n_extra == 0 && wp->w_p_lcs_chars.tab3) + c = (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 && p_extra != NULL && *p_extra != NUL) { - c_extra = NUL; // using p_extra from above + if (wp->w_p_lbr && wlv.p_extra != NULL && *wlv.p_extra != NUL) { + wlv.c_extra = NUL; // using p_extra from above } else { - c_extra = wp->w_p_lcs_chars.tab2; + wlv.c_extra = wp->w_p_lcs_chars.tab2; } - c_final = wp->w_p_lcs_chars.tab3; + wlv.c_final = wp->w_p_lcs_chars.tab3; n_attr = tab_len + 1; - extra_attr = win_hl_attr(wp, HLF_0); - saved_attr2 = char_attr; // save current attr + wlv.extra_attr = win_hl_attr(wp, HLF_0); + saved_attr2 = wlv.char_attr; // save current attr mb_c = c; mb_utf8 = check_mb_utf8(&c, u8cc); } else { - c_final = NUL; - c_extra = ' '; + wlv.c_final = NUL; + wlv.c_extra = ' '; c = ' '; } } else if (c == NUL && (wp->w_p_list || ((fromcol >= 0 || fromcol_prev >= 0) - && tocol > vcol + && tocol > wlv.vcol && VIsual_mode != Ctrl_V - && (wp->w_p_rl ? (col >= 0) : (col < grid->cols)) + && (wp->w_p_rl ? (wlv.col >= 0) : (wlv.col < grid->cols)) && !(noinvcur && lnum == wp->w_cursor.lnum - && vcol == wp->w_virtcol))) + && wlv.vcol == wp->w_virtcol))) && lcs_eol_one > 0) { // 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 "$". if (diff_hlf == (hlf_T)0 - && line_attr == 0 - && line_attr_lowprio == 0) { + && wlv.line_attr == 0 + && wlv.line_attr_lowprio == 0) { // In virtualedit, visual selections may extend beyond end of line if (area_highlighting && virtual_active() - && tocol != MAXCOL && vcol < tocol) { - n_extra = 0; + && tocol != MAXCOL && wlv.vcol < tocol) { + wlv.n_extra = 0; } else { - p_extra = at_end_str; - n_extra = 1; - c_extra = NUL; - c_final = NUL; + wlv.p_extra = at_end_str; + wlv.n_extra = 1; + wlv.c_extra = NUL; + wlv.c_final = NUL; } } if (wp->w_p_list && wp->w_p_lcs_chars.eol > 0) { @@ -2217,46 +2225,46 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, } lcs_eol_one = -1; ptr--; // put it back at the NUL - extra_attr = win_hl_attr(wp, HLF_AT); + wlv.extra_attr = win_hl_attr(wp, HLF_AT); n_attr = 1; mb_c = c; mb_utf8 = check_mb_utf8(&c, u8cc); } else if (c != NUL) { - p_extra = (char *)transchar_buf(wp->w_buffer, c); - if (n_extra == 0) { - n_extra = byte2cells(c) - 1; + wlv.p_extra = (char *)transchar_buf(wp->w_buffer, c); + if (wlv.n_extra == 0) { + wlv.n_extra = byte2cells(c) - 1; } if ((dy_flags & DY_UHEX) && wp->w_p_rl) { - rl_mirror(p_extra); // reverse "<12>" + rl_mirror(wlv.p_extra); // reverse "<12>" } - c_extra = NUL; - c_final = NUL; + wlv.c_extra = NUL; + wlv.c_final = NUL; if (wp->w_p_lbr) { char *p; - c = (uint8_t)(*p_extra); - p = xmalloc((size_t)n_extra + 1); - memset(p, ' ', (size_t)n_extra); + c = (uint8_t)(*wlv.p_extra); + p = xmalloc((size_t)wlv.n_extra + 1); + memset(p, ' ', (size_t)wlv.n_extra); strncpy(p, // NOLINT(runtime/printf) - p_extra + 1, - (size_t)strlen(p_extra) - 1); - p[n_extra] = NUL; - xfree(p_extra_free); - p_extra_free = p_extra = p; + wlv.p_extra + 1, + (size_t)strlen(wlv.p_extra) - 1); + p[wlv.n_extra] = NUL; + xfree(wlv.p_extra_free); + wlv.p_extra_free = wlv.p_extra = p; } else { - n_extra = byte2cells(c) - 1; - c = (uint8_t)(*p_extra++); + wlv.n_extra = byte2cells(c) - 1; + c = (uint8_t)(*wlv.p_extra++); } - n_attr = n_extra + 1; - extra_attr = win_hl_attr(wp, HLF_8); - saved_attr2 = char_attr; // save current attr + n_attr = wlv.n_extra + 1; + wlv.extra_attr = win_hl_attr(wp, HLF_8); + saved_attr2 = wlv.char_attr; // save current attr mb_utf8 = false; // don't draw as UTF-8 } else if (VIsual_active && (VIsual_mode == Ctrl_V || VIsual_mode == 'v') && virtual_active() && tocol != MAXCOL - && vcol < tocol - && (wp->w_p_rl ? (col >= 0) : (col < grid->cols))) { + && wlv.vcol < tocol + && (wp->w_p_rl ? (wlv.col >= 0) : (wlv.col < grid->cols))) { c = ' '; ptr--; // put it back at the NUL } @@ -2266,7 +2274,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, && (wp != curwin || lnum != wp->w_cursor.lnum || conceal_cursor_line(wp)) && ((syntax_flags & HL_CONCEAL) != 0 || has_match_conc > 0 || decor_conceal > 0) && !(lnum_in_visual_area && vim_strchr(wp->w_p_cocu, 'v') == NULL)) { - char_attr = conceal_attr; + wlv.char_attr = conceal_attr; if (((prev_syntax_id != syntax_seqnr && (syntax_flags & HL_CONCEAL) != 0) || has_match_conc > 1 || decor_conceal > 1) && (syn_get_sub_char() != NUL @@ -2281,7 +2289,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, } else if (decor_conceal && decor_state.conceal_char) { c = decor_state.conceal_char; if (decor_state.conceal_attr) { - char_attr = decor_state.conceal_attr; + wlv.char_attr = decor_state.conceal_attr; } } else if (syn_get_sub_char() != NUL) { c = syn_get_sub_char(); @@ -2293,20 +2301,20 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, prev_syntax_id = syntax_seqnr; - if (n_extra > 0) { - vcol_off += n_extra; + if (wlv.n_extra > 0) { + wlv.vcol_off += wlv.n_extra; } - vcol += n_extra; - if (wp->w_p_wrap && n_extra > 0) { + wlv.vcol += wlv.n_extra; + if (wp->w_p_wrap && wlv.n_extra > 0) { if (wp->w_p_rl) { - col -= n_extra; - boguscols -= n_extra; + wlv.col -= wlv.n_extra; + wlv.boguscols -= wlv.n_extra; } else { - boguscols += n_extra; - col += n_extra; + wlv.boguscols += wlv.n_extra; + wlv.col += wlv.n_extra; } } - n_extra = 0; + wlv.n_extra = 0; n_attr = 0; } else if (n_skip == 0) { is_concealing = true; @@ -2327,23 +2335,23 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, // In the cursor line and we may be concealing characters: correct // the cursor column when we reach its position. - if (!did_wcol && draw_state == WL_LINE + if (!did_wcol && wlv.draw_state == WL_LINE && wp == curwin && lnum == wp->w_cursor.lnum && conceal_cursor_line(wp) - && (int)wp->w_virtcol <= vcol + n_skip) { + && (int)wp->w_virtcol <= wlv.vcol + n_skip) { if (wp->w_p_rl) { - wp->w_wcol = grid->cols - col + boguscols - 1; + wp->w_wcol = grid->cols - wlv.col + wlv.boguscols - 1; } else { - wp->w_wcol = col - boguscols; + wp->w_wcol = wlv.col - wlv.boguscols; } - wp->w_wrow = row; + wp->w_wrow = wlv.row; did_wcol = true; wp->w_valid |= VALID_WCOL|VALID_WROW|VALID_VIRTCOL; } // Don't override visual selection highlighting. - if (n_attr > 0 && draw_state == WL_LINE && !search_attr_from_match) { - char_attr = hl_combine_attr(char_attr, extra_attr); + if (n_attr > 0 && wlv.draw_state == WL_LINE && !search_attr_from_match) { + wlv.char_attr = hl_combine_attr(wlv.char_attr, wlv.extra_attr); } // Handle the case where we are in column 0 but not on the first @@ -2351,25 +2359,25 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, // special character (via 'listchars' option "precedes:<char>". if (lcs_prec_todo != NUL && wp->w_p_list - && (wp->w_p_wrap ? (wp->w_skipcol > 0 && row == 0) : wp->w_leftcol > 0) - && filler_todo <= 0 - && draw_state > WL_STC + && (wp->w_p_wrap ? (wp->w_skipcol > 0 && wlv.row == 0) : wp->w_leftcol > 0) + && wlv.filler_todo <= 0 + && wlv.draw_state > WL_STC && c != NUL) { c = wp->w_p_lcs_chars.prec; lcs_prec_todo = NUL; if (utf_char2cells(mb_c) > 1) { // Double-width character being overwritten by the "precedes" // character, need to fill up half the character. - c_extra = MB_FILLER_CHAR; - c_final = NUL; - n_extra = 1; + wlv.c_extra = MB_FILLER_CHAR; + wlv.c_final = NUL; + wlv.n_extra = 1; n_attr = 2; - extra_attr = win_hl_attr(wp, HLF_AT); + wlv.extra_attr = win_hl_attr(wp, HLF_AT); } mb_c = c; mb_utf8 = check_mb_utf8(&c, u8cc); - saved_attr3 = char_attr; // save current attr - char_attr = win_hl_attr(wp, HLF_AT); // overwriting char_attr + saved_attr3 = wlv.char_attr; // save current attr + wlv.char_attr = win_hl_attr(wp, HLF_AT); // overwriting char_attr n_attr3 = 1; } @@ -2385,7 +2393,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, // char on the screen, just overwrite that one (tricky!) Not // needed when a '$' was displayed for 'list'. if (wp->w_p_lcs_chars.eol == lcs_eol_one - && ((area_attr != 0 && vcol == fromcol + && ((area_attr != 0 && wlv.vcol == fromcol && (VIsual_mode != Ctrl_V || lnum == VIsual.lnum || lnum == curwin->w_cursor.lnum)) @@ -2394,22 +2402,22 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, int n = 0; if (wp->w_p_rl) { - if (col < 0) { + if (wlv.col < 0) { n = 1; } } else { - if (col >= grid->cols) { + if (wlv.col >= grid->cols) { n = -1; } } if (n != 0) { // At the window boundary, highlight the last character // instead (better than nothing). - off += n; - col += n; + wlv.off += n; + wlv.col += n; } else { // Add a blank character to highlight. - schar_from_ascii(linebuf_char[off], ' '); + schar_from_ascii(linebuf_char[wlv.off], ' '); } if (area_attr == 0 && !has_fold) { // Use attributes from match with highest priority among @@ -2417,24 +2425,28 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, get_search_match_hl(wp, &screen_search_hl, (long)(ptr - line), // NOLINT(google-readability-casting) - &char_attr); + &wlv.char_attr); } - int eol_attr = char_attr; - if (cul_attr) { - eol_attr = hl_combine_attr(cul_attr, eol_attr); + int eol_attr = wlv.char_attr; + if (wlv.cul_attr) { + eol_attr = hl_combine_attr(wlv.cul_attr, eol_attr); } - linebuf_attr[off] = eol_attr; + linebuf_attr[wlv.off] = eol_attr; if (wp->w_p_rl) { - col--; - off--; + wlv.col--; + wlv.off--; } else { - col++; - off++; + wlv.col++; + wlv.off++; } - vcol++; + wlv.vcol++; eol_hl_off = 1; } + } + + // At end of the text line. + if (c == NUL) { // Highlight 'cursorcolumn' & 'colorcolumn' past end of the line. if (wp->w_p_wrap) { v = wp->w_skipcol; @@ -2443,13 +2455,13 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, } // check if line ends before left margin - if (vcol < v + col - win_col_off(wp)) { - vcol = (colnr_T)v + col - win_col_off(wp); + if (wlv.vcol < v + wlv.col - win_col_off(wp)) { + wlv.vcol = (colnr_T)v + wlv.col - win_col_off(wp); } // Get rid of the boguscols now, we want to draw until the right // edge for 'cursorcolumn'. - col -= boguscols; - // boguscols = 0; // Disabled because value never read after this + wlv.col -= wlv.boguscols; + wlv.boguscols = 0; if (draw_color_col) { draw_color_col = advance_color_col(VCOL_HLC, &color_cols); @@ -2462,16 +2474,16 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, ? 1 : 0); if (has_decor) { - has_virttext = decor_redraw_eol(wp->w_buffer, &decor_state, &line_attr, - col + eol_skip); + has_virttext = decor_redraw_eol(wp->w_buffer, &decor_state, &wlv.line_attr, + wlv.col + eol_skip); } if (((wp->w_p_cuc && (int)wp->w_virtcol >= VCOL_HLC - eol_hl_off && (int)wp->w_virtcol < - (long)grid->cols * (row - startrow + 1) + v + (long)grid->cols * (wlv.row - startrow + 1) + v && lnum != wp->w_cursor.lnum) - || draw_color_col || line_attr_lowprio || line_attr + || draw_color_col || wlv.line_attr_lowprio || wlv.line_attr || diff_hlf != (hlf_T)0 || has_virttext)) { int rightmost_vcol = 0; @@ -2499,16 +2511,16 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, diff_attr = win_hl_attr(wp, (int)diff_hlf); } - int base_attr = hl_combine_attr(line_attr_lowprio, diff_attr); - if (base_attr || line_attr || has_virttext) { + int base_attr = hl_combine_attr(wlv.line_attr_lowprio, diff_attr); + if (base_attr || wlv.line_attr || has_virttext) { rightmost_vcol = INT_MAX; } int col_stride = wp->w_p_rl ? -1 : 1; - while (wp->w_p_rl ? col >= 0 : col < grid->cols) { - schar_from_ascii(linebuf_char[off], ' '); - col += col_stride; + while (wp->w_p_rl ? wlv.col >= 0 : wlv.col < grid->cols) { + schar_from_ascii(linebuf_char[wlv.off], ' '); + wlv.col += col_stride; if (draw_color_col) { draw_color_col = advance_color_col(VCOL_HLC, &color_cols); } @@ -2521,16 +2533,16 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, col_attr = mc_attr; } - col_attr = hl_combine_attr(col_attr, line_attr); + col_attr = hl_combine_attr(col_attr, wlv.line_attr); - linebuf_attr[off] = col_attr; - off += col_stride; + linebuf_attr[wlv.off] = col_attr; + wlv.off += col_stride; if (VCOL_HLC >= rightmost_vcol) { break; } - vcol += 1; + wlv.vcol += 1; } } @@ -2539,24 +2551,24 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, // terminal buffers may need to highlight beyond the end of the // logical line int n = wp->w_p_rl ? -1 : 1; - while (col >= 0 && col < grid->cols) { - schar_from_ascii(linebuf_char[off], ' '); - linebuf_attr[off] = vcol >= TERM_ATTRS_MAX ? 0 : term_attrs[vcol]; - off += n; - vcol += n; - col += n; + while (wlv.col >= 0 && wlv.col < grid->cols) { + schar_from_ascii(linebuf_char[wlv.off], ' '); + linebuf_attr[wlv.off] = wlv.vcol >= TERM_ATTRS_MAX ? 0 : term_attrs[wlv.vcol]; + wlv.off += n; + wlv.vcol += n; + wlv.col += n; } } - draw_virt_text(wp, buf, win_col_offset, &col, grid->cols, row); - grid_put_linebuf(grid, row, 0, col, grid->cols, wp->w_p_rl, wp, bg_attr, false); - row++; + draw_virt_text(wp, buf, win_col_offset, &wlv.col, grid->cols, wlv.row); + grid_put_linebuf(grid, wlv.row, 0, wlv.col, grid->cols, wp->w_p_rl, wp, bg_attr, false); + wlv.row++; // Update w_cline_height and w_cline_folded if the cursor line was // updated (saves a call to plines_win() later). if (wp == curwin && lnum == curwin->w_cursor.lnum) { curwin->w_cline_row = startrow; - curwin->w_cline_height = row - startrow; + curwin->w_cline_height = wlv.row - startrow; curwin->w_cline_folded = foldinfo.fi_lines > 0; curwin->w_valid |= (VALID_CHEIGHT|VALID_CROW); conceal_cursor_used = conceal_cursor_line(curwin); @@ -2567,17 +2579,17 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, // Show "extends" character from 'listchars' if beyond the line end and // 'list' is set. if (wp->w_p_lcs_chars.ext != NUL - && draw_state == WL_LINE + && wlv.draw_state == WL_LINE && wp->w_p_list && !wp->w_p_wrap - && filler_todo <= 0 - && (wp->w_p_rl ? col == 0 : col == grid->cols - 1) + && wlv.filler_todo <= 0 + && (wp->w_p_rl ? wlv.col == 0 : wlv.col == grid->cols - 1) && !has_fold && (*ptr != NUL || lcs_eol_one > 0 - || (n_extra && (c_extra != NUL || *p_extra != NUL)))) { + || (wlv.n_extra && (wlv.c_extra != NUL || *wlv.p_extra != NUL)))) { c = wp->w_p_lcs_chars.ext; - char_attr = win_hl_attr(wp, HLF_AT); + wlv.char_attr = win_hl_attr(wp, HLF_AT); mb_c = c; mb_utf8 = check_mb_utf8(&c, u8cc); } @@ -2594,84 +2606,84 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, // Also highlight the 'colorcolumn' if 'breakindent' and/or 'showbreak' // options are set vcol_save_attr = -1; - if ((draw_state == WL_LINE - || draw_state == WL_BRI - || draw_state == WL_SBR) + if ((wlv.draw_state == WL_LINE + || wlv.draw_state == WL_BRI + || wlv.draw_state == WL_SBR) && !lnum_in_visual_area && search_attr == 0 && area_attr == 0 - && filler_todo <= 0) { + && wlv.filler_todo <= 0) { if (wp->w_p_cuc && VCOL_HLC == (long)wp->w_virtcol && lnum != wp->w_cursor.lnum) { - vcol_save_attr = char_attr; - char_attr = hl_combine_attr(win_hl_attr(wp, HLF_CUC), char_attr); + vcol_save_attr = wlv.char_attr; + wlv.char_attr = hl_combine_attr(win_hl_attr(wp, HLF_CUC), wlv.char_attr); } else if (draw_color_col && VCOL_HLC == *color_cols) { - vcol_save_attr = char_attr; - char_attr = hl_combine_attr(win_hl_attr(wp, HLF_MC), char_attr); + vcol_save_attr = wlv.char_attr; + wlv.char_attr = hl_combine_attr(win_hl_attr(wp, HLF_MC), wlv.char_attr); } } // Apply lowest-priority line attr now, so everything can override it. - if (draw_state == WL_LINE) { - char_attr = hl_combine_attr(line_attr_lowprio, char_attr); + if (wlv.draw_state == WL_LINE) { + wlv.char_attr = hl_combine_attr(wlv.line_attr_lowprio, wlv.char_attr); } // Store character to be displayed. // Skip characters that are left of the screen for 'nowrap'. - vcol_prev = vcol; - if (draw_state < WL_LINE || n_skip <= 0) { + vcol_prev = wlv.vcol; + if (wlv.draw_state < WL_LINE || n_skip <= 0) { // // Store the character. // if (wp->w_p_rl && utf_char2cells(mb_c) > 1) { // A double-wide character is: put first half in left cell. - off--; - col--; + wlv.off--; + wlv.col--; } if (mb_utf8) { - schar_from_cc(linebuf_char[off], mb_c, u8cc); + schar_from_cc(linebuf_char[wlv.off], mb_c, u8cc); } else { - schar_from_ascii(linebuf_char[off], (char)c); + schar_from_ascii(linebuf_char[wlv.off], (char)c); } if (multi_attr) { - linebuf_attr[off] = multi_attr; + linebuf_attr[wlv.off] = multi_attr; multi_attr = 0; } else { - linebuf_attr[off] = char_attr; + linebuf_attr[wlv.off] = wlv.char_attr; } if (utf_char2cells(mb_c) > 1) { // Need to fill two screen columns. - off++; - col++; + wlv.off++; + wlv.col++; // UTF-8: Put a 0 in the second screen char. - linebuf_char[off][0] = 0; - if (draw_state > WL_STC && filler_todo <= 0) { - vcol++; + linebuf_char[wlv.off][0] = 0; + if (wlv.draw_state > WL_STC && wlv.filler_todo <= 0) { + wlv.vcol++; } // When "tocol" is halfway through a character, set it to the end of // the character, otherwise highlighting won't stop. - if (tocol == vcol) { + if (tocol == wlv.vcol) { tocol++; } if (wp->w_p_rl) { // now it's time to backup one cell - off--; - col--; + wlv.off--; + wlv.col--; } } if (wp->w_p_rl) { - off--; - col--; + wlv.off--; + wlv.col--; } else { - off++; - col++; + wlv.off++; + wlv.col++; } } else if (wp->w_p_cole > 0 && is_concealing) { n_skip--; - vcol_off++; - if (n_extra > 0) { - vcol_off += n_extra; + wlv.vcol_off++; + if (wlv.n_extra > 0) { + wlv.vcol_off += wlv.n_extra; } if (wp->w_p_wrap) { // Special voodoo required if 'wrap' is on. @@ -2681,45 +2693,45 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, // take up the same screen space when parts are concealed, // so that cursor line computations aren't messed up. // - // To avoid the fictitious advance of 'col' causing + // To avoid the fictitious advance of 'wlv.col' causing // trailing junk to be written out of the screen line // we are building, 'boguscols' keeps track of the number // of bad columns we have advanced. - if (n_extra > 0) { - vcol += n_extra; + if (wlv.n_extra > 0) { + wlv.vcol += wlv.n_extra; if (wp->w_p_rl) { - col -= n_extra; - boguscols -= n_extra; + wlv.col -= wlv.n_extra; + wlv.boguscols -= wlv.n_extra; } else { - col += n_extra; - boguscols += n_extra; + wlv.col += wlv.n_extra; + wlv.boguscols += wlv.n_extra; } - n_extra = 0; + wlv.n_extra = 0; n_attr = 0; } if (utf_char2cells(mb_c) > 1) { // Need to fill two screen columns. if (wp->w_p_rl) { - boguscols--; - col--; + wlv.boguscols--; + wlv.col--; } else { - boguscols++; - col++; + wlv.boguscols++; + wlv.col++; } } if (wp->w_p_rl) { - boguscols--; - col--; + wlv.boguscols--; + wlv.col--; } else { - boguscols++; - col++; + wlv.boguscols++; + wlv.col++; } } else { - if (n_extra > 0) { - vcol += n_extra; - n_extra = 0; + if (wlv.n_extra > 0) { + wlv.vcol += wlv.n_extra; + wlv.n_extra = 0; n_attr = 0; } } @@ -2727,58 +2739,58 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, n_skip--; } - // Only advance the "vcol" when after the 'number' or 'relativenumber' - // column. - if (draw_state > WL_STC - && filler_todo <= 0) { - vcol++; + // Only advance the "wlv.vcol" when after the 'number' or + // 'relativenumber' column. + if (wlv.draw_state > WL_STC + && wlv.filler_todo <= 0) { + wlv.vcol++; } if (vcol_save_attr >= 0) { - char_attr = vcol_save_attr; + wlv.char_attr = vcol_save_attr; } // restore attributes after "predeces" in 'listchars' - if (draw_state > WL_STC && n_attr3 > 0 && --n_attr3 == 0) { - char_attr = saved_attr3; + if (wlv.draw_state > WL_STC && n_attr3 > 0 && --n_attr3 == 0) { + wlv.char_attr = saved_attr3; } // restore attributes after last 'listchars' or 'number' char - if (n_attr > 0 && draw_state == WL_LINE && --n_attr == 0) { - char_attr = saved_attr2; + if (n_attr > 0 && wlv.draw_state == WL_LINE && --n_attr == 0) { + wlv.char_attr = saved_attr2; } // At end of screen line and there is more to come: Display the line // so far. If there is no more to display it is caught above. - if ((wp->w_p_rl ? (col < 0) : (col >= grid->cols)) + if ((wp->w_p_rl ? (wlv.col < 0) : (wlv.col >= grid->cols)) && (!has_fold || virt_line_offset >= 0) - && (draw_state != WL_LINE + && (wlv.draw_state != WL_LINE || *ptr != NUL - || filler_todo > 0 + || wlv.filler_todo > 0 || (wp->w_p_list && wp->w_p_lcs_chars.eol != NUL - && p_extra != at_end_str) - || (n_extra != 0 - && (c_extra != NUL || *p_extra != NUL)))) { + && wlv.p_extra != at_end_str) + || (wlv.n_extra != 0 + && (wlv.c_extra != NUL || *wlv.p_extra != NUL)))) { bool wrap = wp->w_p_wrap // Wrapping enabled. - && filler_todo <= 0 // Not drawing diff filler lines. + && wlv.filler_todo <= 0 // Not drawing diff filler lines. && lcs_eol_one != -1 // Haven't printed the lcs_eol character. - && row != endrow - 1 // Not the last line being displayed. + && wlv.row != endrow - 1 // Not the last line being displayed. && (grid->cols == Columns // Window spans the width of the screen, || ui_has(kUIMultigrid)) // or has dedicated grid. && !wp->w_p_rl; // Not right-to-left. - int draw_col = col - boguscols; + int draw_col = wlv.col - wlv.boguscols; if (virt_line_offset >= 0) { draw_virt_text_item(buf, virt_line_offset, kv_A(virt_lines, virt_line_index).line, kHlModeReplace, grid->cols, 0); } else { - draw_virt_text(wp, buf, win_col_offset, &draw_col, grid->cols, row); + draw_virt_text(wp, buf, win_col_offset, &draw_col, grid->cols, wlv.row); } - grid_put_linebuf(grid, row, 0, draw_col, grid->cols, wp->w_p_rl, wp, bg_attr, wrap); + grid_put_linebuf(grid, wlv.row, 0, draw_col, grid->cols, wp->w_p_rl, wp, bg_attr, wrap); if (wrap) { ScreenGrid *current_grid = grid; - int current_row = row, dummy_col = 0; // dummy_col unused + int current_row = wlv.row, dummy_col = 0; // dummy_col unused grid_adjust(¤t_grid, ¤t_row, &dummy_col); // Force a redraw of the first column of the next line. @@ -2788,49 +2800,45 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, current_grid->line_wraps[current_row] = true; } - boguscols = 0; - row++; + wlv.boguscols = 0; + wlv.row++; // When not wrapping and finished diff lines, or when displayed // '$' and highlighting until last column, break here. - if ((!wp->w_p_wrap && filler_todo <= 0) || lcs_eol_one == -1) { + if ((!wp->w_p_wrap && wlv.filler_todo <= 0) || lcs_eol_one == -1) { break; } // When the window is too narrow draw all "@" lines. - if (draw_state != WL_LINE && filler_todo <= 0) { - win_draw_end(wp, '@', ' ', true, row, wp->w_grid.rows, HLF_AT); - set_empty_rows(wp, row); - row = endrow; + if (wlv.draw_state != WL_LINE && wlv.filler_todo <= 0) { + win_draw_end(wp, '@', ' ', true, wlv.row, wp->w_grid.rows, HLF_AT); + set_empty_rows(wp, wlv.row); + wlv.row = endrow; } // When line got too long for screen break here. - if (row == endrow) { - row++; + if (wlv.row == endrow) { + wlv.row++; break; } - col = 0; - off = 0; - if (wp->w_p_rl) { - col = grid->cols - 1; // col is not used if breaking! - off += col; - } + win_line_start(wp, &wlv); // reset the drawing state for the start of a wrapped line - draw_state = WL_START; - saved_n_extra = n_extra; - saved_p_extra = p_extra; - saved_c_extra = c_extra; - saved_c_final = c_final; - saved_char_attr = char_attr; - n_extra = 0; + wlv.draw_state = WL_START; + saved_n_extra = wlv.n_extra; + saved_p_extra = wlv.p_extra; + saved_c_extra = wlv.c_extra; + saved_c_final = wlv.c_final; + saved_char_attr = wlv.char_attr; + wlv.n_extra = 0; lcs_prec_todo = wp->w_p_lcs_chars.prec; - if (filler_todo <= 0) { + if (wlv.filler_todo <= 0) { need_showbreak = true; } if (statuscol.draw) { - if (row == startrow + filler_lines + 1 || row == startrow + filler_lines) { + if (wlv.row == startrow + wlv.filler_lines + 1 + || wlv.row == startrow + wlv.filler_lines) { // Re-evaluate 'statuscolumn' for the first wrapped row and non filler line statuscol.textp = NULL; } else if (statuscol.textp) { @@ -2840,11 +2848,11 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, } // Fall back to default columns if the 'n' flag isn't in 'cpo' statuscol.draw = vim_strchr(p_cpo, CPO_NUMCOL) == NULL; } - filler_todo--; + wlv.filler_todo--; virt_line_offset = -1; // When the filler lines are actually below the last line of the // file, don't draw the line itself, break here. - if (filler_todo == 0 && (wp->w_botfill || end_fill)) { + if (wlv.filler_todo == 0 && (wp->w_botfill || end_fill)) { break; } } @@ -2857,6 +2865,6 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, } kv_destroy(virt_lines); - xfree(p_extra_free); - return row; + xfree(wlv.p_extra_free); + return wlv.row; } |