From 327c04a0d183d52d0eae0b677f747a627e20dbcb Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Tue, 4 Aug 2026 07:43:09 +0800 Subject: [PATCH] vim-patch:9.2.0904: "zb" scrolls incorrectly with cursor just above fold (#41143) Problem: "zb" scrolls incorrectly with cursor just above fold. Solution: Handle boff.lnum being set to the last line of a fold (zeertzjq). With the cursor just above fold, botline_forw() moves boff.lnum to the last line of the fold, but curwin->w_botline is at the first line of the fold, so the boff.lnum == curwin->w_botline condition never holds. Instead, check that boff.lnum has just moved to or past w_botline by comparing its previous value with w_botline. Also make a similar change to the loff.lnum check above for symmetry. That one doesn't change behavior, as topline_back() sets loff.lnum to the first line of a fold. related: neovim/neovim#41122 closes: vim/vim#20923 https://github.com/vim/vim/commit/aee686334c2137f8a94b04de130a3f51d928a7ed (cherry picked from commit 21a0227d2f654ddc568c3733e72150021cd84a6b) --- src/nvim/move.c | 8 ++++---- test/old/testdir/test_normal.vim | 9 +++++++-- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/src/nvim/move.c b/src/nvim/move.c index bcb37dbda6..3ba0f07e55 100644 --- a/src/nvim/move.c +++ b/src/nvim/move.c @@ -2040,6 +2040,7 @@ void scroll_cursor_bot(win_T *wp, int min_scroll, bool set_topbot) break; } + linenr_T loff_lnum_before = loff.lnum; // Add one line above topline_back(wp, &loff); if (loff.height == MAXCOL) { @@ -2055,13 +2056,13 @@ void scroll_cursor_bot(win_T *wp, int min_scroll, bool set_topbot) || loff.fill <= fill_below_window)) { // Count screen lines that are below the window. scrolled += loff.height; - if (loff.lnum == wp->w_botline - && loff.fill == 0) { + if (loff.lnum == wp->w_botline && loff_lnum_before > curwin->w_botline) { scrolled -= wp->w_empty_rows; } } if (boff.lnum < wp->w_buffer->b_ml.ml_line_count) { + linenr_T boff_lnum_before = boff.lnum; // Add one line below botline_forw(wp, &boff); assert(boff.height != MAXCOL); @@ -2077,8 +2078,7 @@ void scroll_cursor_bot(win_T *wp, int min_scroll, bool set_topbot) && boff.fill > wp->w_filler_rows)) { // Count screen lines that are below the window. scrolled += boff.height; - if (boff.lnum == wp->w_botline - && boff.fill == 0) { + if (boff.lnum >= curwin->w_botline && boff_lnum_before < curwin->w_botline) { scrolled -= wp->w_empty_rows; } } diff --git a/test/old/testdir/test_normal.vim b/test/old/testdir/test_normal.vim index 6a272c80f4..6c174a63e3 100644 --- a/test/old/testdir/test_normal.vim +++ b/test/old/testdir/test_normal.vim @@ -4307,16 +4307,21 @@ func Test_single_line_filler_zb() endfunc " Test for zb with fewer buffer lines than window height, non-zero 'scrolloff' -" and cursor on fold. -func Test_zb_with_cursor_on_fold() +" and cursor on or just above a fold. +func Test_zb_with_cursor_on_or_just_above_fold() 15new call setline(1, range(1, 5) + ['', 'foo{{{', 'bar}}}', '', 'baz']) setlocal foldmethod=marker scrolloff=1 call assert_equal(8, foldclosedend(7)) + call cursor(7, 1) normal! zb call assert_equal(1, line('w0')) + call cursor(6, 1) + normal! zb + call assert_equal(1, line('w0')) + bwipe! endfunc