From: Hirohito Higashi Date: Fri, 31 Jul 2026 18:39:49 +0000 (+0000) Subject: patch 9.2.0885: scroll: 'smoothscroll' position is lost when the window is squeezed X-Git-Tag: v9.2.0885^0 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=15f8ba5cec35feea22622fbc7c78f3204aad50df;p=thirdparty%2Fvim.git patch 9.2.0885: scroll: 'smoothscroll' position is lost when the window is squeezed Problem: With 'smoothscroll' the scroll position in a long line is lost when a window is temporarily squeezed to a couple of lines, for example when opening and closing a help window. Solution: When the cursor ends up in the skipped columns, skip up to the screen line the cursor is in instead of showing the start of the line. closes: #20892 Co-Authored-By: Claude Opus 5 (1M context) Signed-off-by: Hirohito Higashi Signed-off-by: Christian Brabandt --- diff --git a/src/move.c b/src/move.c index 9f90134249..cd9169de94 100644 --- a/src/move.c +++ b/src/move.c @@ -2537,9 +2537,23 @@ scroll_cursor_top(int min_scroll, int always) { validate_virtcol(); if (curwin->w_skipcol >= curwin->w_virtcol) - // TODO: if the line doesn't fit may optimize w_skipcol instead - // of making it zero - reset_skipcol(); + { + // Skip up to the screen line the cursor is in, so that the + // position in the line is kept. + int width1 = curwin->w_width - curwin_col_off(); + int width2 = width1 + curwin_col_off2(); + int plines_off = 0; + int skipcol; + + if (width2 > 0 && curwin->w_virtcol >= (colnr_T)width1) + plines_off = (curwin->w_virtcol - width1) / width2 + 1; + skipcol = skipcol_from_plines(curwin, plines_off); + if (skipcol != curwin->w_skipcol) + { + curwin->w_skipcol = skipcol; + redraw_later(UPD_SOME_VALID); + } + } } if (curwin->w_topline != old_topline || curwin->w_skipcol != old_skipcol diff --git a/src/testdir/test_scroll_opt.vim b/src/testdir/test_scroll_opt.vim index 992d76388c..fc266da03e 100644 --- a/src/testdir/test_scroll_opt.vim +++ b/src/testdir/test_scroll_opt.vim @@ -1349,6 +1349,27 @@ func Test_smoothscroll_cursor_back_in_line() bwipe! endfunc +func Test_smoothscroll_squeezed_window() + setlocal smoothscroll + call setline(1, [repeat('x', 3000)] + repeat(['line'], 10)) + exe "norm! gg10\" + redraw + let skipcol = winsaveview().skipcol + call assert_notequal(0, skipcol) + let virtcol = virtcol('.') + + " Squeezing the window to one line and restoring it must not scroll back to + " the start of the line. + new + wincmd _ + close + redraw + call assert_notequal(0, winsaveview().skipcol) + call assert_equal(virtcol, virtcol('.')) + + bwipe! +endfunc + func Test_smoothscroll_long_line_zb() call NewWindow(10, 40) call setline(1, 'abcde '->repeat(150)) diff --git a/src/version.c b/src/version.c index 29de0350fa..55f755f23f 100644 --- a/src/version.c +++ b/src/version.c @@ -758,6 +758,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 885, /**/ 884, /**/