patch 9.1.0215: Half-page scrolling does not support smooth-scrolling

Commit: 
https://github.com/vim/vim/commit/5a2e3ec9ac72b6e644fea4ebba7e632498296e2f
Author: Luuk van Baal <luukvb...@gmail.com>
Date:   Thu Mar 28 10:07:29 2024 +0100

    patch 9.1.0215: Half-page scrolling does not support smooth-scrolling
    
    Problem:  Page-wise scrolling with Ctrl-D/Ctrl-U implements
              it's own logic to change the topline and cursor.
              More logic than necessary for scrolling with Ctrl-F/Ctrl-B
              was removed in patch 9.1.0211.
    Solution: Re-use the logic from Ctrl-E/Ctrl-Y/Ctrl-F/Ctrl-B while
              staying backward compatible as much as possible.
              Restore some of the logic that determined how many lines will
              be scrolled (Luuk van Baal)
    
    closes: #14316
    
    Signed-off-by: Luuk van Baal <luukvb...@gmail.com>
    Signed-off-by: Christian Brabandt <c...@256bit.org>

diff --git a/runtime/doc/options.txt b/runtime/doc/options.txt
index ff7497037..4eaedc250 100644
--- a/runtime/doc/options.txt
+++ b/runtime/doc/options.txt
@@ -1,4 +1,4 @@
-*options.txt*  For Vim version 9.1.  Last change: 2024 Mar 26
+*options.txt*  For Vim version 9.1.  Last change: 2024 Mar 28
 
 
                  VIM REFERENCE MANUAL    by Bram Moolenaar
@@ -7503,7 +7503,7 @@ A jump table for the options with a short description can 
be found at |Q_op|.
        You may also want to add "lastline" to the 'display' option to show as
        much of the last line as possible.
        NOTE: only partly implemented, currently works with CTRL-E, CTRL-Y,
-       CTRL-B, CTRL-F and scrolling with the mouse.
+       CTRL-D, CTRL-U, CTRL-F, CTRL-B and scrolling with the mouse.
 
                                        *'softtabstop'* *'sts'*
 'softtabstop' 'sts'    number  (default 0)
@@ -9469,8 +9469,8 @@ A jump table for the options with a short description can 
be found at |Q_op|.
        will scroll 'window' minus two lines, with a minimum of one.
        When 'window' is equal to 'lines' minus one CTRL-F and CTRL-B scroll
        in a much smarter way, taking care of wrapping lines.
-       When resizing the Vim window, the value is smaller than 1 or more than
-       or equal to 'lines' it will be set to 'lines' minus 1.
+       When resizing the Vim window, and the value is smaller than 1 or more
+       than or equal to 'lines' it will be set to 'lines' minus 1.
        Note: Do not confuse this with the height of the Vim window, use
        'lines' for that.
 
diff --git a/runtime/doc/version9.txt b/runtime/doc/version9.txt
index 82482a762..8ea30a4c8 100644
--- a/runtime/doc/version9.txt
+++ b/runtime/doc/version9.txt
@@ -1,4 +1,4 @@
-*version9.txt*  For Vim version 9.1.  Last change: 2024 Mar 26
+*version9.txt*  For Vim version 9.1.  Last change: 2024 Mar 28
 
 
                  VIM REFERENCE MANUAL    by Bram Moolenaar
@@ -41555,6 +41555,7 @@ Changed                                         
*changed-9.2*
 -------
 
 - use 'smoothscroll' logic for CTRL-F and CTRL-B for pagewise scrolling
+- use 'smoothscroll' logic for CTRL-D and CTRL-U for half-pagewise scrolling
 
 Added                                          *added-9.2*
 -----
diff --git a/src/edit.c b/src/edit.c
index c7f90dacd..56643a9d7 100644
--- a/src/edit.c
+++ b/src/edit.c
@@ -4807,7 +4807,7 @@ ins_pageup(void)
     }
 
     tpos = curwin->w_cursor;
