aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLuuk van Baal <luukvbaal@gmail.com>2023-04-27 03:36:31 +0200
committerLuuk van Baal <luukvbaal@gmail.com>2023-05-02 13:11:47 +0200
commit88d13d2778a4fab3fdcc2bf4c1adf631b38ea3ce (patch)
tree6a412cb67c8da4425d325a1ca704976f8d273b15
parent0588329c8569553e3232e72889a28496a30aa54b (diff)
downloadrneovim-88d13d2778a4fab3fdcc2bf4c1adf631b38ea3ce.tar.gz
rneovim-88d13d2778a4fab3fdcc2bf4c1adf631b38ea3ce.tar.bz2
rneovim-88d13d2778a4fab3fdcc2bf4c1adf631b38ea3ce.zip
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. https://github.com/vim/vim/commit/d5337efece7c68e9b4ce864532ea49b02453b674 Co-authored-by: Bram Moolenaar <Bram@vim.org>
-rw-r--r--src/nvim/move.c58
-rw-r--r--src/nvim/plines.c9
-rw-r--r--test/functional/legacy/scroll_opt_spec.lua9
3 files changed, 56 insertions, 20 deletions
diff --git a/src/nvim/move.c b/src/nvim/move.c
index c080cf6691..f245890e40 100644
--- a/src/nvim/move.c
+++ b/src/nvim/move.c
@@ -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
diff --git a/src/nvim/plines.c b/src/nvim/plines.c
index 3c8ee7d66d..3e69e547cb 100644
--- a/src/nvim/plines.c
+++ b/src/nvim/plines.c
@@ -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;
diff --git a/test/functional/legacy/scroll_opt_spec.lua b/test/functional/legacy/scroll_opt_spec.lua
index b5a571d8b5..42d8f31d3c 100644
--- a/test/functional/legacy/scroll_opt_spec.lua
+++ b/test/functional/legacy/scroll_opt_spec.lua
@@ -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()