fix(grid): handle clearing half a double-width char (#27023)

This commit is contained in:
zeertzjq 2024-01-15 23:45:11 +08:00 committed by GitHub
parent 7ed6966023
commit 9c202b9392
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 42 additions and 5 deletions

View File

@ -655,6 +655,7 @@ void grid_put_linebuf(ScreenGrid *grid, int row, int coloff, int col, int endcol
// two-cell character in the same grid, truncate that into a '>'.
if (col > 0 && grid->chars[off_to + (size_t)col] == 0) {
linebuf_char[col - 1] = schar_from_ascii('>');
linebuf_attr[col - 1] = grid->attrs[off_to + (size_t)col - 1];
col--;
}
@ -676,7 +677,7 @@ void grid_put_linebuf(ScreenGrid *grid, int row, int coloff, int col, int endcol
}
}
redraw_next = grid_char_needs_redraw(grid, col, (size_t)col + off_to, endcol - col);
redraw_next = grid_char_needs_redraw(grid, col, off_to + (size_t)col, endcol - col);
int start_dirty = -1;
int end_dirty = 0;
@ -688,7 +689,7 @@ void grid_put_linebuf(ScreenGrid *grid, int row, int coloff, int col, int endcol
char_cells = 2;
}
bool redraw_this = redraw_next; // Does character need redraw?
size_t off = (size_t)col + off_to;
size_t off = off_to + (size_t)col;
redraw_next = grid_char_needs_redraw(grid, col + char_cells,
off + (size_t)char_cells,
endcol - col - char_cells);
@ -732,16 +733,22 @@ void grid_put_linebuf(ScreenGrid *grid, int row, int coloff, int col, int endcol
if (clear_next) {
// Clear the second half of a double-wide character of which the left
// half was overwritten with a single-wide character.
grid->chars[(size_t)col + off_to] = schar_from_ascii(' ');
grid->chars[off_to + (size_t)col] = schar_from_ascii(' ');
end_dirty++;
}
// When clearing the left half of a double-wide char also clear the right half.
if (off_to + (size_t)clear_width < max_off_to
&& grid->chars[off_to + (size_t)clear_width] == 0) {
clear_width++;
}
int clear_dirty_start = -1, clear_end = -1;
// blank out the rest of the line
// TODO(bfredl): we could cache winline widths
col = clear_start;
while (col < clear_width) {
size_t off = (size_t)col + off_to;
size_t off = off_to + (size_t)col;
if (grid->chars[off] != schar_from_ascii(' ')
|| grid->attrs[off] != bg_attr
|| rdb_flags & RDB_NODELTA) {

View File

@ -22,6 +22,8 @@ describe('multibyte rendering', function()
[3] = { background = Screen.colors.LightMagenta },
[4] = { bold = true },
[5] = { foreground = Screen.colors.Blue },
[6] = { reverse = true, bold = true },
[7] = { reverse = true },
})
end)
@ -84,7 +86,7 @@ describe('multibyte rendering', function()
{4:-- INSERT --} |
]])
-- check double-with char is temporarily hidden when overlapped
-- check double-width char is temporarily hidden when overlapped
fn.complete(4, { 'xx', 'yy' })
screen:expect([[
ab xx^ |
@ -104,6 +106,34 @@ describe('multibyte rendering', function()
]])
end)
it('no stray chars when splitting left of window with double-width chars', function()
api.nvim_buf_set_lines(0, 0, -1, true, {
(''):rep(16),
'a' .. (''):rep(16),
'aa' .. (''):rep(16),
'aaa' .. (''):rep(16),
'aaaa' .. (''):rep(16),
})
screen:expect([[
^ |
a口口口口口口口口口口口口口口口口 |
aa口口口口口口口口口口口口口口口口 |
aaa口口口口口口口口口口口口口口口口 |
aaaa口口口口口口口口口口口口口口口口 |
|
]])
command('20vnew')
screen:expect([[
^ |
{1:~ }a口口口口口口口口口口口口口口口口 |
{1:~ }aa口口口口口口口口口口口口口口口口 |
{1:~ }aaa口口口口口口口口口口口口口口口口 |
{6:[No Name] }{7:[No Name] [+] }|
|
]])
end)
it('0xffff is shown as 4 hex digits', function()
command([[call setline(1, "\uFFFF!!!")]])
feed('$')