mirror of
https://github.com/neovim/neovim.git
synced 2025-10-05 17:36: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 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
|
||||
// wp->w_topline changed.
|
||||
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++) {
|
||||
linenr_T last = lnum;
|
||||
bool folded;
|
||||
int n = plines_win_full(wp, lnum, &last, &folded, true);
|
||||
if (lnum == wp->w_topline) {
|
||||
n = adjust_plines_for_skipcol(wp, n);
|
||||
}
|
||||
int n = plines_correct_topline(wp, lnum, &last, &folded);
|
||||
if (lnum <= wp->w_cursor.lnum && last >= wp->w_cursor.lnum) {
|
||||
wp->w_cline_row = done;
|
||||
wp->w_cline_height = n;
|
||||
@@ -606,10 +618,7 @@ static void curs_rows(win_T *wp)
|
||||
} else {
|
||||
linenr_T last = lnum;
|
||||
bool folded;
|
||||
int n = plines_win_full(wp, lnum, &last, &folded, false);
|
||||
if (lnum == wp->w_topline) {
|
||||
n = adjust_plines_for_skipcol(wp, n);
|
||||
}
|
||||
int n = plines_correct_topline(wp, lnum, &last, &folded);
|
||||
lnum = last + 1;
|
||||
if (folded && lnum > wp->w_cursor.lnum) {
|
||||
break;
|
||||
@@ -626,7 +635,7 @@ static void curs_rows(win_T *wp)
|
||||
&& (!wp->w_lines[i].wl_valid
|
||||
|| 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_folded, true);
|
||||
&wp->w_cline_folded, true, true);
|
||||
} else if (i > wp->w_lines_valid) {
|
||||
// a line that is too long to fit on the last screen line
|
||||
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,
|
||||
NULL, &curwin->w_cline_folded,
|
||||
true);
|
||||
true, true);
|
||||
curwin->w_valid |= VALID_CHEIGHT;
|
||||
}
|
||||
|
||||
@@ -1261,6 +1270,14 @@ bool scrolldown(long line_count, int byfold)
|
||||
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"
|
||||
///
|
||||
/// @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;
|
||||
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 width2 = width1 + curwin_col_off2();
|
||||
unsigned size = 0;
|
||||
@@ -1409,7 +1426,7 @@ void adjust_skipcol(void)
|
||||
long scrolloff_cols = so == 0 ? 0 : width1 + (so - 1) * width2;
|
||||
bool scrolled = false;
|
||||
|
||||
validate_virtcol();
|
||||
validate_cheight();
|
||||
if (curwin->w_cline_height == curwin->w_height) {
|
||||
// the line just fits in the window, don't scroll
|
||||
if (curwin->w_skipcol != 0) {
|
||||
@@ -1419,6 +1436,7 @@ void adjust_skipcol(void)
|
||||
return;
|
||||
}
|
||||
|
||||
validate_virtcol();
|
||||
while (curwin->w_skipcol > 0
|
||||
&& curwin->w_virtcol < curwin->w_skipcol + 3 + scrolloff_cols) {
|
||||
// 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) {
|
||||
scroll_cursor_halfway(false, true);
|
||||
} else {
|
||||
// With 'smoothscroll' scroll at least the height of the cursor line.
|
||||
if (curwin->w_p_wrap && curwin->w_p_sms && line_count < min_scrolled) {
|
||||
// With 'smoothscroll' scroll at least the height of the cursor line,
|
||||
// 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;
|
||||
}
|
||||
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
|
||||
|
@@ -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] foldedp if not NULL, whether lnum is on a fold
|
||||
/// @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
|
||||
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);
|
||||
if (foldedp) {
|
||||
@@ -201,9 +202,9 @@ int plines_win_full(win_T *wp, linenr_T lnum, linenr_T *const nextp, bool *const
|
||||
if (folded) {
|
||||
return 1;
|
||||
} 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)
|
||||
@@ -212,7 +213,7 @@ int plines_m_win(win_T *wp, linenr_T first, linenr_T last)
|
||||
|
||||
while (first <= last) {
|
||||
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;
|
||||
}
|
||||
return count;
|
||||
|
@@ -482,7 +482,14 @@ describe('smoothscroll', function()
|
||||
]])
|
||||
-- 'scrolloff' set to 2, scrolling down, cursor moves screen line up
|
||||
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)
|
||||
|
||||
-- oldtest: Test_smoothscroll_one_long_line()
|
||||
|
Reference in New Issue
Block a user