summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorYee Cheng Chin <ychin.git@gmail.com>2022-11-19 12:25:16 +0000
committerBram Moolenaar <Bram@vim.org>2022-11-19 12:25:16 +0000
commit361895d2a15b4b0bbbb4c009261eab5b3d69ebf1 (patch)
tree21c7c932e95563ec43015810b6d007e10f543373
parentd63a85592cef0ee4f0fec5efe2f8d66b31f01f05 (diff)
patch 9.0.0908: with 'smoothscroll' cursor may end up in wrong positionv9.0.0908
Problem: With 'smoothscroll' cursor may end up in wrong position. Solution: Correct the computation of screen lines. (Yee Cheng Chin, closes #11502)
-rw-r--r--src/move.c44
-rw-r--r--src/testdir/dumps/Test_smooth_long_1.dump2
-rw-r--r--src/testdir/dumps/Test_smooth_long_10.dump6
-rw-r--r--src/testdir/dumps/Test_smooth_long_11.dump6
-rw-r--r--src/testdir/dumps/Test_smooth_long_12.dump6
-rw-r--r--src/testdir/dumps/Test_smooth_long_2.dump2
-rw-r--r--src/testdir/dumps/Test_smooth_long_3.dump2
-rw-r--r--src/testdir/dumps/Test_smooth_long_4.dump2
-rw-r--r--src/testdir/dumps/Test_smooth_long_5.dump2
-rw-r--r--src/testdir/dumps/Test_smooth_long_6.dump2
-rw-r--r--src/testdir/dumps/Test_smooth_long_7.dump2
-rw-r--r--src/testdir/dumps/Test_smooth_long_8.dump2
-rw-r--r--src/testdir/dumps/Test_smooth_long_9.dump2
-rw-r--r--src/testdir/test_scroll_opt.vim26
-rw-r--r--src/version.c2
15 files changed, 92 insertions, 16 deletions
diff --git a/src/move.c b/src/move.c
index 66e8c18c59..42054455bb 100644
--- a/src/move.c
+++ b/src/move.c
@@ -2460,18 +2460,50 @@ scroll_cursor_bot(int min_scroll, int set_topbot)
used = curwin->w_cline_height;
#endif
- // If the cursor is below botline, we will at least scroll by the height
- // of the cursor line. Correct for empty lines, which are really part of
- // botline.
+ // If the cursor is on or below botline, we will at least scroll by the
+ // height of the cursor line, which is "used". Correct for empty lines,
+ // which are really part of botline.
if (cln >= curwin->w_botline)
{
scrolled = used;
if (cln == curwin->w_botline)
scrolled -= curwin->w_empty_rows;
min_scrolled = scrolled;
- if (cln > curwin->w_botline && curwin->w_p_sms && curwin->w_p_wrap)
- for (linenr_T lnum = curwin->w_botline + 1; lnum <= cln; ++lnum)
- min_scrolled += PLINES_NOFILL(lnum);
+ if (curwin->w_p_sms && curwin->w_p_wrap)
+ {
+ // 'smoothscroll' and 'wrap' are set
+ if (cln > curwin->w_botline)
+ // add screen lines below w_botline
+ for (linenr_T lnum = curwin->w_botline + 1; lnum <= cln; ++lnum)
+ min_scrolled += PLINES_NOFILL(lnum);
+
+ // Calculate how many screen lines the current top line of window
+ // occupies. If it is occupying more than the entire window, we
+ // need to scroll the additional clipped lines to scroll past the
+ // top line before we can move on to the other lines.
+ int top_plines =
+#ifdef FEAT_DIFF
+ plines_win_nofill
+#else
+ plines_win
+#endif
+ (curwin, curwin->w_topline, FALSE);
+ int skip_lines = 0;
+ int width1 = curwin->w_width - curwin_col_off();
+ int width2 = width1 + curwin_col_off2();
+ // similar formula is used in curs_columns()
+ if (curwin->w_skipcol > width1)
+ skip_lines += (curwin->w_skipcol - width1) / width2 + 1;
+ else if (curwin->w_skipcol > 0)
+ skip_lines = 1;
+
+ top_plines -= skip_lines;
+ if (top_plines > curwin->w_height)
+ {
+ scrolled += (top_plines - curwin->w_height);
+ min_scrolled += (top_plines - curwin->w_height);
+ }
+ }
}
/*
diff --git a/src/testdir/dumps/Test_smooth_long_1.dump b/src/testdir/dumps/Test_smooth_long_1.dump
index a6f4cfb166..86c27ed064 100644
--- a/src/testdir/dumps/Test_smooth_long_1.dump
+++ b/src/testdir/dumps/Test_smooth_long_1.dump
@@ -3,4 +3,4 @@
|h| |l|o|t|s| |o|f| |t|e|x|t| |w|i|t|h| |l|o|t|s| |o|f| |t|e|x|t| |w|i|t|h| |l|o
|t|s| |o|f| |t|e|x|t| |w|i|t|h| |l|o|t|s| |o|f| |t|e|x|t| |w|i|t|h| |l|o|t|s| |o
|f| |t|e|x|t| |w|i|t|h| |l|o|t|s| |o|f| |t|e|x|t| |w|i|t|h| |l|o|t|s| |o|f| |t|e
-| @21|3|,|1|0| @9|B|o|t|
+| @21|3|,|1|0| @9|6@1|%|
diff --git a/src/testdir/dumps/Test_smooth_long_10.dump b/src/testdir/dumps/Test_smooth_long_10.dump
new file mode 100644
index 0000000000..a7aee24f38
--- /dev/null
+++ b/src/testdir/dumps/Test_smooth_long_10.dump
@@ -0,0 +1,6 @@
+>f+0&#ffffff0|o|u|r| @35
+|~+0#4040ff13&| @38
+|~| @38
+|~| @38
+|~| @38
+|:+0#0000000&|s|e|t| |s|c|r|o|l@1|o| @9|4|,|1| @10|B|o|t|
diff --git a/src/testdir/dumps/Test_smooth_long_11.dump b/src/testdir/dumps/Test_smooth_long_11.dump
new file mode 100644
index 0000000000..7f5bff746c
--- /dev/null
+++ b/src/testdir/dumps/Test_smooth_long_11.dump
@@ -0,0 +1,6 @@
+|<+0#4040ff13#ffffff0@2|t+0#0000000&|h| |l|o|t|s| |o|f| |t|e|x|t| |w|i|t|h| |l|o|t|s| |o|f| |t|e|x|t| |w|i|t
+|h| |l|o|t|s| |o|f| |t|e|x|t| |w|i|t|h| |l|o|t|s| |o|f| |t|e|x|t| |w|i|t|h| |l|o
+|t|s| |o|f| |t|e|x|t| |w|i|t|h| |l|o|t|s| |o|f| |t|e|x|t| |w|i|t|h| |l|o|t|s| |o
+|f| |t|e|x|t| |w|i|t|h| |l|o|t|s| |o|f| |t|e|x|t| |e|n|d| @11
+>f|o|u|r| @35
+@22|4|,|1| @10|B|o|t|
diff --git a/src/testdir/dumps/Test_smooth_long_12.dump b/src/testdir/dumps/Test_smooth_long_12.dump
new file mode 100644
index 0000000000..b82fca5994
--- /dev/null
+++ b/src/testdir/dumps/Test_smooth_long_12.dump
@@ -0,0 +1,6 @@
+|<+0#4040ff13#ffffff0@2|t+0#0000000&|h| |l|o|t|s| |o|f| |t|e|x|t| |w|i|t|h| |l|o|t|s| |o|f| |t|e|x|t| |w|i|t
+|h| |l|o|t|s| |o|f| |t|e|x|t| |w|i|t|h| |l|o|t|s| |o|f| |t|e|x|t| |w|i|t|h| |l|o
+|t|s| |o|f| |t|e|x|t| |w|i|t|h| |l|o|t|s| |o|f| |t|e|x|t| |w|i|t|h| |l|o|t|s| |o
+|f| |t|e|x|t| |w|i|t|h| |l|o|t|s| |o|f| |t|e|x|t| |e|n|d| @11
+|f|o|u>r| @35
+@22|4|,|4| @10|B|o|t|
diff --git a/src/testdir/dumps/Test_smooth_long_2.dump b/src/testdir/dumps/Test_smooth_long_2.dump
index 0c2634f18c..6800ba41d5 100644
--- a/src/testdir/dumps/Test_smooth_long_2.dump
+++ b/src/testdir/dumps/Test_smooth_long_2.dump
@@ -3,4 +3,4 @@
|t|s| |o|f| |t|e|x|t| |w|i|t|h| |l|o|t|s| |o|f| |t|e|x|t| |w|i|t|h| |l|o|t|s| |o
|f| |t|e|x|t| |w|i|t|h| |l|o|t|s| |o|f| |t|e|x|t| |w|i|t|h| |l|o|t|s| |o|f| |t|e
|x|t| |w|i|t|h| |l|o|t|s| |o|f| |t|e|x|t| |w|i|t|h| |l|o|t|s| |o|f| |t|e|x|t| |w
-| @21|3|,|5|0| @9|B|o|t|
+| @21|3|,|5|0| @9|6@1|%|
diff --git a/src/testdir/dumps/Test_smooth_long_3.dump b/src/testdir/dumps/Test_smooth_long_3.dump
index c06144c552..63d97940e7 100644
--- a/src/testdir/dumps/Test_smooth_long_3.dump
+++ b/src/testdir/dumps/Test_smooth_long_3.dump
@@ -3,4 +3,4 @@
| |o|f| |t|e|x|t| |w|i|t|h| |l|o|t|s| |o|f| |t|e|x|t| |w|i|t|h| |l|o|t|s| |o|f|
|t|e|x|t| |w|i|t|h| |l|o|t|s| |o|f| |t|e|x|t| |w|i|t|h| |l|o|t|s| |o|f| |t|e|x|t
| |w|i|t|h| |l|o|t|s| |o|f| |t|e|x|t| |w|i|t|h| |l|o|t|s| |o|f| |t|e|x|t| |w|i|t
-| @21|3|,|2|5|0| @8|B|o|t|
+| @21|3|,|2|5|0| @8|6@1|%|
diff --git a/src/testdir/dumps/Test_smooth_long_4.dump b/src/testdir/dumps/Test_smooth_long_4.dump
index 98f2c62563..479dee43a1 100644
--- a/src/testdir/dumps/Test_smooth_long_4.dump
+++ b/src/testdir/dumps/Test_smooth_long_4.dump
@@ -3,4 +3,4 @@
|t|s| |o|f| |t|e|x|t| |w|i|t|h| |l|o|t|s| |o|f| |t|e|x|t| |w|i|t|h| |l|o|t|s| |o
|f| |t|e|x|t| |w|i|t|h| |l|o|t|s| |o|f| |t|e|x|t| |w|i|t|h| |l|o|t|s| |o|f| |t|e
|x|t| |w|i|t|h| |l>o|t|s| |o|f| |t|e|x|t| |w|i|t|h| |l|o|t|s| |o|f| |t|e|x|t| |w
-| @21|3|,|2|1|0| @8|B|o|t|
+| @21|3|,|2|1|0| @8|6@1|%|
diff --git a/src/testdir/dumps/Test_smooth_long_5.dump b/src/testdir/dumps/Test_smooth_long_5.dump
index 901baca90d..0b728b2eb6 100644
--- a/src/testdir/dumps/Test_smooth_long_5.dump
+++ b/src/testdir/dumps/Test_smooth_long_5.dump
@@ -3,4 +3,4 @@
|h| |l|o|t|s| |o|f| |t|e|x|t| |w|i|t|h| |l|o|t|s| |o|f| |t|e|x|t| |w|i|t|h| |l|o
|t|s| |o|f| |t|e|x|t| |w|i|t|h| |l|o|t|s| |o|f| |t|e|x|t| |w|i|t|h| |l|o|t|s| |o
|f| |t|e|x|t| |w|i>t|h| |l|o|t|s| |o|f| |t|e|x|t| |w|i|t|h| |l|o|t|s| |o|f| |t|e
-| @21|3|,|1|7|0| @8|B|o|t|
+| @21|3|,|1|7|0| @8|6@1|%|
diff --git a/src/testdir/dumps/Test_smooth_long_6.dump b/src/testdir/dumps/Test_smooth_long_6.dump
index b7ef6bf445..ba48c2825f 100644
--- a/src/testdir/dumps/Test_smooth_long_6.dump
+++ b/src/testdir/dumps/Test_smooth_long_6.dump
@@ -3,4 +3,4 @@
|t|s| |o|f| |t|e|x|t| |w|i|t|h| |l|o|t|s| |o|f| |t|e|x|t| |w|i|t|h| |l|o|t|s| |o
|f| |t|e|x|t| |w|i|t|h| |l|o|t|s| |o|f| |t|e|x|t| |w|i|t|h| |l|o|t|s| |o|f| |t|e
|x|t| |w|i|t|h| |l|o|t|s| |o|f| |t|e|x|t| |w|i|t|h| |l|o|t|s| |o|f| |t|e|x|t| |w
-| @21|3|,|9|0| @9|B|o|t|
+| @21|3|,|9|0| @9|6@1|%|
diff --git a/src/testdir/dumps/Test_smooth_long_7.dump b/src/testdir/dumps/Test_smooth_long_7.dump
index 27cb393383..222e0019f5 100644
--- a/src/testdir/dumps/Test_smooth_long_7.dump
+++ b/src/testdir/dumps/Test_smooth_long_7.dump
@@ -3,4 +3,4 @@
|t|s| |o|f| |t|e|x|t| |w|i|t|h| |l|o|t|s| |o|f| |t|e|x|t| |w|i|t|h| |l|o|t|s| |o
|f| |t|e|x|t| |w|i>t|h| |l|o|t|s| |o|f| |t|e|x|t| |w|i|t|h| |l|o|t|s| |o|f| |t|e
|x|t| |w|i|t|h| |l|o|t|s| |o|f| |t|e|x|t| |w|i|t|h| |l|o|t|s| |o|f| |t|e|x|t| |w
-| @21|3|,|1|7|0| @8|B|o|t|
+| @21|3|,|1|7|0| @8|6@1|%|
diff --git a/src/testdir/dumps/Test_smooth_long_8.dump b/src/testdir/dumps/Test_smooth_long_8.dump
index 8bdc88971c..f4687be513 100644
--- a/src/testdir/dumps/Test_smooth_long_8.dump
+++ b/src/testdir/dumps/Test_smooth_long_8.dump
@@ -3,4 +3,4 @@
|t|s| |o|f| |t|e|x>t| |w|i|t|h| |l|o|t|s| |o|f| |t|e|x|t| |w|i|t|h| |l|o|t|s| |o
|f| |t|e|x|t| |w|i|t|h| |l|o|t|s| |o|f| |t|e|x|t| |w|i|t|h| |l|o|t|s| |o|f| |t|e
|x|t| |w|i|t|h| |l|o|t|s| |o|f| |t|e|x|t| |w|i|t|h| |l|o|t|s| |o|f| |t|e|x|t| |w
-|:|s|e|t| |s|c|r|o|l@1|o| @9|3|,|1|3|0| @8|B|o|t|
+|:|s|e|t| |s|c|r|o|l@1|o| @9|3|,|1|3|0| @8|6@1|%|
diff --git a/src/testdir/dumps/Test_smooth_long_9.dump b/src/testdir/dumps/Test_smooth_long_9.dump
index d3e6a08fde..8365ecc0a8 100644
--- a/src/testdir/dumps/Test_smooth_long_9.dump
+++ b/src/testdir/dumps/Test_smooth_long_9.dump
@@ -3,4 +3,4 @@
|f| |t|e|x|t| |w|i>t|h| |l|o|t|s| |o|f| |t|e|x|t| |w|i|t|h| |l|o|t|s| |o|f| |t|e
|x|t| |w|i|t|h| |l|o|t|s| |o|f| |t|e|x|t| |w|i|t|h| |l|o|t|s| |o|f| |t|e|x|t| |w
|i|t|h| |l|o|t|s| |o|f| |t|e|x|t| |w|i|t|h| |l|o|t|s| |o|f| |t|e|x|t| |w|i|t|h|
-@22|3|,|1|7|0| @8|B|o|t|
+@22|3|,|1|7|0| @8|6@1|%|
diff --git a/src/testdir/test_scroll_opt.vim b/src/testdir/test_scroll_opt.vim
index 3975a1fe99..d40c650f3c 100644
--- a/src/testdir/test_scroll_opt.vim
+++ b/src/testdir/test_scroll_opt.vim
@@ -246,7 +246,7 @@ func Test_smoothscroll_wrap_long_line()
let lines =<< trim END
vim9script
- setline(1, ['one', 'two', 'Line' .. (' with lots of text'->repeat(30))])
+ setline(1, ['one', 'two', 'Line' .. (' with lots of text'->repeat(30)) .. ' end', 'four'])
set smoothscroll scrolloff=0
normal 3G10|zt
END
@@ -287,6 +287,30 @@ func Test_smoothscroll_wrap_long_line()
call term_sendkeys(buf, "gj")
call term_sendkeys(buf, "\<C-Y>")
call VerifyScreenDump(buf, 'Test_smooth_long_9', {})
+
+ " 'scrolloff' set to 0, move cursor down one line.
+ " Cursor should move properly, and since this is a really long line, it will
+ " be put on top of the screen.
+ call term_sendkeys(buf, ":set scrolloff=0\<CR>")
+ call term_sendkeys(buf, "0j")
+ call VerifyScreenDump(buf, 'Test_smooth_long_10', {})
+
+ " Repeat the step and move the cursor down again.
+ " This time, use a shorter long line that is barely long enough to span more
+ " 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.
+ call term_sendkeys(buf, ":call setline(1, ['one', 'two', 'Line' .. (' with lots of text'->repeat(10)) .. ' end', 'four'])\<CR>")
+ call term_sendkeys(buf, "3Gzt")
+ call term_sendkeys(buf, "j")
+ call VerifyScreenDump(buf, 'Test_smooth_long_11', {})
+
+ " 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
+ " still end up scrolling down to the next line with cursor at bottom of
+ " screen.
+ call term_sendkeys(buf, "3Gzt")
+ call term_sendkeys(buf, "\<C-E>j")
+ call VerifyScreenDump(buf, 'Test_smooth_long_12', {})
call StopVimInTerminal(buf)
endfunc
diff --git a/src/version.c b/src/version.c
index 588c3126ab..f6640c34d8 100644
--- a/src/version.c
+++ b/src/version.c
@@ -696,6 +696,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
+ 908,
+/**/
907,
/**/
906,