From 804a94d300eb7f3ed5ad81155829fc2e4c2b5833 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Fri, 19 Jul 2024 11:54:42 +0800 Subject: [PATCH] vim-patch:9.1.0601: Wrong cursor position with 'breakindent' when wide char doesn't fit (#29793) Problem: Wrong cursor position with 'breakindent' when a double-width character doesn't fit in a screen line (mikoto2000) Solution: Include the width of the 'breakindent' properly. (zeertzjq) fixes: vim/vim#15289 closes: vim/vim#15290 https://github.com/vim/vim/commit/b5d6b5caac752fe15856e37fd3abc5459292d4b8 (cherry picked from commit 35b35cb93cb54d2a9b7f881b930ba42186e57d23) --- src/nvim/plines.c | 2 +- test/functional/ui/decorations_spec.lua | 16 ++++++++++++++-- test/old/testdir/test_breakindent.vim | 11 +++++++++++ test/old/testdir/test_listlbr_utf8.vim | 6 ++++++ 4 files changed, 32 insertions(+), 3 deletions(-) diff --git a/src/nvim/plines.c b/src/nvim/plines.c index 5881d34c48..38f2b8031d 100644 --- a/src/nvim/plines.c +++ b/src/nvim/plines.c @@ -267,7 +267,7 @@ CharSize charsize_regular(CharsizeArg *csarg, char *const cur, colnr_T const vco head += (max_head_vcol - (vcol + head_prev + prev_rem) + width2 - 1) / width2 * head_mid; } else if (max_head_vcol < 0) { - int off = virt_text_cursor_off(csarg, *cur == NUL); + int off = mb_added + virt_text_cursor_off(csarg, *cur == NUL); if (off >= prev_rem) { if (size > off) { head += (1 + (off - prev_rem) / width) * head_mid; diff --git a/test/functional/ui/decorations_spec.lua b/test/functional/ui/decorations_spec.lua index 63f2c9d1a1..74197687e7 100644 --- a/test/functional/ui/decorations_spec.lua +++ b/test/functional/ui/decorations_spec.lua @@ -4027,11 +4027,23 @@ describe('decorations: inline virtual text', function() normal! $ ]]) api.nvim_buf_set_extmark(0, ns, 0, 40, { virt_text = { { ('b'):rep(9) } }, virt_text_pos = 'inline' }) - screen:expect{grid=[[ + screen:expect([[ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbb{1:>}| 口1234^5 | | - ]]} + ]]) + feed('g0') + screen:expect([[ + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbb{1:>}| + ^口12345 | + | + ]]) + command('set showbreak=+++') + screen:expect([[ + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbb{1:>}| + {1:+++}^口12345 | + | + ]]) end) end) diff --git a/test/old/testdir/test_breakindent.vim b/test/old/testdir/test_breakindent.vim index 636ec6f285..f09ab8684f 100644 --- a/test/old/testdir/test_breakindent.vim +++ b/test/old/testdir/test_breakindent.vim @@ -1205,4 +1205,15 @@ func Test_breakindent_min_with_signcol() call s:close_windows() endfunc +func Test_breakindent_with_double_width_wrap() + 50vnew + setlocal tabstop=8 breakindent nolist + call setline(1, "\t" .. repeat('a', winwidth(0) - 9) .. '口口口') + normal! $g0 + call assert_equal(2, winline()) + call assert_equal(9, wincol()) + + bwipe! +endfunc + " vim: shiftwidth=2 sts=2 expandtab diff --git a/test/old/testdir/test_listlbr_utf8.vim b/test/old/testdir/test_listlbr_utf8.vim index 313ff30cc4..693f2015fc 100644 --- a/test/old/testdir/test_listlbr_utf8.vim +++ b/test/old/testdir/test_listlbr_utf8.vim @@ -280,6 +280,9 @@ func Test_chinese_char_on_wrap_column() call s:compare_lines(expect, lines) call assert_equal(len(expect), winline()) call assert_equal(strwidth(trim(expect[-1], ' ', 2)), wincol()) + norm! g0 + call assert_equal(len(expect), winline()) + call assert_equal(1, wincol()) call s:close_windows() endfunc @@ -315,6 +318,9 @@ func Test_chinese_char_on_wrap_column_sbr() call s:compare_lines(expect, lines) call assert_equal(len(expect), winline()) call assert_equal(strwidth(trim(expect[-1], ' ', 2)), wincol()) + norm! g0 + call assert_equal(len(expect), winline()) + call assert_equal(4, wincol()) call s:close_windows() endfunc