-    if (onepage(BACKWARD, 1L) == OK)
+    if (pagescroll(BACKWARD, 1L, FALSE) == OK)
     {
        start_arrow(&tpos);
        can_cindent = TRUE;
@@ -4864,7 +4864,7 @@ ins_pagedown(void)
     }
 
     tpos = curwin->w_cursor;
-    if (onepage(FORWARD, 1L) == OK)
+    if (pagescroll(FORWARD, 1L, FALSE) == OK)
     {
        start_arrow(&tpos);
        can_cindent = TRUE;
diff --git a/src/mouse.c b/src/mouse.c
index af14af050..247c6df8e 100644
--- a/src/mouse.c
+++ b/src/mouse.c
@@ -1129,7 +1129,7 @@ do_mousescroll(cmdarg_T *cap)
        if (!(State & MODE_INSERT) && (mouse_vert_step < 0 || shift_or_ctrl))
        {
            // whole page up or down
-           onepage(cap->arg == MSCR_UP ? FORWARD : BACKWARD, 1L);
+           pagescroll(cap->arg == MSCR_UP ? FORWARD : BACKWARD, 1L, FALSE);
        }
        else
        {
diff --git a/src/move.c b/src/move.c
index 772b173bc..25f419e5a 100644
--- a/src/move.c
+++ b/src/move.c
@@ -3025,6 +3025,67 @@ cursor_correct(void)
     curwin->w_valid |= VALID_TOPLINE;
 }
 
+/*
+ * Decide how much overlap to use for page-up or page-down scrolling.
+ * This is symmetric, so that doing both keeps the same lines displayed.
+ * Three lines are examined:
+ *
+ *  before CTRL-F          after CTRL-F / before CTRL-B
+ *     etc.                    l1
+ *  l1 last but one line       ------------
+ *  l2 last text line          l2 top text line
+ *  -------------              l3 second text line
+ *  l3                            etc.
+ */
+static int get_scroll_overlap(int dir)
+{
+    lineoff_T loff;
+    int            min_height = curwin->w_height - 2;
+
+    validate_botline();
+    if (dir == FORWARD && curwin->w_botline > curbuf->b_ml.ml_line_count)
+       return min_height + 2;  // no overlap, still handle 'smoothscroll'
+
+    loff.lnum = dir == FORWARD ? curwin->w_botline : curwin->w_topline - 1;
+#ifdef FEAT_DIFF
+    loff.fill = diff_check_fill(curwin, loff.lnum + dir == BACKWARD)
+               - (dir == FORWARD ? curwin->w_filler_rows : curwin->w_topfill);
+    loff.height = loff.fill > 0 ? 1 : plines_nofill(loff.lnum);
+#else
+    loff.height = plines(loff.lnum);
+#endif
+
+    int h1 = loff.height;
+    if (h1 > min_height)
+       return min_height + 2;  // no overlap
+    if (dir == FORWARD)
+       topline_back(&loff);
+    else
+       botline_forw(&loff);
+
+    int h2 = loff.height;
+    if (h2 == MAXCOL || h2 + h1 > min_height)
+       return min_height + 2;  // no overlap
+    if (dir == FORWARD)
+       topline_back(&loff);
+    else
+       botline_forw(&loff);
+
+    int h3 = loff.height;
+    if (h3 == MAXCOL || h3 + h2 > min_height)
+       return min_height + 2;  // no overlap
+    if (dir == FORWARD)
+       topline_back(&loff);
+    else
+       botline_forw(&loff);
+
+    int h4 = loff.height;
+    if (h4 == MAXCOL || h4 + h3 + h2 > min_height || h3 + h2 + h1 > min_height)
+       return min_height + 1;  // 1 line overlap
+    else
+       return min_height;      // 2 lines overlap
+}
+
 /*
  * Move screen "count" pages up ("dir" is BACKWARD) or down ("dir" is FORWARD)
  * and update the screen.
@@ -3032,7 +3093,7 @@ cursor_correct(void)
  * Return FAIL for failure, OK otherwise.
  */
     int
-onepage(int dir, long count)
+pagescroll(int dir, long count, int half)
 {
 #ifdef FEAT_DIFF
     int                prev_topfill = curwin->w_topfill;
@@ -3040,9 +3101,17 @@ onepage(int dir, long count)
     linenr_T   prev_topline = curwin->w_topline;
     colnr_T    prev_skipcol = curwin->w_skipcol;
 
-    // Scroll 'window' or current window height lines.
-    count *= ((ONE_WINDOW && p_window > 0 && p_window < Rows - 1) ?
-                                           p_window : curwin->w_height) - 2;
+    if (half)
+    {
+       // Scroll [count], 'scroll' or current window height lines.
+       if (count)
+           curwin->w_p_scr = MIN(curwin->w_height, count);
+       count = MIN(curwin->w_height, curwin->w_p_scr);
+    }
+    else
+       // Scroll 'window' or current window height lines.
+       count *= ((ONE_WINDOW && p_window > 0 && p_window < Rows - 1) ?
+                                           p_window - 2 : 
get_scroll_overlap(dir));
 
     if (curwin->w_p_sms)
        scroll_redraw(dir == FORWARD, count);
@@ -3063,6 +3132,10 @@ onepage(int dir, long count)
            scroll_redraw(dir == FORWARD, count);
        curwin->w_p_sms = FALSE;
     }
+#ifdef FEAT_FOLDING
+       // Move cursor to first line of closed fold.
+       foldAdjustCursor();
+#endif
 
     int nochange = curwin->w_topline == prev_topline
 #ifdef FEAT_DIFF
@@ -3070,198 +3143,22 @@ onepage(int dir, long count)
 #endif
        && curwin->w_skipcol == prev_skipcol;
 
+    // Error if the viewport did not change and the cursor is already
+    // at the boundary.
     if (nochange)
-       beep_flush();
+    {
+       int prev_cursor = curwin->w_cursor.lnum;
+       curwin->w_cursor.lnum += (count + 1) * (dir == FORWARD ? 1 : -1);
+       check_cursor();
+       if (curwin->w_cursor.lnum == prev_cursor)
+           beep_flush();
+    }
     else if (!curwin->w_p_sms || curwin->w_skipcol == prev_skipcol)
        beginline(BL_SOL | BL_FIX);
 
     return nochange;
 }
 
