diff options
author | zeertzjq <zeertzjq@outlook.com> | 2023-09-27 10:48:14 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-09-27 10:48:14 +0800 |
commit | dfa8b582a64aa22d3c57261bfcdc970b26cb58f3 (patch) | |
tree | fcc24f25ee072a5bb08c122ba3b9c92c3c260532 | |
parent | de9348978999aa78f8351b5f55930bb109e742f7 (diff) | |
download | rneovim-dfa8b582a64aa22d3c57261bfcdc970b26cb58f3.tar.gz rneovim-dfa8b582a64aa22d3c57261bfcdc970b26cb58f3.tar.bz2 rneovim-dfa8b582a64aa22d3c57261bfcdc970b26cb58f3.zip |
fix(extmarks): draw TAB in virt_text properly with 'rl' (#25381)
-rw-r--r-- | src/nvim/drawline.c | 33 | ||||
-rw-r--r-- | test/functional/ui/decorations_spec.lua | 15 |
2 files changed, 28 insertions, 20 deletions
diff --git a/src/nvim/drawline.c b/src/nvim/drawline.c index 1e5798db32..9da421e79b 100644 --- a/src/nvim/drawline.c +++ b/src/nvim/drawline.c @@ -207,6 +207,16 @@ static void margin_columns_win(win_T *wp, int *left_col, int *right_col) prev_col_off = cur_col_off; } +/// If one half of a double-width char will be overwritten, +/// change the other half to a space so that grid redraws properly. +static void line_check_overwrite(schar_T *dest, int cells, int maxcells, bool rl) +{ + assert(cells > 0); + if (cells < maxcells && dest[rl ? -cells + 1 : cells] == 0) { + dest[rl ? -cells : cells] = schar_from_ascii(' '); + } +} + /// Put a single char from an UTF-8 buffer into a line buffer. /// /// Handles composing chars and arabic shaping state. @@ -216,12 +226,17 @@ static int line_putchar(buf_T *buf, LineState *s, schar_T *dest, int maxcells, b int cells = utf_ptr2cells(p); int c_len = utfc_ptr2len(p); int u8c, u8cc[MAX_MCO]; + assert(maxcells > 0); if (cells > maxcells) { return -1; } u8c = utfc_ptr2char(p, u8cc); if (*p == TAB) { cells = MIN(tabstop_padding(vcol, buf->b_p_ts, buf->b_p_vts_array), maxcells); + } + + line_check_overwrite(dest, cells, maxcells, rl); + if (*p == TAB) { for (int c = 0; c < cells; c++) { dest[rl ? -c : c] = schar_from_ascii(' '); } @@ -304,8 +319,9 @@ static void draw_virt_text(win_T *wp, buf_T *buf, int col_off, int *end_col, int kv_push(win_extmark_arr, m); } if (kv_size(item->decor.virt_text)) { + int vcol = wp->w_p_rl ? col_off - item->draw_col : item->draw_col - col_off; col = draw_virt_text_item(buf, item->draw_col, item->decor.virt_text, - item->decor.hl_mode, max_col, item->draw_col - col_off, wp->w_p_rl); + item->decor.hl_mode, max_col, vcol, wp->w_p_rl); } item->draw_col = INT_MIN; // deactivate if (item->decor.virt_text_pos == kVTEndOfLine && do_eol) { @@ -356,13 +372,15 @@ static int draw_virt_text_item(buf_T *buf, int col, VirtText vt, HlMode hl_mode, attr = virt_attr; } schar_T dummy[2]; - bool rl_overwrote_double_width = linebuf_char[col] == 0; + int maxcells = rl ? col - max_col : max_col - col; int cells = line_putchar(buf, &s, through ? dummy : &linebuf_char[col], - rl ? col - max_col : max_col - col, rl, vcol); + maxcells, rl, vcol); // If we failed to emit a char, we still need to put a space and advance. if (cells < 1) { - linebuf_char[col] = schar_from_ascii(' '); + assert(!through); cells = 1; + line_check_overwrite(&linebuf_char[col], cells, maxcells, rl); + linebuf_char[col] = schar_from_ascii(' '); } for (int c = 0; c < cells; c++) { linebuf_attr[col] = attr; @@ -372,13 +390,6 @@ static int draw_virt_text_item(buf_T *buf, int col, VirtText vt, HlMode hl_mode, col++; } } - // If one half of a double-width char is overwritten, - // change the other half to a space so that grid redraws properly, - // but don't advance the current column. - if ((rl && col > max_col && rl_overwrote_double_width) - || (!rl && col < max_col && linebuf_char[col] == 0)) { - linebuf_char[col] = schar_from_ascii(' '); - } vcol += cells; } return col; diff --git a/test/functional/ui/decorations_spec.lua b/test/functional/ui/decorations_spec.lua index f378c50792..f535bdd1a6 100644 --- a/test/functional/ui/decorations_spec.lua +++ b/test/functional/ui/decorations_spec.lua @@ -1963,23 +1963,20 @@ describe('extmark decorations', function() it('works with double width char and rightleft', function() screen:try_resize(50, 3) - insert('abcdefghij口klmnop') + insert('abcdefghij口klmnopqrstu口vwx口yz') feed('0') command('set rightleft') screen:expect{grid=[[ - ponmlk口jihgfedcb^a| + zy口xwv口utsrqponmlk口jihgfedcb^a| {1: ~}| | ]]} meths.buf_set_extmark(0, ns, 0, 2, { virt_text = {{'overlayed', 'Underlined'}}, virt_text_pos = 'overlay' }) + meths.buf_set_extmark(0, ns, 0, 14, { virt_text = {{'古', 'Underlined'}}, virt_text_pos = 'overlay' }) + meths.buf_set_extmark(0, ns, 0, 20, { virt_text = {{'\t', 'Underlined'}}, virt_text_pos = 'overlay' }) + meths.buf_set_extmark(0, ns, 0, 29, { virt_text = {{'古', 'Underlined'}}, virt_text_pos = 'overlay' }) screen:expect{grid=[[ - ponmlk {28:deyalrevo}b^a| - {1: ~}| - | - ]]} - meths.buf_set_extmark(0, ns, 0, 15, { virt_text = {{'古', 'Underlined'}}, virt_text_pos = 'overlay' }) - screen:expect{grid=[[ - po{28:古}lk {28:deyalrevo}b^a| + zy {28:古}wv {28: }qpon{28:古}k {28:deyalrevo}b^a| {1: ~}| | ]]} |