mirror of
https://github.com/vim/vim.git
synced 2025-09-28 04:24:06 -04:00
patch 9.0.0445: when opening/closing window text moves up/down
Problem: When opening/closing window text moves up/down. Solution: Add the 'splitscroll' option. When off text will keep its position as much as possible.
This commit is contained in:
committed by
Bram Moolenaar
parent
9510d22463
commit
29ab524358
@@ -7499,6 +7499,18 @@ A jump table for the options with a short description can be found at |Q_op|.
|
|||||||
When on, splitting a window will put the new window right of the
|
When on, splitting a window will put the new window right of the
|
||||||
current one. |:vsplit|
|
current one. |:vsplit|
|
||||||
|
|
||||||
|
*'splitscroll'* *'spsc'* *'nosplitscroll'* *'nospsc'*
|
||||||
|
'splitscroll' 'spsc' boolean (default on)
|
||||||
|
global
|
||||||
|
The value of this option determines the scroll behavior when opening,
|
||||||
|
closing or resizing horizontal splits. When "on", splitting a window
|
||||||
|
horizontally will keep the same relative cursor position in the old and
|
||||||
|
new window, as well windows that are resized. When "off", scrolling
|
||||||
|
will be avoided to stabilize the window content. Instead, the cursor
|
||||||
|
position will be changed when necessary. In this case, the jumplist
|
||||||
|
will be populated with the previous cursor position. Scrolling cannot
|
||||||
|
be guaranteed to be avoided when 'wrap' is enabled.
|
||||||
|
|
||||||
*'startofline'* *'sol'* *'nostartofline'* *'nosol'*
|
*'startofline'* *'sol'* *'nostartofline'* *'nosol'*
|
||||||
'startofline' 'sol' boolean (default on)
|
'startofline' 'sol' boolean (default on)
|
||||||
global
|
global
|
||||||
|
@@ -919,6 +919,7 @@ Short explanation of each option: *option-list*
|
|||||||
'spellsuggest' 'sps' method(s) used to suggest spelling corrections
|
'spellsuggest' 'sps' method(s) used to suggest spelling corrections
|
||||||
'splitbelow' 'sb' new window from split is below the current one
|
'splitbelow' 'sb' new window from split is below the current one
|
||||||
'splitright' 'spr' new window is put right of the current one
|
'splitright' 'spr' new window is put right of the current one
|
||||||
|
'splitscroll' 'spsc' determines scroll behavior when splitting windows
|
||||||
'startofline' 'sol' commands move cursor to first non-blank in line
|
'startofline' 'sol' commands move cursor to first non-blank in line
|
||||||
'statusline' 'stl' custom format for the status line
|
'statusline' 'stl' custom format for the status line
|
||||||
'suffixes' 'su' suffixes that are ignored with multiple match
|
'suffixes' 'su' suffixes that are ignored with multiple match
|
||||||
|
@@ -515,6 +515,8 @@ call <SID>AddOption("splitbelow", gettext("a new window is put below the current
|
|||||||
call <SID>BinOptionG("sb", &sb)
|
call <SID>BinOptionG("sb", &sb)
|
||||||
call <SID>AddOption("splitright", gettext("a new window is put right of the current one"))
|
call <SID>AddOption("splitright", gettext("a new window is put right of the current one"))
|
||||||
call <SID>BinOptionG("spr", &spr)
|
call <SID>BinOptionG("spr", &spr)
|
||||||
|
call <SID>AddOption("splitscroll", gettext("determines scroll behavior when spliting windows"))
|
||||||
|
call <SID>BinOptionG("spsc", &spsc)
|
||||||
call <SID>AddOption("scrollbind", gettext("this window scrolls together with other bound windows"))
|
call <SID>AddOption("scrollbind", gettext("this window scrolls together with other bound windows"))
|
||||||
call append("$", "\t" .. s:local_to_window)
|
call append("$", "\t" .. s:local_to_window)
|
||||||
call <SID>BinOptionL("scb")
|
call <SID>BinOptionL("scb")
|
||||||
|
@@ -981,7 +981,8 @@ curs_columns(
|
|||||||
/*
|
/*
|
||||||
* First make sure that w_topline is valid (after moving the cursor).
|
* First make sure that w_topline is valid (after moving the cursor).
|
||||||
*/
|
*/
|
||||||
update_topline();
|
if (p_spsc)
|
||||||
|
update_topline();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Next make sure that w_cline_row is valid.
|
* Next make sure that w_cline_row is valid.
|
||||||
|
@@ -924,6 +924,7 @@ EXTERN char_u *p_spo; // 'spelloptions'
|
|||||||
EXTERN char_u *p_sps; // 'spellsuggest'
|
EXTERN char_u *p_sps; // 'spellsuggest'
|
||||||
#endif
|
#endif
|
||||||
EXTERN int p_spr; // 'splitright'
|
EXTERN int p_spr; // 'splitright'
|
||||||
|
EXTERN int p_spsc; // 'splitscroll'
|
||||||
EXTERN int p_sol; // 'startofline'
|
EXTERN int p_sol; // 'startofline'
|
||||||
EXTERN char_u *p_su; // 'suffixes'
|
EXTERN char_u *p_su; // 'suffixes'
|
||||||
EXTERN char_u *p_sws; // 'swapsync'
|
EXTERN char_u *p_sws; // 'swapsync'
|
||||||
|
@@ -2349,6 +2349,9 @@ static struct vimoption options[] =
|
|||||||
{"splitright", "spr", P_BOOL|P_VI_DEF,
|
{"splitright", "spr", P_BOOL|P_VI_DEF,
|
||||||
(char_u *)&p_spr, PV_NONE,
|
(char_u *)&p_spr, PV_NONE,
|
||||||
{(char_u *)FALSE, (char_u *)0L} SCTX_INIT},
|
{(char_u *)FALSE, (char_u *)0L} SCTX_INIT},
|
||||||
|
{"splitscroll", "spsc", P_BOOL,
|
||||||
|
(char_u *)&p_spsc, PV_NONE,
|
||||||
|
{(char_u *)TRUE, (char_u *)TRUE} SCTX_INIT},
|
||||||
{"startofline", "sol", P_BOOL|P_VI_DEF|P_VIM,
|
{"startofline", "sol", P_BOOL|P_VI_DEF|P_VIM,
|
||||||
(char_u *)&p_sol, PV_NONE,
|
(char_u *)&p_sol, PV_NONE,
|
||||||
{(char_u *)TRUE, (char_u *)0L} SCTX_INIT},
|
{(char_u *)TRUE, (char_u *)0L} SCTX_INIT},
|
||||||
|
@@ -3570,6 +3570,8 @@ struct window_S
|
|||||||
int w_winrow; // first row of window in screen
|
int w_winrow; // first row of window in screen
|
||||||
int w_height; // number of rows in window, excluding
|
int w_height; // number of rows in window, excluding
|
||||||
// status/command/winbar line(s)
|
// status/command/winbar line(s)
|
||||||
|
int w_prev_winrow; // previous winrow used for 'splitscroll'
|
||||||
|
int w_prev_height; // previous height used for 'splitscroll'
|
||||||
|
|
||||||
int w_status_height; // number of status lines (0 or 1)
|
int w_status_height; // number of status lines (0 or 1)
|
||||||
int w_wincol; // Leftmost column of window in screen.
|
int w_wincol; // Leftmost column of window in screen.
|
||||||
|
@@ -1631,5 +1631,133 @@ func Test_win_equal_last_status()
|
|||||||
set laststatus&
|
set laststatus&
|
||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
|
" Ensure no scrolling happens with 'nosplitscroll' with and without a
|
||||||
|
" winbar, tabline, for each possible value of 'laststatus', 'scrolloff',
|
||||||
|
" 'equalalways', and regardless of the cursor position.
|
||||||
|
func Test_splitscroll_with_splits()
|
||||||
|
set nowrap
|
||||||
|
set nosplitscroll
|
||||||
|
let gui = has("gui_running")
|
||||||
|
inoremap c <cmd>:copen<CR>
|
||||||
|
for winbar in [0, 1]
|
||||||
|
for sb in [0, 1]
|
||||||
|
for ea in [0, 1]
|
||||||
|
for tab in [0, 1]
|
||||||
|
for so in [0, 5]
|
||||||
|
for ls in range(0, 2)
|
||||||
|
for pos in ["H", "M", "L"]
|
||||||
|
let tabline = (gui ? 0 : (tab ? 1 : 0))
|
||||||
|
let winbar_sb = (sb ? winbar : 0)
|
||||||
|
execute 'set scrolloff=' . so
|
||||||
|
execute 'set laststatus=' . ls
|
||||||
|
execute 'set ' . (ea ? 'equalalways' : 'noequalalways')
|
||||||
|
execute 'set ' . (sb ? 'splitbelow' : 'nosplitbelow')
|
||||||
|
execute tab ? 'tabnew' : ''
|
||||||
|
execute winbar ? 'nnoremenu 1.10 WinBar.Test :echo' : ''
|
||||||
|
call setline(1, range(1, 256))
|
||||||
|
execute 'norm gg' . pos
|
||||||
|
" No scroll for vertical split and quit
|
||||||
|
vsplit | quit
|
||||||
|
call assert_equal(1, line("w0"))
|
||||||
|
|
||||||
|
" No scroll for horizontal split
|
||||||
|
split | redraw! | wincmd k
|
||||||
|
call assert_equal(1, line("w0"))
|
||||||
|
|
||||||
|
" No scroll when resizing windows
|
||||||
|
resize +2
|
||||||
|
call assert_equal(1, line("w0"))
|
||||||
|
wincmd j
|
||||||
|
call assert_equal(win_screenpos(0)[0] - tabline - winbar_sb, line("w0"))
|
||||||
|
|
||||||
|
" No scroll when dragging statusline
|
||||||
|
call win_move_statusline(1, -3)
|
||||||
|
call assert_equal(win_screenpos(0)[0] - tabline - winbar_sb, line("w0"))
|
||||||
|
wincmd k
|
||||||
|
call assert_equal(1, line("w0"))
|
||||||
|
|
||||||
|
" No scroll when changing shellsize
|
||||||
|
set lines+=2
|
||||||
|
call assert_equal(1, line("w0"))
|
||||||
|
wincmd j
|
||||||
|
call assert_equal(win_screenpos(0)[0] - tabline - winbar_sb, line("w0"))
|
||||||
|
set lines-=2
|
||||||
|
call assert_equal(win_screenpos(0)[0] - tabline - winbar_sb, line("w0"))
|
||||||
|
wincmd k
|
||||||
|
call assert_equal(1, line("w0"))
|
||||||
|
|
||||||
|
" No scroll when equalizing windows
|
||||||
|
wincmd =
|
||||||
|
call assert_equal(1, line("w0"))
|
||||||
|
wincmd j
|
||||||
|
call assert_equal(win_screenpos(0)[0] - tabline - winbar_sb, line("w0"))
|
||||||
|
wincmd k
|
||||||
|
call assert_equal(1, line("w0"))
|
||||||
|
|
||||||
|
" No scroll in windows split multiple times
|
||||||
|
vsplit | split | 4wincmd w
|
||||||
|
call assert_equal(win_screenpos(0)[0] - tabline - winbar_sb, line("w0"))
|
||||||
|
1wincmd w | quit | wincmd l | split
|
||||||
|
call assert_equal(win_screenpos(0)[0] - tabline - winbar_sb, line("w0"))
|
||||||
|
wincmd j
|
||||||
|
call assert_equal(win_screenpos(0)[0] - tabline - winbar_sb, line("w0"))
|
||||||
|
|
||||||
|
" No scroll in small window
|
||||||
|
2wincmd w | only | 5split | wincmd k
|
||||||
|
call assert_equal(1, line("w0"))
|
||||||
|
wincmd j
|
||||||
|
call assert_equal(win_screenpos(0)[0] - tabline - winbar_sb, line("w0"))
|
||||||
|
|
||||||
|
" No scroll for vertical split
|
||||||
|
quit | vsplit | wincmd l
|
||||||
|
call assert_equal(1, line("w0"))
|
||||||
|
wincmd h
|
||||||
|
call assert_equal(1, line("w0"))
|
||||||
|
|
||||||
|
" No scroll in windows split and quit multiple times
|
||||||
|
quit | split | split | quit
|
||||||
|
call assert_equal(win_screenpos(0)[0] - tabline - winbar_sb, line("w0"))
|
||||||
|
|
||||||
|
" No scroll for new buffer
|
||||||
|
1wincmd w | only | copen | wincmd k
|
||||||
|
call assert_equal(1, line("w0"))
|
||||||
|
only
|
||||||
|
call assert_equal(1, line("w0"))
|
||||||
|
above copen | wincmd j
|
||||||
|
call assert_equal(win_screenpos(0)[0] - tabline, line("w0"))
|
||||||
|
|
||||||
|
" No scroll when opening cmdwin
|
||||||
|
only | norm ggLq:
|
||||||
|
call assert_equal(1, line("w0"))
|
||||||
|
|
||||||
|
" Scroll when cursor becomes invalid in insert mode
|
||||||
|
norm Lic
|
||||||
|
wincmd k | only
|
||||||
|
call assert_notequal(1, line("w0"))
|
||||||
|
|
||||||
|
" No scroll when topline not equal to 1
|
||||||
|
execute "norm gg5\<C-e>" | split | wincmd k
|
||||||
|
call assert_equal(6, line("w0"))
|
||||||
|
wincmd j
|
||||||
|
call assert_equal(5 + win_screenpos(0)[0] - tabline - winbar_sb, line("w0"))
|
||||||
|
only
|
||||||
|
endfor
|
||||||
|
endfor
|
||||||
|
endfor
|
||||||
|
tabonly!
|
||||||
|
endfor
|
||||||
|
endfor
|
||||||
|
endfor
|
||||||
|
endfor
|
||||||
|
|
||||||
|
tabnew | tabonly! | %bwipeout!
|
||||||
|
iunmap c
|
||||||
|
set wrap&
|
||||||
|
set scrolloff&
|
||||||
|
set splitbelow&
|
||||||
|
set laststatus&
|
||||||
|
set equalalways&
|
||||||
|
set splitscroll&
|
||||||
|
endfunc
|
||||||
|
|
||||||
" vim: shiftwidth=2 sts=2 expandtab
|
" vim: shiftwidth=2 sts=2 expandtab
|
||||||
|
@@ -703,6 +703,8 @@ static char *(features[]) =
|
|||||||
|
|
||||||
static int included_patches[] =
|
static int included_patches[] =
|
||||||
{ /* Add new patch number below this line */
|
{ /* Add new patch number below this line */
|
||||||
|
/**/
|
||||||
|
445,
|
||||||
/**/
|
/**/
|
||||||
444,
|
444,
|
||||||
/**/
|
/**/
|
||||||
|
143
src/window.c
143
src/window.c
@@ -25,6 +25,8 @@ static frame_T *win_altframe(win_T *win, tabpage_T *tp);
|
|||||||
static tabpage_T *alt_tabpage(void);
|
static tabpage_T *alt_tabpage(void);
|
||||||
static win_T *frame2win(frame_T *frp);
|
static win_T *frame2win(frame_T *frp);
|
||||||
static int frame_has_win(frame_T *frp, win_T *wp);
|
static int frame_has_win(frame_T *frp, win_T *wp);
|
||||||
|
static void win_fix_scroll(int resize);
|
||||||
|
static void win_fix_cursor(int normal);
|
||||||
static void frame_new_height(frame_T *topfrp, int height, int topfirst, int wfh);
|
static void frame_new_height(frame_T *topfrp, int height, int topfirst, int wfh);
|
||||||
static int frame_fixed_height(frame_T *frp);
|
static int frame_fixed_height(frame_T *frp);
|
||||||
static int frame_fixed_width(frame_T *frp);
|
static int frame_fixed_width(frame_T *frp);
|
||||||
@@ -1323,6 +1325,8 @@ win_split_ins(
|
|||||||
win_equal(wp, TRUE,
|
win_equal(wp, TRUE,
|
||||||
(flags & WSP_VERT) ? (dir == 'v' ? 'b' : 'h')
|
(flags & WSP_VERT) ? (dir == 'v' ? 'b' : 'h')
|
||||||
: dir == 'h' ? 'b' : 'v');
|
: dir == 'h' ? 'b' : 'v');
|
||||||
|
else if (!p_spsc)
|
||||||
|
win_fix_scroll(FALSE);
|
||||||
|
|
||||||
// Don't change the window height/width to 'winheight' / 'winwidth' if a
|
// Don't change the window height/width to 'winheight' / 'winwidth' if a
|
||||||
// size was given.
|
// size was given.
|
||||||
@@ -1407,6 +1411,13 @@ win_init(win_T *newp, win_T *oldp, int flags UNUSED)
|
|||||||
newp->w_prevdir = (oldp->w_prevdir == NULL)
|
newp->w_prevdir = (oldp->w_prevdir == NULL)
|
||||||
? NULL : vim_strsave(oldp->w_prevdir);
|
? NULL : vim_strsave(oldp->w_prevdir);
|
||||||
|
|
||||||
|
if (!p_spsc)
|
||||||
|
{
|
||||||
|
newp->w_botline = oldp->w_botline;
|
||||||
|
newp->w_prev_height = oldp->w_height - WINBAR_HEIGHT(oldp);
|
||||||
|
newp->w_prev_winrow = oldp->w_winrow + 2 * WINBAR_HEIGHT(oldp);
|
||||||
|
}
|
||||||
|
|
||||||
// copy tagstack and folds
|
// copy tagstack and folds
|
||||||
for (i = 0; i < oldp->w_tagstacklen; i++)
|
for (i = 0; i < oldp->w_tagstacklen; i++)
|
||||||
{
|
{
|
||||||
@@ -1914,6 +1925,8 @@ win_equal(
|
|||||||
win_equal_rec(next_curwin == NULL ? curwin : next_curwin, current,
|
win_equal_rec(next_curwin == NULL ? curwin : next_curwin, current,
|
||||||
topframe, dir, 0, tabline_height(),
|
topframe, dir, 0, tabline_height(),
|
||||||
(int)Columns, topframe->fr_height);
|
(int)Columns, topframe->fr_height);
|
||||||
|
if (!p_spsc)
|
||||||
|
win_fix_scroll(TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -2725,7 +2738,11 @@ win_close(win_T *win, int free_buf)
|
|||||||
// only resize that frame. Otherwise resize all windows.
|
// only resize that frame. Otherwise resize all windows.
|
||||||
win_equal(curwin, curwin->w_frame->fr_parent == win_frame, dir);
|
win_equal(curwin, curwin->w_frame->fr_parent == win_frame, dir);
|
||||||
else
|
else
|
||||||
|
{
|
||||||
win_comp_pos();
|
win_comp_pos();
|
||||||
|
if (!p_spsc)
|
||||||
|
win_fix_scroll(FALSE);
|
||||||
|
}
|
||||||
if (close_curwin)
|
if (close_curwin)
|
||||||
{
|
{
|
||||||
// Pass WEE_ALLOW_PARSE_MESSAGES to decrement dont_parse_messages
|
// Pass WEE_ALLOW_PARSE_MESSAGES to decrement dont_parse_messages
|
||||||
@@ -4912,7 +4929,8 @@ win_enter_ext(win_T *wp, int flags)
|
|||||||
|
|
||||||
// Might need to scroll the old window before switching, e.g., when the
|
// Might need to scroll the old window before switching, e.g., when the
|
||||||
// cursor was moved.
|
// cursor was moved.
|
||||||
update_topline();
|
if (p_spsc)
|
||||||
|
update_topline();
|
||||||
|
|
||||||
// may have to copy the buffer options when 'cpo' contains 'S'
|
// may have to copy the buffer options when 'cpo' contains 'S'
|
||||||
if (wp->w_buffer != curbuf)
|
if (wp->w_buffer != curbuf)
|
||||||
@@ -4927,7 +4945,10 @@ win_enter_ext(win_T *wp, int flags)
|
|||||||
check_cursor();
|
check_cursor();
|
||||||
if (!virtual_active())
|
if (!virtual_active())
|
||||||
curwin->w_cursor.coladd = 0;
|
curwin->w_cursor.coladd = 0;
|
||||||
changed_line_abv_curs(); // assume cursor position needs updating
|
if (p_spsc) // assume cursor position needs updating.
|
||||||
|
changed_line_abv_curs();
|
||||||
|
else
|
||||||
|
win_fix_cursor(TRUE);
|
||||||
|
|
||||||
// Now it is OK to parse messages again, which may be needed in
|
// Now it is OK to parse messages again, which may be needed in
|
||||||
// autocommands.
|
// autocommands.
|
||||||
@@ -5458,6 +5479,9 @@ shell_new_rows(void)
|
|||||||
compute_cmdrow();
|
compute_cmdrow();
|
||||||
curtab->tp_ch_used = p_ch;
|
curtab->tp_ch_used = p_ch;
|
||||||
|
|
||||||
|
if (!p_spsc)
|
||||||
|
win_fix_scroll(TRUE);
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
// Disabled: don't want making the screen smaller make a window larger.
|
// Disabled: don't want making the screen smaller make a window larger.
|
||||||
if (p_ea)
|
if (p_ea)
|
||||||
@@ -5662,6 +5686,9 @@ win_setheight_win(int height, win_T *win)
|
|||||||
msg_row = row;
|
msg_row = row;
|
||||||
msg_col = 0;
|
msg_col = 0;
|
||||||
|
|
||||||
|
if (!p_spsc)
|
||||||
|
win_fix_scroll(TRUE);
|
||||||
|
|
||||||
redraw_all_later(UPD_NOT_VALID);
|
redraw_all_later(UPD_NOT_VALID);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -6190,6 +6217,9 @@ win_drag_status_line(win_T *dragwin, int offset)
|
|||||||
p_ch = MAX(Rows - cmdline_row, 1);
|
p_ch = MAX(Rows - cmdline_row, 1);
|
||||||
curtab->tp_ch_used = p_ch;
|
curtab->tp_ch_used = p_ch;
|
||||||
|
|
||||||
|
if (!p_spsc)
|
||||||
|
win_fix_scroll(TRUE);
|
||||||
|
|
||||||
redraw_all_later(UPD_SOME_VALID);
|
redraw_all_later(UPD_SOME_VALID);
|
||||||
showmode();
|
showmode();
|
||||||
}
|
}
|
||||||
@@ -6316,6 +6346,97 @@ set_fraction(win_T *wp)
|
|||||||
+ FRACTION_MULT / 2) / (long)wp->w_height;
|
+ FRACTION_MULT / 2) / (long)wp->w_height;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Handle scroll position for 'nosplitscroll'. Replaces scroll_to_fraction()
|
||||||
|
* call from win_new_height(). Instead we iterate over all windows in a
|
||||||
|
* tabpage and calculate the new scroll/cursor position.
|
||||||
|
* TODO: Ensure this also works with wrapped lines.
|
||||||
|
* Requires topline to be able to be set to a bufferline with some
|
||||||
|
* offset(row-wise scrolling/smoothscroll).
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
win_fix_scroll(int resize)
|
||||||
|
{
|
||||||
|
win_T *wp;
|
||||||
|
linenr_T lnum;
|
||||||
|
|
||||||
|
FOR_ALL_WINDOWS(wp)
|
||||||
|
{
|
||||||
|
// Skip when window height has not changed or when
|
||||||
|
// buffer has less lines than the window height.
|
||||||
|
if (wp->w_height != wp->w_prev_height
|
||||||
|
&& wp->w_height < wp->w_buffer->b_ml.ml_line_count)
|
||||||
|
{
|
||||||
|
// Determine botline needed to avoid scrolling and set cursor.
|
||||||
|
if (wp->w_winrow != wp->w_prev_winrow)
|
||||||
|
{
|
||||||
|
lnum = wp->w_cursor.lnum;
|
||||||
|
wp->w_cursor.lnum = MIN(wp->w_buffer->b_ml.ml_line_count,
|
||||||
|
wp->w_botline - 1 + (wp->w_prev_height
|
||||||
|
? (wp->w_winrow - wp->w_prev_winrow)
|
||||||
|
+ (wp->w_height - wp->w_prev_height)
|
||||||
|
: -WINBAR_HEIGHT(wp)));
|
||||||
|
// Bring the new cursor position to the bottom of the screen.
|
||||||
|
wp->w_fraction = FRACTION_MULT;
|
||||||
|
scroll_to_fraction(wp, wp->w_prev_height);
|
||||||
|
wp->w_cursor.lnum = lnum;
|
||||||
|
}
|
||||||
|
invalidate_botline_win(wp);
|
||||||
|
validate_botline_win(wp);
|
||||||
|
}
|
||||||
|
wp->w_prev_height = wp->w_height;
|
||||||
|
wp->w_prev_winrow = wp->w_winrow;
|
||||||
|
}
|
||||||
|
// Ensure cursor is valid when not in normal mode or when resized.
|
||||||
|
if (!(get_real_state() & (MODE_NORMAL|MODE_CMDLINE)))
|
||||||
|
win_fix_cursor(FALSE);
|
||||||
|
else if (resize)
|
||||||
|
win_fix_cursor(TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Make sure the cursor position is valid for 'nosplitscroll'.
|
||||||
|
* If it is not, put the cursor position in the jumplist and move it.
|
||||||
|
* If we are not in normal mode, scroll to make valid instead.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
win_fix_cursor(int normal)
|
||||||
|
{
|
||||||
|
int top = FALSE;
|
||||||
|
win_T *wp = curwin;
|
||||||
|
long so = get_scrolloff_value();
|
||||||
|
linenr_T nlnum = 0;
|
||||||
|
|
||||||
|
if (wp->w_buffer->b_ml.ml_line_count < wp->w_height)
|
||||||
|
return;
|
||||||
|
|
||||||
|
so = MIN(wp->w_height / 2, so);
|
||||||
|
// Check if cursor position is above topline or below botline.
|
||||||
|
if (wp->w_cursor.lnum < (wp->w_topline + so) && wp->w_topline != 1)
|
||||||
|
top = nlnum = MIN(wp->w_topline + so, wp->w_buffer->b_ml.ml_line_count);
|
||||||
|
else if (wp->w_cursor.lnum > (wp->w_botline - so - 1)
|
||||||
|
&& (wp->w_botline - wp->w_buffer->b_ml.ml_line_count) != 1)
|
||||||
|
nlnum = MAX(wp->w_botline - so - 1, 1);
|
||||||
|
// If cursor was invalid scroll or change cursor.
|
||||||
|
if (nlnum)
|
||||||
|
{
|
||||||
|
if (normal)
|
||||||
|
{ // Make sure cursor is closer to topline than botline.
|
||||||
|
if (so == wp->w_height / 2
|
||||||
|
&& nlnum - wp->w_topline > wp->w_botline - 1 - nlnum)
|
||||||
|
nlnum--;
|
||||||
|
setmark('\''); // save cursor position
|
||||||
|
wp->w_cursor.lnum = nlnum; // change to avoid scrolling
|
||||||
|
curs_columns(TRUE); // validate w_wrow
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{ // Ensure cursor stays visible if we are not in normal mode.
|
||||||
|
wp->w_fraction = top ? 0 : FRACTION_MULT;
|
||||||
|
scroll_to_fraction(wp, wp->w_prev_height);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Set the height of a window.
|
* Set the height of a window.
|
||||||
* "height" excludes any window toolbar.
|
* "height" excludes any window toolbar.
|
||||||
@@ -6336,7 +6457,7 @@ win_new_height(win_T *wp, int height)
|
|||||||
|
|
||||||
if (wp->w_height > 0)
|
if (wp->w_height > 0)
|
||||||
{
|
{
|
||||||
if (wp == curwin)
|
if (wp == curwin && p_spsc)
|
||||||
// w_wrow needs to be valid. When setting 'laststatus' this may
|
// w_wrow needs to be valid. When setting 'laststatus' this may
|
||||||
// call win_new_height() recursively.
|
// call win_new_height() recursively.
|
||||||
validate_cursor();
|
validate_cursor();
|
||||||
@@ -6352,7 +6473,7 @@ win_new_height(win_T *wp, int height)
|
|||||||
|
|
||||||
// There is no point in adjusting the scroll position when exiting. Some
|
// There is no point in adjusting the scroll position when exiting. Some
|
||||||
// values might be invalid.
|
// values might be invalid.
|
||||||
if (!exiting)
|
if (!exiting && p_spsc)
|
||||||
scroll_to_fraction(wp, prev_height);
|
scroll_to_fraction(wp, prev_height);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -6466,7 +6587,7 @@ scroll_to_fraction(win_T *wp, int prev_height)
|
|||||||
|
|
||||||
if (wp == curwin)
|
if (wp == curwin)
|
||||||
{
|
{
|
||||||
if (get_scrolloff_value())
|
if (p_spsc && get_scrolloff_value())
|
||||||
update_topline();
|
update_topline();
|
||||||
curs_columns(FALSE); // validate w_wrow
|
curs_columns(FALSE); // validate w_wrow
|
||||||
}
|
}
|
||||||
@@ -6488,11 +6609,15 @@ win_new_width(win_T *wp, int width)
|
|||||||
wp->w_width = width;
|
wp->w_width = width;
|
||||||
wp->w_lines_valid = 0;
|
wp->w_lines_valid = 0;
|
||||||
changed_line_abv_curs_win(wp);
|
changed_line_abv_curs_win(wp);
|
||||||
invalidate_botline_win(wp);
|
// Handled in win_fix_scroll()
|
||||||
if (wp == curwin)
|
if (p_spsc)
|
||||||
{
|
{
|
||||||
update_topline();
|
invalidate_botline_win(wp);
|
||||||
curs_columns(TRUE); // validate w_wrow
|
if (wp == curwin)
|
||||||
|
{
|
||||||
|
update_topline();
|
||||||
|
curs_columns(TRUE); // validate w_wrow
|
||||||
|
}
|
||||||
}
|
}
|
||||||
redraw_win_later(wp, UPD_NOT_VALID);
|
redraw_win_later(wp, UPD_NOT_VALID);
|
||||||
wp->w_redr_status = TRUE;
|
wp->w_redr_status = TRUE;
|
||||||
|
Reference in New Issue
Block a user