vim-patch:9.0.1543: display errors when making topline shorter

Problem:    Display errors when making topline shorter and 'smoothscroll' is
            set.
Solution:   Reset w_skipcol when the topline becomes shorter than its current
            value. (Luuk van Baal, closes vim/vim#12367)

5d01f86d99
This commit is contained in:
Luuk van Baal
2023-05-11 20:37:49 +02:00
parent 15c684b358
commit 6f41eaa2b5
5 changed files with 82 additions and 12 deletions

View File

@@ -247,11 +247,24 @@ static void changed_common(linenr_T lnum, colnr_T col, linenr_T lnume, linenr_T
wp->w_redr_type = UPD_VALID; wp->w_redr_type = UPD_VALID;
} }
linenr_T last = lnume + xtra - 1; // last line after the change
// Reset "w_skipcol" if the topline length has become smaller to
// such a degree that nothing will be visible anymore, accounting
// for 'smoothscroll' <<< or 'listchars' "precedes" marker.
if (wp->w_skipcol > 0
&& (last < wp->w_topline
|| (wp->w_topline >= lnum
&& wp->w_topline < lnume
&& win_linetabsize(wp, wp->w_topline, ml_get(wp->w_topline), (colnr_T)MAXCOL)
<= (unsigned)wp->w_skipcol + (wp->w_p_list && wp->w_p_lcs_chars.prec ? 1 : 3)))) {
wp->w_skipcol = 0;
}
// Check if a change in the buffer has invalidated the cached // Check if a change in the buffer has invalidated the cached
// values for the cursor. // values for the cursor.
// Update the folds for this window. Can't postpone this, because // Update the folds for this window. Can't postpone this, because
// a following operator might work on the whole fold: ">>dd". // a following operator might work on the whole fold: ">>dd".
linenr_T last = lnume + xtra - 1; // last line after the change
foldUpdate(wp, lnum, last); foldUpdate(wp, lnum, last);
// The change may cause lines above or below the change to become // The change may cause lines above or below the change to become

View File

