aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/nvim/eval.c4
-rw-r--r--src/nvim/move.c12
-rw-r--r--src/nvim/ops.c1
-rw-r--r--test/functional/legacy/put_spec.lua25
-rw-r--r--test/old/testdir/test_put.vim18
5 files changed, 55 insertions, 5 deletions
diff --git a/src/nvim/eval.c b/src/nvim/eval.c
index 52924bf9a5..118c1d3012 100644
--- a/src/nvim/eval.c
+++ b/src/nvim/eval.c
@@ -6511,6 +6511,10 @@ pos_T *var2fpos(const typval_T *const tv, const bool dollar_lnum, int *const ret
pos.coladd = 0;
if (name[0] == 'w' && dollar_lnum) {
+ // the "w_valid" flags are not reset when moving the cursor, but they
+ // do matter for update_topline() and validate_botline().
+ check_cursor_moved(curwin);
+
pos.col = 0;
if (name[1] == '0') { // "w0": first visible line
update_topline(curwin);
diff --git a/src/nvim/move.c b/src/nvim/move.c
index 9e8abbcd96..48691db26d 100644
--- a/src/nvim/move.c
+++ b/src/nvim/move.c
@@ -548,18 +548,20 @@ void set_topline(win_T *wp, linenr_T lnum)
redraw_later(wp, UPD_VALID);
}
-// Call this function when the length of the cursor line (in screen
-// characters) has changed, and the change is before the cursor.
-// Need to take care of w_botline separately!
+/// Call this function when the length of the cursor line (in screen
+/// characters) has changed, and the change is before the cursor.
+/// If the line length changed the number of screen lines might change,
+/// requiring updating w_topline. That may also invalidate w_crow.
+/// Need to take care of w_botline separately!
void changed_cline_bef_curs(void)
{
- curwin->w_valid &= ~(VALID_WROW|VALID_WCOL|VALID_VIRTCOL
+ curwin->w_valid &= ~(VALID_WROW|VALID_WCOL|VALID_VIRTCOL|VALID_CROW
|VALID_CHEIGHT|VALID_TOPLINE);
}
void changed_cline_bef_curs_win(win_T *wp)
{
- wp->w_valid &= ~(VALID_WROW|VALID_WCOL|VALID_VIRTCOL
+ wp->w_valid &= ~(VALID_WROW|VALID_WCOL|VALID_VIRTCOL|VALID_CROW
|VALID_CHEIGHT|VALID_TOPLINE);
}
diff --git a/src/nvim/ops.c b/src/nvim/ops.c
index c39a3273da..2711c3d29c 100644
--- a/src/nvim/ops.c
+++ b/src/nvim/ops.c
@@ -3484,6 +3484,7 @@ void do_put(int regname, yankreg_T *reg, int dir, long count, int flags)
if (lnum == curwin->w_cursor.lnum) {
// make sure curwin->w_virtcol is updated
changed_cline_bef_curs();
+ invalidate_botline();
curwin->w_cursor.col += (colnr_T)(totlen - 1);
}
changed_bytes(lnum, col);
diff --git a/test/functional/legacy/put_spec.lua b/test/functional/legacy/put_spec.lua
index e83fde774a..4a42a1c8a3 100644
--- a/test/functional/legacy/put_spec.lua
+++ b/test/functional/legacy/put_spec.lua
@@ -70,4 +70,29 @@ describe('put', function()
|
]])
end)
+
+ -- oldtest: Test_put_in_last_displayed_line()
+ it('in last displayed line', function()
+ local screen = Screen.new(75, 10)
+ screen:attach()
+ source([[
+ autocmd CursorMoved * eval line('w$')
+ let @a = 'x'->repeat(&columns * 2 - 2)
+ eval range(&lines)->setline(1)
+ call feedkeys('G"ap')
+ ]])
+
+ screen:expect([[
+ 2 |
+ 3 |
+ 4 |
+ 5 |
+ 6 |
+ 7 |
+ 8 |
+ 9xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx|
+ xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx^x |
+ |
+ ]])
+ end)
end)
diff --git a/test/old/testdir/test_put.vim b/test/old/testdir/test_put.vim
index 212a979b4a..6c4bd28386 100644
--- a/test/old/testdir/test_put.vim
+++ b/test/old/testdir/test_put.vim
@@ -266,5 +266,23 @@ func Test_put_other_window()
call StopVimInTerminal(buf)
endfunc
+func Test_put_in_last_displayed_line()
+ CheckRunVimInTerminal
+
+ let lines =<< trim END
+ vim9script
+ autocmd CursorMoved * eval line('w$')
+ @a = 'x'->repeat(&columns * 2 - 2)
+ range(&lines)->setline(1)
+ feedkeys('G"ap')
+ END
+ call writefile(lines, 'Xtest_put_last_line', 'D')
+ let buf = RunVimInTerminal('-S Xtest_put_last_line', #{rows: 10})
+
+ call VerifyScreenDump(buf, 'Test_put_in_last_displayed_line_1', {})
+
+ call StopVimInTerminal(buf)
+endfunc
+
" vim: shiftwidth=2 sts=2 expandtab