diff options
author | zeertzjq <zeertzjq@outlook.com> | 2023-02-16 07:25:16 +0800 |
---|---|---|
committer | zeertzjq <zeertzjq@outlook.com> | 2023-02-16 08:09:41 +0800 |
commit | 968cd1ed933c039b8d60b0110bc6b539c71e387d (patch) | |
tree | 07100b51218fc9888becb0613a00eebe76ff7d4a | |
parent | f1c5887377c9ae547a7564ec4fc52d72656a974f (diff) | |
download | rneovim-968cd1ed933c039b8d60b0110bc6b539c71e387d.tar.gz rneovim-968cd1ed933c039b8d60b0110bc6b539c71e387d.tar.bz2 rneovim-968cd1ed933c039b8d60b0110bc6b539c71e387d.zip |
vim-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 vim/vim#10545)
https://github.com/vim/vim/commit/1d6539cf36a7b6d1afe76fb6316fe662f543bf60
Cherry-pick test_scroll_opt.vim changes from patch 8.2.1432.
Co-authored-by: Bram Moolenaar <Bram@vim.org>
-rw-r--r-- | src/nvim/buffer.c | 2 | ||||
-rw-r--r-- | src/nvim/move.c | 79 | ||||
-rw-r--r-- | src/nvim/normal.c | 2 | ||||
-rw-r--r-- | src/nvim/testdir/test_scroll_opt.vim | 20 | ||||
-rw-r--r-- | src/nvim/testdir/test_scrollbind.vim | 4 | ||||
-rw-r--r-- | test/functional/legacy/search_spec.lua | 2 |
6 files changed, 74 insertions, 35 deletions
diff --git a/src/nvim/buffer.c b/src/nvim/buffer.c index 129a8c6fb2..98832a98c9 100644 --- a/src/nvim/buffer.c +++ b/src/nvim/buffer.c @@ -1676,7 +1676,7 @@ void enter_buffer(buf_T *buf) maketitle(); // when autocmds didn't change it if (curwin->w_topline == 1 && !curwin->w_topline_was_set) { - scroll_cursor_halfway(false); // redisplay at correct position + scroll_cursor_halfway(false, false); // redisplay at correct position } // Change directories when the 'acd' option is set. diff --git a/src/nvim/move.c b/src/nvim/move.c index a946633bf6..8fda73cbec 100644 --- a/src/nvim/move.c +++ b/src/nvim/move.c @@ -235,7 +235,7 @@ void update_topline(win_T *wp) // 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); check_botline = true; @@ -314,7 +314,7 @@ void update_topline(win_T *wp) if (line_count <= wp->w_height_inner + 1) { scroll_cursor_bot(scrolljump_value(), false); } else { - scroll_cursor_halfway(false); + scroll_cursor_halfway(false, false); } } } @@ -1464,7 +1464,7 @@ void scroll_cursor_top(int min_scroll, int always) // This makes sure we get the same position when using "k" and "j" // in a small window. if (used > curwin->w_height_inner) { - scroll_cursor_halfway(false); + scroll_cursor_halfway(false, false); } else { // If "always" is false, only adjust topline to a lower value, higher // value may happen with wrapping lines @@ -1669,7 +1669,7 @@ void scroll_cursor_bot(int min_scroll, int set_topbot) // Scroll up if the cursor is off the bottom of the screen a bit. // Otherwise put it at 1/2 of the screen. if (line_count >= curwin->w_height_inner && line_count > min_scroll) { - scroll_cursor_halfway(false); + scroll_cursor_halfway(false, true); } else { scrollup(line_count, true); } @@ -1690,7 +1690,7 @@ void scroll_cursor_bot(int min_scroll, int set_topbot) /// /// @param atend if true, also put the cursor halfway to the end of the file. /// -void scroll_cursor_halfway(int atend) +void scroll_cursor_halfway(bool atend, bool prefer_above) { int above = 0; int topfill = 0; @@ -1705,38 +1705,59 @@ void scroll_cursor_halfway(int atend) loff.fill = 0; boff.fill = 0; linenr_T topline = loff.lnum; + while (topline > 1) { - if (below <= above) { // add a line below the cursor first - if (boff.lnum < curbuf->b_ml.ml_line_count) { - botline_forw(curwin, &boff); - used += boff.height; + // This may not be right in the middle if the lines' + // physical height > 1 (e.g. 'wrap' is on). + + // Depending on "prefer_above" we add a line above or below first. + // Loop twice to avoid duplicating code. + bool done = false; + for (int round = 1; round <= 2; round++) { + if (prefer_above + ? (round == 2 && below < above) + : (round == 1 && below <= above)) { + // add a line below the cursor + if (boff.lnum < curbuf->b_ml.ml_line_count) { + botline_forw(curwin, &boff); + used += boff.height; + if (used > curwin->w_height_inner) { + done = true; + break; + } + below += boff.height; + } else { + below++; // count a "~" line + if (atend) { + used++; + } + } + } + + if (prefer_above + ? (round == 1 && below >= above) + : (round == 1 && below > above)) { + // add a line above the cursor + topline_back(curwin, &loff); + if (loff.height == MAXCOL) { + used = MAXCOL; + } else { + used += loff.height; + } if (used > curwin->w_height_inner) { + done = true; break; } - below += boff.height; - } else { - below++; // count a "~" line - if (atend) { - used++; - } + above += loff.height; + topline = loff.lnum; + topfill = loff.fill; } } - - if (below > above) { // add a line above the cursor - topline_back(curwin, &loff); - if (loff.height == MAXCOL) { - used = MAXCOL; - } else { - used += loff.height; - } - if (used > curwin->w_height_inner) { - break; - } - above += loff.height; - topline = loff.lnum; - topfill = loff.fill; + if (done) { + break; } } + if (!hasFolding(topline, &curwin->w_topline, NULL)) { curwin->w_topline = topline; } diff --git a/src/nvim/normal.c b/src/nvim/normal.c index a84d5c73a4..f1226584d7 100644 --- a/src/nvim/normal.c +++ b/src/nvim/normal.c @@ -2856,7 +2856,7 @@ static void nv_zet(cmdarg_T *cap) FALLTHROUGH; case 'z': - scroll_cursor_halfway(true); + scroll_cursor_halfway(true, false); redraw_later(curwin, UPD_VALID); set_fraction(curwin); break; diff --git a/src/nvim/testdir/test_scroll_opt.vim b/src/nvim/testdir/test_scroll_opt.vim index 77920eb8b0..64f4ced470 100644 --- a/src/nvim/testdir/test_scroll_opt.vim +++ b/src/nvim/testdir/test_scroll_opt.vim @@ -1,5 +1,4 @@ " Test for reset 'scroll' -" func Test_reset_scroll() let scr = &l:scroll @@ -34,3 +33,22 @@ func Test_reset_scroll() quit! endfunc + +func Test_scolloff_even_line_count() + new + resize 6 + setlocal scrolloff=3 + call setline(1, range(20)) + normal 2j + call assert_equal(1, getwininfo(win_getid())[0].topline) + normal j + call assert_equal(1, getwininfo(win_getid())[0].topline) + normal j + call assert_equal(2, getwininfo(win_getid())[0].topline) + normal j + call assert_equal(3, getwininfo(win_getid())[0].topline) + + bwipe! +endfunc + +" vim: shiftwidth=2 sts=2 expandtab diff --git a/src/nvim/testdir/test_scrollbind.vim b/src/nvim/testdir/test_scrollbind.vim index 6c5488be05..f67a559c60 100644 --- a/src/nvim/testdir/test_scrollbind.vim +++ b/src/nvim/testdir/test_scrollbind.vim @@ -217,8 +217,8 @@ end of window 2 \ '7 line 02 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ 02', \ '56789ABCDEFGHIJKLMNOPQRSTUVWXYZ 02', \ 'UTSRQPONMLKJIHGREDCBA9876543210 02', - \ '. line 11 ZYXWVUTSRQPONMLKJIHGREDCBA9876543210 11', - \ '. line 11 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ 11', + \ '. line 10 ZYXWVUTSRQPONMLKJIHGREDCBA9876543210 10', + \ '. line 10 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ 10', \ ''], getline(1, '$')) enew! diff --git a/test/functional/legacy/search_spec.lua b/test/functional/legacy/search_spec.lua index 3f1f85cf28..4228940eda 100644 --- a/test/functional/legacy/search_spec.lua +++ b/test/functional/legacy/search_spec.lua @@ -290,8 +290,8 @@ describe('search cmdline', function() -- First match feed('/thei') screen:expect([[ + 3 the | 4 {inc:thei}r | - 5 there | /thei^ | ]]) -- Match from initial cursor position when modifying search |