aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorzeertzjq <zeertzjq@outlook.com>2024-01-09 05:37:08 +0800
committerGitHub <noreply@github.com>2024-01-09 05:37:08 +0800
commitee3d4f6b90d0902aa17936d1f0944755516569a1 (patch)
tree284a7556d4620f40071e857b29024706a944dd07
parentc4acbb87babf9c06198e56d85d113067fd705795 (diff)
downloadrneovim-ee3d4f6b90d0902aa17936d1f0944755516569a1.tar.gz
rneovim-ee3d4f6b90d0902aa17936d1f0944755516569a1.tar.bz2
rneovim-ee3d4f6b90d0902aa17936d1f0944755516569a1.zip
fix(extmarks): handle overwriting right half of wide char (#26951)
-rw-r--r--src/nvim/drawline.c19
-rw-r--r--test/functional/ui/decorations_spec.lua32
2 files changed, 48 insertions, 3 deletions
diff --git a/src/nvim/drawline.c b/src/nvim/drawline.c
index dc4ef72e38..7ee7e1911f 100644
--- a/src/nvim/drawline.c
+++ b/src/nvim/drawline.c
@@ -206,6 +206,9 @@ static void margin_columns_win(win_T *wp, int *left_col, int *right_col)
/// Handles composing chars
static int line_putchar(buf_T *buf, const char **pp, schar_T *dest, int maxcells, int vcol)
{
+ // Caller should handle overwriting the left half of a double-width char.
+ assert(dest[0] != 0);
+
const char *p = *pp;
int cells = utf_ptr2cells(p);
int c_len = utfc_ptr2len(p);
@@ -219,6 +222,7 @@ static int line_putchar(buf_T *buf, const char **pp, schar_T *dest, int maxcells
cells = MIN(tabstop_padding(vcol, buf->b_p_ts, buf->b_p_vts_array), maxcells);
}
+ // When overwriting the left half of a double-width char, clear the right half.
if (cells < maxcells && dest[cells] == 0) {
dest[cells] = schar_from_ascii(' ');
}
@@ -330,8 +334,15 @@ static int draw_virt_text_item(buf_T *buf, int col, VirtText vt, HlMode hl_mode,
} else {
attr = virt_attr;
}
- schar_T dummy[2];
+ schar_T dummy[2] = { schar_from_ascii(' '), schar_from_ascii(' ') };
int maxcells = max_col - col;
+ // When overwriting the right half of a double-width char, clear the left half.
+ if (linebuf_char[col] == 0) {
+ assert(col > 0);
+ linebuf_char[col - 1] = schar_from_ascii(' ');
+ // Clear the right half as well for the assertion in line_putchar().
+ linebuf_char[col] = schar_from_ascii(' ');
+ }
int cells = line_putchar(buf, &p, through ? dummy : &linebuf_char[col],
maxcells, vcol);
for (int c = 0; c < cells; c++) {
@@ -867,7 +878,11 @@ static void win_line_start(win_T *wp, winlinevars_T *wlv, bool save_extra)
wlv->col = 0;
wlv->off = 0;
wlv->need_lbr = false;
- memset(linebuf_vcol, -1, (size_t)wp->w_grid.cols * sizeof(*linebuf_vcol));
+ for (int i = 0; i < wp->w_grid.cols; i++) {
+ linebuf_char[i] = schar_from_ascii(' ');
+ linebuf_attr[i] = -1;
+ linebuf_vcol[i] = -1;
+ }
}
static void fix_for_boguscols(winlinevars_T *wlv)
diff --git a/test/functional/ui/decorations_spec.lua b/test/functional/ui/decorations_spec.lua
index 48df6b3295..4860009e38 100644
--- a/test/functional/ui/decorations_spec.lua
+++ b/test/functional/ui/decorations_spec.lua
@@ -2082,7 +2082,37 @@ describe('extmark decorations', function()
]]}
end)
- it('works with double width char and rightleft', function()
+ it('virtual text overwrites double-width char properly', function()
+ screen:try_resize(50, 3)
+ insert('abcdefghij口klmnopqrstu口vwx口yz')
+ feed('0')
+ meths.buf_set_extmark(0, ns, 0, 0, { virt_text = {{'!!!!!', 'Underlined'}}, virt_text_win_col = 11 })
+ screen:expect{grid=[[
+ ^abcdefghij {28:!!!!!}opqrstu口vwx口yz |
+ {1:~ }|
+ |
+ ]]}
+ feed('8x')
+ screen:expect{grid=[[
+ ^ij口klmnopq{28:!!!!!} vwx口yz |
+ {1:~ }|
+ |
+ ]]}
+ feed('3l5x')
+ screen:expect{grid=[[
+ ij口^pqrstu {28:!!!!!} yz |
+ {1:~ }|
+ |
+ ]]}
+ feed('5x')
+ screen:expect{grid=[[
+ ij口^u口vwx {28:!!!!!} |
+ {1:~ }|
+ |
+ ]]}
+ end)
+
+ it('virtual text works with double-width char and rightleft', function()
screen:try_resize(50, 3)
insert('abcdefghij口klmnopqrstu口vwx口yz')
feed('0')