diff src/move.c @ 31954:d8fdafc4b390 v9.0.1309

patch 9.0.1309: scrolling two lines with even line count and 'scrolloff' set Commit: https://github.com/vim/vim/commit/1d6539cf36a7b6d1afe76fb6316fe662f543bf60 Author: Bram Moolenaar <Bram@vim.org> Date: Tue Feb 14 17:41:20 2023 +0000 patch 9.0.1309: scrolling two lines with even line count and 'scrolloff' set Problem: Scrolling two lines with even line count and 'scrolloff' set. Solution: Adjust how the topline is computed. (closes https://github.com/vim/vim/issues/10545)
author Bram Moolenaar <Bram@vim.org>
date Tue, 14 Feb 2023 18:45:05 +0100
parents 2a590b4a3fba
children b232759b29c8
line wrap: on
line diff
--- a/src/move.c
+++ b/src/move.c
@@ -396,7 +396,7 @@ update_topline(void)
 	    // cursor in the middle of the window.  Otherwise put the cursor
 	    // near the top of the window.
 	    if (n >= halfheight)
-		scroll_cursor_halfway(FALSE);
+		scroll_cursor_halfway(FALSE, FALSE);
 	    else
 	    {
 		scroll_cursor_top(scrolljump_value(), FALSE);
@@ -499,7 +499,7 @@ update_topline(void)
 		if (line_count <= curwin->w_height + 1)
 		    scroll_cursor_bot(scrolljump_value(), FALSE);
 		else
-		    scroll_cursor_halfway(FALSE);
+		    scroll_cursor_halfway(FALSE, FALSE);
 	    }
 	}
     }
@@ -2383,7 +2383,7 @@ scroll_cursor_top(int min_scroll, int al
      * in a small window.
      */
     if (used > curwin->w_height)
-	scroll_cursor_halfway(FALSE);
+	scroll_cursor_halfway(FALSE, FALSE);
     else
     {
 	/*
@@ -2720,7 +2720,7 @@ scroll_cursor_bot(int min_scroll, int se
      * Otherwise put it at 1/2 of the screen.
      */
     if (line_count >= curwin->w_height && line_count > min_scroll)
-	scroll_cursor_halfway(FALSE);
+	scroll_cursor_halfway(FALSE, TRUE);
     else
     {
 	// With 'smoothscroll' scroll at least the height of the cursor line,
@@ -2760,7 +2760,7 @@ scroll_cursor_bot(int min_scroll, int se
  * If "atend" is TRUE, also put it halfway at the end of the file.
  */
     void
-scroll_cursor_halfway(int atend)
+scroll_cursor_halfway(int atend, int prefer_above)
 {
     int		above = 0;
     linenr_T	topline;
@@ -2841,43 +2841,62 @@ scroll_cursor_halfway(int atend)
 
 	// If not using smoothscroll, we have to iteratively find how many
 	// lines to scroll down to roughly fit the cursor.
-	// This may not be right in the middle if the lines' physical height >
-	// 1 (e.g. 'wrap' is on).
+	// This may not be right in the middle if the lines'
+	// physical height > 1 (e.g. 'wrap' is on).
 
-	if (below <= above)	    // add a line below the cursor first
+	// Depending on "prefer_above" we add a line above or below first.
+	// Loop twice to avoid duplicating code.
+	int done = FALSE;
+	for (int round = 1; round <= 2; ++round)
 	{
-	    if (boff.lnum < curbuf->b_ml.ml_line_count)
+	    if (prefer_above ? (round == 2 && below < above)
+			     : (round == 1 && below <= above))
 	    {
-		botline_forw(&boff);
-		used += boff.height;
-		if (used > curwin->w_height)
-		    break;
-		below += boff.height;
+		// add a line below the cursor
+		if (boff.lnum < curbuf->b_ml.ml_line_count)
+		{
+		    botline_forw(&boff);
+		    used += boff.height;
+		    if (used > curwin->w_height)
+		    {
+			done = TRUE;
+			break;
+		    }
+		    below += boff.height;
+		}
+		else
+		{
+		    ++below;	    // count a "~" line
+		    if (atend)
+			++used;
+		}
 	    }
-	    else
+
+	    if (prefer_above ? (round == 1 && below >= above)
+			     : (round == 1 && below > above))
 	    {
-		++below;	    // count a "~" line
-		if (atend)
-		    ++used;
+		// add a line above the cursor
+		topline_back(&loff);
+		if (loff.height == MAXCOL)
+		    used = MAXCOL;
+		else
+		    used += loff.height;
+		if (used > curwin->w_height)
+		{
+		    done = TRUE;
+		    break;
+		}
+		above += loff.height;
+		topline = loff.lnum;
+#ifdef FEAT_DIFF
+		topfill = loff.fill;
+#endif
 	    }
 	}
+	if (done)
+	    break;
+    }
 
-	if (below > above)	    // add a line above the cursor
-	{
-	    topline_back(&loff);
-	    if (loff.height == MAXCOL)
-		used = MAXCOL;
-	    else
-		used += loff.height;
-	    if (used > curwin->w_height)
-		break;
-	    above += loff.height;
-	    topline = loff.lnum;
-#ifdef FEAT_DIFF
-	    topfill = loff.fill;
-#endif
-	}
-    }
 #ifdef FEAT_FOLDING
     if (!hasFolding(topline, &curwin->w_topline, NULL))
 #endif