]> granicus.if.org Git - vim/commitdiff
patch 9.0.0734: cursor position invalid when scrolling with 'smoothscroll' v9.0.0734
authorBram Moolenaar <Bram@vim.org>
Wed, 12 Oct 2022 18:53:38 +0000 (19:53 +0100)
committerBram Moolenaar <Bram@vim.org>
Wed, 12 Oct 2022 18:53:38 +0000 (19:53 +0100)
Problem:    Cursor position invalid when scrolling with 'smoothscroll' set.
            (Ernie Rael)
Solution:   Add w_valid_skipcol and clear flags when it changes.  Adjust
            w_skipcol after moving the cursor.

src/edit.c
src/move.c
src/normal.c
src/proto/move.pro
src/structs.h
src/testdir/dumps/Test_smooth_long_8.dump
src/testdir/dumps/Test_smooth_long_9.dump
src/testdir/dumps/Test_smooth_one_long_1.dump [new file with mode: 0644]
src/testdir/dumps/Test_smooth_one_long_2.dump [new file with mode: 0644]
src/testdir/test_scroll_opt.vim
src/version.c

index ab268c185da3f0790097015a05640115b871bae6..755e2db5ef7c0e554e5ade3c746b5b6780364165 100644 (file)
@@ -2636,6 +2636,7 @@ beginline(int flags)
        }
        curwin->w_set_curswant = TRUE;
     }
