commit 42f1864b62be31779fcdcb9345f63a5d43b32bb7
parent ff564237d248d3aad3c795711dfbb888fafa9c31
Author: zeertzjq <zeertzjq@outlook.com>
Date: Tue, 30 Sep 2025 06:37:23 +0800
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
Diffstat:
5 files changed, 149 insertions(+), 15 deletions(-)
diff --git 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
@@ -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
@@ -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
@@ -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
@@ -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