diff options
Diffstat (limited to 'src/nvim/screen.c')
-rw-r--r-- | src/nvim/screen.c | 566 |
1 files changed, 339 insertions, 227 deletions
diff --git a/src/nvim/screen.c b/src/nvim/screen.c index 9fdb476748..10b5b6bba4 100644 --- a/src/nvim/screen.c +++ b/src/nvim/screen.c @@ -147,6 +147,9 @@ static foldinfo_T win_foldinfo; /* info for 'foldcolumn' */ */ static schar_T *current_ScreenLine; +StlClickDefinition *tab_page_click_defs = NULL; +long tab_page_click_defs_size = 0; + # define SCREEN_LINE(r, o, e, c, rl) screen_line((r), (o), (e), (c), (rl)) #ifdef INCLUDE_GENERATED_DECLARATIONS # include "screen.c.generated.h" @@ -384,14 +387,15 @@ void update_screen(int type) if (wp->w_buffer->b_mod_set) { win_T *wwp; - /* Check if we already did this buffer. */ - for (wwp = firstwin; wwp != wp; wwp = wwp->w_next) - if (wwp->w_buffer == wp->w_buffer) + // Check if we already did this buffer. + for (wwp = firstwin; wwp != wp; wwp = wwp->w_next) { + if (wwp->w_buffer == wp->w_buffer) { break; - if ( - wwp == wp && - syntax_present(wp)) + } + } + if (wwp == wp && syntax_present(wp)) { syn_stack_apply_changes(wp->w_buffer); + } } } @@ -752,10 +756,11 @@ static void win_update(win_T *wp) lnumt = wp->w_lines[i].wl_lastlnum + 1; if (lnumb == MAXLNUM && wp->w_lines[i].wl_lnum >= mod_bot) { lnumb = wp->w_lines[i].wl_lnum; - /* When there is a fold column it might need updating - * in the next line ("J" just above an open fold). */ - if (wp->w_p_fdc > 0) - ++lnumb; + // When there is a fold column it might need updating + // in the next line ("J" just above an open fold). + if (compute_foldcolumn(wp, 0) > 0) { + lnumb++; + } } } @@ -1227,16 +1232,16 @@ static void win_update(win_T *wp) || did_update == DID_FOLD || (did_update == DID_LINE && syntax_present(wp) - && ( - (foldmethodIsSyntax(wp) - && hasAnyFolding(wp)) || - syntax_check_changed(lnum))) + && ((foldmethodIsSyntax(wp) + && hasAnyFolding(wp)) + || syntax_check_changed(lnum))) // match in fixed position might need redraw // if lines were inserted or deleted - || (wp->w_match_head != NULL && buf->b_mod_xlines != 0) - ))))) { - if (lnum == mod_top) - top_to_mod = FALSE; + || (wp->w_match_head != NULL + && buf->b_mod_xlines != 0)))))) { + if (lnum == mod_top) { + top_to_mod = false; + } /* * When at start of changed lines: May scroll following lines @@ -1567,10 +1572,11 @@ static void win_draw_end(win_T *wp, int c1, int c2, int row, int endrow, hlf_T h { int n = 0; # define FDC_OFF n + int fdc = compute_foldcolumn(wp, 0); if (wp->w_p_rl) { - /* No check for cmdline window: should never be right-left. */ - n = wp->w_p_fdc; + // No check for cmdline window: should never be right-left. + n = fdc; if (n > 0) { /* draw the fold column at the right */ @@ -1610,8 +1616,8 @@ static void win_draw_end(win_T *wp, int c1, int c2, int row, int endrow, hlf_T h wp->w_wincol, wp->w_wincol + n, cmdwin_type, ' ', hl_attr(HLF_AT)); } - if (wp->w_p_fdc > 0) { - int nn = n + wp->w_p_fdc; + if (fdc > 0) { + int nn = n + fdc; /* draw the fold column at the left */ if (nn > wp->w_width) @@ -1654,6 +1660,20 @@ static int advance_color_col(int vcol, int **color_cols) return **color_cols >= 0; } +// Compute the width of the foldcolumn. Based on 'foldcolumn' and how much +// space is available for window "wp", minus "col". +static int compute_foldcolumn(win_T *wp, int col) +{ + int fdc = wp->w_p_fdc; + int wmw = wp == curwin && p_wmw == 0 ? 1 : p_wmw; + int wwidth = wp->w_width; + + if (fdc > wwidth - (col + wmw)) { + fdc = wwidth - (col + wmw); + } + return fdc; +} + /* * Display one folded line. */ @@ -1692,12 +1712,9 @@ static void fold_line(win_T *wp, long fold_count, foldinfo_T *foldinfo, linenr_T ++col; } - /* - * 2. Add the 'foldcolumn' - */ - fdc = wp->w_p_fdc; - if (fdc > wp->w_width - col) - fdc = wp->w_width - col; + // 2. Add the 'foldcolumn' + // Reduce the width when there is not enough space. + fdc = compute_foldcolumn(wp, col); if (fdc > 0) { fill_foldcolumn(buf, wp, TRUE, lnum); if (wp->w_p_rl) { @@ -2018,37 +2035,42 @@ fill_foldcolumn ( int level; int first_level; int empty; + int fdc = compute_foldcolumn(wp, 0); - /* Init to all spaces. */ - memset(p, ' ', (size_t)wp->w_p_fdc); + // Init to all spaces. + memset(p, ' ', (size_t)fdc); level = win_foldinfo.fi_level; if (level > 0) { - /* If there is only one column put more info in it. */ - empty = (wp->w_p_fdc == 1) ? 0 : 1; + // If there is only one column put more info in it. + empty = (fdc == 1) ? 0 : 1; - /* If the column is too narrow, we start at the lowest level that - * fits and use numbers to indicated the depth. */ - first_level = level - wp->w_p_fdc - closed + 1 + empty; - if (first_level < 1) + // If the column is too narrow, we start at the lowest level that + // fits and use numbers to indicated the depth. + first_level = level - fdc - closed + 1 + empty; + if (first_level < 1) { first_level = 1; + } - for (i = 0; i + empty < wp->w_p_fdc; ++i) { + for (i = 0; i + empty < fdc; i++) { if (win_foldinfo.fi_lnum == lnum - && first_level + i >= win_foldinfo.fi_low_level) + && first_level + i >= win_foldinfo.fi_low_level) { p[i] = '-'; - else if (first_level == 1) + } else if (first_level == 1) { p[i] = '|'; - else if (first_level + i <= 9) + } else if (first_level + i <= 9) { p[i] = '0' + first_level + i; - else + } else { p[i] = '>'; - if (first_level + i == level) + } + if (first_level + i == level) { break; + } } } - if (closed) - p[i >= wp->w_p_fdc ? i - 1 : i] = '+'; + if (closed) { + p[i >= fdc ? i - 1 : i] = '+'; + } } /* @@ -2163,6 +2185,10 @@ win_line ( int prev_c1 = 0; /* first composing char for prev_c */ int did_line_attr = 0; + bool has_bufhl = false; // this buffer has highlight matches + int bufhl_attr = 0; // attributes desired by bufhl + bufhl_lineinfo_T bufhl_info; // bufhl data for this line + /* draw_state: items that are drawn in sequence: */ #define WL_START 0 /* nothing done yet */ # define WL_CMDLINE WL_START + 1 /* cmdline window column */ @@ -2178,11 +2204,13 @@ win_line ( int syntax_seqnr = 0; int prev_syntax_id = 0; int conceal_attr = hl_attr(HLF_CONCEAL); - int 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 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 match_conc = false; ///< cchar for match functions + int has_match_conc = false; ///< match wants to conceal int old_boguscols = 0; # define VCOL_HLC (vcol - vcol_off) # define FIX_FOR_BOGUSCOLS \ @@ -2221,6 +2249,11 @@ win_line ( } } + if (bufhl_start_line(wp->w_buffer, lnum, &bufhl_info)) { + has_bufhl = true; + extra_check = true; + } + /* Check for columns to display for 'colorcolumn'. */ color_cols = wp->w_buffer->terminal ? NULL : wp->w_p_cc_cols; if (color_cols != NULL) @@ -2409,13 +2442,18 @@ win_line ( } } - /* find start of trailing whitespace */ - if (wp->w_p_list && lcs_trail) { - trailcol = (colnr_T)STRLEN(ptr); - while (trailcol > (colnr_T)0 && ascii_iswhite(ptr[trailcol - 1])) - --trailcol; - trailcol += (colnr_T) (ptr - line); - extra_check = TRUE; + if (wp->w_p_list) { + if (lcs_space || lcs_trail) { + extra_check = true; + } + // find start of trailing whitespace + if (lcs_trail) { + trailcol = (colnr_T)STRLEN(ptr); + while (trailcol > (colnr_T)0 && ascii_iswhite(ptr[trailcol - 1])) { + trailcol--; + } + trailcol += (colnr_T) (ptr - line); + } } /* @@ -2435,21 +2473,16 @@ win_line ( mb_ptr_adv(ptr); } - /* When: - * - 'cuc' is set, or - * - 'colorcolumn' is set, or - * - '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) - )) { + // When: + // - 'cuc' is set, or + // - 'colorcolumn' is set, or + // - '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 = v; } @@ -2612,11 +2645,10 @@ win_line ( extra_check = true; } - /* - * Repeat for the whole displayed line. - */ + // Repeat for the whole displayed line. for (;; ) { - /* Skip this quickly when working on the text. */ + has_match_conc = false; + // Skip this quickly when working on the text. if (draw_state != WL_LINE) { if (draw_state == WL_CMDLINE - 1 && n_extra == 0) { draw_state = WL_CMDLINE; @@ -2629,11 +2661,13 @@ win_line ( } if (draw_state == WL_FOLD - 1 && n_extra == 0) { + int fdc = compute_foldcolumn(wp, 0); + draw_state = WL_FOLD; - if (wp->w_p_fdc > 0) { - /* Draw the 'foldcolumn'. */ - fill_foldcolumn(extra, wp, FALSE, lnum); - n_extra = wp->w_p_fdc; + if (fdc > 0) { + // Draw the 'foldcolumn'. + fill_foldcolumn(extra, wp, false, lnum); + n_extra = fdc; p_extra = extra; p_extra[n_extra] = NUL; c_extra = NUL; @@ -2861,8 +2895,16 @@ win_line ( shl->endcol = tmp_col; } shl->attr_cur = shl->attr; + if (cur != NULL && syn_name2id((char_u *)"Conceal") + == cur->hlg_id) { + has_match_conc = true; + match_conc = cur->conceal_char; + } else { + has_match_conc = match_conc = false; + } } else if (v == (long)shl->endcol) { shl->attr_cur = 0; + prev_syntax_id = 0; next_search_hl(wp, shl, lnum, (colnr_T)v, cur); pos_inprogress = !(cur == NULL || cur->pos.cur == 0); @@ -2934,14 +2976,16 @@ win_line ( } } - /* Decide which of the highlight attributes to use. */ - attr_pri = TRUE; - if (area_attr != 0) - char_attr = area_attr; - else if (search_attr != 0) - char_attr = search_attr; - /* Use line_attr when not in the Visual or 'incsearch' area - * (area_attr may be 0 when "noinvcur" is set). */ + // Decide which of the highlight attributes to use. + attr_pri = true; + + if (area_attr != 0) { + char_attr = hl_combine_attr(line_attr, area_attr); + } else if (search_attr != 0) { + char_attr = hl_combine_attr(line_attr, search_attr); + } + // Use line_attr when not in the Visual or 'incsearch' area + // (area_attr may be 0 when "noinvcur" is set). else if (line_attr != 0 && ((fromcol == -10 && tocol == MAXCOL) || vcol < fromcol || vcol_prev < fromcol_prev || vcol >= tocol)) @@ -3176,26 +3220,7 @@ win_line ( } } - ++ptr; - - // 'list': change char 160 to lcs_nbsp and space to lcs_space. - if (wp->w_p_list - && (((c == 160 || (mb_utf8 && mb_c == 160)) && lcs_nbsp) - || (c == ' ' && lcs_space && ptr - line <= trailcol))) { - c = (c == ' ') ? lcs_space : lcs_nbsp; - if (area_attr == 0 && search_attr == 0) { - n_attr = 1; - extra_attr = hl_attr(HLF_8); - saved_attr2 = char_attr; /* save current attr */ - } - mb_c = c; - if (enc_utf8 && (*mb_char2len)(c) > 1) { - mb_utf8 = TRUE; - u8cc[0] = 0; - c = 0xc0; - } else - mb_utf8 = FALSE; - } + ptr++; if (extra_check) { bool can_spell = true; @@ -3244,12 +3269,12 @@ win_line ( * contains the @Spell cluster. */ if (has_spell && v >= word_end && v > cur_checked_col) { spell_attr = 0; - if (!attr_pri) + if (!attr_pri) { char_attr = syntax_attr; - if (c != 0 && ( - !has_syntax || - can_spell)) { - char_u *prev_ptr, *p; + } + if (c != 0 && (!has_syntax || can_spell)) { + char_u *prev_ptr; + char_u *p; int len; hlf_T spell_hlf = HLF_COUNT; if (has_mbyte) { @@ -3315,6 +3340,17 @@ win_line ( char_attr = hl_combine_attr(spell_attr, char_attr); } + if (has_bufhl && v > 0) { + bufhl_attr = bufhl_get_attr(&bufhl_info, (colnr_T)v); + if (bufhl_attr != 0) { + if (!attr_pri) { + char_attr = hl_combine_attr(char_attr, bufhl_attr); + } else { + char_attr = hl_combine_attr(bufhl_attr, char_attr); + } + } + } + if (wp->w_buffer->terminal) { char_attr = hl_combine_attr(char_attr, term_attrs[vcol]); } @@ -3323,16 +3359,15 @@ win_line ( * Found last space before word: check for line break. */ if (wp->w_p_lbr && vim_isbreak(c) && !vim_isbreak(*ptr)) { - char_u *p = ptr - ( - has_mbyte ? mb_l : - 1); + int mb_off = has_mbyte ? (*mb_head_off)(line, ptr - 1) : 0; + char_u *p = ptr - (mb_off + 1); // TODO: is passing p for start of the line OK? n_extra = win_lbr_chartabsize(wp, line, p, (colnr_T)vcol, NULL) - 1; if (c == TAB && n_extra + col > wp->w_width) { n_extra = (int)wp->w_buffer->b_p_ts - vcol % (int)wp->w_buffer->b_p_ts - 1; } - c_extra = ' '; + c_extra = mb_off > 0 ? MB_FILLER_CHAR : ' '; if (ascii_iswhite(c)) { if (c == TAB) /* See "Tab alignment" below. */ @@ -3343,6 +3378,28 @@ win_line ( } } + // 'list': change char 160 to lcs_nbsp and space to lcs_space. + if (wp->w_p_list + && (((c == 160 + || (mb_utf8 && (mb_c == 160 || mb_c == 0x202f))) + && lcs_nbsp) + || (c == ' ' && lcs_space && ptr - line <= trailcol))) { + c = (c == ' ') ? lcs_space : lcs_nbsp; + if (area_attr == 0 && search_attr == 0) { + n_attr = 1; + extra_attr = hl_attr(HLF_8); + saved_attr2 = char_attr; // save current attr + } + mb_c = c; + if (enc_utf8 && (*mb_char2len)(c) > 1) { + mb_utf8 = true; + u8cc[0] = 0; + c = 0xc0; + } else { + mb_utf8 = false; + } + } + if (trailcol != MAXCOL && ptr > line + trailcol && c == ' ') { c = lcs_trail; if (!attr_pri) { @@ -3388,7 +3445,7 @@ win_line ( int i; int saved_nextra = n_extra; - if ((is_concealing || boguscols > 0) && vcol_off > 0) { + if (vcol_off > 0) { // there are characters to conceal tab_len += vcol_off; } @@ -3418,25 +3475,31 @@ win_line ( // n_extra will be increased by FIX_FOX_BOGUSCOLS // macro below, so need to adjust for that here - if ((is_concealing || boguscols > 0) && vcol_off > 0) { + if (vcol_off > 0) { n_extra -= vcol_off; } } - /* Tab alignment should be identical regardless of - * 'conceallevel' value. So tab compensates of all - * previous concealed characters, and thus resets 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; - // Make sure that the highlighting for the tab char will be correctly - // set further below (effectively reverts the FIX_FOR_BOGSUCOLS - // macro). - if (old_boguscols > 0 && n_extra > tab_len && wp->w_p_list - && lcs_tab1) { - tab_len += n_extra - tab_len; + + { + int vc_saved = vcol_off; + + // Tab alignment should be identical regardless of + // 'conceallevel' value. So tab compensates of all + // previous concealed characters, and thus resets + // 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; + + // 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 && lcs_tab1) { + tab_len += vc_saved; + } } - mb_utf8 = FALSE; /* don't draw as UTF-8 */ + + mb_utf8 = (int)false; // don't draw as UTF-8 if (wp->w_p_list) { c = lcs_tab1; if (wp->w_p_lbr) { @@ -3458,7 +3521,7 @@ win_line ( c = ' '; } } else if (c == NUL - && ((wp->w_p_list && lcs_eol > 0) + && (wp->w_p_list || ((fromcol >= 0 || fromcol_prev >= 0) && tocol > vcol && VIsual_mode != Ctrl_V @@ -3468,11 +3531,11 @@ win_line ( && !(noinvcur && lnum == wp->w_cursor.lnum && (colnr_T)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 - * "$". */ + && 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) { /* In virtualedit, visual selections may extend * beyond end of line. */ @@ -3485,10 +3548,11 @@ win_line ( c_extra = NUL; } } - if (wp->w_p_list) + if (wp->w_p_list && lcs_eol > 0) { c = lcs_eol; - else + } else { c = ' '; + } lcs_eol_one = -1; --ptr; /* put it back at the NUL */ if (!attr_pri) { @@ -3539,25 +3603,22 @@ win_line ( wp->w_p_rl ? (col >= 0) : (col < wp->w_width))) { c = ' '; - --ptr; /* put it back at the NUL */ - } else if (( - diff_hlf != (hlf_T)0 || - line_attr != 0 - ) && ( - wp->w_p_rl ? (col >= 0) : - (col - - boguscols - < wp->w_width))) { - /* Highlight until the right side of the window */ + ptr--; // put it back at the NUL + } else if ((diff_hlf != (hlf_T)0 || line_attr != 0) + && (wp->w_p_rl + ? (col >= 0) + : (col - boguscols < wp->w_width))) { + // Highlight until the right side of the window c = ' '; - --ptr; /* put it back at the NUL */ + ptr--; // put it back at the NUL - /* Remember we do the char for line highlighting. */ - ++did_line_attr; + // Remember we do the char for line highlighting. + did_line_attr++; - /* don't do search HL for the rest of the line */ - if (line_attr != 0 && char_attr == search_attr && col > 0) + // don't do search HL for the rest of the line + if (line_attr != 0 && char_attr == search_attr && col > 0) { char_attr = line_attr; + } if (diff_hlf == HLF_TXD) { diff_hlf = HLF_CHD; if (attr == 0 || char_attr != attr) { @@ -3570,24 +3631,28 @@ win_line ( } } - if ( wp->w_p_cole > 0 - && (wp != curwin || lnum != wp->w_cursor.lnum || - conceal_cursor_line(wp)) - && (syntax_flags & HL_CONCEAL) != 0 - && !(lnum_in_visual_area - && vim_strchr(wp->w_p_cocu, 'v') == NULL)) { + if (wp->w_p_cole > 0 + && (wp != curwin || lnum != wp->w_cursor.lnum + || conceal_cursor_line(wp)) + && ((syntax_flags & HL_CONCEAL) != 0 || has_match_conc) + && !(lnum_in_visual_area + && vim_strchr(wp->w_p_cocu, 'v') == NULL)) { char_attr = conceal_attr; if (prev_syntax_id != syntax_seqnr - && (syn_get_sub_char() != NUL || wp->w_p_cole == 1) + && (syn_get_sub_char() != NUL || match_conc + || wp->w_p_cole == 1) && wp->w_p_cole != 3) { - /* First time at this concealed item: display one - * character. */ - if (syn_get_sub_char() != NUL) + // First time at this concealed item: display one + // character. + if (match_conc) { + c = match_conc; + } else if (syn_get_sub_char() != NUL) { c = syn_get_sub_char(); - else if (lcs_conceal != NUL) + } else if (lcs_conceal != NUL) { c = lcs_conceal; - else + } else { c = ' '; + } prev_syntax_id = syntax_seqnr; @@ -3628,9 +3693,13 @@ win_line ( && wp == curwin && lnum == wp->w_cursor.lnum && conceal_cursor_line(wp) && (int)wp->w_virtcol <= vcol + n_skip) { - wp->w_wcol = col - boguscols; + if (wp->w_p_rl) { + wp->w_wcol = wp->w_width - col + boguscols - 1; + } else { + wp->w_wcol = col - boguscols; + } wp->w_wrow = row; - did_wcol = TRUE; + did_wcol = true; } /* Don't override visual selection highlighting. */ @@ -3946,20 +4015,24 @@ win_line ( ScreenAttrs[off] = char_attr; if (has_mbyte && (*mb_char2cells)(mb_c) > 1) { - /* Need to fill two screen columns. */ - ++off; - ++col; - if (enc_utf8) - /* UTF-8: Put a 0 in the second screen char. */ + // Need to fill two screen columns. + off++; + col++; + if (enc_utf8) { + // UTF-8: Put a 0 in the second screen char. ScreenLines[off] = 0; - else - /* DBCS: Put second byte in the second screen char. */ + } else { + // DBCS: Put second byte in the second screen char. ScreenLines[off] = mb_c & 0xff; - ++vcol; - /* When "tocol" is halfway through a character, set it to the end of - * the character, otherwise highlighting won't stop. */ - if (tocol == vcol) - ++tocol; + } + if (draw_state > WL_NR && filler_todo <= 0) { + vcol++; + } + // When "tocol" is halfway through a character, set it to the end of + // the character, otherwise highlighting won't stop. + if (tocol == vcol) { + tocol++; + } if (wp->w_p_rl) { /* now it's time to backup one cell */ --off; @@ -4104,7 +4177,6 @@ win_line ( * xterm/screen: write an extra character beyond the end of * the line. This will work with all terminal types * (regardless of the xn,am settings). - * Only do this on a fast tty. * Only do this if the cursor is on the current line * (something has been written in it). * Don't do this for the GUI. @@ -4977,8 +5049,8 @@ win_redr_custom ( char_u *stl; char_u *p; struct stl_hlrec hltab[STL_MAX_ITEM]; - struct stl_hlrec tabtab[STL_MAX_ITEM]; - int use_sandbox = FALSE; + StlClickRecord tabtab[STL_MAX_ITEM]; + int use_sandbox = false; win_T *ewp; int p_crb_save; @@ -5094,20 +5166,24 @@ win_redr_custom ( screen_puts(p >= buf + len ? (char_u *)"" : p, row, col, curattr); if (wp == NULL) { - /* Fill the TabPageIdxs[] array for clicking in the tab pagesline. */ + // Fill the tab_page_click_defs array for clicking in the tab pages line. col = 0; len = 0; p = buf; - fillchar = 0; + StlClickDefinition cur_click_def = { + .type = kStlClickDisabled, + }; for (n = 0; tabtab[n].start != NULL; n++) { - len += vim_strnsize(p, (int)(tabtab[n].start - p)); - while (col < len) - TabPageIdxs[col++] = fillchar; - p = tabtab[n].start; - fillchar = tabtab[n].userhl; + len += vim_strnsize(p, (int)(tabtab[n].start - (char *) p)); + while (col < len) { + tab_page_click_defs[col++] = cur_click_def; + } + p = (char_u *) tabtab[n].start; + cur_click_def = tabtab[n].def; + } + while (col < Columns) { + tab_page_click_defs[col++] = cur_click_def; } - while (col < Columns) - TabPageIdxs[col++] = fillchar; } theend: @@ -5926,9 +6002,9 @@ void screenalloc(bool doclear) sattr_T *new_ScreenAttrs; unsigned *new_LineOffset; char_u *new_LineWraps; - short *new_TabPageIdxs; - static int entered = FALSE; /* avoid recursiveness */ - static int done_outofmem_msg = FALSE; /* did outofmem message */ + StlClickDefinition *new_tab_page_click_defs; + static bool entered = false; // avoid recursiveness + static bool done_outofmem_msg = false; int retry_count = 0; const bool l_enc_utf8 = enc_utf8; const int l_enc_dbcs = enc_dbcs; @@ -6001,7 +6077,8 @@ retry: new_ScreenAttrs = xmalloc((size_t)((Rows + 1) * Columns * sizeof(sattr_T))); new_LineOffset = xmalloc((size_t)(Rows * sizeof(unsigned))); new_LineWraps = xmalloc((size_t)(Rows * sizeof(char_u))); - new_TabPageIdxs = xmalloc((size_t)(Columns * sizeof(short))); + new_tab_page_click_defs = xcalloc( + (size_t) Columns, sizeof(*new_tab_page_click_defs)); FOR_ALL_TAB_WINDOWS(tp, wp) { win_alloc_lines(wp); @@ -6019,7 +6096,7 @@ retry: || new_ScreenAttrs == NULL || new_LineOffset == NULL || new_LineWraps == NULL - || new_TabPageIdxs == NULL + || new_tab_page_click_defs == NULL || outofmem) { if (ScreenLines != NULL || !done_outofmem_msg) { /* guess the size */ @@ -6045,8 +6122,8 @@ retry: new_LineOffset = NULL; xfree(new_LineWraps); new_LineWraps = NULL; - xfree(new_TabPageIdxs); - new_TabPageIdxs = NULL; + xfree(new_tab_page_click_defs); + new_tab_page_click_defs = NULL; } else { done_outofmem_msg = FALSE; @@ -6125,7 +6202,8 @@ retry: ScreenAttrs = new_ScreenAttrs; LineOffset = new_LineOffset; LineWraps = new_LineWraps; - TabPageIdxs = new_TabPageIdxs; + tab_page_click_defs = new_tab_page_click_defs; + tab_page_click_defs_size = Columns; /* It's important that screen_Rows and screen_Columns reflect the actual * size of ScreenLines[]. Set them before calling anything. */ @@ -6164,7 +6242,25 @@ void free_screenlines(void) xfree(ScreenAttrs); xfree(LineOffset); xfree(LineWraps); - xfree(TabPageIdxs); + clear_tab_page_click_defs(tab_page_click_defs, tab_page_click_defs_size); + xfree(tab_page_click_defs); +} + +/// Clear tab_page_click_defs table +/// +/// @param[out] tpcd Table to clear. +/// @param[in] tpcd_size Size of the table. +void clear_tab_page_click_defs(StlClickDefinition *const tpcd, + const long tpcd_size) +{ + if (tpcd != NULL) { + for (long i = 0; i < tpcd_size; i++) { + if (i == 0 || tpcd[i].func != tpcd[i - 1].func) { + xfree(tpcd[i].func); + } + } + memset(tpcd, 0, (size_t) tpcd_size * sizeof(tpcd[0])); + } } void screenclear(void) @@ -6681,8 +6777,8 @@ int showmode(void) if (Recording && edit_submode == NULL /* otherwise it gets too long */ ) { - MSG_PUTS_ATTR(_("recording"), attr); - need_clear = TRUE; + recording_mode(attr); + need_clear = true; } mode_displayed = TRUE; @@ -6721,26 +6817,33 @@ static void msg_pos_mode(void) msg_row = Rows - 1; } -/* - * Delete mode message. Used when ESC is typed which is expected to end - * Insert mode (but Insert mode didn't end yet!). - * Caller should check "mode_displayed". - */ -void unshowmode(int force) +/// Delete mode message. Used when ESC is typed which is expected to end +/// Insert mode (but Insert mode didn't end yet!). +/// Caller should check "mode_displayed". +void unshowmode(bool force) { - /* - * Don't delete it right now, when not redrawing or inside a mapping. - */ - if (!redrawing() || (!force && char_avail() && !KeyTyped)) - redraw_cmdline = TRUE; /* delete mode later */ - else { + // Don't delete it right now, when not redrawing or inside a mapping. + if (!redrawing() || (!force && char_avail() && !KeyTyped)) { + redraw_cmdline = true; // delete mode later + } else { msg_pos_mode(); - if (Recording) - MSG_PUTS_ATTR(_("recording"), hl_attr(HLF_CM)); + if (Recording) { + recording_mode(hl_attr(HLF_CM)); + } msg_clr_eos(); } } +static void recording_mode(int attr) +{ + MSG_PUTS_ATTR(_("recording"), attr); + if (!shortmess(SHM_RECORDING)) { + char_u s[4]; + vim_snprintf((char *)s, ARRAY_SIZE(s), " @%c", Recording); + MSG_PUTS_ATTR(s, attr); + } +} + /* * Draw the tab pages line at the top of the Vim window. */ @@ -6772,9 +6875,9 @@ static void draw_tabline(void) return; - /* Init TabPageIdxs[] to zero: Clicking outside of tabs has no effect. */ - for (scol = 0; scol < Columns; ++scol) - TabPageIdxs[scol] = 0; + // Init TabPageIdxs[] to zero: Clicking outside of tabs has no effect. + assert(Columns == tab_page_click_defs_size); + clear_tab_page_click_defs(tab_page_click_defs, tab_page_click_defs_size); /* Use the 'tabline' option if it's set. */ if (*p_tal != NUL) { @@ -6872,11 +6975,16 @@ static void draw_tabline(void) } screen_putchar(' ', 0, col++, attr); - /* Store the tab page number in TabPageIdxs[], so that - * jump_to_mouse() knows where each one is. */ - ++tabcount; - while (scol < col) - TabPageIdxs[scol++] = tabcount; + // Store the tab page number in tab_page_click_defs[], so that + // jump_to_mouse() knows where each one is. + tabcount++; + while (scol < col) { + tab_page_click_defs[scol++] = (StlClickDefinition) { + .type = kStlClickTabSwitch, + .tabnr = tabcount, + .func = NULL, + }; + } } if (use_sep_chars) @@ -6888,7 +6996,11 @@ static void draw_tabline(void) /* Put an "X" for closing the current tab if there are several. */ if (first_tabpage->tp_next != NULL) { screen_putchar('X', 0, (int)Columns - 1, attr_nosel); - TabPageIdxs[Columns - 1] = -999; + tab_page_click_defs[Columns - 1] = (StlClickDefinition) { + .type = kStlClickTabClose, + .tabnr = 999, + .func = NULL, + }; } } |