+    adjust_skipcol();
 }
 
 /*
@@ -2683,6 +2684,7 @@ oneright(void)
     curwin->w_cursor.col += l;
 
     curwin->w_set_curswant = TRUE;
+    adjust_skipcol();
     return OK;
 }
 
@@ -2742,6 +2744,7 @@ oneleft(void)
     // character, move to its first byte
     if (has_mbyte)
        mb_adjust_cursor();
+    adjust_skipcol();
     return OK;
 }
 
index 32cd6f37e73c79d1f94e4cf7215da5a3c8df80a3..343c6c8e02bb58cfb2b937a3f923383b51be8fa6 100644 (file)
@@ -552,6 +552,16 @@ check_cursor_moved(win_T *wp)
                                      |VALID_BOTLINE|VALID_BOTLINE_AP);
        wp->w_valid_cursor = wp->w_cursor;
        wp->w_valid_leftcol = wp->w_leftcol;
+       wp->w_valid_skipcol = wp->w_skipcol;
+    }
+    else if (wp->w_skipcol != wp->w_valid_skipcol)
+    {
+       wp->w_valid &= ~(VALID_WROW|VALID_WCOL|VALID_VIRTCOL
+                                     |VALID_CHEIGHT|VALID_CROW
+                                     |VALID_BOTLINE|VALID_BOTLINE_AP);
+       wp->w_valid_cursor = wp->w_cursor;
+       wp->w_valid_leftcol = wp->w_leftcol;
+       wp->w_valid_skipcol = wp->w_skipcol;
     }
     else if (wp->w_cursor.col != wp->w_valid_cursor.col
             || wp->w_leftcol != wp->w_valid_leftcol
@@ -878,7 +888,6 @@ curs_rows(win_T *wp)
 
     redraw_for_cursorline(curwin);
     wp->w_valid |= VALID_CROW|VALID_CHEIGHT;
-
 }
 
 /*
@@ -1092,6 +1101,11 @@ curs_columns(
     {
        width = textwidth + curwin_col_off2();
 
+       // skip columns that are not visible
+       if (curwin->w_cursor.lnum == curwin->w_topline
+               && curwin->w_wcol >= curwin->w_skipcol)
+           curwin->w_wcol -= curwin->w_skipcol;
+
        // long line wrapping, adjust curwin->w_wrow
        if (curwin->w_wcol >= curwin->w_width)
        {
@@ -1265,10 +1279,12 @@ curs_columns(
            while (endcol > curwin->w_virtcol)
                endcol -= width;
            if (endcol > curwin->w_skipcol)
+           {
+               curwin->w_wrow -= (endcol - curwin->w_skipcol) / width;
                curwin->w_skipcol = endcol;
+           }
        }
 
-       curwin->w_wrow -= curwin->w_skipcol / width;
        if (curwin->w_wrow >= curwin->w_height)
        {
            // small window, make sure cursor is in it
@@ -1302,8 +1318,10 @@ curs_columns(
        curwin->w_flags &= ~(WFLAG_WCOL_OFF_ADDED + WFLAG_WROW_OFF_ADDED);
 #endif
 
-    // now w_leftcol is valid, avoid check_cursor_moved() thinking otherwise
+    // now w_leftcol and w_skipcol are valid, avoid check_cursor_moved()
+    // thinking otherwise
     curwin->w_valid_leftcol = curwin->w_leftcol;
+    curwin->w_valid_skipcol = curwin->w_skipcol;
 
     curwin->w_valid |= VALID_WCOL|VALID_WROW|VALID_VIRTCOL;
 }
@@ -1772,7 +1790,71 @@ scrollup(
                col += width2;
            curwin->w_curswant = col;
            coladvance(curwin->w_curswant);
+
+           // validate_virtcol() marked various things as valid, but after
+           // moving the cursor they need to be recomputed
+           curwin->w_valid &=
+              ~(VALID_WROW|VALID_WCOL|VALID_CHEIGHT|VALID_CROW|VALID_VIRTCOL);
+       }
+    }
+}
+
+/*
+ * Called after changing the cursor column: make sure that curwin->w_skipcol is
+ * valid for 'smoothscroll'.
+ */
+    void
+adjust_skipcol(void)
+{
+    if (!curwin->w_p_wrap
+           || !curwin->w_p_sms
+           || curwin->w_cursor.lnum != curwin->w_topline)
+       return;
+
+    int            width1 = curwin->w_width - curwin_col_off();
+    int            width2 = width1 + curwin_col_off2();
+    long    so = curwin->w_p_so >= 0 ? curwin->w_p_so : p_so;
+    int            scrolloff_cols = so == 0 ? 0 : width1 + (so - 1) * width2;
+    int            scrolled = FALSE;
+
+    validate_virtcol();
+    while (curwin->w_skipcol > 0
+                && curwin->w_virtcol < curwin->w_skipcol + 3 + scrolloff_cols)
+    {
+       // scroll a screen line down
+       if (curwin->w_skipcol >= width1 + width2)
+           curwin->w_skipcol -= width2;
+       else
+           curwin->w_skipcol -= width1;
+       redraw_later(UPD_NOT_VALID);
+       scrolled = TRUE;
+       validate_virtcol();
+    }
+    if (scrolled)
+       return;  // don't scroll in the other direction now
+
+    int col = curwin->w_virtcol - curwin->w_skipcol + scrolloff_cols;
+    int row = 0;
+    if (col >= width1)
+    {
+       col -= width1;
+       ++row;
+    }
+    if (col > width2)
+    {
+       row += col / width2;
+       col = col % width2;
+    }
+    if (row >= curwin->w_height)
+    {
+       if (curwin->w_skipcol == 0)
+       {
+           curwin->w_skipcol += width1;
+           --row;
        }
+       if (row >= curwin->w_height)
+           curwin->w_skipcol += (row - curwin->w_height) * width2;
+       redraw_later(UPD_NOT_VALID);
     }
 }
 
index 08e9fc9848c2133f3353d53d5c049d4fe0a60281..5c7bc2e9702123cb4c23c0801ab1995619ab4b72 100644 (file)
@@ -2448,6 +2448,7 @@ nv_screengo(oparg_T *oap, int dir, long dist)
 
     if (atend)
        curwin->w_curswant = MAXCOL;        // stick in the last column
+    adjust_skipcol();
 
     return retval;
 }
index de8bf51e12cf2967a17808e03b5ab88fbd87fcc3..07a70d2da63a2295f0639f7744528eaf1649de06 100644 (file)
@@ -35,6 +35,7 @@ void f_screenpos(typval_T *argvars, typval_T *rettv);
 void f_virtcol2col(typval_T *argvars, typval_T *rettv);
 void scrolldown(long line_count, int byfold);
 void scrollup(long line_count, int byfold);
