aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/screen.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/nvim/screen.c')
-rw-r--r--src/nvim/screen.c277
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,
+ };
}
}