commit 2aab242a0110b6af80305f6fdf7db50c806113d9
parent 1e498b8f772c9d04fa18bd0251818506043bdf51
Author: zeertzjq <zeertzjq@outlook.com>
Date: Sat, 27 Sep 2025 21:28:40 +0800
vim-patch:9.1.1798: Wrong display with 'sms' and long wrapped virt text at EOL (#35930)
Problem: Wrong display with 'smoothscroll' and long wrapped virtual
text at EOL.
Solution: Handle w_skipcol inside long wrapped virtual text at EOL
(zeertzjq).
closes: vim/vim#18408
https://github.com/vim/vim/commit/d9318acc0223bafd3ed5e7f8cdde26328bf200e7
Diffstat:
2 files changed, 163 insertions(+), 12 deletions(-)
diff --git a/src/nvim/drawline.c b/src/nvim/drawline.c
@@ -1477,10 +1477,13 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, int col_rows, b
csarg.max_head_vcol = start_vcol;
int vcol = wlv.vcol;
StrCharInfo ci = utf_ptr2StrCharInfo(ptr);
- while (vcol < start_vcol && *ci.ptr != NUL) {
+ while (vcol < start_vcol) {
cs = win_charsize(cstype, vcol, ci.ptr, ci.chr.value, &csarg);
vcol += cs.width;
prev_ptr = ci.ptr;
+ if (*prev_ptr == NUL) {
+ break;
+ }
ci = utfc_next(ci);
if (wp->w_p_list) {
in_multispace = *prev_ptr == ' ' && (*ci.ptr == ' '
diff --git a/test/functional/ui/decorations_spec.lua b/test/functional/ui/decorations_spec.lua
@@ -5665,53 +5665,201 @@ describe('decorations: inline virtual text', function()
it('line size is correct with inline virt text at EOL and showbreak', function()
screen:try_resize(50, 8)
insert(('0123456789'):rep(5) .. '\nfoo\nbar')
- api.nvim_buf_set_extmark(0, ns, 0, 50, { virt_text = { { ('x'):rep(49), 'ErrorMsg' } }, virt_text_pos = 'inline' })
+ api.nvim_buf_set_extmark(0, ns, 0, 50, { virt_text = { { ('x'):rep(145), 'ErrorMsg' } }, virt_text_pos = 'inline' })
- command([[set showbreak=>\ cursorline]])
+ command([[set cursorline scrolloff=0 showbreak=>\ smoothscroll]])
screen:expect([[
01234567890123456789012345678901234567890123456789|
- {1:> }{4:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx}|
+ {1:> }{4:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx}|*3
+ {1:> }{4:x} |
+ foo |
+ {22:ba^r }|
+ |
+ ]])
+ eq(5, api.nvim_win_text_height(0, { start_row = 0, end_row = 0 }).all)
+ feed('<C-E>')
+ screen:expect([[
+ {1:> }{4:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx}|*3
+ {1:> }{4:x} |
+ foo |
+ {22:ba^r }|
+ {1:~ }|
+ |
+ ]])
+ feed('<C-E>')
+ screen:expect([[
+ {1:> }{4:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx}|*2
{1:> }{4:x} |
foo |
{22:ba^r }|
{1:~ }|*2
|
]])
- eq(3, api.nvim_win_text_height(0, { start_row = 0, end_row = 0 }).all)
+ feed('<C-E>')
+ screen:expect([[
+ {1:> }{4:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx}|
+ {1:> }{4:x} |
+ foo |
+ {22:ba^r }|
+ {1:~ }|*3
+ |
+ ]])
+ feed('<C-E>')
+ screen:expect([[
+ {1:> }{4:x} |
+ foo |
+ {22:ba^r }|
+ {1:~ }|*4
+ |
+ ]])
+ feed('<C-E>')
+ screen:expect([[
+ foo |
+ {22:ba^r }|
+ {1:~ }|*5
+ |
+ ]])
- feed('gg$x<C-O>')
+ feed('gg$xG$')
screen:expect([[
0123456789012345678901234567890123456789012345678{4:x}|
- {1:> }{4:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx}|
+ {1:> }{4:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx}|*3
+ foo |
+ {22:ba^r }|
+ {1:~ }|
+ |
+ ]])
+ eq(4, api.nvim_win_text_height(0, { start_row = 0, end_row = 0 }).all)
+ feed('<C-E>')
+ screen:expect([[
+ {1:> }{4:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx}|*3
+ foo |
+ {22:ba^r }|
+ {1:~ }|*2
+ |
+ ]])
+ feed('<C-E>')
+ screen:expect([[
+ {1:> }{4:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx}|*2
foo |
{22:ba^r }|
{1:~ }|*3
|
]])
- eq(2, api.nvim_win_text_height(0, { start_row = 0, end_row = 0 }).all)
+ feed('<C-E>')
+ screen:expect([[
+ {1:> }{4:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx}|
+ foo |
+ {22:ba^r }|
+ {1:~ }|*4
+ |
+ ]])
+ feed('<C-E>')
+ screen:expect([[
+ foo |
+ {22:ba^r }|
+ {1:~ }|*5
+ |
+ ]])
+ feed('zb')
command('set list listchars=eol:$')
screen:expect([[
0123456789012345678901234567890123456789012345678{4:x}|
- {1:> }{4:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx}|
+ {1:> }{4:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx}|*3
+ {1:> $} |
+ foo{1:$} |
+ {22:ba^r}{23:$}{22: }|
+ |
+ ]])
+ eq(5, api.nvim_win_text_height(0, { start_row = 0, end_row = 0 }).all)
+ feed('<C-E>')
+ screen:expect([[
+ {1:> }{4:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx}|*3
+ {1:> $} |
+ foo{1:$} |
+ {22:ba^r}{23:$}{22: }|
+ {1:~ }|
+ |
+ ]])
+ feed('<C-E>')
+ screen:expect([[
+ {1:> }{4:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx}|*2
{1:> $} |
foo{1:$} |
{22:ba^r}{23:$}{22: }|
{1:~ }|*2
|
]])
- eq(3, api.nvim_win_text_height(0, { start_row = 0, end_row = 0 }).all)
+ feed('<C-E>')
+ screen:expect([[
+ {1:> }{4:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx}|
+ {1:> $} |
+ foo{1:$} |
+ {22:ba^r}{23:$}{22: }|
+ {1:~ }|*3
+ |
+ ]])
+ feed('<C-E>')
+ screen:expect([[
+ {1:> $} |
+ foo{1:$} |
+ {22:ba^r}{23:$}{22: }|
+ {1:~ }|*4
+ |
+ ]])
+ feed('<C-E>')
+ screen:expect([[
+ foo{1:$} |
+ {22:ba^r}{23:$}{22: }|
+ {1:~ }|*5
+ |
+ ]])
- feed('gg$x<C-O>')
+ feed('gg$xG$')
screen:expect([[
012345678901234567890123456789012345678901234567{4:xx}|
+ {1:> }{4:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx}|*2
+ {1:> }{4:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx}{1:$}|
+ foo{1:$} |
+ {22:ba^r}{23:$}{22: }|
+ {1:~ }|
+ |
+ ]])
+ eq(4, api.nvim_win_text_height(0, { start_row = 0, end_row = 0 }).all)
+ feed('<C-E>')
+ screen:expect([[
+ {1:> }{4:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx}|*2
+ {1:> }{4:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx}{1:$}|
+ foo{1:$} |
+ {22:ba^r}{23:$}{22: }|
+ {1:~ }|*2
+ |
+ ]])
+ feed('<C-E>')
+ screen:expect([[
+ {1:> }{4:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx}|
{1:> }{4:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx}{1:$}|
foo{1:$} |
{22:ba^r}{23:$}{22: }|
{1:~ }|*3
|
]])
- eq(2, api.nvim_win_text_height(0, { start_row = 0, end_row = 0 }).all)
+ feed('<C-E>')
+ screen:expect([[
+ {1:> }{4:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx}{1:$}|
+ foo{1:$} |
+ {22:ba^r}{23:$}{22: }|
+ {1:~ }|*4
+ |
+ ]])
+ feed('<C-E>')
+ screen:expect([[
+ foo{1:$} |
+ {22:ba^r}{23:$}{22: }|
+ {1:~ }|*5
+ |
+ ]])
end)
end)