+void adjust_skipcol(void);
 void check_topfill(win_T *wp, int down);
 void scrolldown_clamp(void);
 void scrollup_clamp(void);
index 686aa8f6c725bd36e41a07344d2e1314e9669925..90fddc3b572eb92bb5edc5664d61e2b67d96503f 100644 (file)
@@ -3714,6 +3714,7 @@ struct window_S
     pos_T      w_valid_cursor;     // last known position of w_cursor, used
                                    // to adjust w_valid
     colnr_T    w_valid_leftcol;    // last known w_leftcol
+    colnr_T    w_valid_skipcol;    // last known w_skipcol
 
     /*
      * w_cline_height is the number of physical lines taken by the buffer line
index c796d9a5ba765b8f7cad052e1233430637691478..8bdc88971c9ad5411bf8439b5f77fe8691dcf812 100644 (file)
@@ -3,4 +3,4 @@
 |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
-| @21|3|,|1|3|0| @8|B|o|t| 
+|:|s|e|t| |s|c|r|o|l@1|o| @9|3|,|1|3|0| @8|B|o|t| 
index d3e6a08fde33ae7224cf3616475c5a137d4e47bd..8bdc88971c9ad5411bf8439b5f77fe8691dcf812 100644 (file)
@@ -1,6 +1,6 @@
-|<+0#4040ff13#ffffff0@2|o+0#0000000&|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
+|<+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| |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| 
-@22|3|,|1|7|0| @8|B|o|t| 
+|:|s|e|t| |s|c|r|o|l@1|o| @9|3|,|1|3|0| @8|B|o|t| 
diff --git a/src/testdir/dumps/Test_smooth_one_long_1.dump b/src/testdir/dumps/Test_smooth_one_long_1.dump
new file mode 100644 (file)
index 0000000..82c1ea3
--- /dev/null
@@ -0,0 +1,6 @@
+>w+0&#ffffff0|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| @34
+|~+0#4040ff13&| @38
+| +0#0000000&@21|1|,|1| @10|A|l@1| 
diff --git a/src/testdir/dumps/Test_smooth_one_long_2.dump b/src/testdir/dumps/Test_smooth_one_long_2.dump
new file mode 100644 (file)
index 0000000..46e4f59
--- /dev/null
@@ -0,0 +1,6 @@
+|<+0#4040ff13#ffffff0@2|t+0#0000000&|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| @34
+|~+0#4040ff13&| @38
+|~| @38
+| +0#0000000&@21|1|,|8|1| @9|A|l@1| 
index 5bea957235b6618723b664d8eca427519ddddf1e..48c81f2cf908446f7591feb8557f236c364cf25c 100644 (file)
@@ -248,5 +248,26 @@ func Test_smoothscroll_wrap_long_line()
   call StopVimInTerminal(buf)
 endfunc
 
+func Test_smoothscroll_one_long_line()
+  CheckScreendump
+
+  let lines =<< trim END
+      vim9script
+      setline(1, 'with lots of text '->repeat(7))
+      set smoothscroll scrolloff=0
+  END
+  call writefile(lines, 'XSmoothOneLong', 'D')
+  let buf = RunVimInTerminal('-S XSmoothOneLong', #{rows: 6, cols: 40})
+  call VerifyScreenDump(buf, 'Test_smooth_one_long_1', {})
+  
+  call term_sendkeys(buf, "\<C-E>")
+  call VerifyScreenDump(buf, 'Test_smooth_one_long_2', {})
+
+  call term_sendkeys(buf, "0")
+  call VerifyScreenDump(buf, 'Test_smooth_one_long_1', {})
+
+  call StopVimInTerminal(buf)
+endfunc
+
 
 " vim: shiftwidth=2 sts=2 expandtab
index eeb1579ef23825b78aa1de8a855cb1daaecde29d..8ee824a3915cb4b2cb80b1077b645784aeb5f368 100644 (file)
@@ -699,6 +699,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    734,
 /**/
     733,
 /**/