aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorzeertzjq <zeertzjq@outlook.com>2023-02-16 07:25:16 +0800
committerzeertzjq <zeertzjq@outlook.com>2023-02-16 08:09:41 +0800
commit968cd1ed933c039b8d60b0110bc6b539c71e387d (patch)
tree07100b51218fc9888becb0613a00eebe76ff7d4a
parentf1c5887377c9ae547a7564ec4fc52d72656a974f (diff)
downloadrneovim-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.c2
-rw-r--r--src/nvim/move.c79
-rw-r--r--src/nvim/normal.c2
-rw-r--r--src/nvim/testdir/test_scroll_opt.vim20
-rw-r--r--src/nvim/testdir/test_scrollbind.vim4
-rw-r--r--test/functional/legacy/search_spec.lua2
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