changeset 32387:1ddef52ea786 v9.0.1525

patch 9.0.1525: 'smoothscroll' does not always work properly Commit: https://github.com/vim/vim/commit/3ce8c389155fc1257082cdb0cef7801b49f6aaf9 Author: Luuk van Baal <luukvbaal@gmail.com> Date: Mon May 8 15:51:14 2023 +0100 patch 9.0.1525: 'smoothscroll' does not always work properly Problem: 'smoothscroll' does not always work properly. Solution: Do not reset w_skipcol after it was intentionally set. (Luuk van Baal, closes #12360, closes #12199, closes #12323)
author Bram Moolenaar <Bram@vim.org>
date Mon, 08 May 2023 17:00:04 +0200
parents 1714bba63e87
children 8f59127b4db4
files src/move.c src/testdir/dumps/Test_smooth_cursormoved_line.dump src/testdir/dumps/Test_smooth_eob_1.dump src/testdir/dumps/Test_smooth_eob_2.dump src/testdir/dumps/Test_smooth_long_10.dump src/testdir/test_scroll_opt.vim src/version.c
diffstat 7 files changed, 101 insertions(+), 27 deletions(-) [+]
line wrap: on
line diff
--- a/src/move.c
+++ b/src/move.c
@@ -276,10 +276,6 @@ update_topline(void)
     long	line_count;
     int		halfheight;
     int		n;
-    linenr_T	old_topline;
-#ifdef FEAT_DIFF
-    int		old_topfill;
-#endif
 #ifdef FEAT_FOLDING
     linenr_T	lnum;
 #endif
@@ -311,9 +307,10 @@ update_topline(void)
     if (mouse_dragging > 0)
 	*so_ptr = mouse_dragging - 1;
 
-    old_topline = curwin->w_topline;
+    linenr_T old_topline = curwin->w_topline;
+    colnr_T old_skipcol = curwin->w_skipcol;
 #ifdef FEAT_DIFF
