From 4db62d96bc289bbc9e975f314ff21e313290b68c Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Sat, 27 Sep 2025 21:28:40 +0800 Subject: [PATCH] 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 --- src/nvim/drawline.c | 5 +- test/functional/ui/decorations_spec.lua | 172 ++++++++++++++++++++++-- 2 files changed, 164 insertions(+), 13 deletions(-) diff --git a/src/nvim/drawline.c b/src/nvim/drawline.c index c2c6bc966b..235ab755a6 100644 --- a/src/nvim/drawline.c +++ b/src/nvim/drawline.c @@ -1458,10 +1458,13 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, int col_rows, b csarg.max_head_vcol = start_col; int vcol = wlv.vcol; StrCharInfo ci = utf_ptr2StrCharInfo(ptr); - while (vcol < start_col && *ci.ptr != NUL) { + while (vcol < start_col) { 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 index 03edfac071..2e37204921 100644 --- a/test/functional/ui/decorations_spec.lua +++ b/test/functional/ui/decorations_spec.lua @@ -4898,53 +4898,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('') + screen:expect([[ + {1:> }{4:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx}|*3 + {1:> }{4:x} | + foo | + {22:ba^r }| + {1:~ }| + | + ]]) + feed('') + 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('gg$x') + feed('') screen:expect([[ - 0123456789012345678901234567890123456789012345678{4:x}| {1:> }{4:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx}| + {1:> }{4:x} | foo | {22:ba^r }| {1:~ }|*3 | ]]) - eq(2, api.nvim_win_text_height(0, { start_row = 0, end_row = 0 }).all) + feed('') + screen:expect([[ + {1:> }{4:x} | + foo | + {22:ba^r }| + {1:~ }|*4 + | + ]]) + feed('') + screen:expect([[ + foo | + {22:ba^r }| + {1:~ }|*5 + | + ]]) + feed('gg$xG$') + screen:expect([[ + 0123456789012345678901234567890123456789012345678{4:x}| + {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('') + screen:expect([[ + {1:> }{4:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx}|*3 + foo | + {22:ba^r }| + {1:~ }|*2 + | + ]]) + feed('') + screen:expect([[ + {1:> }{4:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx}|*2 + foo | + {22:ba^r }| + {1:~ }|*3 + | + ]]) + feed('') + screen:expect([[ + {1:> }{4:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx}| + foo | + {22:ba^r }| + {1:~ }|*4 + | + ]]) + feed('') + 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('') + screen:expect([[ + {1:> }{4:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx}|*3 + {1:> $} | + foo{1:$} | + {22:ba^r}{23:$}{22: }| + {1:~ }| + | + ]]) + feed('') + 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('') + screen:expect([[ + {1:> }{4:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx}| + {1:> $} | + foo{1:$} | + {22:ba^r}{23:$}{22: }| + {1:~ }|*3 + | + ]]) + feed('') + screen:expect([[ + {1:> $} | + foo{1:$} | + {22:ba^r}{23:$}{22: }| + {1:~ }|*4 + | + ]]) + feed('') + screen:expect([[ + foo{1:$} | + {22:ba^r}{23:$}{22: }| + {1:~ }|*5 + | + ]]) - feed('gg$x') + 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('') + screen:expect([[ + {1:> }{4:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx}|*2 + {1:> }{4:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx}{1:$}| + foo{1:$} | + {22:ba^r}{23:$}{22: }| + {1:~ }|*2 + | + ]]) + feed('') + 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('') + screen:expect([[ + {1:> }{4:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx}{1:$}| + foo{1:$} | + {22:ba^r}{23:$}{22: }| + {1:~ }|*4 + | + ]]) + feed('') + screen:expect([[ + foo{1:$} | + {22:ba^r}{23:$}{22: }| + {1:~ }|*5 + | + ]]) end) end)