# HG changeset patch # User Bram Moolenaar # Date 1664807404 -7200 # Node ID f2f35161d75a121b9d5d70251d564cbacc8fea50 # Parent 22b9858176012695344e73c01d96c2ffcb3f7aca patch 9.0.0647: the 'splitscroll' option is not a good name Commit: https://github.com/vim/vim/commit/13ece2ae1d09009d3fb8acf858c288e7848ecdac Author: Luuk van Baal Date: Mon Oct 3 15:28:08 2022 +0100 patch 9.0.0647: the 'splitscroll' option is not a good name Problem: The 'splitscroll' option is not a good name. Solution: Rename 'splitscroll' to 'splitkeep' and make it a string option, also supporting "topline". (Luuk van Baal, closes #11258) diff --git a/runtime/doc/options.txt b/runtime/doc/options.txt --- a/runtime/doc/options.txt +++ b/runtime/doc/options.txt @@ -7518,24 +7518,28 @@ A jump table for the options with a shor When on, splitting a window will put the new window below the current one. |:split| + *'splitkeep'* *'spk' +'splitkeep' 'spk' string (default "cursor") + global + The value of this option determines the scroll behavior when opening, + closing or resizing horizontal splits. + + Possible values are: + cursor Keep the same relative cursor position. + screen Keep the text on the same screen line. + topline Keep the topline the same. + + For the "screen" and "topline" values, the cursor position will be + changed when necessary. In this case, the jumplist will be populated + with the previous cursor position. For "screen", the text cannot always + be kept on the same screen line when 'wrap' is enabled. + *'splitright'* *'spr'* *'nosplitright'* *'nospr'* 'splitright' 'spr' boolean (default off) global When on, splitting a window will put the new window right of the 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' boolean (default on) global diff --git a/runtime/doc/quickref.txt b/runtime/doc/quickref.txt --- a/runtime/doc/quickref.txt +++ b/runtime/doc/quickref.txt @@ -919,8 +919,8 @@ Short explanation of each option: *opti 'spelloptions' 'spo' options for spell checking 'spellsuggest' 'sps' method(s) used to suggest spelling corrections 'splitbelow' 'sb' new window from split is below the current one +'splitkeep' 'spk' determines scroll behavior for split windows 'splitright' 'spr' new window is put right of the current one -'splitscroll' 'spsc' determines scroll behavior for split windows 'startofline' 'sol' commands move cursor to first non-blank in line 'statusline' 'stl' custom format for the status line 'suffixes' 'su' suffixes that are ignored with multiple match diff --git a/runtime/optwin.vim b/runtime/optwin.vim --- a/runtime/optwin.vim +++ b/runtime/optwin.vim @@ -516,10 +516,10 @@ call AddOption("switchbuf", gettext call OptionG("swb", &swb) call AddOption("splitbelow", gettext("a new window is put below the current one")) call BinOptionG("sb", &sb) +call AddOption("splitkeep", gettext("determines scroll behavior for split windows")) +call BinOptionG("spk", &spk) call AddOption("splitright", gettext("a new window is put right of the current one")) call BinOptionG("spr", &spr) -call AddOption("splitscroll", gettext("determines scroll behavior for split windows")) -call BinOptionG("spsc", &spsc) call AddOption("scrollbind", gettext("this window scrolls together with other bound windows")) call append("$", "\t" .. s:local_to_window) call BinOptionL("scb") diff --git a/src/globals.h b/src/globals.h --- a/src/globals.h +++ b/src/globals.h @@ -1975,10 +1975,10 @@ EXTERN int channel_need_redraw INIT(= FA EXTERN optmagic_T magic_overruled INIT(= OPTION_MAGIC_NOT_SET); #ifdef FEAT_CMDWIN -// Skip win_fix_cursor() call for 'nosplitscroll' when cmdwin is closed. +// Skip win_fix_cursor() call for 'splitkeep' when cmdwin is closed. EXTERN int skip_win_fix_cursor INIT(= FALSE); #endif -// Skip win_fix_scroll() call for 'nosplitscroll' when closing tab page. +// Skip win_fix_scroll() call for 'splitkeep' when closing tab page. EXTERN int skip_win_fix_scroll INIT(= FALSE); // Skip update_topline() call while executing win_fix_scroll(). EXTERN int skip_update_topline INIT(= FALSE); diff --git a/src/move.c b/src/move.c --- a/src/move.c +++ b/src/move.c @@ -219,6 +219,10 @@ update_topline(void) long *so_ptr = curwin->w_p_so >= 0 ? &curwin->w_p_so : &p_so; int save_so = *so_ptr; + // Cursor is updated instead when this is TRUE for 'splitkeep'. + if (skip_update_topline) + return; + // If there is no valid screen and when the window height is zero just use // the cursor line. if (!screen_valid(TRUE) || curwin->w_height == 0) @@ -1027,8 +1031,7 @@ curs_columns( /* * First make sure that w_topline is valid (after moving the cursor). */ - if (!skip_update_topline) - update_topline(); + update_topline(); /* * Next make sure that w_cline_row is valid. diff --git a/src/option.h b/src/option.h --- a/src/option.h +++ b/src/option.h @@ -924,11 +924,11 @@ EXTERN char_u *p_spo; // 'spelloptions' EXTERN char_u *p_sps; // 'spellsuggest' #endif EXTERN int p_spr; // 'splitright' -EXTERN int p_spsc; // 'splitscroll' EXTERN int p_sol; // 'startofline' EXTERN char_u *p_su; // 'suffixes' EXTERN char_u *p_sws; // 'swapsync' EXTERN char_u *p_swb; // 'switchbuf' +EXTERN char_u *p_spk; // 'splitkeep' EXTERN unsigned swb_flags; // Keep in sync with p_swb_values in optionstr.c #define SWB_USEOPEN 0x001 diff --git a/src/optiondefs.h b/src/optiondefs.h --- a/src/optiondefs.h +++ b/src/optiondefs.h @@ -2350,12 +2350,12 @@ static struct vimoption options[] = {"splitbelow", "sb", P_BOOL|P_VI_DEF, (char_u *)&p_sb, PV_NONE, {(char_u *)FALSE, (char_u *)0L} SCTX_INIT}, + {"splitkeep", "spk", P_STRING, + (char_u *)&p_spk, PV_NONE, + {(char_u *)"cursor", (char_u *)"cursor"} SCTX_INIT}, {"splitright", "spr", P_BOOL|P_VI_DEF, (char_u *)&p_spr, PV_NONE, {(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, (char_u *)&p_sol, PV_NONE, {(char_u *)TRUE, (char_u *)0L} SCTX_INIT}, diff --git a/src/optionstr.c b/src/optionstr.c --- a/src/optionstr.c +++ b/src/optionstr.c @@ -46,6 +46,7 @@ static char *(p_ssop_values[]) = {"buffe #endif // Keep in sync with SWB_ flags in option.h static char *(p_swb_values[]) = {"useopen", "usetab", "split", "newtab", "vsplit", "uselast", NULL}; +static char *(p_spk_values[]) = {"cursor", "screen", "topline", NULL}; static char *(p_tc_values[]) = {"followic", "ignore", "match", "followscs", "smart", NULL}; #if defined(FEAT_TOOLBAR) && !defined(FEAT_GUI_MSWIN) static char *(p_toolbar_values[]) = {"text", "icons", "tooltips", "horiz", NULL}; @@ -1683,6 +1684,13 @@ did_set_string_option( errmsg = e_invalid_argument; } + // 'splitkeep' + else if (varp == &p_spk) + { + if (check_opt_strings(p_spk, p_spk_values, FALSE) != OK) + errmsg = e_invalid_argument; + } + // 'debug' else if (varp == &p_debug) { @@ -1722,7 +1730,7 @@ did_set_string_option( int is_spellfile = varp == &(curwin->w_s->b_p_spf); if ((is_spellfile && !valid_spellfile(*varp)) - || (!is_spellfile && !valid_spelllang(*varp))) + || (!is_spellfile && !valid_spelllang(*varp))) errmsg = e_invalid_argument; else errmsg = did_set_spell_option(is_spellfile); diff --git a/src/structs.h b/src/structs.h --- a/src/structs.h +++ b/src/structs.h @@ -3621,8 +3621,8 @@ struct window_S int w_winrow; // first row of window in screen int w_height; // number of rows in window, excluding // 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_prev_winrow; // previous winrow used for 'splitkeep' + int w_prev_height; // previous height used for 'splitkeep' int w_status_height; // number of status lines (0 or 1) int w_wincol; // Leftmost column of window in screen. diff --git a/src/testdir/dumps/Test_nosplitscroll_callback_1.dump b/src/testdir/dumps/Test_splitkeep_callback_1.dump rename from src/testdir/dumps/Test_nosplitscroll_callback_1.dump rename to src/testdir/dumps/Test_splitkeep_callback_1.dump diff --git a/src/testdir/dumps/Test_nosplitscroll_callback_2.dump b/src/testdir/dumps/Test_splitkeep_callback_2.dump rename from src/testdir/dumps/Test_nosplitscroll_callback_2.dump rename to src/testdir/dumps/Test_splitkeep_callback_2.dump diff --git a/src/testdir/dumps/Test_nosplitscroll_callback_3.dump b/src/testdir/dumps/Test_splitkeep_callback_3.dump rename from src/testdir/dumps/Test_nosplitscroll_callback_3.dump rename to src/testdir/dumps/Test_splitkeep_callback_3.dump diff --git a/src/testdir/dumps/Test_nosplitscroll_callback_4.dump b/src/testdir/dumps/Test_splitkeep_callback_4.dump rename from src/testdir/dumps/Test_nosplitscroll_callback_4.dump rename to src/testdir/dumps/Test_splitkeep_callback_4.dump diff --git a/src/testdir/dumps/Test_nosplitscroll_fold_1.dump b/src/testdir/dumps/Test_splitkeep_fold_1.dump rename from src/testdir/dumps/Test_nosplitscroll_fold_1.dump rename to src/testdir/dumps/Test_splitkeep_fold_1.dump diff --git a/src/testdir/dumps/Test_nosplitscroll_fold_2.dump b/src/testdir/dumps/Test_splitkeep_fold_2.dump rename from src/testdir/dumps/Test_nosplitscroll_fold_2.dump rename to src/testdir/dumps/Test_splitkeep_fold_2.dump diff --git a/src/testdir/dumps/Test_nosplitscroll_fold_3.dump b/src/testdir/dumps/Test_splitkeep_fold_3.dump rename from src/testdir/dumps/Test_nosplitscroll_fold_3.dump rename to src/testdir/dumps/Test_splitkeep_fold_3.dump diff --git a/src/testdir/dumps/Test_nosplitscroll_fold_4.dump b/src/testdir/dumps/Test_splitkeep_fold_4.dump rename from src/testdir/dumps/Test_nosplitscroll_fold_4.dump rename to src/testdir/dumps/Test_splitkeep_fold_4.dump diff --git a/src/testdir/gen_opt_test.vim b/src/testdir/gen_opt_test.vim --- a/src/testdir/gen_opt_test.vim +++ b/src/testdir/gen_opt_test.vim @@ -134,6 +134,7 @@ let test_values = { \ 'spelllang': [['', 'xxx', 'sr@latin'], ['not&lang', "that\\\rthere"]], \ 'spelloptions': [['', 'camel'], ['xxx']], \ 'spellsuggest': [['', 'best', 'double,33'], ['xxx']], + \ 'splitkeep': [['cursor', 'screen', 'topline'], ['xxx']], \ 'switchbuf': [['', 'useopen', 'split,newtab'], ['xxx']], \ 'tagcase': [['smart', 'match'], ['', 'xxx', 'smart,match']], \ 'term': [[], []], diff --git a/src/testdir/test_window_cmd.vim b/src/testdir/test_window_cmd.vim --- a/src/testdir/test_window_cmd.vim +++ b/src/testdir/test_window_cmd.vim @@ -1632,31 +1632,29 @@ func Test_win_equal_last_status() set laststatus& endfunc -" Ensure no scrolling happens with 'nosplitscroll' for a sequence of +" Test "screen" and "cursor" values for 'splitkeep' with a sequence of " split operations for various options: with and without a winbar, " tabline, for each possible value of 'laststatus', 'scrolloff', -" 'equalalways', and regardless of the cursor position. -func Test_nosplitscroll_options() - set nowrap - set nosplitscroll - +" 'equalalways', and with the cursor at the top, middle and bottom. +func Test_splitkeep_options() " disallow window resizing let save_WS = &t_WS set t_WS= let gui = has("gui_running") inoremap c "copenwincmd k" - for run in range(0, 10) - tabnew | tabonly! | redraw - let tabline = (gui ? 0 : ((run % 5) ? 1 : 0)) - let winbar_sb = (run % 2) && (run % 3) - execute 'set scrolloff=' . (!(run % 4) ? 0 : run) - execute 'set laststatus=' . (run % 3) - execute 'set ' . ((run % 2) ? 'equalalways' : 'noequalalways') - execute 'set ' . ((run % 3) ? 'splitbelow' : 'nosplitbelow') + for run in range(0, 20) + let &splitkeep = run > 10 ? 'topline' : 'screen' + let &scrolloff = (!(run % 4) ? 0 : run) + let &laststatus = (run % 3) + let &splitbelow = (run % 3) + let &equalalways = (run % 2) + let wsb = (run % 2) && &splitbelow + let tl = (gui ? 0 : ((run % 5) ? 1 : 0)) + let pos = !(run % 3) ? 'H' : ((run % 2) ? 'M' : 'L') + tabnew | tabonly! | redraw execute (run % 5) ? 'tabnew' : '' execute (run % 2) ? 'nnoremenu 1.10 WinBar.Test :echo' : '' - let pos = !(run % 3) ? 'H' : ((run % 2) ? 'M' : 'L') call setline(1, range(1, 256)) " No scroll for restore_snapshot norm G @@ -1672,17 +1670,17 @@ func Test_nosplitscroll_options() call assert_equal(1, line("w0")) call assert_equal(&scroll, winheight(0) / 2) wincmd j - call assert_equal(win_screenpos(0)[0] - tabline - winbar_sb, line("w0")) + call assert_equal(&spk == 'topline' ? 1 : win_screenpos(0)[0] - tl - wsb, line("w0")) " No scroll when resizing windows - wincmd k | resize +2 + wincmd k | resize +2 | redraw call assert_equal(1, line("w0")) wincmd j - call assert_equal(win_screenpos(0)[0] - tabline - winbar_sb, line("w0")) + call assert_equal(&spk == 'topline' ? 1 : win_screenpos(0)[0] - tl - wsb, 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")) + call assert_equal(&spk == 'topline' ? 1 : win_screenpos(0)[0] - tl - wsb, line("w0")) wincmd k call assert_equal(1, line("w0")) @@ -1690,9 +1688,9 @@ func Test_nosplitscroll_options() set lines+=2 call assert_equal(1, line("w0")) wincmd j - call assert_equal(win_screenpos(0)[0] - tabline - winbar_sb, line("w0")) + call assert_equal(&spk == 'topline' ? 1 : win_screenpos(0)[0] - tl - wsb, line("w0")) set lines-=2 - call assert_equal(win_screenpos(0)[0] - tabline - winbar_sb, line("w0")) + call assert_equal(&spk == 'topline' ? 1 : win_screenpos(0)[0] - tl - wsb, line("w0")) wincmd k call assert_equal(1, line("w0")) @@ -1700,23 +1698,23 @@ func Test_nosplitscroll_options() wincmd = call assert_equal(1, line("w0")) wincmd j - call assert_equal(win_screenpos(0)[0] - tabline - winbar_sb, line("w0")) + call assert_equal(&spk == 'topline' ? 1 : win_screenpos(0)[0] - tl - wsb, 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")) + call assert_equal(&spk == 'topline' ? 1 : win_screenpos(0)[0] - tl - wsb, line("w0")) 1wincmd w | quit | wincmd l | split - call assert_equal(win_screenpos(0)[0] - tabline - winbar_sb, line("w0")) + call assert_equal(&spk == 'topline' ? 1 : win_screenpos(0)[0] - tl - wsb, line("w0")) wincmd j - call assert_equal(win_screenpos(0)[0] - tabline - winbar_sb, line("w0")) + call assert_equal(&spk == 'topline' ? 1 : win_screenpos(0)[0] - tl - wsb, 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")) + call assert_equal(&spk == 'topline' ? 1 : win_screenpos(0)[0] - tl - wsb, line("w0")) " No scroll for vertical split quit | vsplit | wincmd l @@ -1725,8 +1723,8 @@ func Test_nosplitscroll_options() call assert_equal(1, line("w0")) " No scroll in windows split and quit multiple times - quit | redraw | split | redraw | split | redraw | quit | redraw - call assert_equal(win_screenpos(0)[0] - tabline - winbar_sb, line("w0")) + quit | redraw | split | split | quit | redraw + call assert_equal(&spk == 'topline' ? 1 : win_screenpos(0)[0] - tl - wsb, line("w0")) " No scroll for new buffer 1wincmd w | only | copen | wincmd k @@ -1734,7 +1732,7 @@ func Test_nosplitscroll_options() only call assert_equal(1, line("w0")) above copen | wincmd j - call assert_equal(win_screenpos(0)[0] - tabline, line("w0")) + call assert_equal(&spk == 'topline' ? 1 : win_screenpos(0)[0] - tl, line("w0")) " No scroll when opening cmdwin, and no cursor move when closing cmdwin. only | norm ggL @@ -1751,22 +1749,21 @@ func Test_nosplitscroll_options() only | execute "norm gg5\" | split | wincmd k call assert_equal(6, line("w0")) wincmd j - call assert_equal(5 + win_screenpos(0)[0] - tabline - winbar_sb, line("w0")) + call assert_equal(&spk == 'topline' ? 6 : 5 + win_screenpos(0)[0] - tl - wsb, line("w0")) endfor tabnew | tabonly! | %bwipeout! iunmap c - set wrap& set scrolloff& set splitbelow& set laststatus& set equalalways& - set splitscroll& + set splitkeep& let &t_WS = save_WS endfunc -function Test_nosplitscroll_cmdwin_cursor_position() - set nosplitscroll +function Test_splitkeep_cmdwin_cursor_position() + set splitkeep=screen call setline(1, range(&lines)) " No scroll when cursor is at near bottom of window and cusor position @@ -1789,11 +1786,11 @@ function Test_nosplitscroll_cmdwin_curso call assert_equal(1, col('.')) %bwipeout! - set splitscroll& + set splitkeep& endfunction -function Test_nosplitscroll_misc() - set nosplitscroll +function Test_splitkeep_misc() + set splitkeep=screen set splitbelow call setline(1, range(1, &lines)) @@ -1815,67 +1812,68 @@ function Test_nosplitscroll_misc() %bwipeout! set splitbelow& - set splitscroll& + set splitkeep& endfunc -function Test_nosplitscroll_callback() +function Test_splitkeep_callback() CheckScreendump let lines =<< trim END - set nosplitscroll + set splitkeep=screen call setline(1, range(&lines)) - function WincmdCb(a, b) + function C1(a, b) split | wincmd p endfunction - function TermCb(a, b) + function C2(a, b) close | split endfunction - nnoremap t call popup_create(term_start(&shell, { 'hidden': 1, 'exit_cb': 'TermCb' }), {}) - nnoremap j call job_start([&shell, &shellcmdflag, "echo"], { 'exit_cb': 'WincmdCb' }) + nn j call job_start([&sh, &shcf, "true"], { 'exit_cb': 'C1' }) + nn t call popup_create(term_start([&sh, &shcf, "true"], + \ { 'hidden': 1, 'exit_cb': 'C2' }), {}) END - call writefile(lines, 'XTestNosplitscrollCallback', 'D') - let buf = RunVimInTerminal('-S XTestNosplitscrollCallback', #{rows: 8}) + call writefile(lines, 'XTestSplitkeepCallback', 'D') + let buf = RunVimInTerminal('-S XTestSplitkeepCallback', #{rows: 8}) call term_sendkeys(buf, "j") - call VerifyScreenDump(buf, 'Test_nosplitscroll_callback_1', {}) + call VerifyScreenDump(buf, 'Test_splitkeep_callback_1', {}) - call term_sendkeys(buf, ":quit\Htexit\") - call VerifyScreenDump(buf, 'Test_nosplitscroll_callback_2', {}) + call term_sendkeys(buf, ":quit\Ht") + call VerifyScreenDump(buf, 'Test_splitkeep_callback_2', {}) call term_sendkeys(buf, ":set sb\:quit\Gj") - call VerifyScreenDump(buf, 'Test_nosplitscroll_callback_3', {}) + call VerifyScreenDump(buf, 'Test_splitkeep_callback_3', {}) - call term_sendkeys(buf, ":quit\Gtexit\") - call VerifyScreenDump(buf, 'Test_nosplitscroll_callback_4', {}) + call term_sendkeys(buf, ":quit\Gt") + call VerifyScreenDump(buf, 'Test_splitkeep_callback_4', {}) endfunc -function Test_nosplitscroll_fold() -CheckScreendump +function Test_splitkeep_fold() + CheckScreendump -let lines =<< trim END - set nosplitscroll - set foldmethod=marker - set number - let line = 1 - for n in range(1, &lines) - call setline(line, ['int FuncName() {/*{{{*/', 1, 2, 3, 4, 5, '}/*}}}*/', - \ 'after fold']) - let line += 8 - endfor -END - call writefile(lines, 'XTestNosplitscrollFold', 'D') - let buf = RunVimInTerminal('-S XTestNosplitscrollFold', #{rows: 10}) + let lines =<< trim END + set splitkeep=screen + set foldmethod=marker + set number + let line = 1 + for n in range(1, &lines) + call setline(line, ['int FuncName() {/*{{{*/', 1, 2, 3, 4, 5, '}/*}}}*/', + \ 'after fold']) + let line += 8 + endfor + END + call writefile(lines, 'XTestSplitkeepFold', 'D') + let buf = RunVimInTerminal('-S XTestSplitkeepFold', #{rows: 10}) call term_sendkeys(buf, "L:wincmd s\") - call VerifyScreenDump(buf, 'Test_nosplitscroll_fold_1', {}) + call VerifyScreenDump(buf, 'Test_splitkeep_fold_1', {}) call term_sendkeys(buf, ":quit\") - call VerifyScreenDump(buf, 'Test_nosplitscroll_fold_2', {}) + call VerifyScreenDump(buf, 'Test_splitkeep_fold_2', {}) call term_sendkeys(buf, "H:below split\") - call VerifyScreenDump(buf, 'Test_nosplitscroll_fold_3', {}) + call VerifyScreenDump(buf, 'Test_splitkeep_fold_3', {}) call term_sendkeys(buf, ":wincmd k\:quit\") - call VerifyScreenDump(buf, 'Test_nosplitscroll_fold_4', {}) + call VerifyScreenDump(buf, 'Test_splitkeep_fold_4', {}) endfunction " vim: shiftwidth=2 sts=2 expandtab diff --git a/src/version.c b/src/version.c --- a/src/version.c +++ b/src/version.c @@ -700,6 +700,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 647, +/**/ 646, /**/ 645, diff --git a/src/window.c b/src/window.c --- a/src/window.c +++ b/src/window.c @@ -1325,7 +1325,7 @@ win_split_ins( win_equal(wp, TRUE, (flags & WSP_VERT) ? (dir == 'v' ? 'b' : 'h') : dir == 'h' ? 'b' : 'v'); - else if (!p_spsc && wp != aucmd_win) + else if (*p_spk != 'c' && wp != aucmd_win) win_fix_scroll(FALSE); // Don't change the window height/width to 'winheight' / 'winwidth' if a @@ -1411,7 +1411,7 @@ win_init(win_T *newp, win_T *oldp, int f newp->w_prevdir = (oldp->w_prevdir == NULL) ? NULL : vim_strsave(oldp->w_prevdir); - if (!p_spsc) + if (*p_spk != 'c') { newp->w_botline = oldp->w_botline; newp->w_prev_height = oldp->w_height - WINBAR_HEIGHT(oldp); @@ -1925,7 +1925,7 @@ win_equal( win_equal_rec(next_curwin == NULL ? curwin : next_curwin, current, topframe, dir, 0, tabline_height(), (int)Columns, topframe->fr_height); - if (!p_spsc && next_curwin != aucmd_win) + if (*p_spk != 'c' && next_curwin != aucmd_win) win_fix_scroll(TRUE); } @@ -2733,7 +2733,7 @@ win_close(win_T *win, int free_buf) else { win_comp_pos(); - if (!p_spsc) + if (*p_spk != 'c') win_fix_scroll(FALSE); } if (close_curwin) @@ -4931,7 +4931,7 @@ win_enter_ext(win_T *wp, int flags) // Might need to scroll the old window before switching, e.g., when the // cursor was moved. - if (p_spsc) + if (*p_spk == 'c') update_topline(); // may have to copy the buffer options when 'cpo' contains 'S' @@ -4947,7 +4947,7 @@ win_enter_ext(win_T *wp, int flags) check_cursor(); if (!virtual_active()) curwin->w_cursor.coladd = 0; - if (p_spsc) // assume cursor position needs updating. + if (*p_spk == 'c') // assume cursor position needs updating changed_line_abv_curs(); else win_fix_cursor(TRUE); @@ -5068,7 +5068,7 @@ static int last_win_id = LOWEST_WIN_ID - * FALSE. */ static win_T * -win_alloc(win_T *after UNUSED, int hidden UNUSED) +win_alloc(win_T *after, int hidden) { win_T *new_wp; @@ -5480,7 +5480,7 @@ shell_new_rows(void) compute_cmdrow(); curtab->tp_ch_used = p_ch; - if (!p_spsc && !skip_win_fix_scroll) + if (*p_spk != 'c' && !skip_win_fix_scroll) win_fix_scroll(TRUE); #if 0 @@ -5687,7 +5687,7 @@ win_setheight_win(int height, win_T *win msg_row = row; msg_col = 0; - if (!p_spsc) + if (*p_spk != 'c') win_fix_scroll(TRUE); redraw_all_later(UPD_NOT_VALID); @@ -6218,7 +6218,7 @@ win_drag_status_line(win_T *dragwin, int p_ch = MAX(Rows - cmdline_row, 1); curtab->tp_ch_used = p_ch; - if (!p_spsc) + if (*p_spk != 'c') win_fix_scroll(TRUE); redraw_all_later(UPD_SOME_VALID); @@ -6348,7 +6348,7 @@ set_fraction(win_T *wp) } /* - * Handle scroll position for 'nosplitscroll'. Replaces scroll_to_fraction() + * Handle scroll position for 'splitkeep'. Replaces scroll_to_fraction() * call from win_new_height(). Instead we iterate over all windows in a * tabpage and calculate the new scroll position. * TODO: Ensure this also works with wrapped lines. @@ -6362,14 +6362,14 @@ win_fix_scroll(int resize) win_T *wp; linenr_T lnum; - skip_update_topline = TRUE; // avoid scrolling in curs_columns() + skip_update_topline = TRUE; FOR_ALL_WINDOWS(wp) { // Skip when window height has not changed. if (wp->w_height != wp->w_prev_height) { // If window has moved update botline to keep the same screenlines. - if (wp->w_winrow != wp->w_prev_winrow) + if (*p_spk == 's' && wp->w_winrow != wp->w_prev_winrow) { lnum = wp->w_cursor.lnum; diff = (wp->w_winrow - wp->w_prev_winrow) @@ -6403,7 +6403,7 @@ win_fix_scroll(int resize) } /* - * Make sure the cursor position is valid for 'nosplitscroll'. + * Make sure the cursor position is valid for 'splitkeep'. * 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. */ @@ -6413,9 +6413,9 @@ win_fix_cursor(int normal) long so = get_scrolloff_value(); win_T *wp = curwin; linenr_T nlnum = 0; - linenr_T lnum = wp->w_cursor.lnum; - linenr_T bot; - linenr_T top; + linenr_T lnum = wp->w_cursor.lnum; + linenr_T bot; + linenr_T top; if (wp->w_buffer->b_ml.ml_line_count < wp->w_height) return; @@ -6429,25 +6429,23 @@ win_fix_cursor(int normal) top = cursor_down_inner(wp, so); wp->w_cursor.lnum = wp->w_botline - 1; bot = cursor_up_inner(wp, so); + wp->w_cursor.lnum = lnum; // Check if cursor position is above or below valid cursor range. if (lnum > bot && (wp->w_botline - wp->w_buffer->b_ml.ml_line_count) != 1) nlnum = bot; else if (lnum < top && wp->w_topline != 1) nlnum = (so == wp->w_height / 2) ? bot : top; - wp->w_cursor.lnum = lnum; - if (nlnum) // Cursor is invalid for current scroll position. { if (normal) // Save to jumplist and set cursor to avoid scrolling. { setmark('\''); wp->w_cursor.lnum = nlnum; - curs_columns(TRUE); // validate w_wrow } else // Scroll instead when not in normal mode. { - wp->w_fraction = 0.5 * FRACTION_MULT; + wp->w_fraction = (nlnum == bot) ? FRACTION_MULT : 0; scroll_to_fraction(wp, wp->w_prev_height); validate_botline_win(curwin); } @@ -6474,7 +6472,7 @@ win_new_height(win_T *wp, int height) if (wp->w_height > 0) { - if (wp == curwin && p_spsc) + if (wp == curwin && *p_spk == 'c') // w_wrow needs to be valid. When setting 'laststatus' this may // call win_new_height() recursively. validate_cursor(); @@ -6490,7 +6488,7 @@ win_new_height(win_T *wp, int height) // There is no point in adjusting the scroll position when exiting. Some // values might be invalid. - if (!exiting && p_spsc) + if (!exiting && *p_spk == 'c') scroll_to_fraction(wp, prev_height); } @@ -6604,7 +6602,7 @@ scroll_to_fraction(win_T *wp, int prev_h if (wp == curwin) { - if (p_spsc && get_scrolloff_value()) + if (get_scrolloff_value()) update_topline(); curs_columns(FALSE); // validate w_wrow } @@ -6627,15 +6625,13 @@ win_new_width(win_T *wp, int width) wp->w_width = width < 0 ? 0 : width; wp->w_lines_valid = 0; changed_line_abv_curs_win(wp); - // Handled in win_fix_scroll() - if (p_spsc) - { - invalidate_botline_win(wp); - if (wp == curwin) - { - update_topline(); - curs_columns(TRUE); // validate w_wrow - } + invalidate_botline_win(wp); + if (wp == curwin) + { + skip_update_topline = (*p_spk != 'c'); + update_topline(); + curs_columns(TRUE); // validate w_wrow + skip_update_topline = FALSE; } redraw_win_later(wp, UPD_NOT_VALID); wp->w_redr_status = TRUE;