aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLuuk van Baal <luukvbaal@gmail.com>2024-04-03 23:06:23 +0200
committerLuuk van Baal <luukvbaal@gmail.com>2024-04-08 23:15:43 +0200
commite21423bb35077fe4bbb6a8fab1000e8bfc6b6b7b (patch)
tree772262a17c90d4b9a7ecfae87f0b5d8fa5ad4a90
parente6cfa22c4cd5b3b422aa4f8350c8e73a3eb2a090 (diff)
downloadrneovim-e21423bb35077fe4bbb6a8fab1000e8bfc6b6b7b.tar.gz
rneovim-e21423bb35077fe4bbb6a8fab1000e8bfc6b6b7b.tar.bz2
rneovim-e21423bb35077fe4bbb6a8fab1000e8bfc6b6b7b.zip
vim-patch:9.1.0260: Problems with "zb" and scrolling to new topline with 'smoothscroll'
Problem: "zb" does not reveal filler lines at the start of a buffer. Scrolled cursor position with 'smoothscroll' is unpredictable, and may reset skipcol later if it is not visible (after v9.1.258) Solution: Replace confusing for loop that reaches final control value too early with while loop. Set "w_curswant" accordingly so cursor will be placed in visible part of topline. (Luuk van Baal) https://github.com/vim/vim/commit/bd28cae1f1c21c0e3743e3427c98bbd848fad237
-rw-r--r--src/nvim/move.c38
-rw-r--r--test/functional/legacy/normal_spec.lua3
-rw-r--r--test/old/testdir/test_normal.vim15
-rw-r--r--test/old/testdir/test_scroll_opt.vim9
4 files changed, 43 insertions, 22 deletions
diff --git a/src/nvim/move.c b/src/nvim/move.c
index 63505c72ab..a1c0a02837 100644
--- a/src/nvim/move.c
+++ b/src/nvim/move.c
@@ -1231,6 +1231,10 @@ bool scrolldown(win_T *wp, linenr_T line_count, int byfold)
wp->w_topline--;
wp->w_skipcol = 0;
wp->w_topfill = 0;
+ // Adjusting the cursor later should not adjust skipcol.
+ if (do_sms) {
+ curwin->w_curswant = MAXCOL;
+ }
// A sequence of folded lines only counts for one logical line
linenr_T first;
if (hasFolding(wp, wp->w_topline, &first, NULL)) {
@@ -1385,9 +1389,10 @@ bool scrollup(win_T *wp, linenr_T line_count, bool byfold)
wp->w_topline = lnum;
wp->w_topfill = win_get_fill(wp, lnum);
wp->w_skipcol = 0;
- // Adjusting the cursor later should not adjust skipcol:
- // bring it to the first screenline on this new topline.
- wp->w_curswant %= width1;
+ // Adjusting the cursor later should not adjust skipcol.
+ if (do_sms) {
+ curwin->w_curswant = 0;
+ }
if (todo > 1 && do_sms) {
size = linetabsize(wp, wp->w_topline);
}
@@ -1846,15 +1851,11 @@ void scroll_cursor_bot(win_T *wp, int min_scroll, bool set_topbot)
bool do_sms = wp->w_p_wrap && wp->w_p_sms;
if (set_topbot) {
- bool set_skipcol = false;
-
int used = 0;
wp->w_botline = cln + 1;
+ loff.lnum = cln + 1;
loff.fill = 0;
- for (wp->w_topline = wp->w_botline;
- wp->w_topline > 1;
- wp->w_topline = loff.lnum) {
- loff.lnum = wp->w_topline;
+ while (true) {
topline_back_winheight(wp, &loff, false);
if (loff.height == MAXCOL) {
break;
@@ -1872,25 +1873,23 @@ void scroll_cursor_bot(win_T *wp, int min_scroll, bool set_topbot)
wp->w_topline = loff.lnum;
wp->w_skipcol = skipcol_from_plines(wp, plines_offset);
wp->w_cursor.col = wp->w_skipcol + overlap;
- set_skipcol = true;
}
}
break;
}
- used += loff.height;
wp->w_topfill = loff.fill;
+ wp->w_topline = loff.lnum;
+ used += loff.height;
}
- if (wp->w_topline > wp->w_buffer->b_ml.ml_line_count) {
- wp->w_topline = wp->w_buffer->b_ml.ml_line_count;
- }
+
set_empty_rows(wp, used);
wp->w_valid |= VALID_BOTLINE|VALID_BOTLINE_AP;
if (wp->w_topline != old_topline
|| wp->w_topfill != old_topfill
- || set_skipcol
+ || wp->w_skipcol != old_skipcol
|| wp->w_skipcol != 0) {
wp->w_valid &= ~(VALID_WROW|VALID_CROW);
- if (set_skipcol) {
+ if (wp->w_skipcol != old_skipcol) {
redraw_later(wp, UPD_NOT_VALID);
} else {
reset_skipcol(wp);
@@ -2305,7 +2304,8 @@ static int get_scroll_overlap(Direction dir)
int min_height = curwin->w_height_inner - 2;
validate_botline(curwin);
- if (dir == FORWARD && curwin->w_botline > curbuf->b_ml.ml_line_count) {
+ if ((dir == BACKWARD && curwin->w_topline == 1)
+ || (dir == FORWARD && curwin->w_botline > curbuf->b_ml.ml_line_count)) {
return min_height + 2; // no overlap, still handle 'smoothscroll'
}
@@ -2435,7 +2435,6 @@ int pagescroll(Direction dir, int count, bool half)
} else {
cursor_up_inner(curwin, count);
}
- curwin->w_curswant = prev_curswant;
if (get_scrolloff_value(curwin)) {
cursor_correct(curwin);
@@ -2453,12 +2452,13 @@ int pagescroll(Direction dir, int count, bool half)
nochange = scroll_with_sms(dir, &count);
}
+ curwin->w_curswant = prev_curswant;
// Error if both the viewport and cursor did not change.
if (nochange) {
beep_flush();
} else if (!curwin->w_p_sms) {
beginline(BL_SOL | BL_FIX);
- } else if (p_sol) {
+ } else if (p_sol || curwin->w_skipcol) {
nv_g_home_m_cmd(&ca);
}
diff --git a/test/functional/legacy/normal_spec.lua b/test/functional/legacy/normal_spec.lua
index 113f7c668a..c57e51c18e 100644
--- a/test/functional/legacy/normal_spec.lua
+++ b/test/functional/legacy/normal_spec.lua
@@ -94,10 +94,9 @@ describe('normal', function()
feed('ggG<C-D>')
screen:expect({
grid = [[
- foobar one two three |*8
+ foobar one two three |*16
^foobar one two three |
{2:---} |
- {1:~ }|*8
|
]],
})
diff --git a/test/old/testdir/test_normal.vim b/test/old/testdir/test_normal.vim
index 013d8959ca..10fbf4125a 100644
--- a/test/old/testdir/test_normal.vim
+++ b/test/old/testdir/test_normal.vim
@@ -4220,4 +4220,19 @@ func Test_single_line_scroll()
call prop_type_delete(vt)
endfunc
+" Test for zb in buffer with a single line and filler lines
+func Test_single_line_filler_zb()
+ call setline(1, ['', 'foobar one two three'])
+ diffthis
+ new
+ call setline(1, ['foobar one two three'])
+ diffthis
+
+ " zb scrolls to reveal filler lines at the start of the buffer.
+ exe "normal \<C-E>zb"
+ call assert_equal(1, winsaveview().topfill)
+
+ bw!
+endfunc
+
" vim: shiftwidth=2 sts=2 expandtab nofoldenable
diff --git a/test/old/testdir/test_scroll_opt.vim b/test/old/testdir/test_scroll_opt.vim
index 4e551cdaad..d381456032 100644
--- a/test/old/testdir/test_scroll_opt.vim
+++ b/test/old/testdir/test_scroll_opt.vim
@@ -1021,6 +1021,8 @@ func Test_smoothscroll_page()
call assert_equal(0, winsaveview().skipcol)
" Half-page scrolling does not go beyond end of buffer and moves the cursor.
+ " Even with 'nostartofline', the correct amount of lines is scrolled.
+ setl nostartofline
exe "norm! 0\<C-D>"
call assert_equal(200, winsaveview().skipcol)
call assert_equal(204, col('.'))
@@ -1044,7 +1046,7 @@ func Test_smoothscroll_page()
call assert_equal(204, col('.'))
exe "norm! \<C-U>"
call assert_equal(0, winsaveview().skipcol)
- call assert_equal(1, col('.'))
+ call assert_equal(40, col('.'))
bwipe!
endfunc
@@ -1062,6 +1064,11 @@ func Test_smoothscroll_next_topline()
redraw
call assert_equal(0, winsaveview().skipcol)
+ " Also when scrolling back.
+ exe "norm! G\<C-Y>"
+ redraw
+ call assert_equal(880, winsaveview().skipcol)
+
" Cursor in correct place when not in the first screenline of a buffer line.
exe "norm! gg4gj20\<C-D>\<C-D>"
redraw