-/*
- * Scroll 'scroll' lines up or down.
- */
-    void
-halfpage(int flag, linenr_T Prenum)
-{
-    long       scrolled = 0;
-    int                i;
-    int                n;
-    int                room;
-
-    if (Prenum)
-       curwin->w_p_scr = (Prenum > curwin->w_height) ?
-                                               curwin->w_height : Prenum;
-    n = (curwin->w_p_scr <= curwin->w_height) ?
-                                   curwin->w_p_scr : curwin->w_height;
-
-    update_topline();
-    validate_botline();
-    room = curwin->w_empty_rows;
-#ifdef FEAT_DIFF
-    room += curwin->w_filler_rows;
-#endif
-    if (flag)
-    {
-       /*
-        * scroll the text up
-        */
-       while (n > 0 && curwin->w_botline <= curbuf->b_ml.ml_line_count)
-       {
-#ifdef FEAT_DIFF
-           if (curwin->w_topfill > 0)
-           {
-               i = 1;
-               --n;
-               --curwin->w_topfill;
-           }
-           else
-#endif
-           {
-               i = PLINES_NOFILL(curwin->w_topline);
-               n -= i;
-               if (n < 0 && scrolled > 0)
-                   break;
-#ifdef FEAT_FOLDING
-               (void)hasFolding(curwin->w_topline, NULL, &curwin->w_topline);
-#endif
-               ++curwin->w_topline;
-#ifdef FEAT_DIFF
-               curwin->w_topfill = diff_check_fill(curwin, curwin->w_topline);
-#endif
-
-               if (curwin->w_cursor.lnum < curbuf->b_ml.ml_line_count)
-               {
-                   ++curwin->w_cursor.lnum;
-                   curwin->w_valid &=
-                                   ~(VALID_VIRTCOL|VALID_CHEIGHT|VALID_WCOL);
-               }
-           }
-           curwin->w_valid &= ~(VALID_CROW|VALID_WROW);
-           scrolled += i;
-
-           /*
-            * Correct w_botline for changed w_topline.
-            * Won't work when there are filler lines.
-            */
-#ifdef FEAT_DIFF
-           if (curwin->w_p_diff)
-               curwin->w_valid &= ~(VALID_BOTLINE|VALID_BOTLINE_AP);
-           else
-#endif
-           {
-               room += i;
-               do
-               {
-                   i = plines(curwin->w_botline);
-                   if (i > room)
-                       break;
-#ifdef FEAT_FOLDING
-                   (void)hasFolding(curwin->w_botline, NULL,
-                                                         &curwin->w_botline);
-#endif
-                   ++curwin->w_botline;
-                   room -= i;
-               } while (curwin->w_botline <= curbuf->b_ml.ml_line_count);
-           }
-       }
-
-       /*
-        * When hit bottom of the file: move cursor down.
-        */
-       if (n > 0)
-       {
-# ifdef FEAT_FOLDING
-           if (hasAnyFolding(curwin))
-           {
-               while (--n >= 0
-                       && curwin->w_cursor.lnum < curbuf->b_ml.ml_line_count)
-               {
-                   (void)hasFolding(curwin->w_cursor.lnum, NULL,
-                                                     &curwin->w_cursor.lnum);
-                   ++curwin->w_cursor.lnum;
-               }
-           }
-           else
-# endif
-               curwin->w_cursor.lnum += n;
-           check_cursor_lnum();
-       }
-    }
-    else
-    {
-       /*
-        * scroll the text down
-        */
-       while (n > 0 && curwin->w_topline > 1)
-       {
-#ifdef FEAT_DIFF
-           if (curwin->w_topfill < diff_check_fill(curwin, curwin->w_topline))
-           {
-               i = 1;
-               --n;
-               ++curwin->w_topfill;
-           }
-           else
-#endif
-           {
-               i = PLINES_NOFILL(curwin->w_topline - 1);
-               n -= i;
-               if (n < 0 && scrolled > 0)
-                   break;
-               --curwin->w_topline;
-#ifdef FEAT_FOLDING
-               (void)hasFolding(curwin->w_topline, &curwin->w_topline, NULL);
-#endif
-#ifdef FEAT_DIFF
-               curwin->w_topfill = 0;
-#endif
-           }
-           curwin->w_valid &= ~(VALID_CROW|VALID_WROW|
-                                             VALID_BOTLINE|VALID_BOTLINE_AP);
-           scrolled += i;
-           if (curwin->w_cursor.lnum > 1)
-           {
-               --curwin->w_cursor.lnum;
-               curwin->w_valid &= ~(VALID_VIRTCOL|VALID_CHEIGHT|VALID_WCOL);
-           }
-       }
-
-       /*
-        * When hit top of the file: move cursor up.
-        */
-       if (n > 0)
-       {
-           if (curwin->w_cursor.lnum <= (linenr_T)n)
-               curwin->w_cursor.lnum = 1;
-           else
-# ifdef FEAT_FOLDING
-           if (hasAnyFolding(curwin))
-           {
-               while (--n >= 0 && curwin->w_cursor.lnum > 1)
-               {
-                   --curwin->w_cursor.lnum;
-                   (void)hasFolding(curwin->w_cursor.lnum,
-                                               &curwin->w_cursor.lnum, NULL);
-               }
-           }
-           else
-# endif
-               curwin->w_cursor.lnum -= n;
-       }
-    }
-# ifdef FEAT_FOLDING
-    // Move cursor to first line of closed fold.
-    foldAdjustCursor();
-# endif
-#ifdef FEAT_DIFF
-    check_topfill(curwin, !flag);
-#endif
-    cursor_correct();
-    beginline(BL_SOL | BL_FIX);
-    redraw_later(UPD_VALID);
-}
-
     void
 do_check_cursorbind(void)
 {
diff --git a/src/normal.c b/src/normal.c
index fcd6311c7..83b74ccc6 100644
--- a/src/normal.c
+++ b/src/normal.c
@@ -2066,7 +2066,7 @@ nv_page(cmdarg_T *cap)
            goto_tabpage((int)cap->count0);
     }
     else
