From 42f1864b62be31779fcdcb9345f63a5d43b32bb7 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Tue, 30 Sep 2025 06:37:23 +0800 Subject: [PATCH] vim-patch:9.1.1808: Option insecure flags not copied when splitting window Problem: Option insecure flags not copied when splitting window. Solution: Move window-local insecure flags to winopt_T and copy them properly (zeertzjq). closes: vim/vim#18434 https://github.com/vim/vim/commit/b3740f4b00a78701637a49445adeb20b13e6edf6 --- src/nvim/buffer_defs.h | 18 ++++++---- src/nvim/option.c | 18 ++++++++++ test/old/testdir/test_fold.vim | 54 ++++++++++++++++++++++++++++ test/old/testdir/test_modeline.vim | 40 +++++++++++++++++++-- test/old/testdir/test_statusline.vim | 34 ++++++++++++++---- 5 files changed, 149 insertions(+), 15 deletions(-) diff --git a/src/nvim/buffer_defs.h b/src/nvim/buffer_defs.h index f9f8a183ab..cf1131ee19 100644 --- a/src/nvim/buffer_defs.h +++ b/src/nvim/buffer_defs.h @@ -211,6 +211,18 @@ typedef struct { OptInt wo_winbl; #define w_p_winbl w_onebuf_opt.wo_winbl // 'winblend' + // A few options have local flags for kOptFlagInsecure. + uint32_t wo_wrap_flags; // flags for 'wrap' +#define w_p_wrap_flags w_onebuf_opt.wo_wrap_flags + uint32_t wo_stl_flags; // flags for 'statusline' +#define w_p_stl_flags w_onebuf_opt.wo_stl_flags + uint32_t wo_wbr_flags; // flags for 'winbar' +#define w_p_wbr_flags w_onebuf_opt.wo_wbr_flags + uint32_t wo_fde_flags; // flags for 'foldexpr' +#define w_p_fde_flags w_onebuf_opt.wo_fde_flags + uint32_t wo_fdt_flags; // flags for 'foldtext' +#define w_p_fdt_flags w_onebuf_opt.wo_fdt_flags + sctx_T wo_script_ctx[kWinOptCount]; // SCTXs for window-local options #define w_p_script_ctx w_onebuf_opt.wo_script_ctx } winopt_T; @@ -1302,12 +1314,6 @@ struct window_S { // transform a pointer to a "onebuf" option into a "allbuf" option #define GLOBAL_WO(p) ((char *)(p) + sizeof(winopt_T)) - // A few options have local flags for kOptFlagInsecure. - uint32_t w_p_wrap_flags; // flags for 'wrap' - uint32_t w_p_stl_flags; // flags for 'statusline' - uint32_t w_p_wbr_flags; // flags for 'winbar' - uint32_t w_p_fde_flags; // flags for 'foldexpr' - uint32_t w_p_fdt_flags; // flags for 'foldtext' int *w_p_cc_cols; // array of columns to highlight or NULL uint8_t w_p_culopt_flags; // flags for cursorline highlighting diff --git a/src/nvim/option.c b/src/nvim/option.c index 2757bd2934..0edc393e76 100644 --- a/src/nvim/option.c +++ b/src/nvim/option.c @@ -1668,6 +1668,18 @@ uint32_t *insecure_flag(win_T *const wp, OptIndex opt_idx, int opt_flags) default: break; } + } else { + // For global value of window-local options, use flags in w_allbuf_opt. + switch (opt_idx) { + case kOptWrap: + return &wp->w_allbuf_opt.wo_wrap_flags; + case kOptFoldexpr: + return &wp->w_allbuf_opt.wo_fde_flags; + case kOptFoldtext: + return &wp->w_allbuf_opt.wo_fdt_flags; + default: + break; + } } // Nothing special, return global flags field. return &options[opt_idx].flags; @@ -4925,6 +4937,12 @@ void copy_winopt(winopt_T *from, winopt_T *to) to->wo_winbl = from->wo_winbl; to->wo_stc = copy_option_val(from->wo_stc); + to->wo_wrap_flags = from->wo_wrap_flags; + to->wo_stl_flags = from->wo_stl_flags; + to->wo_wbr_flags = from->wo_wbr_flags; + to->wo_fde_flags = from->wo_fde_flags; + to->wo_fdt_flags = from->wo_fdt_flags; + // Copy the script context so that we know were the value was last set. memmove(to->wo_script_ctx, from->wo_script_ctx, sizeof(to->wo_script_ctx)); check_winopt(to); // don't want NULL pointers diff --git a/test/old/testdir/test_fold.vim b/test/old/testdir/test_fold.vim index 8db66c9be8..756cab15ed 100644 --- a/test/old/testdir/test_fold.vim +++ b/test/old/testdir/test_fold.vim @@ -1518,6 +1518,11 @@ func Test_foldtext_in_modeline() call assert_equal('folded text', foldtextresult(1)) call assert_equal(['before'], readfile('Xmodelinefoldtext_write')) + split + call assert_equal('folded text', foldtextresult(1)) + call assert_equal(['before'], readfile('Xmodelinefoldtext_write')) + close + setglobal foldtext=ModelineFoldText() call assert_equal('folded text', foldtextresult(1)) call assert_equal(['before'], readfile('Xmodelinefoldtext_write')) @@ -1545,6 +1550,28 @@ func Test_foldtext_in_modeline() call Check_foldtext_in_modeline('setlocal') call Check_foldtext_in_modeline('set') + new Xa + sandbox setglobal foldenable foldtext=ModelineFoldText() + setlocal bufhidden=wipe + call writefile(['before'], 'Xmodelinefoldtext_write', 'D') + edit! Xb + call setline(1, ['func T()', ' let i = 1', 'endfunc']) | %fold + call assert_equal('folded text', foldtextresult(1)) + call assert_equal(['before'], readfile('Xmodelinefoldtext_write')) + setglobal foldtext=ModelineFoldText() + call assert_equal('folded text', foldtextresult(1)) + call assert_equal(['before'], readfile('Xmodelinefoldtext_write')) + setlocal foldtext=ModelineFoldText() + call assert_equal('folded text', foldtextresult(1)) + call assert_equal(['after'], readfile('Xmodelinefoldtext_write')) + setlocal bufhidden=wipe + call writefile(['before'], 'Xmodelinefoldtext_write', 'D') + edit! Xc + call setline(1, ['func T()', ' let i = 1', 'endfunc']) | %fold + call assert_equal('folded text', foldtextresult(1)) + call assert_equal(['after'], readfile('Xmodelinefoldtext_write')) + bwipe! + set modeline& modelineexpr& delfunc ModelineFoldText delfunc Check_foldtext_in_modeline @@ -1574,6 +1601,11 @@ func Test_foldexpr_in_modeline() call assert_equal(2, foldlevel(3)) call assert_equal(['before'], readfile('Xmodelinefoldexpr_write')) + split + call assert_equal(2, foldlevel(3)) + call assert_equal(['before'], readfile('Xmodelinefoldexpr_write')) + close + setglobal foldexpr=ModelineFoldExpr() call assert_equal(2, foldlevel(3)) call assert_equal(['before'], readfile('Xmodelinefoldexpr_write')) @@ -1601,6 +1633,28 @@ func Test_foldexpr_in_modeline() call Check_foldexpr_in_modeline('setlocal') call Check_foldexpr_in_modeline('set') + new Xa + sandbox setglobal foldenable foldmethod=expr foldexpr=ModelineFoldExpr() + setlocal bufhidden=wipe + call writefile(['before'], 'Xmodelinefoldexpr_write', 'D') + edit! Xb + call setline(1, lines[0:5]) + call assert_equal(2, foldlevel(3)) + call assert_equal(['before'], readfile('Xmodelinefoldexpr_write')) + setglobal foldexpr=ModelineFoldExpr() + call assert_equal(2, foldlevel(3)) + call assert_equal(['before'], readfile('Xmodelinefoldexpr_write')) + setlocal foldexpr=ModelineFoldExpr() + call assert_equal(2, foldlevel(3)) + call assert_equal(['after'], readfile('Xmodelinefoldexpr_write')) + setlocal bufhidden=wipe + call writefile(['before'], 'Xmodelinefoldexpr_write', 'D') + edit! Xc + call setline(1, lines[0:5]) + call assert_equal(2, foldlevel(3)) + call assert_equal(['after'], readfile('Xmodelinefoldexpr_write')) + bwipe! + set modeline& modelineexpr& delfunc ModelineFoldExpr delfunc Check_foldexpr_in_modeline diff --git a/test/old/testdir/test_modeline.vim b/test/old/testdir/test_modeline.vim index 6d24e9572d..628c4770db 100644 --- a/test/old/testdir/test_modeline.vim +++ b/test/old/testdir/test_modeline.vim @@ -382,19 +382,35 @@ func Test_modeline_nowrap_lcs_extends() \ 'ccc evil', \ 'ddd vim: nowrap', \ ], 'Xmodeline_nowrap', 'D') - call NewWindow(10, 20) + set noequalalways + 11new | 20vsplit func Check_modeline_nowrap(expect_insecure, expect_secure, set_cmd) edit Xmodeline_nowrap call assert_equal(a:expect_insecure, ScreenLines([1, 5], 20)) + + 5split + call assert_equal(a:expect_insecure, ScreenLines([1, 5], 20)) + call assert_equal(a:expect_insecure, ScreenLines([7, 11], 20)) + + exe a:set_cmd 'nowrap' + call assert_equal(a:expect_secure, ScreenLines([1, 5], 20)) + call assert_equal(a:expect_insecure, ScreenLines([7, 11], 20)) + + close + call assert_equal(a:expect_insecure, ScreenLines([1, 5], 20)) + setglobal nowrap call assert_equal(a:expect_insecure, ScreenLines([1, 5], 20)) setglobal wrap call assert_equal(a:expect_insecure, ScreenLines([1, 5], 20)) + exe a:set_cmd 'nowrap' call assert_equal(a:expect_secure, ScreenLines([1, 5], 20)) + exe 'sandbox' a:set_cmd 'nowrap' call assert_equal(a:expect_insecure, ScreenLines([1, 5], 20)) + exe a:set_cmd 'nowrap' call assert_equal(a:expect_secure, ScreenLines([1, 5], 20)) endfunc @@ -463,8 +479,28 @@ func Test_modeline_nowrap_lcs_extends() call Check_modeline_nowrap(expect_insecure, expect_secure, 'setlocal') call Check_modeline_nowrap(expect_insecure, expect_secure, 'set') - call CloseWindow() + sandbox setglobal nowrap + setglobal list listchars=eol:$ + setlocal bufhidden=wipe + enew! + call setline(1, ['aaa bbb']) + call assert_equal(['aaa >'], ScreenLines(1, 20)) + setglobal nowrap + call assert_equal(['aaa >'], ScreenLines(1, 20)) + setlocal nowrap + call assert_equal(['aaa '], ScreenLines(1, 20)) + normal! 20zl + call assert_equal([' bbb$ '], ScreenLines(1, 20)) + setlocal bufhidden=wipe + enew! + call setline(1, ['ccc ddd']) + call assert_equal(['ccc '], ScreenLines(1, 20)) + normal! 20zl + call assert_equal([' ddd$ '], ScreenLines(1, 20)) + + bwipe! delfunc Check_modeline_nowrap + set equalalways& endfunc " vim: shiftwidth=2 sts=2 expandtab diff --git a/test/old/testdir/test_statusline.vim b/test/old/testdir/test_statusline.vim index 4c23288438..6886700e83 100644 --- a/test/old/testdir/test_statusline.vim +++ b/test/old/testdir/test_statusline.vim @@ -649,17 +649,31 @@ func Test_statusline_in_sandbox() endfunc func Check_statusline_in_sandbox(set_cmd0, set_cmd1) - new | only - call writefile(['before'], 'Xsandboxstatusline_write', 'D') + only + 11new | 20vsplit + call setline(1, 'foo') + windo setlocal statusline=SomethingElse + wincmd t setlocal statusline= + call writefile(['before'], 'Xsandboxstatusline_write', 'D') + exe 'sandbox' a:set_cmd0 'statusline=%!SandboxStatusLine()' call assert_equal('', &l:statusline) sandbox setlocal statusline=%!SandboxStatusLine() call assert_fails('redrawstatus', 'E48:') call assert_equal(['before'], readfile('Xsandboxstatusline_write')) + wincmd b + call assert_fails('redrawstatus!', 'E48:') + call assert_equal(['before'], readfile('Xsandboxstatusline_write')) + wincmd t + + 5split + call assert_fails('redrawstatus!', 'E48:') + call assert_equal(['before'], readfile('Xsandboxstatusline_write')) + close setlocal statusline=%!SandboxStatusLine() | redrawstatus - call assert_equal('status line', Screenline(&lines - 1)) + call assert_equal('status line', Screenline(12)) call assert_equal(['after'], readfile('Xsandboxstatusline_write')) call writefile(['before'], 'Xsandboxstatusline_write') @@ -667,19 +681,25 @@ func Test_statusline_in_sandbox() call assert_fails('redrawstatus', 'E48:') call assert_equal(['before'], readfile('Xsandboxstatusline_write')) - exe a:set_cmd1 'statusline=%!SandboxStatusLine()' | redrawstatus + 5split + call assert_fails('redrawstatus!', 'E48:') + call assert_equal(['before'], readfile('Xsandboxstatusline_write')) + + exe a:set_cmd1 'statusline=%!SandboxStatusLine()' | redrawstatus! call assert_equal('', &l:statusline) - call assert_equal('status line', Screenline(&lines - 1)) + call assert_equal('status line', Screenline(6)) + call assert_equal('status line', Screenline(12)) call assert_equal(['after'], readfile('Xsandboxstatusline_write')) - bw! + bwipe! endfunc + set noequalalways call Check_statusline_in_sandbox('setglobal', 'setglobal') call Check_statusline_in_sandbox('setglobal', 'set') call Check_statusline_in_sandbox('set', 'setglobal') call Check_statusline_in_sandbox('set', 'set') - set statusline& + set equalalways& statusline& delfunc SandboxStatusLine delfunc Check_statusline_in_sandbox endfunc