0
0
mirror of https://github.com/vim/vim.git synced 2025-09-28 04:24:06 -04:00

patch 9.1.0260: Problems with "zb" and scrolling to new topline with 'smoothscroll'

Problem: "zb" does not reveal filler lines at the start of a buffer.
          Scrolled cursor position with 'smoothscroll' is unpredictable,
          and may reset skipcol later if it is not visible (after v9.1.258)
Solution: Replace confusing for loop that reaches final control value too
          early with while loop. Set "w_curswant" accordingly so cursor
          will be placed in visible part of topline.
          (Luuk van Baal)

closes: #14394

Signed-off-by: Luuk van Baal <luukvbaal@gmail.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
This commit is contained in:
Luuk van Baal
2024-04-03 22:50:40 +02:00
committed by Christian Brabandt
parent 08d2401fbc
commit bd28cae1f1
4 changed files with 42 additions and 19 deletions

View File

@@ -1663,6 +1663,9 @@ scrolldown(
#ifdef FEAT_DIFF #ifdef FEAT_DIFF
curwin->w_topfill = 0; curwin->w_topfill = 0;
#endif #endif
// Adjusting the cursor later should not adjust skipcol.
if (do_sms)
curwin->w_curswant = MAXCOL;
#ifdef FEAT_FOLDING #ifdef FEAT_FOLDING
// A sequence of folded lines only counts for one logical line // A sequence of folded lines only counts for one logical line
if (hasFolding(curwin->w_topline, &first, NULL)) if (hasFolding(curwin->w_topline, &first, NULL))
@@ -1856,9 +1859,9 @@ scrollup(
curwin->w_topfill = diff_check_fill(curwin, lnum); curwin->w_topfill = diff_check_fill(curwin, lnum);
# endif # endif
curwin->w_skipcol = 0; curwin->w_skipcol = 0;
// Adjusting the cursor later should not adjust skipcol: // Adjusting the cursor later should not adjust skipcol.
// bring it to the first screenline on this new topline. if (do_sms)
curwin->w_curswant %= width1; curwin->w_curswant = 0;
if (todo > 1 && do_sms) if (todo > 1 && do_sms)
size = linetabsize(curwin, curwin->w_topline); size = linetabsize(curwin, curwin->w_topline);
} }
@@ -2464,18 +2467,14 @@ scroll_cursor_bot(int min_scroll, int set_topbot)
cln = curwin->w_cursor.lnum; cln = curwin->w_cursor.lnum;
if (set_topbot) if (set_topbot)
{ {
int set_skipcol = FALSE;
used = 0; used = 0;
curwin->w_botline = cln + 1; curwin->w_botline = cln + 1;
loff.lnum = cln + 1;
#ifdef FEAT_DIFF #ifdef FEAT_DIFF
loff.fill = 0; loff.fill = 0;
#endif #endif
for (curwin->w_topline = curwin->w_botline; while (TRUE)
curwin->w_topline > 1;
curwin->w_topline = loff.lnum)
{ {
loff.lnum = curwin->w_topline;
topline_back_winheight(&loff, FALSE); topline_back_winheight(&loff, FALSE);
if (loff.height == MAXCOL) if (loff.height == MAXCOL)
break; break;
@@ -2499,29 +2498,28 @@ scroll_cursor_bot(int min_scroll, int set_topbot)
curwin->w_skipcol = skipcol_from_plines( curwin->w_skipcol = skipcol_from_plines(
curwin, plines_offset); curwin, plines_offset);
curwin->w_cursor.col = curwin->w_skipcol + overlap; curwin->w_cursor.col = curwin->w_skipcol + overlap;
set_skipcol = TRUE;
} }
} }
break; break;
} }
used += loff.height;
#ifdef FEAT_DIFF #ifdef FEAT_DIFF
curwin->w_topfill = loff.fill; curwin->w_topfill = loff.fill;
#endif #endif
curwin->w_topline = loff.lnum;
used += loff.height;
} }
if (curwin->w_topline > curbuf->b_ml.ml_line_count)
curwin->w_topline = curbuf->b_ml.ml_line_count;
set_empty_rows(curwin, used); set_empty_rows(curwin, used);
curwin->w_valid |= VALID_BOTLINE|VALID_BOTLINE_AP; curwin->w_valid |= VALID_BOTLINE|VALID_BOTLINE_AP;
if (curwin->w_topline != old_topline if (curwin->w_topline != old_topline
#ifdef FEAT_DIFF #ifdef FEAT_DIFF
|| curwin->w_topfill != old_topfill || curwin->w_topfill != old_topfill
#endif #endif
|| set_skipcol || curwin->w_skipcol != old_skipcol
|| curwin->w_skipcol != 0) || curwin->w_skipcol != 0)
{ {
curwin->w_valid &= ~(VALID_WROW|VALID_CROW); curwin->w_valid &= ~(VALID_WROW|VALID_CROW);
if (set_skipcol) if (curwin->w_skipcol != old_skipcol)
redraw_later(UPD_NOT_VALID); redraw_later(UPD_NOT_VALID);
else else
reset_skipcol(); reset_skipcol();
@@ -3051,7 +3049,8 @@ static int get_scroll_overlap(int dir)
int min_height = curwin->w_height - 2; int min_height = curwin->w_height - 2;
validate_botline(); validate_botline();
if (dir == FORWARD && curwin->w_botline > curbuf->b_ml.ml_line_count) if ((dir == BACKWARD && curwin->w_topline == 1)
|| (dir == FORWARD && curwin->w_botline > curbuf->b_ml.ml_line_count))
return min_height + 2; // no overlap, still handle 'smoothscroll' return min_height + 2; // no overlap, still handle 'smoothscroll'
loff.lnum = dir == FORWARD ? curwin->w_botline : curwin->w_topline - 1; loff.lnum = dir == FORWARD ? curwin->w_botline : curwin->w_topline - 1;
@@ -3189,7 +3188,6 @@ pagescroll(int dir, long count, int half)
cursor_down_inner(curwin, count); cursor_down_inner(curwin, count);
else else
cursor_up_inner(curwin, count); cursor_up_inner(curwin, count);
curwin->w_curswant = prev_curswant;
if (get_scrolloff_value()) if (get_scrolloff_value())
cursor_correct(); cursor_correct();
@@ -3210,12 +3208,13 @@ pagescroll(int dir, long count, int half)
nochange = scroll_with_sms(dir, &count); nochange = scroll_with_sms(dir, &count);
} }
curwin->w_curswant = prev_curswant;
// Error if both the viewport and cursor did not change. // Error if both the viewport and cursor did not change.
if (nochange) if (nochange)
beep_flush(); beep_flush();
else if (!curwin->w_p_sms) else if (!curwin->w_p_sms)
beginline(BL_SOL | BL_FIX); beginline(BL_SOL | BL_FIX);
else if (p_sol) else if (p_sol || curwin->w_skipcol)
nv_g_home_m_cmd(&ca); nv_g_home_m_cmd(&ca);
return nochange; return nochange;

