changeset 32397:f9d4988a86ef v9.0.1530

patch 9.0.1530: cursor moves to wrong line when 'foldmethod' is "diff" Commit: https://github.com/vim/vim/commit/aa6ba308a1498dc8da04d1d30ec0470018bf782a Author: Luuk van Baal <luukvbaal@gmail.com> Date: Tue May 9 16:01:17 2023 +0100 patch 9.0.1530: cursor moves to wrong line when 'foldmethod' is "diff" Problem: Cursor moves to wrong line when 'foldmethod' is "diff". (Rick Howe) Solution: Adjust logic for scrolling. (Luuk van Baal, closes #12364, closes #12218)
author Bram Moolenaar <Bram@vim.org>
date Tue, 09 May 2023 17:15:03 +0200
parents 9feee1b0b58a
children 0c8925ba7971
files src/move.c src/testdir/dumps/Test_normal_j_below_botline.dump src/testdir/test_normal.vim src/version.c
diffstat 4 files changed, 56 insertions(+), 43 deletions(-) [+]
line wrap: on
line diff
--- a/src/move.c
+++ b/src/move.c
@@ -1753,22 +1753,6 @@ scrolldown(
 }
 
 /*
- * Return TRUE if scrollup() will scroll by screen line rather than text line.
- */
-    static int
-scrolling_screenlines(int byfold UNUSED)
-{
-    return (curwin->w_p_wrap && curwin->w_p_sms)
-# ifdef FEAT_FOLDING
-	|| (byfold && hasAnyFolding(curwin))
-# endif
-# ifdef FEAT_DIFF
-	|| (curwin->w_p_diff && !curwin->w_p_wrap)
-# endif
-	;
-}
-
-/*
  * Scroll the current window up by "line_count" logical lines.  "CTRL-E"
  */
     void
