# HG changeset patch # User Bram Moolenaar # Date 1683645303 -7200 # Node ID f9d4988a86efc51df08c673a3de4233ae3b3f6f8 # Parent 9feee1b0b58a1d3b0d35894f698447b1d59f6027 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 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) diff --git a/src/move.c b/src/move.c --- 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); } /* diff --git a/src/testdir/dumps/Test_normal_j_below_botline.dump b/src/testdir/dumps/Test_normal_j_below_botline.dump 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|%| diff --git a/src/testdir/test_normal.vim b/src/testdir/test_normal.vim --- 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 diff --git a/src/version.c b/src/version.c --- 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,