mirror of
https://github.com/neovim/neovim.git
synced 2025-09-06 03:18:16 +00:00
vim-patch:9.0.1772: Cursor may be adjusted in 'splitkeep'ed windows
Problem: Cursor is adjusted in window that did not change in size by
'splitkeep'.
Solution: Only check that cursor position is valid in a window that
has changed in size.
closes: vim/vim#12509
16af913eee
Co-authored-by: Luuk van Baal <luukvbaal@gmail.com>
This commit is contained in:
@@ -1193,6 +1193,7 @@ struct window_S {
|
|||||||
int w_hsep_height; // Number of horizontal separator rows (0 or 1)
|
int w_hsep_height; // Number of horizontal separator rows (0 or 1)
|
||||||
int w_vsep_width; // Number of vertical separator columns (0 or 1).
|
int w_vsep_width; // Number of vertical separator columns (0 or 1).
|
||||||
pos_save_T w_save_cursor; // backup of cursor pos and topline
|
pos_save_T w_save_cursor; // backup of cursor pos and topline
|
||||||
|
bool w_do_win_fix_cursor; // if true cursor may be invalid
|
||||||
|
|
||||||
int w_winrow_off; ///< offset from winrow to the inner window area
|
int w_winrow_off; ///< offset from winrow to the inner window area
|
||||||
int w_wincol_off; ///< offset from wincol to the inner window area
|
int w_wincol_off; ///< offset from wincol to the inner window area
|
||||||
|
@@ -6409,6 +6409,10 @@ void win_fix_scroll(int resize)
|
|||||||
FOR_ALL_WINDOWS_IN_TAB(wp, curtab) {
|
FOR_ALL_WINDOWS_IN_TAB(wp, curtab) {
|
||||||
// Skip when window height has not changed or when floating.
|
// Skip when window height has not changed or when floating.
|
||||||
if (!wp->w_floating && wp->w_height != wp->w_prev_height) {
|
if (!wp->w_floating && wp->w_height != wp->w_prev_height) {
|
||||||
|
// Cursor position in this window may now be invalid. It is kept
|
||||||
|
// potentially invalid until the window is made the current window.
|
||||||
|
wp->w_do_win_fix_cursor = true;
|
||||||
|
|
||||||
// If window has moved update botline to keep the same screenlines.
|
// If window has moved update botline to keep the same screenlines.
|
||||||
if (*p_spk == 's' && wp->w_winrow != wp->w_prev_winrow
|
if (*p_spk == 's' && wp->w_winrow != wp->w_prev_winrow
|
||||||
&& wp->w_botline - 1 <= wp->w_buffer->b_ml.ml_line_count) {
|
&& wp->w_botline - 1 <= wp->w_buffer->b_ml.ml_line_count) {
|
||||||
@@ -6432,6 +6436,7 @@ void win_fix_scroll(int resize)
|
|||||||
} else if (wp == curwin) {
|
} else if (wp == curwin) {
|
||||||
wp->w_valid &= ~VALID_CROW;
|
wp->w_valid &= ~VALID_CROW;
|
||||||
}
|
}
|
||||||
|
|
||||||
invalidate_botline_win(wp);
|
invalidate_botline_win(wp);
|
||||||
validate_botline(wp);
|
validate_botline(wp);
|
||||||
}
|
}
|
||||||
@@ -6449,16 +6454,19 @@ void win_fix_scroll(int resize)
|
|||||||
|
|
||||||
/// Make sure the cursor position is valid for 'splitkeep'.
|
/// Make sure the cursor position is valid for 'splitkeep'.
|
||||||
/// If it is not, put the cursor position in the jumplist and move it.
|
/// If it is not, put the cursor position in the jumplist and move it.
|
||||||
/// If we are not in normal mode ("normal" is zero), make it valid by scrolling
|
/// If we are not in normal mode ("normal" is false), make it valid by scrolling
|
||||||
/// instead.
|
/// instead.
|
||||||
static void win_fix_cursor(int normal)
|
static void win_fix_cursor(bool normal)
|
||||||
{
|
{
|
||||||
win_T *wp = curwin;
|
win_T *wp = curwin;
|
||||||
|
|
||||||
if (skip_win_fix_cursor || wp->w_buffer->b_ml.ml_line_count < wp->w_height) {
|
if (skip_win_fix_cursor
|
||||||
|
|| !wp->w_do_win_fix_cursor
|
||||||
|
|| wp->w_buffer->b_ml.ml_line_count < wp->w_height_inner) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
wp->w_do_win_fix_cursor = false;
|
||||||
// Determine valid cursor range.
|
// Determine valid cursor range.
|
||||||
long so = MIN(wp->w_height_inner / 2, get_scrolloff_value(wp));
|
long so = MIN(wp->w_height_inner / 2, get_scrolloff_value(wp));
|
||||||
linenr_T lnum = wp->w_cursor.lnum;
|
linenr_T lnum = wp->w_cursor.lnum;
|
||||||
@@ -6477,7 +6485,7 @@ static void win_fix_cursor(int normal)
|
|||||||
if (lnum > bot && (wp->w_botline - wp->w_buffer->b_ml.ml_line_count) != 1) {
|
if (lnum > bot && (wp->w_botline - wp->w_buffer->b_ml.ml_line_count) != 1) {
|
||||||
nlnum = bot;
|
nlnum = bot;
|
||||||
} else if (lnum < top && wp->w_topline != 1) {
|
} else if (lnum < top && wp->w_topline != 1) {
|
||||||
nlnum = (so == wp->w_height / 2) ? bot : top;
|
nlnum = (so == wp->w_height_inner / 2) ? bot : top;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nlnum != 0) { // Cursor is invalid for current scroll position.
|
if (nlnum != 0) { // Cursor is invalid for current scroll position.
|
||||||
|
@@ -43,6 +43,61 @@ describe('splitkeep', function()
|
|||||||
screen:attach()
|
screen:attach()
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
-- oldtest: Test_splitkeep_cursor()
|
||||||
|
it('does not adjust cursor in window that did not change size', function()
|
||||||
|
screen:try_resize(75, 8)
|
||||||
|
-- FIXME: bottom window is different without the "vsplit | close"
|
||||||
|
exec([[
|
||||||
|
vsplit | close
|
||||||
|
set scrolloff=5
|
||||||
|
set splitkeep=screen
|
||||||
|
autocmd CursorMoved * wincmd p | wincmd p
|
||||||
|
call setline(1, range(1, 200))
|
||||||
|
func CursorEqualize()
|
||||||
|
call cursor(100, 1)
|
||||||
|
wincmd =
|
||||||
|
endfunc
|
||||||
|
wincmd s
|
||||||
|
call CursorEqualize()
|
||||||
|
]])
|
||||||
|
|
||||||
|
screen:expect([[
|
||||||
|
99 |
|
||||||
|
^100 |
|
||||||
|
101 |
|
||||||
|
[No Name] [+] |
|
||||||
|
5 |
|
||||||
|
6 |
|
||||||
|
[No Name] [+] |
|
||||||
|
|
|
||||||
|
]])
|
||||||
|
|
||||||
|
feed('j')
|
||||||
|
screen:expect([[
|
||||||
|
100 |
|
||||||
|
^101 |
|
||||||
|
102 |
|
||||||
|
[No Name] [+] |
|
||||||
|
5 |
|
||||||
|
6 |
|
||||||
|
[No Name] [+] |
|
||||||
|
|
|
||||||
|
]])
|
||||||
|
|
||||||
|
command('set scrolloff=0')
|
||||||
|
feed('G')
|
||||||
|
screen:expect([[
|
||||||
|
198 |
|
||||||
|
199 |
|
||||||
|
^200 |
|
||||||
|
[No Name] [+] |
|
||||||
|
5 |
|
||||||
|
6 |
|
||||||
|
[No Name] [+] |
|
||||||
|
|
|
||||||
|
]])
|
||||||
|
end)
|
||||||
|
|
||||||
-- oldtest: Test_splitkeep_callback()
|
-- oldtest: Test_splitkeep_callback()
|
||||||
it('does not scroll when split in callback', function()
|
it('does not scroll when split in callback', function()
|
||||||
exec([[
|
exec([[
|
||||||
|
@@ -1807,7 +1807,34 @@ function Test_splitkeep_misc()
|
|||||||
set splitkeep&
|
set splitkeep&
|
||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
function Test_splitkeep_callback()
|
func Test_splitkeep_cursor()
|
||||||
|
CheckScreendump
|
||||||
|
let lines =<< trim END
|
||||||
|
set splitkeep=screen
|
||||||
|
autocmd CursorMoved * wincmd p | wincmd p
|
||||||
|
call setline(1, range(1, 200))
|
||||||
|
func CursorEqualize()
|
||||||
|
call cursor(100, 1)
|
||||||
|
wincmd =
|
||||||
|
endfunc
|
||||||
|
wincmd s
|
||||||
|
call CursorEqualize()
|
||||||
|
END
|
||||||
|
call writefile(lines, 'XTestSplitkeepCallback', 'D')
|
||||||
|
let buf = RunVimInTerminal('-S XTestSplitkeepCallback', #{rows: 8})
|
||||||
|
|
||||||
|
call VerifyScreenDump(buf, 'Test_splitkeep_cursor_1', {})
|
||||||
|
|
||||||
|
call term_sendkeys(buf, "j")
|
||||||
|
call VerifyScreenDump(buf, 'Test_splitkeep_cursor_2', {})
|
||||||
|
|
||||||
|
call term_sendkeys(buf, ":set scrolloff=0\<CR>G")
|
||||||
|
call VerifyScreenDump(buf, 'Test_splitkeep_cursor_3', {})
|
||||||
|
|
||||||
|
call StopVimInTerminal(buf)
|
||||||
|
endfunc
|
||||||
|
|
||||||
|
func Test_splitkeep_callback()
|
||||||
CheckScreendump
|
CheckScreendump
|
||||||
let lines =<< trim END
|
let lines =<< trim END
|
||||||
set splitkeep=screen
|
set splitkeep=screen
|
||||||
|
Reference in New Issue
Block a user