mirror of
https://github.com/neovim/neovim.git
synced 2025-10-06 01:46:29 +00:00
vim-patch:9.0.0807: with 'smoothscroll' typing "0" may not go to the first column
Problem: With 'smoothscroll' typing "0" may not go to the first column.
Solution: Recompute w_cline_height when needed. Do not scroll up when it
would move the cursor.
d5337efece
Co-authored-by: Bram Moolenaar <Bram@vim.org>
This commit is contained in:
@@ -79,6 +79,21 @@ static int adjust_plines_for_skipcol(win_T *wp, int n)
|
|||||||
return n - off;
|
return n - off;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Return how many lines "lnum" will take on the screen, taking into account
|
||||||
|
/// whether it is the first line, whether w_skipcol is non-zero and limiting to
|
||||||
|
/// the window height.
|
||||||
|
static int plines_correct_topline(win_T *wp, linenr_T lnum, linenr_T *nextp, bool *foldedp)
|
||||||
|
{
|
||||||
|
int n = plines_win_full(wp, lnum, nextp, foldedp, true, false);
|
||||||
|
if (lnum == wp->w_topline) {
|
||||||
|
n = adjust_plines_for_skipcol(wp, n);
|
||||||
|
}
|
||||||
|
if (n > wp->w_height) {
|
||||||
|
return wp->w_height;
|
||||||
|
}
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
// Compute wp->w_botline for the current wp->w_topline. Can be called after
|
// Compute wp->w_botline for the current wp->w_topline. Can be called after
|
||||||
// wp->w_topline changed.
|
// wp->w_topline changed.
|
||||||
static void comp_botline(win_T *wp)
|
static void comp_botline(win_T *wp)
|
||||||
@@ -100,10 +115,7 @@ static void comp_botline(win_T *wp)
|
|||||||
for (; lnum <= wp->w_buffer->b_ml.ml_line_count; lnum++) {
|
for (; lnum <= wp->w_buffer->b_ml.ml_line_count; lnum++) {
|
||||||
linenr_T last = lnum;
|
linenr_T last = lnum;
|
||||||
bool folded;
|
bool folded;
|
||||||
int n = plines_win_full(wp, lnum, &last, &folded, true);
|
int n = plines_correct_topline(wp, lnum, &last, &folded);
|
||||||
if (lnum == wp->w_topline) {
|
|
||||||
n = adjust_plines_for_skipcol(wp, n);
|
|
||||||
}
|
|
||||||
if (lnum <= wp->w_cursor.lnum && last >= wp->w_cursor.lnum) {
|
if (lnum <= wp->w_cursor.lnum && last >= wp->w_cursor.lnum) {
|
||||||
wp->w_cline_row = done;
|
wp->w_cline_row = done;
|
||||||
wp->w_cline_height = n;
|
wp->w_cline_height = n;
|
||||||
@@ -606,10 +618,7 @@ static void curs_rows(win_T *wp)
|
|||||||
} else {
|
} else {
|
||||||
linenr_T last = lnum;
|
linenr_T last = lnum;
|
||||||
bool folded;
|
bool folded;
|
||||||
int n = plines_win_full(wp, lnum, &last, &folded, false);
|
int n = plines_correct_topline(wp, lnum, &last, &folded);
|
||||||
if (lnum == wp->w_topline) {
|
|
||||||
n = adjust_plines_for_skipcol(wp, n);
|
|
||||||
}
|
|
||||||
lnum = last + 1;
|
lnum = last + 1;
|
||||||
if (folded && lnum > wp->w_cursor.lnum) {
|
if (folded && lnum > wp->w_cursor.lnum) {
|
||||||
break;
|
break;
|
||||||
@@ -626,7 +635,7 @@ static void curs_rows(win_T *wp)
|
|||||||
&& (!wp->w_lines[i].wl_valid
|
&& (!wp->w_lines[i].wl_valid
|
||||||
|| wp->w_lines[i].wl_lnum != wp->w_cursor.lnum))) {
|
|| wp->w_lines[i].wl_lnum != wp->w_cursor.lnum))) {
|
||||||
wp->w_cline_height = plines_win_full(wp, wp->w_cursor.lnum, NULL,
|
wp->w_cline_height = plines_win_full(wp, wp->w_cursor.lnum, NULL,
|
||||||
&wp->w_cline_folded, true);
|
&wp->w_cline_folded, true, true);
|
||||||
} else if (i > wp->w_lines_valid) {
|
} else if (i > wp->w_lines_valid) {
|
||||||
// a line that is too long to fit on the last screen line
|
// a line that is too long to fit on the last screen line
|
||||||
wp->w_cline_height = 0;
|
wp->w_cline_height = 0;
|
||||||
@@ -673,7 +682,7 @@ void validate_cheight(void)
|
|||||||
|
|
||||||
curwin->w_cline_height = plines_win_full(curwin, curwin->w_cursor.lnum,
|
curwin->w_cline_height = plines_win_full(curwin, curwin->w_cursor.lnum,
|
||||||
NULL, &curwin->w_cline_folded,
|
NULL, &curwin->w_cline_folded,
|
||||||
true);
|
true, true);
|
||||||
curwin->w_valid |= VALID_CHEIGHT;
|
curwin->w_valid |= VALID_CHEIGHT;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1261,6 +1270,14 @@ bool scrolldown(long line_count, int byfold)
|
|||||||
return moved;
|
return moved;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Return TRUE if scrollup() will scroll by screen line rather than text line.
|
||||||
|
static int scrolling_screenlines(bool byfold)
|
||||||
|
{
|
||||||
|
return (curwin->w_p_wrap && curwin->w_p_sms)
|
||||||
|
|| (byfold && hasAnyFolding(curwin))
|
||||||
|
|| curwin->w_p_diff;
|
||||||
|
}
|
||||||
|
|
||||||
/// Scroll the current window up by "line_count" logical lines. "CTRL-E"
|
/// Scroll the current window up by "line_count" logical lines. "CTRL-E"
|
||||||
///
|
///
|
||||||
/// @param line_count number of lines to scroll
|
/// @param line_count number of lines to scroll
|
||||||
@@ -1271,7 +1288,7 @@ bool scrollup(long line_count, int byfold)
|
|||||||
linenr_T botline = curwin->w_botline;
|
linenr_T botline = curwin->w_botline;
|
||||||
int do_sms = curwin->w_p_wrap && curwin->w_p_sms;
|
int do_sms = curwin->w_p_wrap && curwin->w_p_sms;
|
||||||
|
|
||||||
if (do_sms || (byfold && hasAnyFolding(curwin)) || win_may_fill(curwin)) {
|
if (scrolling_screenlines(byfold) || win_may_fill(curwin)) {
|
||||||
int width1 = curwin->w_width - curwin_col_off();
|
int width1 = curwin->w_width - curwin_col_off();
|
||||||
int width2 = width1 + curwin_col_off2();
|
int width2 = width1 + curwin_col_off2();
|
||||||
unsigned size = 0;
|
unsigned size = 0;
|
||||||
@@ -1409,7 +1426,7 @@ void adjust_skipcol(void)
|
|||||||
long scrolloff_cols = so == 0 ? 0 : width1 + (so - 1) * width2;
|
long scrolloff_cols = so == 0 ? 0 : width1 + (so - 1) * width2;
|
||||||
bool scrolled = false;
|
bool scrolled = false;
|
||||||
|
|
||||||
validate_virtcol();
|
validate_cheight();
|
||||||
if (curwin->w_cline_height == curwin->w_height) {
|
if (curwin->w_cline_height == curwin->w_height) {
|
||||||
// the line just fits in the window, don't scroll
|
// the line just fits in the window, don't scroll
|
||||||
if (curwin->w_skipcol != 0) {
|
if (curwin->w_skipcol != 0) {
|
||||||
@@ -1419,6 +1436,7 @@ void adjust_skipcol(void)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
validate_virtcol();
|
||||||
while (curwin->w_skipcol > 0
|
while (curwin->w_skipcol > 0
|
||||||
&& curwin->w_virtcol < curwin->w_skipcol + 3 + scrolloff_cols) {
|
&& curwin->w_virtcol < curwin->w_skipcol + 3 + scrolloff_cols) {
|
||||||
// scroll a screen line down
|
// scroll a screen line down
|
||||||
@@ -1940,11 +1958,21 @@ void scroll_cursor_bot(int min_scroll, int set_topbot)
|
|||||||
if (line_count >= curwin->w_height_inner && line_count > min_scroll) {
|
if (line_count >= curwin->w_height_inner && line_count > min_scroll) {
|
||||||
scroll_cursor_halfway(false, true);
|
scroll_cursor_halfway(false, true);
|
||||||
} else {
|
} else {
|
||||||
// With 'smoothscroll' scroll at least the height of the cursor line.
|
// With 'smoothscroll' scroll at least the height of the cursor line,
|
||||||
if (curwin->w_p_wrap && curwin->w_p_sms && line_count < min_scrolled) {
|
// unless it would move the cursor.
|
||||||
|
if (curwin->w_p_wrap && curwin->w_p_sms && line_count < min_scrolled
|
||||||
|
&& (curwin->w_cursor.lnum < curwin->w_topline
|
||||||
|
|| (curwin->w_virtcol - curwin->w_skipcol >=
|
||||||
|
curwin->w_width - curwin_col_off()))) {
|
||||||
line_count = min_scrolled;
|
line_count = min_scrolled;
|
||||||
}
|
}
|
||||||
scrollup(line_count, true);
|
if (line_count > 0) {
|
||||||
|
if (scrolling_screenlines(true)) {
|
||||||
|
scrollup(scrolled, true); // TODO(vim):
|
||||||
|
} else {
|
||||||
|
scrollup(line_count, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// If topline didn't change we need to restore w_botline and w_empty_rows
|
// If topline didn't change we need to restore w_botline and w_empty_rows
|
||||||
|
@@ -189,10 +189,11 @@ int plines_win_col(win_T *wp, linenr_T lnum, long column)
|
|||||||
/// @param[out] nextp if not NULL, the line after a fold
|
/// @param[out] nextp if not NULL, the line after a fold
|
||||||
/// @param[out] foldedp if not NULL, whether lnum is on a fold
|
/// @param[out] foldedp if not NULL, whether lnum is on a fold
|
||||||
/// @param[in] cache whether to use the window's cache for folds
|
/// @param[in] cache whether to use the window's cache for folds
|
||||||
|
/// @param[in] winheight when true limit to window height
|
||||||
///
|
///
|
||||||
/// @return the total number of screen lines
|
/// @return the total number of screen lines
|
||||||
int plines_win_full(win_T *wp, linenr_T lnum, linenr_T *const nextp, bool *const foldedp,
|
int plines_win_full(win_T *wp, linenr_T lnum, linenr_T *const nextp, bool *const foldedp,
|
||||||
const bool cache)
|
const bool cache, const bool winheight)
|
||||||
{
|
{
|
||||||
bool folded = hasFoldingWin(wp, lnum, NULL, nextp, cache, NULL);
|
bool folded = hasFoldingWin(wp, lnum, NULL, nextp, cache, NULL);
|
||||||
if (foldedp) {
|
if (foldedp) {
|
||||||
@@ -201,9 +202,9 @@ int plines_win_full(win_T *wp, linenr_T lnum, linenr_T *const nextp, bool *const
|
|||||||
if (folded) {
|
if (folded) {
|
||||||
return 1;
|
return 1;
|
||||||
} else if (lnum == wp->w_topline) {
|
} else if (lnum == wp->w_topline) {
|
||||||
return plines_win_nofill(wp, lnum, true) + wp->w_topfill;
|
return plines_win_nofill(wp, lnum, winheight) + wp->w_topfill;
|
||||||
}
|
}
|
||||||
return plines_win(wp, lnum, true);
|
return plines_win(wp, lnum, winheight);
|
||||||
}
|
}
|
||||||
|
|
||||||
int plines_m_win(win_T *wp, linenr_T first, linenr_T last)
|
int plines_m_win(win_T *wp, linenr_T first, linenr_T last)
|
||||||
@@ -212,7 +213,7 @@ int plines_m_win(win_T *wp, linenr_T first, linenr_T last)
|
|||||||
|
|
||||||
while (first <= last) {
|
while (first <= last) {
|
||||||
linenr_T next = first;
|
linenr_T next = first;
|
||||||
count += plines_win_full(wp, first, &next, NULL, false);
|
count += plines_win_full(wp, first, &next, NULL, false, true);
|
||||||
first = next + 1;
|
first = next + 1;
|
||||||
}
|
}
|
||||||
return count;
|
return count;
|
||||||
|
@@ -482,7 +482,14 @@ describe('smoothscroll', function()
|
|||||||
]])
|
]])
|
||||||
-- 'scrolloff' set to 2, scrolling down, cursor moves screen line up
|
-- 'scrolloff' set to 2, scrolling down, cursor moves screen line up
|
||||||
feed('<C-E>gj<C-Y>')
|
feed('<C-E>gj<C-Y>')
|
||||||
screen:expect_unchanged()
|
screen:expect([[
|
||||||
|
<<<ots of text with lots of text with lo|
|
||||||
|
ts of text with lots of text with lots o|
|
||||||
|
f text wi^th lots of text with lots of te|
|
||||||
|
xt with lots of text with lots of text w|
|
||||||
|
ith lots of text with lots of text with |
|
||||||
|
|
|
||||||
|
]])
|
||||||
end)
|
end)
|
||||||
|
|
||||||
-- oldtest: Test_smoothscroll_one_long_line()
|
-- oldtest: Test_smoothscroll_one_long_line()
|
||||||
|
Reference in New Issue
Block a user