diff options
Diffstat (limited to 'src/nvim/screen.c')
-rw-r--r-- | src/nvim/screen.c | 277 |
1 files changed, 172 insertions, 105 deletions
diff --git a/src/nvim/screen.c b/src/nvim/screen.c index 9a64a7c3a9..3b5836f0b5 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" @@ -2196,11 +2199,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 \ @@ -2427,13 +2432,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); + } } /* @@ -2630,11 +2640,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; @@ -2881,8 +2890,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); @@ -3198,26 +3215,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; @@ -3364,6 +3362,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) { @@ -3409,7 +3429,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; } @@ -3439,25 +3459,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) { @@ -3592,24 +3618,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; @@ -3968,20 +3998,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; @@ -4998,8 +5032,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; @@ -5115,20 +5149,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: @@ -5947,9 +5985,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; @@ -6022,7 +6060,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); @@ -6040,7 +6079,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 */ @@ -6066,8 +6105,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; @@ -6146,7 +6185,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. */ @@ -6185,7 +6225,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) @@ -6793,9 +6851,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) { @@ -6893,11 +6951,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) @@ -6909,7 +6972,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, + }; } } |