-       (void)onepage(cap->arg, cap->count1);
+       (void)pagescroll(cap->arg, cap->count1, FALSE);
 }
 
 /*
@@ -7263,12 +7263,8 @@ nv_at(cmdarg_T *cap)
     static void
 nv_halfpage(cmdarg_T *cap)
 {
-    if ((cap->cmdchar == Ctrl_U && curwin->w_cursor.lnum == 1)
-           || (cap->cmdchar == Ctrl_D
-               && curwin->w_cursor.lnum == curbuf->b_ml.ml_line_count))
-       clearopbeep(cap->oap);
-    else if (!checkclearop(cap->oap))
-       halfpage(cap->cmdchar == Ctrl_D, cap->count0);
+    if (!checkclearop(cap->oap))
+       pagescroll(cap->cmdchar == Ctrl_D, cap->count0, TRUE);
 }
 
 /*
diff --git a/src/proto/move.pro b/src/proto/move.pro
index bc9c02563..91c879180 100644
--- a/src/proto/move.pro
+++ b/src/proto/move.pro
@@ -46,7 +46,6 @@ void set_empty_rows(win_T *wp, int used);
 void scroll_cursor_bot(int min_scroll, int set_topbot);
 void scroll_cursor_halfway(int atend, int prefer_above);
 void cursor_correct(void);
-int onepage(int dir, long count);
-void halfpage(int flag, linenr_T Prenum);
+int pagescroll(int dir, long count, int half);
 void do_check_cursorbind(void);
 /* vim: set ft=c : */