View File

@@ -4210,4 +4210,19 @@ func Test_single_line_scroll()
call prop_type_delete(vt) call prop_type_delete(vt)
endfunc endfunc
" Test for zb in buffer with a single line and filler lines
func Test_single_line_filler_zb()
call setline(1, ['', 'foobar one two three'])
diffthis
new
call setline(1, ['foobar one two three'])
diffthis
" zb scrolls to reveal filler lines at the start of the buffer.
exe "normal \<C-E>zb"
call assert_equal(1, winsaveview().topfill)
bw!
endfunc
" vim: shiftwidth=2 sts=2 expandtab nofoldenable " vim: shiftwidth=2 sts=2 expandtab nofoldenable

View File

@@ -1018,6 +1018,8 @@ func Test_smoothscroll_page()
call assert_equal(0, winsaveview().skipcol) call assert_equal(0, winsaveview().skipcol)
" Half-page scrolling does not go beyond end of buffer and moves the cursor. " Half-page scrolling does not go beyond end of buffer and moves the cursor.
" Even with 'nostartofline', the correct amount of lines is scrolled.
setl nostartofline
exe "norm! 0\<C-D>" exe "norm! 0\<C-D>"
call assert_equal(200, winsaveview().skipcol) call assert_equal(200, winsaveview().skipcol)
call assert_equal(204, col('.')) call assert_equal(204, col('.'))
@@ -1041,7 +1043,7 @@ func Test_smoothscroll_page()
call assert_equal(204, col('.')) call assert_equal(204, col('.'))
exe "norm! \<C-U>" exe "norm! \<C-U>"
call assert_equal(0, winsaveview().skipcol) call assert_equal(0, winsaveview().skipcol)
call assert_equal(1, col('.')) call assert_equal(40, col('.'))
bwipe! bwipe!
endfunc endfunc
@@ -1059,6 +1061,11 @@ func Test_smoothscroll_next_topline()
redraw redraw
call assert_equal(0, winsaveview().skipcol) call assert_equal(0, winsaveview().skipcol)
" Also when scrolling back.
exe "norm! G\<C-Y>"
redraw
call assert_equal(880, winsaveview().skipcol)
" Cursor in correct place when not in the first screenline of a buffer line. " Cursor in correct place when not in the first screenline of a buffer line.
exe "norm! gg4gj20\<C-D>\<C-D>" exe "norm! gg4gj20\<C-D>\<C-D>"
redraw redraw

View File

@@ -704,6 +704,8 @@ static char *(features[]) =
static int included_patches[] = static int included_patches[] =
{ /* Add new patch number below this line */ { /* Add new patch number below this line */
/**/
260,
/**/ /**/
259, 259,
/**/ /**/