@@ -200,13 +200,13 @@ describe('display', function()
local screen = Screen.new(35, 14) local screen = Screen.new(35, 14)
screen:attach() screen:attach()
exec([[ exec([[
set display=lastline scrolloff=5 set display=lastline smoothscroll scrolloff=0
call setline(1, [ call setline(1, [
\'aaaaa'->repeat(100), \'aaaaa'->repeat(500),
\'bbbbb '->repeat(7) .. 'ccccc '->repeat(7) .. 'ddddd '->repeat(7) \'bbbbb '->repeat(7) .. 'ccccc '->repeat(7) .. 'ddddd '->repeat(7)
\]) \])
]]) ]])
feed('482|') feed('736|')
screen:expect([[ screen:expect([[
<<<aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa| <<<aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa| aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
@@ -219,10 +219,11 @@ describe('display', function()
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa| aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa| aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa| aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
aaaaaaaaaaaaaaaaaaaaaaaaaa^aaaaaaaaa| aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
aaaaaaaaaa | ^aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
| |
]]) ]])
-- The correct part of the last line is moved into view.
feed('D') feed('D')
screen:expect([[ screen:expect([[
<<<aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa| <<<aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
@@ -236,10 +237,48 @@ describe('display', function()
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa| aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa| aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa| aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
aaaaaaaaaaaaaaaaaaaaaaaaa^a | aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa^a|
bbbbb bbbbb bbbbb bbbbb bbbbb bb@@@| bbbbb bbbbb bbbbb bbbbb bbbbb bb@@@|
| |
]]) ]])
-- "w_skipcol" does not change because the topline is still long enough
-- to maintain the current skipcol.
feed('g04l11gkD')
screen:expect([[
<<<^a |
bbbbb bbbbb bbbbb bbbbb bbbbb bbbbb|
bbbbb ccccc ccccc ccccc ccccc cccc|
c ccccc ccccc ddddd ddddd ddddd ddd|
dd ddddd ddddd ddddd |
~ |
~ |
~ |
~ |
~ |
~ |
~ |
~ |
|
]])
-- "w_skipcol" is reset to bring the entire topline into view because
-- the line length is now smaller than the current skipcol + marker.
feed('x')
screen:expect([[
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
aa^a |
bbbbb bbbbb bbbbb bbbbb bbbbb bbbbb|
bbbbb ccccc ccccc ccccc ccccc cccc|
c ccccc ccccc ddddd ddddd ddddd @@@|
|
]])
end) end)
-- oldtest: Test_display_cursor_long_line() -- oldtest: Test_display_cursor_long_line()

View File

@@ -588,6 +588,9 @@ describe('smoothscroll', function()
-- than one window. Note that the cursor is at the bottom this time because -- than one window. Note that the cursor is at the bottom this time because
-- Vim prefers to do so if we are scrolling a few lines only. -- Vim prefers to do so if we are scrolling a few lines only.
exec("call setline(1, ['one', 'two', 'Line' .. (' with lots of text'->repeat(10)) .. ' end', 'four'])") exec("call setline(1, ['one', 'two', 'Line' .. (' with lots of text'->repeat(10)) .. ' end', 'four'])")
-- Currently visible lines were replaced, test that the lines and cursor
-- are correctly displayed.
screen:expect_unchanged()
feed('3Gztj') feed('3Gztj')
screen:expect_unchanged() screen:expect_unchanged()
-- Repeat the step but this time start it when the line is smooth-scrolled by -- Repeat the step but this time start it when the line is smooth-scrolled by

View File

@@ -482,9 +482,9 @@ func Test_display_long_lastline()
CheckScreendump CheckScreendump
let lines =<< trim END let lines =<< trim END
set display=lastline set display=lastline smoothscroll scrolloff=0
call setline(1, [ call setline(1, [
\'aaaaa'->repeat(100), \'aaaaa'->repeat(150),
\'bbbbb '->repeat(7) .. 'ccccc '->repeat(7) .. 'ddddd '->repeat(7) \'bbbbb '->repeat(7) .. 'ccccc '->repeat(7) .. 'ddddd '->repeat(7)
\]) \])
END END
@@ -492,11 +492,23 @@ func Test_display_long_lastline()
call writefile(lines, 'XdispLongline', 'D') call writefile(lines, 'XdispLongline', 'D')
let buf = RunVimInTerminal('-S XdispLongline', #{rows: 14, cols: 35}) let buf = RunVimInTerminal('-S XdispLongline', #{rows: 14, cols: 35})
call term_sendkeys(buf, "482|") call term_sendkeys(buf, "736|")
call VerifyScreenDump(buf, 'Test_display_long_line_1', {}) call VerifyScreenDump(buf, 'Test_display_long_line_1', {})
" The correct part of the last line is moved into view.
call term_sendkeys(buf, "D") call term_sendkeys(buf, "D")
call VerifyScreenDump(buf, 'Test_display_long_line_2', {}) call VerifyScreenDump(buf, 'Test_display_long_line_2', {})
" "w_skipcol" does not change because the topline is still long enough
" to maintain the current skipcol.
call term_sendkeys(buf, "g04l11gkD")
call VerifyScreenDump(buf, 'Test_display_long_line_3', {})
" "w_skipcol" is reset to bring the entire topline into view because
" the line length is now smaller than the current skipcol + marker.
call term_sendkeys(buf, "x")
call VerifyScreenDump(buf, 'Test_display_long_line_4', {})
call StopVimInTerminal(buf) call StopVimInTerminal(buf)
endfunc endfunc

View File

@@ -335,9 +335,12 @@ func Test_smoothscroll_wrap_long_line()
" than one window. Note that the cursor is at the bottom this time because " than one window. Note that the cursor is at the bottom this time because
" Vim prefers to do so if we are scrolling a few lines only. " Vim prefers to do so if we are scrolling a few lines only.
call term_sendkeys(buf, ":call setline(1, ['one', 'two', 'Line' .. (' with lots of text'->repeat(10)) .. ' end', 'four'])\<CR>") call term_sendkeys(buf, ":call setline(1, ['one', 'two', 'Line' .. (' with lots of text'->repeat(10)) .. ' end', 'four'])\<CR>")
" Currently visible lines were replaced, test that the lines and cursor
" are correctly displayed.
call VerifyScreenDump(buf, 'Test_smooth_long_14', {})
call term_sendkeys(buf, "3Gzt") call term_sendkeys(buf, "3Gzt")
call term_sendkeys(buf, "j") call term_sendkeys(buf, "j")
call VerifyScreenDump(buf, 'Test_smooth_long_14', {}) call VerifyScreenDump(buf, 'Test_smooth_long_15', {})
" Repeat the step but this time start it when the line is smooth-scrolled by " Repeat the step but this time start it when the line is smooth-scrolled by
" one line. This tests that the offset calculation is still correct and " one line. This tests that the offset calculation is still correct and
@@ -345,7 +348,7 @@ func Test_smoothscroll_wrap_long_line()
" screen. " screen.
call term_sendkeys(buf, "3Gzt") call term_sendkeys(buf, "3Gzt")
call term_sendkeys(buf, "\<C-E>j") call term_sendkeys(buf, "\<C-E>j")
call VerifyScreenDump(buf, 'Test_smooth_long_15', {}) call VerifyScreenDump(buf, 'Test_smooth_long_16', {})
call StopVimInTerminal(buf) call StopVimInTerminal(buf)
endfunc endfunc