diff --git a/src/testdir/dumps/Test_cursorline_redraw_2.dump 
b/src/testdir/dumps/Test_cursorline_redraw_2.dump
index 323bef8e2..d1b4e4e17 100644
--- a/src/testdir/dumps/Test_cursorline_redraw_2.dump
+++ b/src/testdir/dumps/Test_cursorline_redraw_2.dump
@@ -1,20 +1,20 @@
-| +0&#ffffff0@39
-|T|h|e| |{|o|p|t|i|o|n|}| |a|r|g|u|m|e|n|t|s| |t|o| |"|:|s|e|t|"| |m|a|y| 
|b|e| 
+|T+0&#ffffff0|h|e| |{|o|p|t|i|o|n|}| |a|r|g|u|m|e|n|t|s| |t|o| |"|:|s|e|t|"| 
|m|a|y| |b|e| 
 |r|e|p|e|a|t|e|d|.| @1|F|o|r| |e|x|a|m|p|l|e|:| |>| @14
-| +8&&@7>:|s|e|t| |a|i| |n|o|s|i| |s|w|=|3| |t|s|=|3| @9
-|I+0&&|f| |y|o|u| |m|a|k|e| |a|n| |e|r@1|o|r| |i|n| |o|n|e| |o|f| |t|h|e| 
|a|r|g|u|m
+@8|:|s|e|t| |a|i| |n|o|s|i| |s|w|=|3| |t|s|=|3| @9
+|I|f| |y|o|u| |m|a|k|e| |a|n| |e|r@1|o|r| |i|n| |o|n|e| |o|f| |t|h|e| 
|a|r|g|u|m
 |e|n|t|s|,| |a|n| |e|r@1|o|r| |m|e|s@1|a|g|e| |w|i|l@1| |b|e| |g|i|v|e|n| @3
 |a|n|d| |t|h|e| |f|o|l@1|o|w|i|n|g| |a|r|g|u|m|e|n|t|s| |w|i|l@1| |b|e| 
|i|g|n|o
 |r|e|d|.| @35
 @40
 @40
 @16|*|:|s|e|t|-|v|e|r|b|o|s|e|*| @9
-|W|h|e|n| |'|v|e|r|b|o|s|e|'| |i|s| |n|o|n|-|z|e|r|o|,| |d|i|s|p|l|a|y|i|n|g| 
|a
+>W+8&&|h|e|n| |'|v|e|r|b|o|s|e|'| |i|s| |n|o|n|-|z|e|r|o|,| 
|d|i|s|p|l|a|y|i|n|g| |a
 |n| |o|p|t|i|o|n| |v|a|l|u|e| |w|i|l@1| |a|l|s|o| |t|e|l@1| |w|h|e|r|e| |i|t| 