@@ -1778,7 +1762,14 @@ scrollup(
 {
     int		do_sms = curwin->w_p_wrap && curwin->w_p_sms;
 
-    if (scrolling_screenlines(byfold))
+    if (do_sms
+# ifdef FEAT_FOLDING
+	    || (byfold && hasAnyFolding(curwin))
+# endif
+# ifdef FEAT_DIFF
+	    || (curwin->w_p_diff && !curwin->w_p_wrap)
+# endif
+       )
     {
 	int	    width1 = curwin->w_width - curwin_col_off();
 	int	    width2 = width1 + curwin_col_off2();
@@ -2466,7 +2457,6 @@ scroll_cursor_bot(int min_scroll, int se
 {
     int		used;
     int		scrolled = 0;
-    int		min_scrolled = 1;
     int		extra = 0;
     int		i;
     linenr_T	line_count;
@@ -2483,6 +2473,7 @@ scroll_cursor_bot(int min_scroll, int se
     int		old_empty_rows = curwin->w_empty_rows;
     linenr_T	cln;		    // Cursor Line Number
     long	so = get_scrolloff_value();
+    int		do_sms = curwin->w_p_wrap && curwin->w_p_sms;
 
     cln = curwin->w_cursor.lnum;
     if (set_topbot)
@@ -2504,7 +2495,7 @@ scroll_cursor_bot(int min_scroll, int se
 		break;
 	    if (used + loff.height > curwin->w_height)
 	    {
-		if (curwin->w_p_sms && curwin->w_p_wrap)
+		if (do_sms)
 		{
 		    // 'smoothscroll' and 'wrap' are set.  The above line is
 		    // too long to show in its entirety, so we show just a part
@@ -2565,15 +2556,9 @@ scroll_cursor_bot(int min_scroll, int se
 	scrolled = used;
 	if (cln == curwin->w_botline)
 	    scrolled -= curwin->w_empty_rows;
-	min_scrolled = scrolled;
-	if (curwin->w_p_sms && curwin->w_p_wrap)
+	if (do_sms)
 	{
-	    // '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);
-
+	    // 'smoothscroll' and 'wrap' are set.
 	    // 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
@@ -2598,7 +2583,6 @@ scroll_cursor_bot(int min_scroll, int se
 	    if (top_plines > curwin->w_height)
 	    {
 		scrolled += (top_plines - curwin->w_height);
-		min_scrolled += (top_plines - curwin->w_height);
 	    }
 	}
     }
@@ -2725,22 +2709,12 @@ scroll_cursor_bot(int min_scroll, int se
      */
     if (line_count >= curwin->w_height && line_count > min_scroll)
 	scroll_cursor_halfway(FALSE, TRUE);
-    else
+    else if (line_count > 0)
     {
-	// With 'smoothscroll' scroll at least the height of the cursor line,
-	// unless it would move the cursor.
-	if (curwin->w_p_wrap && curwin->w_p_sms && line_count < min_scrolled
-		&& (curwin->w_cursor.lnum < curwin->w_topline
-		    || (curwin->w_virtcol - curwin->w_skipcol >=
-					  curwin->w_width - curwin_col_off())))
-	    line_count = min_scrolled;
-	if (line_count > 0)
-	{
-	    if (scrolling_screenlines(TRUE))
-		scrollup(scrolled, TRUE);  // TODO
-	    else
-		scrollup(line_count, TRUE);
-	}
+	if (do_sms)
+	    scrollup(scrolled, TRUE);  // TODO
+	else
+	    scrollup(line_count, TRUE);
     }
 
     /*
new file mode 100644
--- /dev/null
+++ b/src/testdir/dumps/Test_normal_j_below_botline.dump
@@ -0,0 +1,19 @@
+| +0#af5f00255#ffffff0@1|2| |2+0#0000000&@35
+| +0#af5f00255&@3|2+0#0000000&@35
+| +0#af5f00255&@3|2+0#0000000&@35
+| +0#af5f00255&@3|2+0#0000000&@35
+| +0#af5f00255&@3|2+0#0000000&@35
+| +0#af5f00255&@3|2+0#0000000&@19| @15
+| +0#af5f00255&@1|3| |3+0#0000000&@35
+| +0#af5f00255&@3|3+0#0000000&@35
+| +0#af5f00255&@3|3+0#0000000&@35
+| +0#af5f00255&@3|3+0#0000000&@35
+| +0#af5f00255&@3|3+0#0000000&@35
+| +0#af5f00255&@3|3+0#0000000&@19| @15
+| +0#af5f00255&@1|4| >4+0#0000000&@35
+| +0#af5f00255&@3|4+0#0000000&@35
+| +0#af5f00255&@3|4+0#0000000&@35
+| +0#af5f00255&@3|4+0#0000000&@35
+| +0#af5f00255&@3|4+0#0000000&@35
+| +0#af5f00255&@3|4+0#0000000&@19| @15
+@22|4|,|1| @10|1|6|%| 
--- a/src/testdir/test_normal.vim
+++ b/src/testdir/test_normal.vim
@@ -3980,4 +3980,22 @@ func Test_mouse_shape_after_cancelling_g
   call delete('Xmouseshapes')
 endfunc
 
+" Test that "j" does not skip lines when scrolling below botline and
+" 'foldmethod' is not "manual".
+func Test_normal_j_below_botline()
+  CheckScreendump
+
+  let lines =<< trim END
+    set number foldmethod=diff scrolloff=0
+    call setline(1, map(range(1, 9), 'repeat(v:val, 200)'))
+    norm Lj
+  END
+  call writefile(lines, 'XNormalJBelowBotline', 'D')
+  let buf = RunVimInTerminal('-S XNormalJBelowBotline', #{rows: 19, cols: 40})
+
+  call VerifyScreenDump(buf, 'Test_normal_j_below_botline', {})
+
+  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 */
 /**/
+    1530,
+/**/
     1529,
 /**/
     1528,