changeset 30622:ffd6e3bd65b8 v9.0.0646

patch 9.0.0646: with 'smoothscroll' CTRL-E is wrong when 'foldmethod' set Commit: https://github.com/vim/vim/commit/6b2d4ff7148e0b416ba745d20d061e6f7bb53ee7 Author: Bram Moolenaar <Bram@vim.org> Date: Mon Oct 3 14:06:02 2022 +0100 patch 9.0.0646: with 'smoothscroll' CTRL-E is wrong when 'foldmethod' set Problem: with 'smoothscroll' set CTRL-E does not work properly when 'foldmethod' is set to "indent". (Yee Cheng Chin) Solution: Merge the code for scroling with folds and 'smoothscroll'. (closes #11262)
author Bram Moolenaar <Bram@vim.org>
date Mon, 03 Oct 2022 15:15:04 +0200
parents 802b1a4878c2
children 22b985817601
files src/move.c src/testdir/test_scroll_opt.vim src/version.c
diffstat 3 files changed, 77 insertions(+), 53 deletions(-) [+]
line wrap: on
line diff
--- a/src/move.c
+++ b/src/move.c
@@ -984,8 +984,8 @@ curwin_col_off(void)
 
 /*
  * Return the difference in column offset for the second screen line of a
- * wrapped line.  It's 8 if 'number' or 'relativenumber' is on and 'n' is in
- * 'cpoptions'.
+ * wrapped line.  It's positive if 'number' or 'relativenumber' is on and 'n'
+ * is in 'cpoptions'.
  */
     int
 win_col_off2(win_T *wp)