@1
-|w|a|s| |l|a|s|t| |s|e|t|.| @1|E|x|a|m|p|l|e|:| |>| @14
+|w+0&&|a|s| |l|a|s|t| |s|e|t|.| @1|E|x|a|m|p|l|e|:| |>| @14
 @8|:|v|e|r|b|o|s|e| |s|e|t| |s|h|i|f|t|w|i|d|t|h| |c|i|n|d|e|n|t|?
 |<| @1|s|h|i|f|t|w|i|d|t|h|=|4| |~| @22
 @10|L|a|s|t| |s|e|t| |f|r|o|m| |m|o|d|e|l|i|n|e| |l|i|n|e| |1| 
 |~| @38
 @2|c|i|n|d|e|n|t| |~| @28
-@22|7|,|2|-|9| @8|4@1|%| 
+|@+0#4040ff13&@2| @36
+| +0#0000000&@21|1|2|,|1| @9|5|0|%| 
diff --git a/src/testdir/test_edit.vim b/src/testdir/test_edit.vim
index c81c24453..fbe7b9ba1 100644
--- a/src/testdir/test_edit.vim
+++ b/src/testdir/test_edit.vim
@@ -1294,15 +1294,15 @@ func Test_edit_PAGEUP_PAGEDOWN()
   call feedkeys("i\<PageDown>\<esc>", 'tnix')
   call assert_equal([0, 30, 1, 0], getpos('.'))
   call feedkeys("A\<PageUp>\<esc>", 'tnix')
-  call assert_equal([0, 30, 1, 0], getpos('.'))
+  call assert_equal([0, 29, 1, 0], getpos('.'))
   call feedkeys("A\<PageUp>\<esc>", 'tnix')
-  call assert_equal([0, 23, 1, 0], getpos('.'))
+  call assert_equal([0, 21, 1, 0], getpos('.'))
   call feedkeys("A\<PageUp>\<esc>", 'tnix')
-  call assert_equal([0, 15, 1, 0], getpos('.'))
+  call assert_equal([0, 13, 1, 0], getpos('.'))
   call feedkeys("A\<PageUp>\<esc>", 'tnix')
   call assert_equal([0, 10, 1, 0], getpos('.'))
   call feedkeys("A\<PageUp>\<esc>", 'tnix')
-  call assert_equal([0, 10, 11, 0], getpos('.'))
+  call assert_equal([0, 2, 11, 0], getpos('.'))
   " <S-Up> is the same as <PageUp>
   " <S-Down> is the same as <PageDown>
   call cursor(1, 1)
@@ -1317,28 +1317,28 @@ func Test_edit_PAGEUP_PAGEDOWN()
   call feedkeys("i\<S-Down>\<esc>", 'tnix')
   call assert_equal([0, 30, 1, 0], getpos('.'))
   call feedkeys("A\<S-Up>\<esc>", 'tnix')
-  call assert_equal([0, 30, 1, 0], getpos('.'))
+  call assert_equal([0, 29, 1, 0], getpos('.'))
   call feedkeys("A\<S-Up>\<esc>", 'tnix')
-  call assert_equal([0, 23, 1, 0], getpos('.'))
+  call assert_equal([0, 21, 1, 0], getpos('.'))
   call feedkeys("A\<S-Up>\<esc>", 'tnix')
-  call assert_equal([0, 15, 1, 0], getpos('.'))
+  call assert_equal([0, 13, 1, 0], getpos('.'))
   call feedkeys("A\<S-Up>\<esc>", 'tnix')
   call assert_equal([0, 10, 1, 0], getpos('.'))
   call feedkeys("A\<S-Up>\<esc>", 'tnix')
-  call assert_equal([0, 10, 11, 0], getpos('.'))
+  call assert_equal([0, 2, 11, 0], getpos('.'))
   set nostartofline
   call cursor(30, 11)
   norm! zt
   call feedkeys("A\<PageUp>\<esc>", 'tnix')
