1
0
forked from aniani/vim

patch 9.1.0215: Half-page scrolling does not support smooth-scrolling

Problem:  Page-wise scrolling with Ctrl-D/Ctrl-U implements
          it's own logic to change the topline and cursor.
          More logic than necessary for scrolling with Ctrl-F/Ctrl-B
          was removed in patch 9.1.0211.
Solution: Re-use the logic from Ctrl-E/Ctrl-Y/Ctrl-F/Ctrl-B while
          staying backward compatible as much as possible.
          Restore some of the logic that determined how many lines will
          be scrolled (Luuk van Baal)

closes: #14316

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-03-28 10:07:29 +01:00
committed by Christian Brabandt
parent 982e191b38
commit 5a2e3ec9ac
12 changed files with 166 additions and 242 deletions

View File

@@ -3025,6 +3025,67 @@ cursor_correct(void)
curwin->w_valid |= VALID_TOPLINE;
}
/*
* Decide how much overlap to use for page-up or page-down scrolling.
* This is symmetric, so that doing both keeps the same lines displayed.
* Three lines are examined:
*
* before CTRL-F after CTRL-F / before CTRL-B
* etc. l1
* l1 last but one line ------------
* l2 last text line l2 top text line
* ------------- l3 second text line
* l3 etc.
*/
static int get_scroll_overlap(int dir)
{
lineoff_T loff;
int min_height = curwin->w_height - 2;
validate_botline();
if (dir == FORWARD && curwin->w_botline > curbuf->b_ml.ml_line_count)
return min_height + 2; // no overlap, still handle 'smoothscroll'
loff.lnum = dir == FORWARD ? curwin->w_botline : curwin->w_topline - 1;
#ifdef FEAT_DIFF
loff.fill = diff_check_fill(curwin, loff.lnum + dir == BACKWARD)
- (dir == FORWARD ? curwin->w_filler_rows : curwin->w_topfill);
loff.height = loff.fill > 0 ? 1 : plines_nofill(loff.lnum);
#else
loff.height = plines(loff.lnum);
#endif
int h1 = loff.height;
if (h1 > min_height)
return min_height + 2; // no overlap
if (dir == FORWARD)
topline_back(&loff);
else
botline_forw(&loff);
int h2 = loff.height;
if (h2 == MAXCOL || h2 + h1 > min_height)
return min_height + 2; // no overlap
if (dir == FORWARD)
topline_back(&loff);
else
botline_forw(&loff);
int h3 = loff.height;
if (h3 == MAXCOL || h3 + h2 > min_height)
return min_height + 2; // no overlap
if (dir == FORWARD)
topline_back(&loff);
else
botline_forw(&loff);
int h4 = loff.height;
if (h4 == MAXCOL || h4 + h3 + h2 > min_height || h3 + h2 + h1 > min_height)
return min_height + 1; // 1 line overlap
else
return min_height; // 2 lines overlap
}
/*
* Move screen "count" pages up ("dir" is BACKWARD) or down ("dir" is FORWARD)
* and update the screen.
@@ -3032,7 +3093,7 @@ cursor_correct(void)
* Return FAIL for failure, OK otherwise.
*/
int
onepage(int dir, long count)
pagescroll(int dir, long count, int half)
{
#ifdef FEAT_DIFF
int prev_topfill = curwin->w_topfill;
@@ -3040,9 +3101,17 @@ onepage(int dir, long count)
linenr_T prev_topline = curwin->w_topline;
colnr_T prev_skipcol = curwin->w_skipcol;
// Scroll 'window' or current window height lines.
count *= ((ONE_WINDOW && p_window > 0 && p_window < Rows - 1) ?
p_window : curwin->w_height) - 2;
if (half)
{
// Scroll [count], 'scroll' or current window height lines.
if (count)
curwin->w_p_scr = MIN(curwin->w_height, count);
count = MIN(curwin->w_height, curwin->w_p_scr);
}
else
// Scroll 'window' or current window height lines.
count *= ((ONE_WINDOW && p_window > 0 && p_window < Rows - 1) ?
p_window - 2 : get_scroll_overlap(dir));
if (curwin->w_p_sms)
scroll_redraw(dir == FORWARD, count);
@@ -3063,6 +3132,10 @@ onepage(int dir, long count)
scroll_redraw(dir == FORWARD, count);
curwin->w_p_sms = FALSE;
}
#ifdef FEAT_FOLDING
// Move cursor to first line of closed fold.
foldAdjustCursor();
#endif
int nochange = curwin->w_topline == prev_topline
#ifdef FEAT_DIFF
@@ -3070,198 +3143,22 @@ onepage(int dir, long count)
#endif
&& curwin->w_skipcol == prev_skipcol;
// Error if the viewport did not change and the cursor is already
// at the boundary.
if (nochange)
beep_flush();
{
int prev_cursor = curwin->w_cursor.lnum;
curwin->w_cursor.lnum += (count + 1) * (dir == FORWARD ? 1 : -1);
check_cursor();
if (curwin->w_cursor.lnum == prev_cursor)
beep_flush();
}
else if (!curwin->w_p_sms || curwin->w_skipcol == prev_skipcol)
beginline(BL_SOL | BL_FIX);
return nochange;
}
/*
* Scroll 'scroll' lines up or down.
*/
void
halfpage(int flag, linenr_T Prenum)
{
long scrolled = 0;
int i;
int n;
int room;
if (Prenum)
curwin->w_p_scr = (Prenum > curwin->w_height) ?
curwin->w_height : Prenum;
n = (curwin->w_p_scr <= curwin->w_height) ?
curwin->w_p_scr : curwin->w_height;
update_topline();
validate_botline();
room = curwin->w_empty_rows;
#ifdef FEAT_DIFF
room += curwin->w_filler_rows;
#endif
if (flag)
{
/*
* scroll the text up
*/
while (n > 0 && curwin->w_botline <= curbuf->b_ml.ml_line_count)
{
#ifdef FEAT_DIFF
if (curwin->w_topfill > 0)
{
i = 1;
--n;
--curwin->w_topfill;
}
else
#endif
{
i = PLINES_NOFILL(curwin->w_topline);
n -= i;
if (n < 0 && scrolled > 0)
break;
#ifdef FEAT_FOLDING
(void)hasFolding(curwin->w_topline, NULL, &curwin->w_topline);
#endif
++curwin->w_topline;
#ifdef FEAT_DIFF
curwin->w_topfill = diff_check_fill(curwin, curwin->w_topline);
#endif
if (curwin->w_cursor.lnum < curbuf->b_ml.ml_line_count)
{
++curwin->w_cursor.lnum;
curwin->w_valid &=
~(VALID_VIRTCOL|VALID_CHEIGHT|VALID_WCOL);
}
}
curwin->w_valid &= ~(VALID_CROW|VALID_WROW);
scrolled += i;
/*
* Correct w_botline for changed w_topline.
* Won't work when there are filler lines.
*/
#ifdef FEAT_DIFF
if (curwin->w_p_diff)
curwin->w_valid &= ~(VALID_BOTLINE|VALID_BOTLINE_AP);
else
#endif
{
room += i;
do
{
i = plines(curwin->w_botline);
if (i > room)
break;
#ifdef FEAT_FOLDING
(void)hasFolding(curwin->w_botline, NULL,
&curwin->w_botline);
#endif
++curwin->w_botline;
room -= i;
} while (curwin->w_botline <= curbuf->b_ml.ml_line_count);
}
}
/*
* When hit bottom of the file: move cursor down.
*/
if (n > 0)
{
# ifdef FEAT_FOLDING
if (hasAnyFolding(curwin))
{
while (--n >= 0
&& curwin->w_cursor.lnum < curbuf->b_ml.ml_line_count)
{
(void)hasFolding(curwin->w_cursor.lnum, NULL,
&curwin->w_cursor.lnum);
++curwin->w_cursor.lnum;
}
}
else
# endif
curwin->w_cursor.lnum += n;
check_cursor_lnum();
}
}
else
{
/*
* scroll the text down
*/
while (n > 0 && curwin->w_topline > 1)
{
#ifdef FEAT_DIFF
if (curwin->w_topfill < diff_check_fill(curwin, curwin->w_topline))
{
i = 1;
--n;
++curwin->w_topfill;
}
else
#endif
{
i = PLINES_NOFILL(curwin->w_topline - 1);
n -= i;
if (n < 0 && scrolled > 0)
break;
--curwin->w_topline;
#ifdef FEAT_FOLDING
(void)hasFolding(curwin->w_topline, &curwin->w_topline, NULL);
#endif
#ifdef FEAT_DIFF
curwin->w_topfill = 0;
#endif
}
curwin->w_valid &= ~(VALID_CROW|VALID_WROW|
VALID_BOTLINE|VALID_BOTLINE_AP);
scrolled += i;
if (curwin->w_cursor.lnum > 1)
{
--curwin->w_cursor.lnum;
curwin->w_valid &= ~(VALID_VIRTCOL|VALID_CHEIGHT|VALID_WCOL);
}
}
/*
* When hit top of the file: move cursor up.
*/
if (n > 0)
{
if (curwin->w_cursor.lnum <= (linenr_T)n)
curwin->w_cursor.lnum = 1;
else
# ifdef FEAT_FOLDING
if (hasAnyFolding(curwin))
{
while (--n >= 0 && curwin->w_cursor.lnum > 1)
{
--curwin->w_cursor.lnum;
(void)hasFolding(curwin->w_cursor.lnum,
&curwin->w_cursor.lnum, NULL);
}
}
else
# endif
curwin->w_cursor.lnum -= n;
}
}
# ifdef FEAT_FOLDING
// Move cursor to first line of closed fold.
foldAdjustCursor();
# endif
#ifdef FEAT_DIFF
check_topfill(curwin, !flag);
#endif
cursor_correct();
beginline(BL_SOL | BL_FIX);
redraw_later(UPD_VALID);
}
void
do_check_cursorbind(void)
{