mirror of
https://github.com/vim/vim.git
synced 2025-09-24 03:44:06 -04:00
patch 9.1.0280: several issues with 'smoothscroll' support
Problem: Logic to make sure cursor is in visible part of the screen after scrolling the text with 'smoothscroll' is scattered, asymmetric and contains bugs. Solution: Adjust and create helper function for 'smoothscroll' cursor logic. (Luuk van Baal) closes: #14410 Signed-off-by: Luuk van Baal <luukvbaal@gmail.com> Signed-off-by: Christian Brabandt <cb@256bit.org>
This commit is contained in:
committed by
Christian Brabandt
parent
196b6678c5
commit
9148ba8a46
@@ -519,6 +519,8 @@ plines_m_win(win_T *wp, linenr_T first, linenr_T last, int limit_winheight)
|
|||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
#ifdef FEAT_DIFF
|
#ifdef FEAT_DIFF
|
||||||
|
if (first == wp->w_buffer->b_ml.ml_line_count)
|
||||||
|
count += diff_check_fill(wp, first + 1);
|
||||||
if (first == wp->w_topline)
|
if (first == wp->w_topline)
|
||||||
count += plines_win_nofill(wp, first, limit_winheight)
|
count += plines_win_nofill(wp, first, limit_winheight)
|
||||||
+ wp->w_topfill;
|
+ wp->w_topfill;
|
||||||
|
286
src/move.c
286
src/move.c
@@ -59,7 +59,7 @@ adjust_plines_for_skipcol(win_T *wp)
|
|||||||
* the window height.
|
* the window height.
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
plines_correct_topline(win_T *wp, linenr_T lnum)
|
plines_correct_topline(win_T *wp, linenr_T lnum, int limit_winheight)
|
||||||
{
|
{
|
||||||
int n;
|
int n;
|
||||||
#ifdef FEAT_DIFF
|
#ifdef FEAT_DIFF
|
||||||
@@ -70,7 +70,7 @@ plines_correct_topline(win_T *wp, linenr_T lnum)
|
|||||||
n = plines_win(wp, lnum, FALSE);
|
n = plines_win(wp, lnum, FALSE);
|
||||||
if (lnum == wp->w_topline)
|
if (lnum == wp->w_topline)
|
||||||
n -= adjust_plines_for_skipcol(wp);
|
n -= adjust_plines_for_skipcol(wp);
|
||||||
if (n > wp->w_height)
|
if (limit_winheight && n > wp->w_height)
|
||||||
n = wp->w_height;
|
n = wp->w_height;
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
@@ -119,7 +119,7 @@ comp_botline(win_T *wp)
|
|||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
n = plines_correct_topline(wp, lnum);
|
n = plines_correct_topline(wp, lnum, TRUE);
|
||||||
}
|
}
|
||||||
if (
|
if (
|
||||||
#ifdef FEAT_FOLDING
|
#ifdef FEAT_FOLDING
|
||||||
@@ -921,7 +921,7 @@ curs_rows(win_T *wp)
|
|||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
wp->w_cline_row += plines_correct_topline(wp, lnum);
|
wp->w_cline_row += plines_correct_topline(wp, lnum, TRUE);
|
||||||
++lnum;
|
++lnum;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1601,6 +1601,127 @@ f_virtcol2col(typval_T *argvars UNUSED, typval_T *rettv)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Make sure the cursor is in the visible part of the topline after scrolling
|
||||||
|
* the screen with 'smoothscroll'.
|
||||||
|
*/
|
||||||
|
static void cursor_correct_sms(void)
|
||||||
|
{
|
||||||
|
if (!curwin->w_p_sms ||!curwin->w_p_wrap
|
||||||
|
|| curwin->w_cursor.lnum != curwin->w_topline)
|
||||||
|
return;
|
||||||
|
|
||||||
|
long so = get_scrolloff_value();
|
||||||
|
int width1 = curwin->w_width - curwin_col_off();
|
||||||
|
int width2 = width1 + curwin_col_off2();
|
||||||
|
int so_cols = so == 0 ? 0 : width1 + (so - 1) * width2;
|
||||||
|
int space_cols = (curwin->w_height - 1) * width2;
|
||||||
|
int size = so == 0 ? 0 : win_linetabsize(curwin, curwin->w_topline,
|
||||||
|
ml_get(curwin->w_topline), (colnr_T)MAXCOL);
|
||||||
|
|
||||||
|
if (curwin->w_topline == 1 && curwin->w_skipcol == 0)
|
||||||
|
so_cols = 0; // Ignore 'scrolloff' at top of buffer.
|
||||||
|
else if (so_cols > space_cols / 2)
|
||||||
|
so_cols = space_cols / 2; // Not enough room: put cursor in the middle.
|
||||||
|
|
||||||
|
// Not enough screen lines in topline: ignore 'scrolloff'.
|
||||||
|
while (so_cols > size && so_cols - width2 >= width1)
|
||||||
|
so_cols -= width2;
|
||||||
|
if (so_cols >= width1 && so_cols > size)
|
||||||
|
so_cols -= width1;
|
||||||
|
|
||||||
|
// If there is no marker or we have non-zero scrolloff, just ignore it.
|
||||||
|
int overlap = (curwin->w_skipcol == 0 || so_cols != 0) ? 0
|
||||||
|
: sms_marker_overlap(curwin, -1);
|
||||||
|
int top = curwin->w_skipcol + overlap + so_cols;
|
||||||
|
int bot = curwin->w_skipcol + width1 + (curwin->w_height - 1) * width2
|
||||||
|
- so_cols;
|
||||||
|
validate_virtcol();
|
||||||
|
colnr_T col = curwin->w_virtcol;
|
||||||
|
|
||||||
|
if (col < top)
|
||||||
|
{
|
||||||
|
if (col < width1)
|
||||||
|
col += width1;
|
||||||
|
while (width2 > 0 && col < top)
|
||||||
|
col += width2;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
while (width2 > 0 && col >= bot)
|
||||||
|
col -= width2;
|
||||||
|
|
||||||
|
if (col != curwin->w_virtcol)
|
||||||
|
{
|
||||||
|
curwin->w_curswant = col;
|
||||||
|
coladvance(curwin->w_curswant);
|
||||||
|
// validate_virtcol() marked various things as valid, but after
|
||||||
|
// moving the cursor they need to be recomputed
|
||||||
|
curwin->w_valid &=
|
||||||
|
~(VALID_WROW|VALID_WCOL|VALID_CHEIGHT|VALID_CROW|VALID_VIRTCOL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Scroll "count" lines up or down, and redraw.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
scroll_redraw(int up, long count)
|
||||||
|
{
|
||||||
|
linenr_T prev_topline = curwin->w_topline;
|
||||||
|
int prev_skipcol = curwin->w_skipcol;
|
||||||
|
#ifdef FEAT_DIFF
|
||||||
|
int prev_topfill = curwin->w_topfill;
|
||||||
|
#endif
|
||||||
|
linenr_T prev_lnum = curwin->w_cursor.lnum;
|
||||||
|
|
||||||
|
if (up)
|
||||||
|
scrollup(count, TRUE);
|
||||||
|
else
|
||||||
|
scrolldown(count, TRUE);
|
||||||
|
if (get_scrolloff_value() > 0)
|
||||||
|
{
|
||||||
|
// Adjust the cursor position for 'scrolloff'. Mark w_topline as
|
||||||
|
// valid, otherwise the screen jumps back at the end of the file.
|
||||||
|
cursor_correct();
|
||||||
|
check_cursor_moved(curwin);
|
||||||
|
curwin->w_valid |= VALID_TOPLINE;
|
||||||
|
|
||||||
|
// If moved back to where we were, at least move the cursor, otherwise
|
||||||
|
// we get stuck at one position. Don't move the cursor up if the
|
||||||
|
// first line of the buffer is already on the screen
|
||||||
|
while (curwin->w_topline == prev_topline
|
||||||
|
&& curwin->w_skipcol == prev_skipcol
|
||||||
|
#ifdef FEAT_DIFF
|
||||||
|
&& curwin->w_topfill == prev_topfill
|
||||||
|
#endif
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if (up)
|
||||||
|
{
|
||||||
|
if (curwin->w_cursor.lnum > prev_lnum
|
||||||
|
|| cursor_down(1L, FALSE) == FAIL)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (curwin->w_cursor.lnum < prev_lnum
|
||||||
|
|| prev_topline == 1L
|
||||||
|
|| cursor_up(1L, FALSE) == FAIL)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// Mark w_topline as valid, otherwise the screen jumps back at the
|
||||||
|
// end of the file.
|
||||||
|
check_cursor_moved(curwin);
|
||||||
|
curwin->w_valid |= VALID_TOPLINE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cursor_correct_sms();
|
||||||
|
if (curwin->w_cursor.lnum != prev_lnum)
|
||||||
|
coladvance(curwin->w_curswant);
|
||||||
|
redraw_later(UPD_VALID);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Scroll the current window down by "line_count" logical lines. "CTRL-Y"
|
* Scroll the current window down by "line_count" logical lines. "CTRL-Y"
|
||||||
*/
|
*/
|
||||||
@@ -1663,9 +1784,6 @@ 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))
|
||||||
@@ -1749,35 +1867,8 @@ scrolldown(
|
|||||||
#endif
|
#endif
|
||||||
coladvance(curwin->w_curswant);
|
coladvance(curwin->w_curswant);
|
||||||
}
|
}
|
||||||
|
if (curwin->w_cursor.lnum < curwin->w_topline)
|
||||||
if (curwin->w_cursor.lnum == curwin->w_topline && do_sms)
|
curwin->w_cursor.lnum = curwin->w_topline;
|
||||||
{
|
|
||||||
long so = get_scrolloff_value();
|
|
||||||
int scrolloff_cols = so == 0 ? 0 : width1 + (so - 1) * width2;
|
|
||||||
|
|
||||||
// make sure the cursor is in the visible text
|
|
||||||
validate_virtcol();
|
|
||||||
int col = curwin->w_virtcol - curwin->w_skipcol + scrolloff_cols;
|
|
||||||
int row = 0;
|
|
||||||
if (col >= width1)
|
|
||||||
{
|
|
||||||
col -= width1;
|
|
||||||
++row;
|
|
||||||
}
|
|
||||||
if (col > width2 && width2 > 0)
|
|
||||||
{
|
|
||||||
row += col / width2;
|
|
||||||
// even so col is not used anymore,
|
|
||||||
// make sure it is correct, just in case
|
|
||||||
col = col % width2;
|
|
||||||
}
|
|
||||||
if (row >= curwin->w_height)
|
|
||||||
{
|
|
||||||
curwin->w_curswant = curwin->w_virtcol
|
|
||||||
- (row - curwin->w_height + 1) * width2;
|
|
||||||
coladvance(curwin->w_curswant);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -1859,9 +1950,6 @@ 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.
|
|
||||||
if (do_sms)
|
|
||||||
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);
|
||||||
}
|
}
|
||||||
@@ -1902,47 +1990,6 @@ scrollup(
|
|||||||
~(VALID_WROW|VALID_WCOL|VALID_CHEIGHT|VALID_CROW|VALID_VIRTCOL);
|
~(VALID_WROW|VALID_WCOL|VALID_CHEIGHT|VALID_CROW|VALID_VIRTCOL);
|
||||||
coladvance(curwin->w_curswant);
|
coladvance(curwin->w_curswant);
|
||||||
}
|
}
|
||||||
if (curwin->w_cursor.lnum == curwin->w_topline
|
|
||||||
&& do_sms && curwin->w_skipcol > 0)
|
|
||||||
{
|
|
||||||
int col_off = curwin_col_off();
|
|
||||||
int col_off2 = curwin_col_off2();
|
|
||||||
|
|
||||||
int width1 = curwin->w_width - col_off;
|
|
||||||
int width2 = width1 + col_off2;
|
|
||||||
int extra2 = col_off - col_off2;
|
|
||||||
long so = get_scrolloff_value();
|
|
||||||
int scrolloff_cols = so == 0 ? 0 : width1 + (so - 1) * width2;
|
|
||||||
int space_cols = (curwin->w_height - 1) * width2;
|
|
||||||
|
|
||||||
// If we have non-zero scrolloff, just ignore the marker as we are
|
|
||||||
// going past it anyway.
|
|
||||||
int overlap = scrolloff_cols != 0 ? 0
|
|
||||||
: sms_marker_overlap(curwin, extra2);
|
|
||||||
|
|
||||||
// Make sure the cursor is in a visible part of the line, taking
|
|
||||||
// 'scrolloff' into account, but using screen lines.
|
|
||||||
// If there are not enough screen lines put the cursor in the middle.
|
|
||||||
if (scrolloff_cols > space_cols / 2)
|
|
||||||
scrolloff_cols = space_cols / 2;
|
|
||||||
validate_virtcol();
|
|
||||||
if (curwin->w_virtcol < curwin->w_skipcol + overlap + scrolloff_cols)
|
|
||||||
{
|
|
||||||
colnr_T col = curwin->w_virtcol;
|
|
||||||
|
|
||||||
if (col < width1)
|
|
||||||
col += width1;
|
|
||||||
while (col < curwin->w_skipcol + overlap + scrolloff_cols)
|
|
||||||
col += width2;
|
|
||||||
curwin->w_curswant = col;
|
|
||||||
coladvance(curwin->w_curswant);
|
|
||||||
|
|
||||||
// validate_virtcol() marked various things as valid, but after
|
|
||||||
// moving the cursor they need to be recomputed
|
|
||||||
curwin->w_valid &=
|
|
||||||
~(VALID_WROW|VALID_WCOL|VALID_CHEIGHT|VALID_CROW|VALID_VIRTCOL);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -2489,7 +2536,6 @@ scroll_cursor_bot(int min_scroll, int set_topbot)
|
|||||||
{
|
{
|
||||||
int plines_offset = used + loff.height
|
int plines_offset = used + loff.height
|
||||||
- curwin->w_height;
|
- curwin->w_height;
|
||||||
int overlap = sms_marker_overlap(curwin, -1);
|
|
||||||
used = curwin->w_height;
|
used = curwin->w_height;
|
||||||
#ifdef FEAT_DIFF
|
#ifdef FEAT_DIFF
|
||||||
curwin->w_topfill = loff.fill;
|
curwin->w_topfill = loff.fill;
|
||||||
@@ -2497,7 +2543,6 @@ scroll_cursor_bot(int min_scroll, int set_topbot)
|
|||||||
curwin->w_topline = loff.lnum;
|
curwin->w_topline = loff.lnum;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -2722,6 +2767,8 @@ scroll_cursor_bot(int min_scroll, int set_topbot)
|
|||||||
curwin->w_valid = old_valid;
|
curwin->w_valid = old_valid;
|
||||||
}
|
}
|
||||||
curwin->w_valid |= VALID_TOPLINE;
|
curwin->w_valid |= VALID_TOPLINE;
|
||||||
|
|
||||||
|
cursor_correct_sms();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -3094,10 +3141,10 @@ static int get_scroll_overlap(int dir)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Scroll "count" lines with 'smoothscroll' in direction "dir". Adjust "count"
|
* Scroll "count" lines with 'smoothscroll' in direction "dir". Return TRUE
|
||||||
* when scrolling more than "count" and return TRUE when scrolling happened.
|
* when scrolling happened.
|
||||||
*/
|
*/
|
||||||
static int scroll_with_sms(int dir, long *count)
|
static int scroll_with_sms(int dir, long count)
|
||||||
{
|
{
|
||||||
int prev_sms = curwin->w_p_sms;
|
int prev_sms = curwin->w_p_sms;
|
||||||
colnr_T prev_skipcol = curwin->w_skipcol;
|
colnr_T prev_skipcol = curwin->w_skipcol;
|
||||||
@@ -3107,11 +3154,10 @@ static int scroll_with_sms(int dir, long *count)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
curwin->w_p_sms = TRUE;
|
curwin->w_p_sms = TRUE;
|
||||||
scroll_redraw(dir == FORWARD, *count);
|
scroll_redraw(dir == FORWARD, count);
|
||||||
|
|
||||||
// Not actually smoothscrolling but ended up with partially visible line.
|
// Not actually smoothscrolling but ended up with partially visible line.
|
||||||
// Continue scrolling and update "count" so that cursor can be moved
|
// Continue scrolling until skipcol is zero.
|
||||||
// accordingly for half-page scrolling.
|
|
||||||
if (!prev_sms && curwin->w_skipcol > 0)
|
if (!prev_sms && curwin->w_skipcol > 0)
|
||||||
{
|
{
|
||||||
int fixdir = dir;
|
int fixdir = dir;
|
||||||
@@ -3122,10 +3168,7 @@ static int scroll_with_sms(int dir, long *count)
|
|||||||
validate_cursor();
|
validate_cursor();
|
||||||
while (curwin->w_skipcol > 0
|
while (curwin->w_skipcol > 0
|
||||||
&& curwin->w_topline < curbuf->b_ml.ml_line_count)
|
&& curwin->w_topline < curbuf->b_ml.ml_line_count)
|
||||||
{
|
|
||||||
scroll_redraw(fixdir == FORWARD, 1);
|
scroll_redraw(fixdir == FORWARD, 1);
|
||||||
*count += (fixdir == dir ? 1 : -1);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
curwin->w_p_sms = prev_sms;
|
curwin->w_p_sms = prev_sms;
|
||||||
|
|
||||||
@@ -3149,7 +3192,6 @@ pagescroll(int dir, long count, int half)
|
|||||||
int nochange = TRUE;
|
int nochange = TRUE;
|
||||||
int buflen = curbuf->b_ml.ml_line_count;
|
int buflen = curbuf->b_ml.ml_line_count;
|
||||||
colnr_T prev_col = curwin->w_cursor.col;
|
colnr_T prev_col = curwin->w_cursor.col;
|
||||||
colnr_T prev_curswant = curwin->w_curswant;
|
|
||||||
linenr_T prev_lnum = curwin->w_cursor.lnum;
|
linenr_T prev_lnum = curwin->w_cursor.lnum;
|
||||||
oparg_T oa = { 0 };
|
oparg_T oa = { 0 };
|
||||||
cmdarg_T ca = { 0 };
|
cmdarg_T ca = { 0 };
|
||||||
@@ -3162,34 +3204,45 @@ pagescroll(int dir, long count, int half)
|
|||||||
curwin->w_p_scr = MIN(curwin->w_height, count);
|
curwin->w_p_scr = MIN(curwin->w_height, count);
|
||||||
count = MIN(curwin->w_height, curwin->w_p_scr);
|
count = MIN(curwin->w_height, curwin->w_p_scr);
|
||||||
|
|
||||||
// Don't scroll if we already know that it will reveal end of buffer lines.
|
int curscount = count;
|
||||||
if (dir == BACKWARD
|
// Adjust count so as to not reveal end of buffer lines.
|
||||||
|| (curwin->w_botline - 1 < buflen)
|
if (dir == FORWARD)
|
||||||
|| (curwin->w_p_sms && curwin->w_botline - 1 == buflen
|
|
||||||
&& curwin->w_skipcol < linetabsize(curwin, buflen)))
|
|
||||||
{
|
{
|
||||||
nochange = scroll_with_sms(dir, &count);
|
int n = plines_correct_topline(curwin, curwin->w_topline, FALSE);
|
||||||
validate_botline();
|
if (n - count < curwin->w_height && curwin->w_topline < buflen)
|
||||||
// Hide any potentially revealed end of buffer lines.
|
n += plines_m_win(curwin, curwin->w_topline + 1, buflen, TRUE);
|
||||||
if (!nochange && curwin->w_botline - 1 == buflen)
|
if (n - count < curwin->w_height)
|
||||||
|
count = n - curwin->w_height;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Scroll the window and determine number of lines to move the cursor.
|
||||||
|
if (count > 0)
|
||||||
|
{
|
||||||
|
validate_cursor();
|
||||||
|
int prev_wrow = curwin->w_wrow;
|
||||||
|
nochange = scroll_with_sms(dir, count);
|
||||||
|
if (!nochange)
|
||||||
{
|
{
|
||||||
curwin->w_cursor.lnum = buflen;
|
validate_cursor();
|
||||||
scroll_cursor_bot(0, TRUE);
|
curscount = abs(prev_wrow - curwin->w_wrow);
|
||||||
|
dir = prev_wrow > curwin->w_wrow ? FORWARD : BACKWARD;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Move the cursor "count" screen lines.
|
int so = get_scrolloff_value();
|
||||||
curwin->w_curswant = MAXCOL;
|
// Move the cursor the same amount of screen lines except if
|
||||||
curwin->w_cursor.col = prev_col;
|
// 'scrolloff' is set and cursor was at start or end of buffer.
|
||||||
curwin->w_cursor.lnum = prev_lnum;
|
if (so == 0 || (prev_lnum != 1 && prev_lnum != buflen))
|
||||||
if (curwin->w_p_wrap)
|
{
|
||||||
nv_screengo(&oa, dir, count);
|
if (curwin->w_p_wrap)
|
||||||
else if (dir == FORWARD)
|
nv_screengo(&oa, dir, curscount);
|
||||||
cursor_down_inner(curwin, count);
|
else if (dir == FORWARD)
|
||||||
else
|
cursor_down_inner(curwin, curscount);
|
||||||
cursor_up_inner(curwin, count);
|
else
|
||||||
|
cursor_up_inner(curwin, curscount);
|
||||||
|
}
|
||||||
|
|
||||||
if (get_scrolloff_value())
|
if (so > 0)
|
||||||
cursor_correct();
|
cursor_correct();
|
||||||
#ifdef FEAT_FOLDING
|
#ifdef FEAT_FOLDING
|
||||||
// Move cursor to first line of closed fold.
|
// Move cursor to first line of closed fold.
|
||||||
@@ -3205,16 +3258,15 @@ pagescroll(int dir, long count, int half)
|
|||||||
// Scroll [count] times 'window' or current window height lines.
|
// Scroll [count] times 'window' or current window height lines.
|
||||||
count *= ((ONE_WINDOW && p_window > 0 && p_window < Rows - 1) ?
|
count *= ((ONE_WINDOW && p_window > 0 && p_window < Rows - 1) ?
|
||||||
MAX(1, p_window - 2) : get_scroll_overlap(dir));
|
MAX(1, p_window - 2) : get_scroll_overlap(dir));
|
||||||
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 || curwin->w_skipcol)
|
else if (p_sol)
|
||||||
nv_g_home_m_cmd(&ca);
|
nv_g_home_m_cmd(&ca);
|
||||||
|
|
||||||
return nochange;
|
return nochange;
|
||||||
|
59
src/normal.c
59
src/normal.c
@@ -2473,65 +2473,6 @@ nv_scroll_line(cmdarg_T *cap)
|
|||||||
scroll_redraw(cap->arg, cap->count1);
|
scroll_redraw(cap->arg, cap->count1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Scroll "count" lines up or down, and redraw.
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
scroll_redraw(int up, long count)
|
|
||||||
{
|
|
||||||
linenr_T prev_topline = curwin->w_topline;
|
|
||||||
int prev_skipcol = curwin->w_skipcol;
|
|
||||||
#ifdef FEAT_DIFF
|
|
||||||
int prev_topfill = curwin->w_topfill;
|
|
||||||
#endif
|
|
||||||
linenr_T prev_lnum = curwin->w_cursor.lnum;
|
|
||||||
|
|
||||||
if (up)
|
|
||||||
scrollup(count, TRUE);
|
|
||||||
else
|
|
||||||
scrolldown(count, TRUE);
|
|
||||||
if (get_scrolloff_value() > 0)
|
|
||||||
{
|
|
||||||
// Adjust the cursor position for 'scrolloff'. Mark w_topline as
|
|
||||||
// valid, otherwise the screen jumps back at the end of the file.
|
|
||||||
cursor_correct();
|
|
||||||
check_cursor_moved(curwin);
|
|
||||||
curwin->w_valid |= VALID_TOPLINE;
|
|
||||||
|
|
||||||
// If moved back to where we were, at least move the cursor, otherwise
|
|
||||||
// we get stuck at one position. Don't move the cursor up if the
|
|
||||||
// first line of the buffer is already on the screen
|
|
||||||
while (curwin->w_topline == prev_topline
|
|
||||||
&& curwin->w_skipcol == prev_skipcol
|
|
||||||
#ifdef FEAT_DIFF
|
|
||||||
&& curwin->w_topfill == prev_topfill
|
|
||||||
#endif
|
|
||||||
)
|
|
||||||
{
|
|
||||||
if (up)
|
|
||||||
{
|
|
||||||
if (curwin->w_cursor.lnum > prev_lnum
|
|
||||||
|| cursor_down(1L, FALSE) == FAIL)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (curwin->w_cursor.lnum < prev_lnum
|
|
||||||
|| prev_topline == 1L
|
|
||||||
|| cursor_up(1L, FALSE) == FAIL)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
// Mark w_topline as valid, otherwise the screen jumps back at the
|
|
||||||
// end of the file.
|
|
||||||
check_cursor_moved(curwin);
|
|
||||||
curwin->w_valid |= VALID_TOPLINE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (curwin->w_cursor.lnum != prev_lnum)
|
|
||||||
coladvance(curwin->w_curswant);
|
|
||||||
redraw_later(UPD_VALID);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Get the count specified after a 'z' command. Only the 'z<CR>', 'zl', 'zh',
|
* Get the count specified after a 'z' command. Only the 'z<CR>', 'zl', 'zh',
|
||||||
* 'z<Left>', and 'z<Right>' commands accept a count after 'z'.
|
* 'z<Left>', and 'z<Right>' commands accept a count after 'z'.
|
||||||
|
@@ -37,6 +37,7 @@ void f_screenpos(typval_T *argvars, typval_T *rettv);
|
|||||||
void f_virtcol2col(typval_T *argvars, typval_T *rettv);
|
void f_virtcol2col(typval_T *argvars, typval_T *rettv);
|
||||||
void scrolldown(long line_count, int byfold);
|
void scrolldown(long line_count, int byfold);
|
||||||
void scrollup(long line_count, int byfold);
|
void scrollup(long line_count, int byfold);
|
||||||
|
void scroll_redraw(int up, long count);
|
||||||
void adjust_skipcol(void);
|
void adjust_skipcol(void);
|
||||||
void check_topfill(win_T *wp, int down);
|
void check_topfill(win_T *wp, int down);
|
||||||
void scrolldown_clamp(void);
|
void scrolldown_clamp(void);
|
||||||
|
@@ -25,7 +25,6 @@ int find_decl(char_u *ptr, int len, int locally, int thisblock, int flags_arg);
|
|||||||
void nv_g_home_m_cmd(cmdarg_T *cap);
|
void nv_g_home_m_cmd(cmdarg_T *cap);
|
||||||
int nv_screengo(oparg_T *oap, int dir, long dist);
|
int nv_screengo(oparg_T *oap, int dir, long dist);
|
||||||
void nv_scroll_line(cmdarg_T *cap);
|
void nv_scroll_line(cmdarg_T *cap);
|
||||||
void scroll_redraw(int up, long count);
|
|
||||||
void handle_tabmenu(void);
|
void handle_tabmenu(void);
|
||||||
void do_nv_ident(int c1, int c2);
|
void do_nv_ident(int c1, int c2);
|
||||||
int get_visual_text(cmdarg_T *cap, char_u **pp, int *lenp);
|
int get_visual_text(cmdarg_T *cap, char_u **pp, int *lenp);
|
||||||
|
@@ -3,4 +3,4 @@
|
|||||||
|t|s| |o|f| |t|e|x|t| |w|i|t|h| |l|o|t|s| |o|f| |t|e|x|t| |w|i|t|h| |l|o|t|s| |o
|
|t|s| |o|f| |t|e|x|t| |w|i|t|h| |l|o|t|s| |o|f| |t|e|x|t| |w|i|t|h| |l|o|t|s| |o
|
||||||
|f| |t|e|x|t| |w|i|t|h| |l|o|t|s| |o|f| |t|e|x|t| |w|i|t|h| |l|o|t|s| |o|f| |t|e
|
|f| |t|e|x|t| |w|i|t|h| |l|o|t|s| |o|f| |t|e|x|t| |w|i|t|h| |l|o|t|s| |o|f| |t|e
|
||||||
|x|t| |w|i|t|h| |l|o|t|s| |o|f| |t|e|x|t| |w|i|t|h| |l|o|t|s| |o|f| |t|e|x|t| |w
|
|x|t| |w|i|t|h| |l|o|t|s| |o|f| |t|e|x|t| |w|i|t|h| |l|o|t|s| |o|f| |t|e|x|t| |w
|
||||||
| @21|3|,|9|0| @9|6@1|%|
|
|:|s|e|t| |s|c|r|o|l@1|o| @9|3|,|9|0| @9|6@1|%|
|
||||||
|
@@ -3,4 +3,4 @@
|
|||||||
|t|s| |o|f| |t|e|x|t| |w|i|t|h| |l|o|t|s| |o|f| |t|e|x|t| |w|i|t|h| |l|o|t|s| |o
|
|t|s| |o|f| |t|e|x|t| |w|i|t|h| |l|o|t|s| |o|f| |t|e|x|t| |w|i|t|h| |l|o|t|s| |o
|
||||||
|f| |t|e|x|t| |w|i>t|h| |l|o|t|s| |o|f| |t|e|x|t| |w|i|t|h| |l|o|t|s| |o|f| |t|e
|
|f| |t|e|x|t| |w|i>t|h| |l|o|t|s| |o|f| |t|e|x|t| |w|i|t|h| |l|o|t|s| |o|f| |t|e
|
||||||
|x|t| |w|i|t|h| |l|o|t|s| |o|f| |t|e|x|t| |w|i|t|h| |l|o|t|s| |o|f| |t|e|x|t| |w
|
|x|t| |w|i|t|h| |l|o|t|s| |o|f| |t|e|x|t| |w|i|t|h| |l|o|t|s| |o|f| |t|e|x|t| |w
|
||||||
| @21|3|,|1|7|0| @8|6@1|%|
|
|:|s|e|t| |s|c|r|o|l@1|o| @9|3|,|1|7|0| @8|6@1|%|
|
||||||
|
@@ -2023,4 +2023,19 @@ func Test_diff_toggle_wrap_skipcol_leftcol()
|
|||||||
\ screenpos(win2, line('.', win2), col('.', win2)))
|
\ screenpos(win2, line('.', win2), col('.', win2)))
|
||||||
|
|
||||||
bwipe!
|
bwipe!
|
||||||
|
bwipe!
|
||||||
|
endfunc
|
||||||
|
|
||||||
|
" Ctrl-D reveals filler lines below the last line in the buffer.
|
||||||
|
func Test_diff_eob_halfpage()
|
||||||
|
5new
|
||||||
|
call setline(1, ['']->repeat(10) + ['a'])
|
||||||
|
diffthis
|
||||||
|
5new
|
||||||
|
call setline(1, ['']->repeat(3) + ['a', 'b'])
|
||||||
|
diffthis
|
||||||
|
wincmd j
|
||||||
|
exe "norm! G\<C-D>"
|
||||||
|
call assert_equal(6, line('w0'))
|
||||||
|
|
||||||
%bwipe!
|
%bwipe!
|
||||||
|
@@ -1020,30 +1020,36 @@ func Test_smoothscroll_page()
|
|||||||
" 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.
|
" Even with 'nostartofline', the correct amount of lines is scrolled.
|
||||||
setl nostartofline
|
setl nostartofline
|
||||||
exe "norm! 0\<C-D>"
|
exe "norm! 15|\<C-D>"
|
||||||
call assert_equal(200, winsaveview().skipcol)
|
call assert_equal(200, winsaveview().skipcol)
|
||||||
call assert_equal(204, col('.'))
|
call assert_equal(215, col('.'))
|
||||||
exe "norm! \<C-D>"
|
exe "norm! \<C-D>"
|
||||||
call assert_equal(400, winsaveview().skipcol)
|
call assert_equal(400, winsaveview().skipcol)
|
||||||
call assert_equal(404, col('.'))
|
call assert_equal(415, col('.'))
|
||||||
exe "norm! \<C-D>"
|
exe "norm! \<C-D>"
|
||||||
call assert_equal(520, winsaveview().skipcol)
|
call assert_equal(520, winsaveview().skipcol)
|
||||||
call assert_equal(601, col('.'))
|
call assert_equal(535, col('.'))
|
||||||
exe "norm! \<C-D>"
|
exe "norm! \<C-D>"
|
||||||
call assert_equal(520, winsaveview().skipcol)
|
call assert_equal(520, winsaveview().skipcol)
|
||||||
call assert_equal(801, col('.'))
|
call assert_equal(735, col('.'))
|
||||||
exe "norm! \<C-U>"
|
exe "norm! \<C-D>"
|
||||||
call assert_equal(520, winsaveview().skipcol)
|
call assert_equal(520, winsaveview().skipcol)
|
||||||
call assert_equal(601, col('.'))
|
call assert_equal(895, col('.'))
|
||||||
exe "norm! \<C-U>"
|
exe "norm! \<C-U>"
|
||||||
call assert_equal(400, winsaveview().skipcol)
|
call assert_equal(320, winsaveview().skipcol)
|
||||||
call assert_equal(404, col('.'))
|
call assert_equal(695, col('.'))
|
||||||
exe "norm! \<C-U>"
|
exe "norm! \<C-U>"
|
||||||
call assert_equal(200, winsaveview().skipcol)
|
call assert_equal(120, winsaveview().skipcol)
|
||||||
call assert_equal(204, col('.'))
|
call assert_equal(495, col('.'))
|
||||||
exe "norm! \<C-U>"
|
exe "norm! \<C-U>"
|
||||||
call assert_equal(0, winsaveview().skipcol)
|
call assert_equal(0, winsaveview().skipcol)
|
||||||
call assert_equal(40, col('.'))
|
call assert_equal(375, col('.'))
|
||||||
|
exe "norm! \<C-U>"
|
||||||
|
call assert_equal(0, winsaveview().skipcol)
|
||||||
|
call assert_equal(175, col('.'))
|
||||||
|
exe "norm! \<C-U>"
|
||||||
|
call assert_equal(0, winsaveview().skipcol)
|
||||||
|
call assert_equal(15, col('.'))
|
||||||
|
|
||||||
bwipe!
|
bwipe!
|
||||||
endfunc
|
endfunc
|
||||||
@@ -1071,6 +1077,14 @@ func Test_smoothscroll_next_topline()
|
|||||||
redraw
|
redraw
|
||||||
call assert_equal(2, line('w0'))
|
call assert_equal(2, line('w0'))
|
||||||
|
|
||||||
|
" Cursor does not end up above topline, adjusting topline later.
|
||||||
|
setlocal nu cpo+=n
|
||||||
|
exe "norm! G$g013\<C-Y>"
|
||||||
|
redraw
|
||||||
|
call assert_equal(2, line('.'))
|
||||||
|
call assert_equal(0, winsaveview().skipcol)
|
||||||
|
|
||||||
|
set cpo-=n
|
||||||
bwipe!
|
bwipe!
|
||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
|
@@ -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 */
|
||||||
|
/**/
|
||||||
|
280,
|
||||||
/**/
|
/**/
|
||||||
279,
|
279,
|
||||||
/**/
|
/**/
|
||||||
|
Reference in New Issue
Block a user