-  call assert_equal([0, 30, 11, 0], getpos('.'))
+  call assert_equal([0, 29, 11, 0], getpos('.'))
   call feedkeys("A\<PageUp>\<esc>", 'tnix')
-  call assert_equal([0, 23, 11, 0], getpos('.'))
+  call assert_equal([0, 21, 11, 0], getpos('.'))
   call feedkeys("A\<PageUp>\<esc>", 'tnix')
-  call assert_equal([0, 15, 11, 0], getpos('.'))
+  call assert_equal([0, 13, 11, 0], getpos('.'))
   call feedkeys("A\<PageUp>\<esc>", 'tnix')
   call assert_equal([0, 10, 11, 0], getpos('.'))
   call feedkeys("A\<PageUp>\<esc>", 'tnix')
-  call assert_equal([0, 10, 11, 0], getpos('.'))
+  call assert_equal([0, 2, 11, 0], getpos('.'))
   call cursor(1, 1)
   call feedkeys("A\<PageDown>\<esc>", 'tnix')
   call assert_equal([0, 9, 11, 0], getpos('.'))
@@ -1355,15 +1355,15 @@ func Test_edit_PAGEUP_PAGEDOWN()
   call cursor(30, 11)
   norm! zt
   call feedkeys("A\<S-Up>\<esc>", 'tnix')
-  call assert_equal([0, 30, 11, 0], getpos('.'))
+  call assert_equal([0, 29, 11, 0], getpos('.'))
   call feedkeys("A\<S-Up>\<esc>", 'tnix')
-  call assert_equal([0, 23, 11, 0], getpos('.'))
+  call assert_equal([0, 21, 11, 0], getpos('.'))
   call feedkeys("A\<S-Up>\<esc>", 'tnix')
-  call assert_equal([0, 15, 11, 0], getpos('.'))
+  call assert_equal([0, 13, 11, 0], getpos('.'))
   call feedkeys("A\<S-Up>\<esc>", 'tnix')
   call assert_equal([0, 10, 11, 0], getpos('.'))
   call feedkeys("A\<S-Up>\<esc>", 'tnix')
-  call assert_equal([0, 10, 11, 0], getpos('.'))
+  call assert_equal([0, 2, 11, 0], getpos('.'))
   call cursor(1, 1)
   call feedkeys("A\<S-Down>\<esc>", 'tnix')
   call assert_equal([0, 9, 11, 0], getpos('.'))
diff --git a/src/testdir/test_normal.vim b/src/testdir/test_normal.vim
index dd2f2be2f..3a7248fd0 100644
--- a/src/testdir/test_normal.vim
+++ b/src/testdir/test_normal.vim
@@ -1280,9 +1280,13 @@ func Test_vert_scroll_cmds()
   exe "normal \<C-D>"
   call assert_equal(46, line('.'))
   exe "normal \<C-U>"
-  call assert_equal(36, line('.'))
+  call assert_equal(36, line('w0'))
+  call assert_equal(46, line('.'))
   exe "normal \<C-U>"
-  call assert_equal(10, line('.'))
+  call assert_equal(1,  line('w0'))
+  call assert_equal(40, line('.'))
+  exe "normal \<C-U>"
+  call assert_equal(30, line('.'))
   exe "normal \<C-U>"
   call assert_equal(1, line('.'))
   set scroll&
@@ -1303,9 +1307,8 @@ func Test_vert_scroll_cmds()
   call assert_equal(50, line('.'))
   call assert_equal(100, line('w$'))
   normal z.
-  let lnum = winline()
   exe "normal \<C-D>"
-  call assert_equal(lnum, winline())
+  call assert_equal(1, winline())
   call assert_equal(50, line('.'))
   normal zt
   exe "normal \<C-D>"
@@ -3066,7 +3069,8 @@ func Test_normal42_halfpage()
   call assert_equal(2, &scroll)
   set scroll=5
   exe "norm! \<c-u>"
-  call assert_equal('3', getline('.'))
+  call assert_equal('3', getline('w0'))
+  call assert_equal('8', getline('.'))
   1
   set scrolloff=5
   exe "norm! \<c-d>"