-    old_topfill = curwin->w_topfill;
+    int old_topfill = curwin->w_topfill;
 #endif
 
     /*
@@ -516,7 +513,10 @@ update_topline(void)
     {
 	dollar_vcol = -1;
 	redraw_later(UPD_VALID);
-	reset_skipcol();
+
+	// Only reset w_skipcol if it was not just set to make cursor visible.
+	if (curwin->w_skipcol == old_skipcol)
+	    reset_skipcol();
 
 	// May need to set w_skipcol when cursor in w_topline.
 	if (curwin->w_cursor.lnum == curwin->w_topline)
@@ -2769,7 +2769,6 @@ scroll_cursor_halfway(int atend, int pre
     int		above = 0;
     linenr_T	topline;
     colnr_T	skipcol = 0;
-    int		set_skipcol = FALSE;
 #ifdef FEAT_DIFF
     int		topfill = 0;
 #endif
@@ -2798,14 +2797,19 @@ scroll_cursor_halfway(int atend, int pre
 #endif
     topline = loff.lnum;
 
-    int half_height = 0;
+    int want_height;
     int smooth_scroll = FALSE;
     if (curwin->w_p_sms && curwin->w_p_wrap)
     {
 	// 'smoothscroll' and 'wrap' are set
 	smooth_scroll = TRUE;
-	half_height = (curwin->w_height - used) / 2;
-	used = 0;
+	if (atend)
+	{
+	    want_height = (curwin->w_height - used) / 2;
+	    used = 0;
+	}
+	else
+	    want_height = curwin->w_height;
     }
 
     while (topline > 1)
@@ -2817,22 +2821,21 @@ scroll_cursor_halfway(int atend, int pre
 	    topline_back_winheight(&loff, FALSE);
 	    if (loff.height == MAXCOL)
 		break;
-	    else
-		used += loff.height;
-	    if (used > half_height)
+	    used += loff.height;
+	    if (!atend && boff.lnum < curbuf->b_ml.ml_line_count)
 	    {
-		if (used - loff.height < half_height)
+		botline_forw(&boff);
+		used += boff.height;
+	    }
+	    if (used > want_height)
+	    {
+		if (used - loff.height < want_height)
 		{
-		    int plines_offset = used - half_height;
-		    loff.height -= plines_offset;
-		    used = half_height;
-
 		    topline = loff.lnum;
 #ifdef FEAT_DIFF
 		    topfill = loff.fill;
 #endif
-		    skipcol = skipcol_from_plines(curwin, plines_offset);
-		    set_skipcol = TRUE;
+		    skipcol = skipcol_from_plines(curwin, used - want_height);
 		}
 		break;
 	    }
@@ -2906,11 +2909,11 @@ scroll_cursor_halfway(int atend, int pre
 #endif
     {
 	if (curwin->w_topline != topline
-		|| set_skipcol
+		|| skipcol != 0
 		|| curwin->w_skipcol != 0)
 	{
 	    curwin->w_topline = topline;
-	    if (set_skipcol)
+	    if (skipcol != 0)
 	    {
 		curwin->w_skipcol = skipcol;
 		redraw_later(UPD_NOT_VALID);
new file mode 100644
--- /dev/null
+++ b/src/testdir/dumps/Test_smooth_cursormoved_line.dump
@@ -0,0 +1,6 @@
+|<+0#4040ff13#ffffff0@2|_+0#0000000&@71
+@75
+@73>x@1
+@1|_@72|x
+@2| @72
+@57|3|,|7|4| @9|B|o|t| 
new file mode 100644
--- /dev/null
+++ b/src/testdir/dumps/Test_smooth_eob_1.dump
@@ -0,0 +1,10 @@
+| +0&#ffffff0@74
+@75
+@75
+@75
+@75
+@75
+@75
+@75
+> @74
+@57|1|0@1|,|0|-|1| @6|B|o|t| 
new file mode 100644
--- /dev/null
+++ b/src/testdir/dumps/Test_smooth_eob_2.dump
@@ -0,0 +1,10 @@
+|<+0#4040ff13#ffffff0@2|a+0#0000000&@21| @49
+@75
+@75
+@75
+@75
+@75
+@75
+@75
+> @74
+@57|1|0@1|,|0|-|1| @6|B|o|t| 
--- a/src/testdir/dumps/Test_smooth_long_10.dump
+++ b/src/testdir/dumps/Test_smooth_long_10.dump
@@ -1,6 +1,6 @@
-|<+0#4040ff13#ffffff0@2|o+0#0000000&|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
+|<+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
-|~+0#4040ff13&| @38
-|~| @38
-|:+0#0000000&|s|e|t| |s|c|r|o|l@1|o| @9|4|,|1| @10|B|o|t| 
+|:|s|e|t| |s|c|r|o|l@1|o| @9|4|,|1| @10|B|o|t| 
--- a/src/testdir/test_scroll_opt.vim
+++ b/src/testdir/test_scroll_opt.vim
@@ -638,4 +638,47 @@ func Test_smoothscroll_ins_lines()
   call StopVimInTerminal(buf)
 endfunc
 
+" this placed the cursor in the command line
+func Test_smoothscroll_cursormoved_line()
+  CheckScreendump
+
+  let lines =<< trim END
+      set smoothscroll
+      call setline(1, [
+        \'',
+        \'_'->repeat(&lines * &columns),
+        \(('_')->repeat(&columns - 2) .. 'xxx')->repeat(2)
+      \])
+      autocmd CursorMoved * eval [line('w0'), line('w$')]
+      call search('xxx')
+  END
+  call writefile(lines, 'XSmoothCursorMovedLine', 'D')
+  let buf = RunVimInTerminal('-S XSmoothCursorMovedLine', #{rows: 6})
+
+  call VerifyScreenDump(buf, 'Test_smooth_cursormoved_line', {})
+
+  call StopVimInTerminal(buf)
+endfunc
+
+func Test_smoothscroll_eob()
+  CheckScreendump
+
+  let lines =<< trim END
+      set smoothscroll
+      call setline(1, ['']->repeat(100))
+      norm G
+  END
+  call writefile(lines, 'XSmoothEob', 'D')
+  let buf = RunVimInTerminal('-S XSmoothEob', #{rows: 10})
+
+  " does not scroll halfway when scrolling to end of buffer
+  call VerifyScreenDump(buf, 'Test_smooth_eob_1', {})
+
+  " cursor is not placed below window
+  call term_sendkeys(buf, ":call setline(92, 'a'->repeat(100))\<CR>\<C-B>G")
+  call VerifyScreenDump(buf, 'Test_smooth_eob_2', {})
+
+  call StopVimInTerminal(buf)
+endfunc
+
 " vim: shiftwidth=2 sts=2 expandtab
--- 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 */
 /**/
+    1525,
+/**/
     1524,
 /**/
     1523,