fix(ui): fix visual and search highlighting interfering with virtual text

vim-patch:9.0.0193: search and match highlgith interfere with virtual text

Problem:    Search and match highlgith interfere with virtual text highlight.
            (Ben Jackson)
Solution:   Check for match highlight after text properties.  Reset and
            restore search highlight when showing virtual text.
            (closes vim/vim#10892)

e38fc86180

vim-patch:9.0.0452: Visual highlighting extends into virtual text prop

Problem:    Visual highlighting extends into virtual text prop.
Solution:   Do not highlight what isn't actually selected.  Fix ordering of
            stored text props.

6eda17d881

Co-authored-by: Bram Moolenaar <Bram@vim.org>
This commit is contained in:
Ibby
2023-03-27 01:25:37 +11:00
committed by bfredl
parent e12b5882af
commit c5bf838f8a
2 changed files with 146 additions and 38 deletions

View File

@ -978,7 +978,10 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
bool area_highlighting = false; // Visual or incsearch highlighting in this line bool area_highlighting = false; // Visual or incsearch highlighting in this line
int vi_attr = 0; // attributes for Visual and incsearch highlighting int vi_attr = 0; // attributes for Visual and incsearch highlighting
int area_attr = 0; // attributes desired by highlighting int area_attr = 0; // attributes desired by highlighting
int saved_area_attr = 0; // idem for area_attr
int search_attr = 0; // attributes desired by 'hlsearch' int search_attr = 0; // attributes desired by 'hlsearch'
int saved_search_attr = 0; // search_attr to be used when n_extra
// goes to zero
int vcol_save_attr = 0; // saved attr for 'cursorcolumn' int vcol_save_attr = 0; // saved attr for 'cursorcolumn'
int syntax_attr = 0; // attributes desired by syntax int syntax_attr = 0; // attributes desired by syntax
bool has_syntax = false; // this buffer has syntax highl. bool has_syntax = false; // this buffer has syntax highl.
@ -1729,6 +1732,50 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
area_active = false; area_active = false;
} }
if (has_decor && v >= 0) {
bool selected = (area_active || (area_highlighting && noinvcur
&& wlv.vcol == wp->w_virtcol));
extmark_attr = decor_redraw_col(wp, (colnr_T)v, wlv.off,
selected, &decor_state);
// we could already be inside an existing virt_line with multiple chunks
if (!(virt_inline_i < kv_size(virt_inline))) {
DecorState *state = &decor_state;
for (size_t i = 0; i < kv_size(state->active); i++) {
DecorRange *item = &kv_A(state->active, i);
if (!(item->start_row == state->row
&& kv_size(item->decor.virt_text)
&& item->decor.virt_text_pos == kVTInline)) {
continue;
}
if (item->win_col >= -1 && item->start_col <= v) {
virt_inline = item->decor.virt_text;
virt_inline_i = 0;
item->win_col = -2;
break;
}
}
}
if (wlv.n_extra <= 0 && virt_inline_i < kv_size(virt_inline)) {
VirtTextChunk vtc = kv_A(virt_inline, virt_inline_i);
wlv.p_extra = vtc.text;
wlv.n_extra = (int)strlen(wlv.p_extra);
wlv.c_extra = NUL;
wlv.c_final = NUL;
wlv.extra_attr = vtc.hl_id ? syn_id2attr(vtc.hl_id) : 0;
n_attr = mb_charlen(vtc.text);
// restore search_attr and area_attr when n_extra
// is down to zero
saved_search_attr = search_attr;
saved_area_attr = area_attr;
search_attr = 0;
area_attr = 0;
extmark_attr = 0;
virt_inline_i++;
}
}
if (!wlv.n_extra) { if (!wlv.n_extra) {
// Check for start/end of 'hlsearch' and other matches. // Check for start/end of 'hlsearch' and other matches.
// After end, check for start/end of next match. // After end, check for start/end of next match.
@ -1792,43 +1839,6 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
wlv.char_attr = 0; wlv.char_attr = 0;
} }
} }
if (has_decor && v >= 0) {
bool selected = (area_active || (area_highlighting && noinvcur
&& wlv.vcol == wp->w_virtcol));
extmark_attr = decor_redraw_col(wp, (colnr_T)v, wlv.off, selected, &decor_state);
// we could already be inside an existing virt_line with multiple chunks
if (!(virt_inline_i < kv_size(virt_inline))) {
DecorState *state = &decor_state;
for (size_t i = 0; i < kv_size(state->active); i++) {
DecorRange *item = &kv_A(state->active, i);
if (!(item->start_row == state->row
&& kv_size(item->decor.virt_text)
&& item->decor.virt_text_pos == kVTInline)) {
continue;
}
if (item->win_col >= -1 && item->start_col <= v) {
virt_inline = item->decor.virt_text;
virt_inline_i = 0;
item->win_col = -2;
break;
}
}
}
if (wlv.n_extra <= 0 && virt_inline_i < kv_size(virt_inline)) {
VirtTextChunk vtc = kv_A(virt_inline, virt_inline_i);
wlv.p_extra = vtc.text;
wlv.n_extra = (int)strlen(wlv.p_extra);
wlv.c_extra = NUL;
wlv.c_final = NUL;
wlv.extra_attr = vtc.hl_id ? syn_id2attr(vtc.hl_id) : 0;
n_attr = mb_charlen(vtc.text);
extmark_attr = 0;
virt_inline_i++;
}
}
} }
// Get the next character to put on the screen. // Get the next character to put on the screen.
@ -1890,6 +1900,14 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
wlv.p_extra++; wlv.p_extra++;
} }
wlv.n_extra--; wlv.n_extra--;
if (wlv.n_extra <= 0) {
if (search_attr == 0) {
search_attr = saved_search_attr;
}
if (area_attr == 0 && *ptr != NUL) {
area_attr = saved_area_attr;
}
}
} else if (foldinfo.fi_lines > 0) { } else if (foldinfo.fi_lines > 0) {
// skip writing the buffer line itself // skip writing the buffer line itself
c = NUL; c = NUL;

View File

@ -646,6 +646,8 @@ describe('extmark decorations', function()
[26] = {background=Screen.colors.DarkGrey, foreground=Screen.colors.LightGrey}; [26] = {background=Screen.colors.DarkGrey, foreground=Screen.colors.LightGrey};
[27] = {background = Screen.colors.Plum1}; [27] = {background = Screen.colors.Plum1};
[28] = {foreground = Screen.colors.SlateBlue}; [28] = {foreground = Screen.colors.SlateBlue};
[29] = {background = Screen.colors.Yellow1};
[30] = {reverse = true};
} }
ns = meths.create_namespace 'test' ns = meths.create_namespace 'test'
@ -1582,7 +1584,7 @@ bbbbbbb]])
]]} ]]}
end) end)
it('has correct cursor position with virtual text on an empty line', function() it('cursor position is correct with virtual text on an empty line', function()
command('set linebreak') command('set linebreak')
insert('one twoword') insert('one twoword')
feed('0') feed('0')
@ -1606,6 +1608,94 @@ bbbbbbb]])
| |
]]} ]]}
end) end)
it('search highlight is correct with virtual text attatched to', function()
insert('foo foo foo foo')
feed('0')
meths.buf_set_extmark(0, ns, 0, 8,
{ virt_text = { { 'virtual text', 'Special' } }, virt_text_pos = 'inline' })
screen:expect { grid = [[
^foo foo {28:virtual text}foo foo |
{1:~ }|
{1:~ }|
{1:~ }|
{1:~ }|
{1:~ }|
{1:~ }|
{1:~ }|
{1:~ }|
{1:~ }|
{1:~ }|
{1:~ }|
{1:~ }|
{1:~ }|
|
]]}
feed('/foo')
screen:expect { grid = [[
{29:foo} {30:foo} {28:virtual text}{29:foo} {29:foo} |
{1:~ }|
{1:~ }|
{1:~ }|
{1:~ }|
{1:~ }|
{1:~ }|
{1:~ }|
{1:~ }|
{1:~ }|
{1:~ }|
{1:~ }|
{1:~ }|
{1:~ }|
/foo^ |
]]}
end)
it('visual select highlight is correct with virtual text attatched to', function()
insert('foo foo foo foo')
feed('0')
meths.buf_set_extmark(0, ns, 0, 8,
{ virt_text = { { 'virtual text', 'Special' } }, virt_text_pos = 'inline' })
feed('8l')
screen:expect { grid = [[
foo foo {28:virtual text}^foo foo |
{1:~ }|
{1:~ }|
{1:~ }|
{1:~ }|
{1:~ }|
{1:~ }|
{1:~ }|
{1:~ }|
{1:~ }|
{1:~ }|
{1:~ }|
{1:~ }|
{1:~ }|
|
]]}
feed('v')
feed('2h')
screen:expect { grid = [[
foo fo^o{18: }{28:virtual text}{18:f}oo foo |
{1:~ }|
{1:~ }|
{1:~ }|
{1:~ }|
{1:~ }|
{1:~ }|
{1:~ }|
{1:~ }|
{1:~ }|
{1:~ }|
{1:~ }|
{1:~ }|
{1:~ }|
{24:-- VISUAL --} |
]]}
end)
end) end)
describe('decorations: virtual lines', function() describe('decorations: virtual lines', function()