@@ -3813,11 +3817,11 @@ func Test_normal_vert_scroll_longline()
   call assert_equal(11, line('.'))
   call assert_equal(1, winline())
   exe "normal \<C-B>"
-  call assert_equal(11, line('.'))
-  call assert_equal(9, winline())
+  call assert_equal(10, line('.'))
+  call assert_equal(10, winline())
   exe "normal \<C-B>\<C-B>"
   call assert_equal(5, line('.'))
-  call assert_equal(1, winline())
+  call assert_equal(5, winline())
 
   bwipe!
 endfunc
@@ -4186,12 +4190,16 @@ func Test_single_line_scroll()
   norm! {
   call assert_equal([0, 1, 1, 0], getpos('.'))
 
-  " Ctrl-B scrolls up with hidden "above" virtual text.
+  " Ctrl-B/Ctrl-U scroll up with hidden "above" virtual text.
   set smoothscroll
   exe "normal \<C-E>"
   call assert_notequal(0, winsaveview().skipcol)
   exe "normal \<C-B>"
   call assert_equal(0, winsaveview().skipcol)
+  exe "normal \<C-E>"
+  call assert_notequal(0, winsaveview().skipcol)
+  exe "normal \<C-U>"
+  call assert_equal(0, winsaveview().skipcol)
 
   set smoothscroll&
   bw!
diff --git a/src/testdir/test_scroll_opt.vim b/src/testdir/test_scroll_opt.vim
index 24804956f..788870f87 100644
--- a/src/testdir/test_scroll_opt.vim
+++ b/src/testdir/test_scroll_opt.vim
@@ -1005,18 +1005,39 @@ func Test_smoothscroll_page()
   call setline(1, 'abcde '->repeat(150))
 
   exe "norm! \<C-F>"
-  call assert_equal(320, winsaveview().skipcol)
+  call assert_equal(400, winsaveview().skipcol)
   exe "norm! \<C-F>"
-  call assert_equal(640, winsaveview().skipcol)
+  call assert_equal(800, winsaveview().skipcol)
   exe "norm! \<C-F>"
   call assert_equal(880, winsaveview().skipcol)
   exe "norm! \<C-B>"
-  call assert_equal(560, winsaveview().skipcol)
+  call assert_equal(480, winsaveview().skipcol)
   exe "norm! \<C-B>"
-  call assert_equal(240, winsaveview().skipcol)
+  call assert_equal(80, winsaveview().skipcol)
   exe "norm! \<C-B>"
   call assert_equal(0, winsaveview().skipcol)
 
+  exe "norm! \<C-D>"
+  call assert_equal(200, winsaveview().skipcol)
+  exe "norm! \<C-D>"
+  call assert_equal(400, winsaveview().skipcol)
+  exe "norm! \<C-D>"
+  call assert_equal(600, winsaveview().skipcol)
+  exe "norm! \<C-D>"
+  call assert_equal(800, winsaveview().skipcol)
+  exe "norm! \<C-D>"
+  call assert_equal(880, winsaveview().skipcol)
+  exe "norm! \<C-U>"
+  call assert_equal(680, winsaveview().skipcol)
+  exe "norm! \<C-U>"
+  call assert_equal(480, winsaveview().skipcol)
+  exe "norm! \<C-U>"
+  call assert_equal(280, winsaveview().skipcol)
+  exe "norm! \<C-U>"
+  call assert_equal(80, winsaveview().skipcol)
+  exe "norm! \<C-U>"
+  call assert_equal(0, winsaveview().skipcol)
+
   set smoothscroll&
 endfunc
 
diff --git a/src/version.c b/src/version.c
index e8b478d95..46dd27331 100644
--- a/src/version.c
+++ b/src/version.c
@@ -704,6 +704,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    215,
 /**/
     214,
 /**/

-- 
-- 
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php

--- 
You received this message because you are subscribed to the Google Groups 
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to vim_dev+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/vim_dev/E1rplqm-00Anmy-P6%40256bit.org.

Raspunde prin e-mail lui