@@ -1463,7 +1463,7 @@ scrolldown(
     if (curwin->w_p_wrap && curwin->w_p_sms)
     {
 	width1 = curwin->w_width - curwin_col_off();
-	width2 = width1 - curwin_col_off2();
+	width2 = width1 + curwin_col_off2();
     }
 
 #ifdef FEAT_FOLDING
@@ -1601,24 +1601,31 @@ scrollup(
     long	line_count,
     int		byfold UNUSED)	// TRUE: count a closed fold as one line
 {
-#if defined(FEAT_FOLDING) || defined(FEAT_DIFF)
-    linenr_T	lnum;
+    int		do_smoothscroll = curwin->w_p_wrap && curwin->w_p_sms;
 
-    if (
+    if (do_smoothscroll
 # ifdef FEAT_FOLDING
-	    (byfold && hasAnyFolding(curwin))
-#  ifdef FEAT_DIFF
-	    ||
-#  endif
+	    || (byfold && hasAnyFolding(curwin))
 # endif
 # ifdef FEAT_DIFF
-	    curwin->w_p_diff
+	    || curwin->w_p_diff
 # endif
 	    )
     {
-	// count each sequence of folded lines as one logical line
-	lnum = curwin->w_topline;
-	while (line_count--)
+	int	    width1 = curwin->w_width - curwin_col_off();
+	int	    width2 = width1 + curwin_col_off2();
+	int	    size = 0;
+	linenr_T    prev_topline = curwin->w_topline;
+
+	if (do_smoothscroll)
+	    size = win_linetabsize(curwin, curwin->w_topline,
+				   ml_get(curwin->w_topline), (colnr_T)MAXCOL);
+
+	// diff mode: first consume "topfill"
+	// 'smoothscroll': increase "w_skipcol" until it goes over the end of
+	// the line, then advance to the next line.
+	// folding: count each sequence of folded lines as one logical line.
+	for (int todo = line_count; todo > 0; --todo)
 	{
 # ifdef FEAT_DIFF
 	    if (curwin->w_topfill > 0)
@@ -1626,54 +1633,54 @@ scrollup(
 	    else
 # endif
 	    {
+		linenr_T lnum = curwin->w_topline;
+
 # ifdef FEAT_FOLDING
 		if (byfold)
+		    // for a closed fold: go to the last line in the fold
 		    (void)hasFolding(lnum, NULL, &lnum);
 # endif
-		if (lnum >= curbuf->b_ml.ml_line_count)
-		    break;
-		++lnum;
+		if (lnum == curwin->w_topline
+					&& curwin->w_p_wrap && curwin->w_p_sms)
+		{
+		    // 'smoothscroll': increase "w_skipcol" until it goes over
+		    // the end of the line, then advance to the next line.
+		    int add = curwin->w_skipcol > 0 ? width2 : width1;
+		    curwin->w_skipcol += add;
+		    if (curwin->w_skipcol >= size)
+		    {
+			if (lnum == curbuf->b_ml.ml_line_count)
+			{
+			    // at the last screen line, can't scroll further
+			    curwin->w_skipcol -= add;
+			    break;
+			}
+			++lnum;
+		    }
+		}
+		else
+		{
+		    if (lnum >= curbuf->b_ml.ml_line_count)
+			break;
+		    ++lnum;
+		}
+
+		if (lnum > curwin->w_topline)
+		{
+		    // approximate w_botline
+		    curwin->w_botline += lnum - curwin->w_topline;
+		    curwin->w_topline = lnum;
 # ifdef FEAT_DIFF
-		curwin->w_topfill = diff_check_fill(curwin, lnum);
+		    curwin->w_topfill = diff_check_fill(curwin, lnum);
 # endif
+		    curwin->w_skipcol = 0;
+		    if (todo > 1 && do_smoothscroll)
+			size = win_linetabsize(curwin, curwin->w_topline,
+				ml_get(curwin->w_topline), (colnr_T)MAXCOL);
+		}
 	    }
 	}
-	// approximate w_botline
-	curwin->w_botline += lnum - curwin->w_topline;
-	curwin->w_topline = lnum;
-    }
-    else
-#endif
-    if (curwin->w_p_wrap && curwin->w_p_sms)
-    {
-	int off1 = curwin_col_off();
-	int off2 = off1 + curwin_col_off2();
-	int add;
-	int size = win_linetabsize(curwin, curwin->w_topline,
-				   ml_get(curwin->w_topline), (colnr_T)MAXCOL);
-	linenr_T prev_topline = curwin->w_topline;
 
-	// 'smoothscroll': increase "w_skipcol" until it goes over the end of
-	// the line, then advance to the next line.
-	for (int todo = line_count; todo > 0; --todo)
-	{
-	    add = curwin->w_width - (curwin->w_skipcol > 0 ? off2 : off1);
-	    curwin->w_skipcol += add;
-	    if (curwin->w_skipcol >= size)
-	    {
-		if (curwin->w_topline == curbuf->b_ml.ml_line_count)
-		{
-		    curwin->w_skipcol -= add;
-		    break;
-		}
-		++curwin->w_topline;
-		++curwin->w_botline;	// approximate w_botline
-		curwin->w_skipcol = 0;
-		if (todo > 1)
-		    size = win_linetabsize(curwin, curwin->w_topline,
-				   ml_get(curwin->w_topline), (colnr_T)MAXCOL);
-	    }
-	}
 	if (curwin->w_topline == prev_topline)
 	    // need to redraw even though w_topline didn't change
 	    redraw_later(UPD_NOT_VALID);
--- a/src/testdir/test_scroll_opt.vim
+++ b/src/testdir/test_scroll_opt.vim
@@ -88,6 +88,21 @@ func Test_smoothscroll_CtrlE_CtrlY()
   call term_sendkeys(buf, "\<C-Y>")
   call VerifyScreenDump(buf, 'Test_smoothscroll_8', {})
 
+  if has('folding')
+    call term_sendkeys(buf, ":set foldmethod=indent\<CR>")
+    " move the cursor so we can reuse the same dumps
+    call term_sendkeys(buf, "5G")
+    call term_sendkeys(buf, "\<C-E>")
+    call VerifyScreenDump(buf, 'Test_smoothscroll_1', {})
+    call term_sendkeys(buf, "\<C-E>")
+    call VerifyScreenDump(buf, 'Test_smoothscroll_2', {})
+    call term_sendkeys(buf, "7G")
+    call term_sendkeys(buf, "\<C-Y>")
+    call VerifyScreenDump(buf, 'Test_smoothscroll_7', {})
+    call term_sendkeys(buf, "\<C-Y>")
+    call VerifyScreenDump(buf, 'Test_smoothscroll_8', {})
+  endif
+
   call StopVimInTerminal(buf)
 endfunc
 
--- a/src/version.c
+++ b/src/version.c
@@ -700,6 +700,8 @@ static char *(features[]) =
 static int included_patches[] =
 {   /* Add new patch number below this line */
 /**/
+    646,
+/**/
     645,
 /**/
     644,