From: Foxe Chen Date: Mon, 2 Mar 2026 19:36:07 +0000 (+0000) Subject: patch 9.2.0093: Not possible to have window-local highlighting groups X-Git-Tag: v9.2.0093^0 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=98174caabb5dc5a5aeda2fb328c922fe9a670be4;p=thirdparty%2Fvim.git patch 9.2.0093: Not possible to have window-local highlighting groups Problem: Not possible to have window-local highlighting groups (Hima) Solution: Port Neovims 'winhighlight' option to Vim (Foxe Chen). fixes: #3576 closes: #19493 Signed-off-by: Foxe Chen Signed-off-by: Christian Brabandt --- diff --git a/ci/hlgroups.ignore b/ci/hlgroups.ignore index a046eb127d..681b120875 100644 --- a/ci/hlgroups.ignore +++ b/ci/hlgroups.ignore @@ -67,3 +67,4 @@ Visual VisualNOS WarningMsg WildMenu +WinColor diff --git a/runtime/doc/options.txt b/runtime/doc/options.txt index 6986fde86b..327494d68a 100644 --- a/runtime/doc/options.txt +++ b/runtime/doc/options.txt @@ -4810,6 +4810,9 @@ A jump table for the options with a short description can be found at |Q_op|. |hl-PmenuBorder| j popup menu border characters |hl-PmenuShadow| H popup menu shadow |hl-PreInsert| I text inserted when "preinsert" is in 'completeopt' + |hl-Normal| ( Window color (supersedes 'wincolor' option) + + Note that the "(" occasion is not set by default. The display modes are: r reverse (termcap entry "mr" and "me") @@ -10246,8 +10249,19 @@ A jump table for the options with a short description can be found at |Q_op|. *'wincolor'* *'wcr'* 'wincolor' 'wcr' string (default empty) local to window + DEPRECATED: Use 'winhighlight' if possible, this option uses + 'winhighlight' internally by setting it to: >vim + set winhighlight=!(:HighlightGroup +< If this option is set and 'winhighlight' is changed, then it will not + update the option value. For example, if 'wincolor' is set to "A" and + then 'winhighlight' is to an empty value, then 'wincolor' will still + remain as "A". Additionally, the existing value in 'winhighlight' will + be discarded when this option is set. + Highlight group name to use for this window instead of the Normal - color |hl-Normal|. + color |hl-Normal|. For other |highlight-groups|, see 'winhighlight'. + Note that it is not recommended to set this and 'winhighlight' at the + same time. *'window'* *'wi'* 'window' 'wi' number (default screen height - 1) @@ -10306,6 +10320,35 @@ A jump table for the options with a short description can be found at |Q_op|. 'winheight' applies to the current window. Use 'winminheight' to set the minimal height for other windows. + *'winhighlight'* *'whl'* +'winhighlight' 'whl' string (default empty) + local to window + Window-local highlight group mappings. Comma-delimited list of + highlight |group-name| pairs "{hl-from}:{hl-to},..." where each + {hl-from} is a |highlight-groups| item to be overridden by {hl-to} + group in the window. If {hl-from} is "Normal", then it will always + map to the "(" (window color) value in 'highlight'. + + If a highlight group name starts with "!", then it is assumed to map + to a value in 'highlight'. For example, this will override the + visual mode setting: >vim + set winhighlight=!v:SomeHighlightGroup +< This will map the occasion "v" to occasion "l" >vim + set winhighlight=!v:!l +< + Highlights of vertical separators are determined by the window to the + left of the separator. The 'tabline' highlight of a tabpage is + decided by the last-focused window of the tabpage. Highlights of + the popupmenu are determined by the current window. Highlights in the + message area cannot be overridden. + + When handling highlight group links, if a highlight group (which may + be a link as well) is overridden by 'winhighlight', then all highlight + groups that link to it will be affected. For example, if highlight + group C links to B which links to A, then >vim + set winhighlight=B:SomeHighlightGroup +< will make SomeHighlightGroup override groups B and C, but not A. + *'winminheight'* *'wmh'* 'winminheight' 'wmh' number (default 1) global diff --git a/runtime/doc/popup.txt b/runtime/doc/popup.txt index 021410eb2c..e968a21075 100644 --- a/runtime/doc/popup.txt +++ b/runtime/doc/popup.txt @@ -1,4 +1,4 @@ -*popup.txt* For Vim version 9.2. Last change: 2026 Feb 18 +*popup.txt* For Vim version 9.2. Last change: 2026 Mar 02 VIM REFERENCE MANUAL by Bram Moolenaar @@ -773,6 +773,8 @@ The second argument of |popup_create()| is a dictionary with options: the popup window. highlight Highlight group name to use for the text, stored in the 'wincolor' option. + highlights Highlight group overrides, stored in the + 'winhighlight' option (same format). opacity Opacity of the popup, a value between 0 and 100: 0 is fully transparent (background text fully visible) 100 is fully opaque (default, no transparency) diff --git a/runtime/doc/quickref.txt b/runtime/doc/quickref.txt index 2d4cf57e78..e7b2068b02 100644 --- a/runtime/doc/quickref.txt +++ b/runtime/doc/quickref.txt @@ -1,4 +1,4 @@ -*quickref.txt* For Vim version 9.2. Last change: 2026 Mar 01 +*quickref.txt* For Vim version 9.2. Last change: 2026 Mar 02 VIM REFERENCE MANUAL by Bram Moolenaar @@ -1017,6 +1017,7 @@ Short explanation of each option: *option-list* 'wildoptions' 'wop' specifies how command line completion is done 'winaltkeys' 'wak' when the windows system handles ALT keys 'wincolor' 'wcr' window-local highlighting +'winhighlight' 'whl' window-local highlighting mappings 'window' 'wi' nr of lines to scroll for CTRL-F and CTRL-B 'winfixbuf' 'wfb' keep window focused on a single buffer 'winfixheight' 'wfh' keep window height when opening/closing windows diff --git a/runtime/doc/tags b/runtime/doc/tags index e4478f0d7a..a881c0acfe 100644 --- a/runtime/doc/tags +++ b/runtime/doc/tags @@ -1335,6 +1335,7 @@ $quote eval.txt /*$quote* 'wfw' options.txt /*'wfw'* 'wh' options.txt /*'wh'* 'whichwrap' options.txt /*'whichwrap'* +'whl' options.txt /*'whl'* 'wi' options.txt /*'wi'* 'wic' options.txt /*'wic'* 'wig' options.txt /*'wig'* @@ -1353,6 +1354,7 @@ $quote eval.txt /*$quote* 'winfixheight' options.txt /*'winfixheight'* 'winfixwidth' options.txt /*'winfixwidth'* 'winheight' options.txt /*'winheight'* +'winhighlight' options.txt /*'winhighlight'* 'winminheight' options.txt /*'winminheight'* 'winminwidth' options.txt /*'winminwidth'* 'winptydll' options.txt /*'winptydll'* diff --git a/runtime/doc/version9.txt b/runtime/doc/version9.txt index 85a6c80322..120c1960d4 100644 --- a/runtime/doc/version9.txt +++ b/runtime/doc/version9.txt @@ -1,4 +1,4 @@ -*version9.txt* For Vim version 9.2. Last change: 2026 Mar 01 +*version9.txt* For Vim version 9.2. Last change: 2026 Mar 02 VIM REFERENCE MANUAL by Bram Moolenaar @@ -52613,6 +52613,7 @@ Options: ~ 'statuslineopt' Extra options for the 'statusline', e.g. use the "maxheight" suboption to use several lines. +'winhighlight' Window-local highlight group mappings. ============================================================================== PATCHES *patches-9.3* *bug-fixes-9.3* diff --git a/runtime/optwin.vim b/runtime/optwin.vim index 28d91abc5c..705195d0e0 100644 --- a/runtime/optwin.vim +++ b/runtime/optwin.vim @@ -1,7 +1,7 @@ " These commands create the option window. " " Maintainer: The Vim Project -" Last Change: 2026 Mar 01 +" Last Change: 2026 Mar 02 " Former Maintainer: Bram Moolenaar " If there already is an option window, jump to that one. @@ -445,6 +445,9 @@ call BinOptionG("hls", &hls) call AddOption("wincolor", gettext("highlight group to use for the window")) call append("$", "\t" .. s:local_to_window) call OptionL("wcr") +call AddOption("winhighlight", gettext("highlight group mappings for the window")) +call append("$", "\t" .. s:local_to_window) +call OptionL("whl") if has("termguicolors") call AddOption("termguicolors", gettext("use GUI colors for the terminal")) call BinOptionG("tgc", &tgc) diff --git a/runtime/syntax/vim.vim b/runtime/syntax/vim.vim index 4c96b6e7a1..a81f82bd58 100644 --- a/runtime/syntax/vim.vim +++ b/runtime/syntax/vim.vim @@ -2,7 +2,7 @@ " Language: Vim script " Maintainer: Hirohito Higashi " Doug Kearns -" Last Change: 2026 Mar 01 +" Last Change: 2026 Mar 02 " Former Maintainer: Charles E. Campbell " DO NOT CHANGE DIRECTLY. @@ -72,7 +72,7 @@ syn keyword vimOption contained mmd maxmapdepth mm maxmem mmp maxmempattern mmt syn keyword vimOption contained popt printoptions prompt pb pumborder ph pumheight pmw pummaxwidth pw pumwidth pythondll pythonhome pythonthreedll pythonthreehome pyx pyxversion qftf quickfixtextfunc qe quoteescape ro readonly rdt redrawtime re regexpengine rnu relativenumber remap rop renderoptions report rs restorescreen ri revins rl rightleft rlc rightleftcmd rubydll ru ruler ruf rulerformat rtp runtimepath scr scroll scb scrollbind scf scrollfocus sj scrolljump so scrolloff sbo scrollopt sect sections secure sel selection slm selectmode ssop sessionoptions sh shell shcf shellcmdflag sp shellpipe shq shellquote srr shellredir ssl shellslash stmp shelltemp st shelltype sxe shellxescape sxq shellxquote sr shiftround sw shiftwidth shm shortmess sn shortname sbr showbreak skipwhite nextgroup=vimSetEqual,vimSetMod syn keyword vimOption contained sc showcmd sloc showcmdloc sft showfulltag sm showmatch smd showmode stal showtabline stpl showtabpanel ss sidescroll siso sidescrolloff scl signcolumn scs smartcase si smartindent sta smarttab sms smoothscroll sts softtabstop spell spc spellcapcheck spf spellfile spl spelllang spo spelloptions sps spellsuggest sb splitbelow spk splitkeep spr splitright sol startofline stl statusline stlo statuslineopt su suffixes sua suffixesadd swf swapfile sws swapsync swb switchbuf smc synmaxcol syn syntax tcl tabclose tal tabline tpm tabpagemax tpl tabpanel tplo tabpanelopt ts tabstop tbs tagbsearch tc tagcase tfu tagfunc tl taglength tr tagrelative tag tags tgst tagstack tcldll term tbidi termbidi tenc termencoding tgc termguicolors twk termwinkey skipwhite nextgroup=vimSetEqual,vimSetMod syn keyword vimOption contained twsl termwinscroll tws termwinsize twt termwintype terse ta textauto tx textmode tw textwidth tsr thesaurus tsrfu thesaurusfunc top tildeop to timeout tm timeoutlen title titlelen titleold titlestring tb toolbar tbis toolbariconsize ttimeout ttm ttimeoutlen tbi ttybuiltin tf ttyfast ttym ttymouse tsl ttyscroll tty ttytype udir undodir udf undofile ul undolevels ur undoreload uc updatecount ut updatetime vsts varsofttabstop vts vartabstop vbs verbose vfile verbosefile vdir viewdir vop viewoptions vi viminfo vif viminfofile ve virtualedit vb visualbell warn wiv weirdinvert ww whichwrap wc wildchar wcm wildcharm wig wildignore wic wildignorecase wmnu wildmenu wim wildmode wop wildoptions wak winaltkeys wcr wincolor wi window wfb winfixbuf skipwhite nextgroup=vimSetEqual,vimSetMod -syn keyword vimOption contained wfh winfixheight wfw winfixwidth wh winheight wmh winminheight wmw winminwidth winptydll wiw winwidth wse wlseat wst wlsteal wtm wltimeoutlen wrap wm wrapmargin ws wrapscan write wa writeany wb writebackup wd writedelay xtermcodes skipwhite nextgroup=vimSetEqual,vimSetMod +syn keyword vimOption contained wfh winfixheight wfw winfixwidth wh winheight whl winhighlight wmh winminheight wmw winminwidth winptydll wiw winwidth wse wlseat wst wlsteal wtm wltimeoutlen wrap wm wrapmargin ws wrapscan write wa writeany wb writebackup wd writedelay xtermcodes skipwhite nextgroup=vimSetEqual,vimSetMod " vimOptions: These are the turn-off setting variants {{{2 " GEN_SYN_VIM: vimOption turn-off, START_STR='syn keyword vimOption contained', END_STR='' @@ -111,7 +111,7 @@ syn keyword vimOptionVarName contained mfd maxfuncdepth mmd maxmapdepth mm maxme syn keyword vimOptionVarName contained pmbfn printmbfont popt printoptions prompt pb pumborder ph pumheight pmw pummaxwidth pw pumwidth pythondll pythonhome pythonthreedll pythonthreehome pyx pyxversion qftf quickfixtextfunc qe quoteescape ro readonly rdt redrawtime re regexpengine rnu relativenumber remap rop renderoptions report rs restorescreen ri revins rl rightleft rlc rightleftcmd rubydll ru ruler ruf rulerformat rtp runtimepath scr scroll scb scrollbind scf scrollfocus sj scrolljump so scrolloff sbo scrollopt sect sections secure sel selection slm selectmode ssop sessionoptions sh shell shcf shellcmdflag sp shellpipe shq shellquote srr shellredir ssl shellslash stmp shelltemp st shelltype sxe shellxescape sxq shellxquote sr shiftround sw shiftwidth shm shortmess syn keyword vimOptionVarName contained sn shortname sbr showbreak sc showcmd sloc showcmdloc sft showfulltag sm showmatch smd showmode stal showtabline stpl showtabpanel ss sidescroll siso sidescrolloff scl signcolumn scs smartcase si smartindent sta smarttab sms smoothscroll sts softtabstop spell spc spellcapcheck spf spellfile spl spelllang spo spelloptions sps spellsuggest sb splitbelow spk splitkeep spr splitright sol startofline stl statusline stlo statuslineopt su suffixes sua suffixesadd swf swapfile sws swapsync swb switchbuf smc synmaxcol syn syntax tcl tabclose tal tabline tpm tabpagemax tpl tabpanel tplo tabpanelopt ts tabstop tbs tagbsearch tc tagcase tfu tagfunc tl taglength tr tagrelative tag tags tgst tagstack tcldll term tbidi termbidi tenc termencoding syn keyword vimOptionVarName contained tgc termguicolors twk termwinkey twsl termwinscroll tws termwinsize twt termwintype terse ta textauto tx textmode tw textwidth tsr thesaurus tsrfu thesaurusfunc top tildeop to timeout tm timeoutlen title titlelen titleold titlestring tb toolbar tbis toolbariconsize ttimeout ttm ttimeoutlen tbi ttybuiltin tf ttyfast ttym ttymouse tsl ttyscroll tty ttytype udir undodir udf undofile ul undolevels ur undoreload uc updatecount ut updatetime vsts varsofttabstop vts vartabstop vbs verbose vfile verbosefile vdir viewdir vop viewoptions vi viminfo vif viminfofile ve virtualedit vb visualbell warn wiv weirdinvert ww whichwrap wc wildchar wcm wildcharm wig wildignore wic wildignorecase wmnu wildmenu wim wildmode wop wildoptions wak winaltkeys -syn keyword vimOptionVarName contained wcr wincolor wi window wfb winfixbuf wfh winfixheight wfw winfixwidth wh winheight wmh winminheight wmw winminwidth winptydll wiw winwidth wse wlseat wst wlsteal wtm wltimeoutlen wrap wm wrapmargin ws wrapscan write wa writeany wb writebackup wd writedelay xtermcodes +syn keyword vimOptionVarName contained wcr wincolor wi window wfb winfixbuf wfh winfixheight wfw winfixwidth wh winheight whl winhighlight wmh winminheight wmw winminwidth winptydll wiw winwidth wse wlseat wst wlsteal wtm wltimeoutlen wrap wm wrapmargin ws wrapscan write wa writeany wb writebackup wd writedelay xtermcodes " GEN_SYN_VIM: vimOption term output code variable, START_STR='syn keyword vimOptionVarName contained', END_STR='' syn keyword vimOptionVarName contained t_AB t_AF t_AU t_AL t_al t_bc t_BE t_BD t_cd t_ce t_Ce t_CF t_cl t_cm t_Co t_CS t_Cs t_cs t_CV t_da t_db t_DL t_dl t_ds t_Ds t_EC t_EI t_fs t_fd t_fe t_GP t_IE t_IS t_ke t_ks t_le t_mb t_md t_me t_mr t_ms t_nd t_op t_RF t_RB t_RC t_RI t_Ri t_RK t_RS t_RT t_RV t_Sb t_SC t_se t_Sf t_SH t_SI t_Si t_so t_SR t_sr t_ST t_Te t_te t_TE t_ti t_TI t_Ts t_ts t_u7 t_ue t_us t_Us t_ut t_vb t_ve t_vi t_VS t_vs t_WP t_WS t_XM t_xn t_xs t_ZH t_ZR t_8f t_8b t_8u t_xo syn keyword vimOptionVarName contained t_F1 t_F2 t_F3 t_F4 t_F5 t_F6 t_F7 t_F8 t_F9 t_k1 t_K1 t_k2 t_k3 t_K3 t_k4 t_K4 t_k5 t_K5 t_k6 t_K6 t_k7 t_K7 t_k8 t_K8 t_k9 t_K9 t_KA t_kb t_kB t_KB t_KC t_kd t_kD t_KD t_KE t_KF t_KG t_kh t_KH t_kI t_KI t_KJ t_KK t_kl t_KL t_kN t_kP t_kr t_ku diff --git a/src/drawline.c b/src/drawline.c index 2758e882ec..4597d8d3ca 100644 --- a/src/drawline.c +++ b/src/drawline.c @@ -127,7 +127,6 @@ typedef struct { int win_attr; // background for the whole window, except // margins and "~" lines. - int wcr_attr; // attributes from 'wincolor' #ifdef FEAT_SYN_HL int cul_attr; // set when 'cursorline' active #endif @@ -261,9 +260,9 @@ handle_foldcolumn(win_T *wp, winlinevars_T *wlv) wlv->c_extra = NUL; wlv->c_final = NUL; if (use_cursor_line_highlight(wp, wlv->lnum)) - wlv->char_attr = hl_combine_attr(wlv->wcr_attr, HL_ATTR(HLF_CLF)); + wlv->char_attr = hl_combine_attr(get_win_attr(wp), HL_ATTR(HLF_CLF)); else - wlv->char_attr = hl_combine_attr(wlv->wcr_attr, HL_ATTR(HLF_FC)); + wlv->char_attr = hl_combine_attr(get_win_attr(wp), HL_ATTR(HLF_FC)); } #endif @@ -293,9 +292,9 @@ get_sign_display_info( else { if (use_cursor_line_highlight(wp, wlv->lnum)) - wlv->char_attr = hl_combine_attr(wlv->wcr_attr, HL_ATTR(HLF_CLS)); + wlv->char_attr = hl_combine_attr(get_win_attr(wp), HL_ATTR(HLF_CLS)); else - wlv->char_attr = hl_combine_attr(wlv->wcr_attr, HL_ATTR(HLF_SC)); + wlv->char_attr = hl_combine_attr(get_win_attr(wp), HL_ATTR(HLF_SC)); wlv->n_extra = 2; } @@ -467,7 +466,7 @@ handle_lnum_col( wlv->c_final = NUL; } wlv->n_extra = number_width(wp) + 1; - wlv->char_attr = hl_combine_attr(wlv->wcr_attr, HL_ATTR(HLF_N)); + wlv->char_attr = hl_combine_attr(get_win_attr(wp), HL_ATTR(HLF_N)); #ifdef FEAT_SYN_HL // When 'cursorline' is set highlight the line number of // the current line differently. @@ -481,16 +480,16 @@ handle_lnum_col( && (wlv->row == lnum_row || (wlv->row > lnum_row && (wp->w_p_culopt_flags & CULOPT_LINE)))) - wlv->char_attr = hl_combine_attr(wlv->wcr_attr, HL_ATTR(HLF_CLN)); + wlv->char_attr = hl_combine_attr(get_win_attr(wp), HL_ATTR(HLF_CLN)); #endif if (wp->w_p_rnu && wlv->lnum < wp->w_cursor.lnum && HL_ATTR(HLF_LNA) != 0) // Use LineNrAbove - wlv->char_attr = hl_combine_attr(wlv->wcr_attr, HL_ATTR(HLF_LNA)); + wlv->char_attr = hl_combine_attr(get_win_attr(wp), HL_ATTR(HLF_LNA)); if (wp->w_p_rnu && wlv->lnum > wp->w_cursor.lnum && HL_ATTR(HLF_LNB) != 0) // Use LineNrBelow - wlv->char_attr = hl_combine_attr(wlv->wcr_attr, HL_ATTR(HLF_LNB)); + wlv->char_attr = hl_combine_attr(get_win_attr(wp), HL_ATTR(HLF_LNB)); } #ifdef FEAT_SIGNS if (num_attr) @@ -608,7 +607,7 @@ handle_showbreak_and_filler(win_T *wp, winlinevars_T *wlv) // required when 'linebreak' is also set. if (wlv->tocol == wlv->vcol) wlv->tocol = wlv->vcol_sbr; - // combine 'showbreak' with 'wincolor' + // combine 'showbreak' with HLF_WIN wlv->char_attr = hl_combine_attr(wlv->win_attr, HL_ATTR(HLF_AT)); # ifdef FEAT_SYN_HL // combine 'showbreak' with 'cursorline' @@ -1676,10 +1675,9 @@ win_line( } } - wlv.wcr_attr = get_wcr_attr(wp); - if (wlv.wcr_attr != 0) + if (get_win_attr(wp) != 0) { - wlv.win_attr = wlv.wcr_attr; + wlv.win_attr = get_win_attr(wp); area_highlighting = TRUE; } @@ -1993,7 +1991,7 @@ win_line( wlv.c_extra = cmdwin_type; wlv.c_final = NUL; wlv.char_attr = - hl_combine_attr(wlv.wcr_attr, HL_ATTR(HLF_AT)); + hl_combine_attr(get_win_attr(wp), HL_ATTR(HLF_AT)); } } #ifdef FEAT_FOLDING @@ -2655,7 +2653,7 @@ win_line( #endif } - // combine attribute with 'wincolor' + // combine attribute with HLF_WIN if (wlv.win_attr != 0) { if (wlv.char_attr == 0) @@ -4303,7 +4301,7 @@ win_line( { #ifdef FEAT_CONCEAL wlv.col -= wlv.boguscols; - // Apply 'cursorline' and 'wincolor' highlight. + // Apply 'cursorline' and HLF_WIN highlight. if (wlv.boguscols != 0 && ( # ifdef LINE_ATTR wlv.line_attr != 0 || diff --git a/src/drawscreen.c b/src/drawscreen.c index aff03cb872..8ce8826c12 100644 --- a/src/drawscreen.c +++ b/src/drawscreen.c @@ -100,6 +100,7 @@ update_screen(int type_arg) #ifdef FEAT_PROP_POPUP int did_redraw_window = FALSE; #endif + bool override_success; // Don't do anything if the screen structures are (not yet) valid. if (!screen_valid(TRUE)) @@ -319,6 +320,8 @@ update_screen(int type_arg) #endif FOR_ALL_WINDOWS(wp) { + override_success = push_highlight_overrides(wp->w_hl, wp->w_hl_len); + if (wp->w_redr_type != 0) { cursor_off(); @@ -353,6 +356,10 @@ update_screen(int type_arg) cursor_off(); win_redr_status(wp, TRUE); // any popup menu will be redrawn below } + + if (override_success) + pop_highlight_overrides(); + } #if defined(FEAT_SEARCH_EXTRA) end_search_hl(); @@ -624,6 +631,7 @@ redraw_custom_statusline(win_T *wp) void showruler(int always) { + bool override_success; if (!always && !redrawing()) return; if (pum_visible()) @@ -632,12 +640,15 @@ showruler(int always) curwin->w_redr_status = TRUE; return; } + override_success = push_highlight_overrides(curwin->w_hl, curwin->w_hl_len); #if defined(FEAT_STL_OPT) if ((*p_stl != NUL || *curwin->w_p_stl != NUL) && curwin->w_status_height) redraw_custom_statusline(curwin); else #endif win_redr_ruler(curwin, always, FALSE); + if (override_success) + pop_highlight_overrides(); if (need_maketitle #ifdef FEAT_STL_OPT @@ -3379,7 +3390,12 @@ redraw_statuslines(void) FOR_ALL_WINDOWS(wp) if (wp->w_redr_status) + { + bool ret = push_highlight_overrides(wp->w_hl, wp->w_hl_len); win_redr_status(wp, FALSE); + if (ret) + pop_highlight_overrides(); + } if (redraw_tabline) draw_tabline(); diff --git a/src/highlight.c b/src/highlight.c index f4d6867aa5..5ce3ea107b 100644 --- a/src/highlight.c +++ b/src/highlight.c @@ -181,6 +181,28 @@ typedef struct #endif } hl_group_T; +typedef struct hl_overrides_S hl_overrides_T; +struct hl_overrides_S +{ + hl_override_T *arr; + int len; + hl_overrides_T *next; // Used to handle recursive calls + + int attr[HLF_COUNT]; // highlight_attr[] before being updated. +}; + +static hl_overrides_T *overrides = NULL; + +// Synced with highlight_attr, each is the highlight group id for each attr. If +// an element is 0, then there is no attr for it. If an element is -1, then it +// means it was set to itself. +static int highlight_ids[HLF_COUNT]; + +// Same as highlight_attr[] but is not modified by highlight group overrides +static int highlight_attr_raw[HLF_COUNT]; + +static int hl_flags[HLF_COUNT] = HL_FLAGS; + // highlight groups for 'highlight' option static garray_T highlight_ga; #define HL_TABLE() ((hl_group_T *)((highlight_ga.ga_data))) @@ -3766,6 +3788,20 @@ set_hl_attr( } } +/* + * Check if highlight id is overridden, and return the overriding highlight id. + * Otherwise return the original id if no override. + */ + static int +syn_override(int id) +{ + if (overrides != NULL && overrides->arr != NULL) + for (int k = 0; k < overrides->len; k++) + if (overrides->arr[k].from == id) + return overrides->arr[k].to; + return id; +} + /* * Lookup a highlight group name and return its ID. * If it is not found, 0 is returned. @@ -4041,13 +4077,20 @@ syn_get_final_id(int hl_id) // Look out for loops! Break after 100 links. for (count = 100; --count >= 0; ) { + int tmp = hl_id; + sgp = &HL_TABLE()[hl_id - 1]; // index is ID minus one if (sgp->sg_link == 0 || sgp->sg_link > highlight_ga.ga_len) break; + + // This is to handle highlight groups that are overridden but are in the + // middle of a link chain. + hl_id = syn_override(hl_id); + if (tmp != hl_id) + continue; hl_id = sgp->sg_link; } - - return hl_id; + return syn_override(hl_id); } #if defined(FEAT_GUI) || defined(FEAT_TERMGUICOLORS) @@ -4211,18 +4254,22 @@ highlight_changed(void) int hlcnt; # endif #endif - static int hl_flags[HLF_COUNT] = HL_FLAGS; + win_T *wp; need_highlight_changed = FALSE; #ifdef FEAT_TERMINAL term_update_colors_all(); - term_update_wincolor_all(); + term_update_hlfwin_all(); #endif // Clear all attributes. for (hlf = 0; hlf < (int)HLF_COUNT; ++hlf) + { highlight_attr[hlf] = 0; + highlight_attr_raw[hlf] = 0; + highlight_ids[hlf] = 0; + } // First set all attributes to their default value. // Then use the attributes from the 'highlight' option. @@ -4309,11 +4356,20 @@ highlight_changed(void) } } highlight_attr[hlf] = attr; + highlight_attr_raw[hlf] = attr; + highlight_ids[hlf] = id; p = skip_to_option_part(p); // skip comma and spaces } } + FOR_ALL_WINDOWS(wp) + wp->w_hlfwin_id = hlf_get_id(wp, HLF_WIN); + +#ifdef FEAT_TERMINAL + term_update_hlfwin_all(); +#endif + #ifdef USER_HIGHLIGHT // Setup the user highlights // @@ -4948,7 +5004,7 @@ highlight_get_info(int hl_idx, int resolve_link) if (dict_add_number(dict, "id", hlgid) == FAIL) goto error; - if (sgp->sg_link && resolve_link) + if (resolve_link) { // resolve the highlight group link recursively while (sgp->sg_link) @@ -5399,3 +5455,351 @@ f_hlset(typval_T *argvars, typval_T *rettv) rettv->vval.v_number = 0; } #endif + +/* + * If "old" is in the override stack, then update it to "new". Does not free + * "old". + */ + void +update_highlight_overrides(hl_override_T *old, hl_override_T *new, int newlen) +{ + if (old == NULL) + return; + + for (hl_overrides_T *set = overrides; set != NULL; set = set->next) + { + if (set->arr == old) + { + set->arr = new; + set->len = newlen; + break; + } + } +} + +/* + * Update highlight_attr[] array. If "update_ids" is true, then update + * highlight_ids[] array instead. + */ + static void +set_highlight_attr(hl_override_T *arr, int len, bool update_ids) +{ + for (int i = 0; i < len; i++) + { + hl_override_T *override = arr + i; + int hlf = -1, attr; + + if (override->from <= 0) + // Directly map to highlight_attr + hlf = -override->from; + else + { + for (int k = 0; k < HLF_COUNT; k++) + if (override->from == highlight_ids[k]) + { + hlf = k; + break; + } + + if (hlf == -1) + continue; + } + + if (update_ids) + { + if (override->to <= 0) + { + if (hlf == -override->to) + highlight_ids[hlf] = -1; + else + highlight_ids[hlf] = highlight_ids[-override->to]; + } + else + highlight_ids[hlf] = override->to; + } + else + { + if (override->to <= 0) + // Directly use highlight_attr[] + attr = highlight_attr[-override->to]; + else + attr = syn_id2attr(override->to); + + highlight_attr[hlf] = attr; + } + } +} + +/* + * Set the current highlight override to "arr". Returns true if successful + */ + bool +push_highlight_overrides(hl_override_T *arr, int len) +{ + // Don't want to do anything if "arr" is NULL or if "arr" is already the + // current override. + if (arr == NULL || (overrides != NULL && overrides->arr == arr)) + return false; + + hl_overrides_T *set; + + set = ALLOC_ONE(hl_overrides_T); + if (set == NULL) + return false; + + set->arr = arr; + set->len = len; + + // Push to front of list + set->next = overrides; + overrides = set; + + // Save current highlight_attr[], so it can be restored later after this + // override is popped. + memcpy(set->attr, highlight_attr, sizeof(highlight_attr)); + + // Reset highlight_attr[] to default values, as we don't want changes from + // other overrides. + memcpy(highlight_attr, highlight_attr_raw, sizeof(highlight_attr)); + + // Update highlight_attr[] array + set_highlight_attr(arr, len, false); + + return true; +} + +/* + * Pop the current highlight override (if any) from the stack. This should + * always be paired with a *successful* push. + */ + void +pop_highlight_overrides(void) +{ + hl_overrides_T *set = overrides; + + if (overrides == NULL) + return; + + overrides = set->next; + + // Set highlight_attr[] to state before override was pushed. + memcpy(highlight_attr, set->attr, sizeof(highlight_attr)); + vim_free(set); +} + +/* + * Parse the 'winhighlight' option and return array. Returns NULL on failure or + * if empty option. If failure, then errmsg is set. + */ + static hl_override_T * +parse_winhighlight(char_u *opt, int *len, char **errmsg) +{ + char_u *p = opt; + hl_override_T *arr; + int i = 0; + int num = 1; + + if (*p == NUL) + return NULL; + + // Get number of overrides first so we can allocate array + while ((p = vim_strchr(p, ',')) != NULL) + { + p++; + num++; + } + + arr = ALLOC_MULT(hl_override_T, num); + if (arr == NULL) + { + *errmsg = e_out_of_memory; + return NULL; + } + + p = opt; + + while (true) + { + hl_override_T *override = arr + i++; + char_u *fromname = p, *toname; + char_u *tmp; + char_u **names[2] = {&fromname, &toname}; + int fromlen, tolen; + int *lens[2] = {&fromlen, &tolen}; + int fromid, toid; + int *ids[2] = {&fromid, &toid}; + + p = vim_strchr(p, ':'); + + if (p == NULL) + goto fail; + + fromlen = p - fromname; // Get hl for "from" + p++; // Skip colon ':' + if (*p == NUL) + goto fail; + + toname = p; + tmp = vim_strchr(p, ','); + + // Get hl for "to", must check for no trailing comma in case last + // element. + if (tmp == NULL) + tolen = (int)STRLEN(p); + else + { + tolen = tmp - toname; + p = ++tmp; + } + + for (int k = 0; k < 2; k++) + { + char_u *name = *names[k]; + int nlen = *lens[k]; + + if (*name == '!') + { + // If starts with "!", then it maps directly to a 'highlight' + // occasion. + int hlf; + + if (nlen != 2) + goto fail; + + for (hlf = 0; hlf < (int)HLF_COUNT; ++hlf) + if (hl_flags[hlf] == name[1]) + break; + + if (hlf >= HLF_COUNT) + goto fail; + + *ids[k] = -hlf; + } + else + { + // Otherwise get the highlight group id. + if (syn_check_group(name, nlen) == 0) + goto fail; + + *ids[k] = syn_namen2id(name, nlen); + if (*ids[k] == 0) + goto fail; + + // Always map "Normal" group to HLF_WIN + if (ids[k] == &fromid && + STRCMP(HL_TABLE()[*ids[k] - 1].sg_name_u, "NORMAL") == 0) + *ids[k] = -HLF_WIN; + } + } + + // If fromid == toid, leave it be, this is so that we know HLF_WIN has + // been set (even to itself e.g. "Normal"), and therefore know to use + // its attr instead. + override->from = fromid; + override->to = toid; + + if (tmp == NULL) + break; + } + + *len = num; + return arr; +fail: + vim_free(arr); + *errmsg = e_invalid_argument; + return NULL; +} + +/* + * Update w_hl for "wp" using given option value. Returns error + * message on failure, otherwise NULL. + */ + char * +update_winhighlight(win_T *wp, char_u *opt) +{ + char *err = NULL; + hl_override_T *arr; + int num = 1; + + arr = parse_winhighlight(opt, &num, &err); + + if (arr == NULL && err != NULL) + return err; + + update_highlight_overrides(wp->w_hl, arr, num); + + vim_free(wp->w_hl); + wp->w_hl = arr; + wp->w_hl_len = num; + + wp->w_hlfwin_id = hlf_get_id(wp, HLF_WIN); + +#ifdef FEAT_TERMINAL + term_update_hlfwin(wp); +#endif + +#ifdef FEAT_TERMINAL + // May be NULL (such as in after_copy_winopt()) + if (wp->w_buffer != NULL) + { + // Make sure terminal highlighting is updated + bool ret = push_highlight_overrides(wp->w_hl, wp->w_hl_len); + + if (wp->w_buffer->b_term != NULL) + term_init_default_colors(wp->w_buffer->b_term); + if (ret) + pop_highlight_overrides(); + } +#endif + + return NULL; +} + +/* + * Get id that the hlf attr is using in window "wp", otherwise zero. Note that + * -1 may be returned if the hlf was set to itself. + */ + int +hlf_get_id(win_T *wp, int hlf) +{ + int id; + static int prev[HLF_COUNT]; + + if (wp->w_hl == NULL) + return highlight_ids[hlf]; + + memcpy(prev, highlight_ids, sizeof(highlight_ids)); + set_highlight_attr(wp->w_hl, wp->w_hl_len, true); + id = highlight_ids[hlf]; + memcpy(highlight_ids, prev, sizeof(highlight_ids)); + + return id; +} + +/* + * Update 'winhighlight' using a 'wincolor' style option value. Returns error + * message on failure otherwise NULL. Does not update the actual 'wincolor' + * value, but does update the 'winhighlight' value. + */ + char * +update_wincolor(win_T *wp, char_u *opt) +{ + char_u *str = *opt == NUL ? "" : alloc(sizeof("!(:") + STRLEN(opt)); + char *errmsg; + + if (str == NULL) + return e_out_of_memory; + + if (*opt != NUL) + sprintf((char *)str, "!(:%s", opt); + + errmsg = update_winhighlight(wp, str); + + if (errmsg == NULL) + set_string_option_direct_in_win(wp, (char_u *)"winhighlight", -1, + str, OPT_FREE|OPT_LOCAL, 0); + + if (*opt != NUL) + free(str); + return errmsg; +} diff --git a/src/match.c b/src/match.c index ff7e8d9f3d..912abfd74b 100644 --- a/src/match.c +++ b/src/match.c @@ -323,6 +323,9 @@ init_search_hl(win_T *wp, match_T *search_hl) cur->mit_hl.first_lnum = 0; cur = cur->mit_next; } + // Must update this every time since highlight group override can change it. + search_hl->attr = HL_ATTR(HLF_L); + search_hl->buf = wp->w_buffer; search_hl->lnum = 0; search_hl->first_lnum = 0; diff --git a/src/option.c b/src/option.c index e4a94e1c6e..8de0d9c685 100644 --- a/src/option.c +++ b/src/option.c @@ -4401,7 +4401,7 @@ did_set_termguicolors(optset_T *args UNUSED) # ifdef FEAT_TERMINAL term_update_colors_all(); term_update_palette_all(); - term_update_wincolor_all(); + term_update_hlfwin_all(); # endif p_tgc_set = TRUE; @@ -6860,6 +6860,8 @@ get_varp(struct vimoption *p) case PV_COCU: return (char_u *)&(curwin->w_p_cocu); case PV_COLE: return (char_u *)&(curwin->w_p_cole); #endif + case PV_WHL: return (char_u *)&(curwin->w_p_whl); + #ifdef FEAT_TERMINAL case PV_TWK: return (char_u *)&(curwin->w_p_twk); case PV_TWS: return (char_u *)&(curwin->w_p_tws); @@ -7041,6 +7043,11 @@ win_copy_options(win_T *wp_from, win_T *wp_to) void after_copy_winopt(win_T *wp) { + char *errmsg = update_winhighlight(wp, wp->w_p_whl); + + if (errmsg != NULL) + emsg(_(errmsg)); + // Set w_leftcol or w_skipcol to zero. if (wp->w_p_wrap) wp->w_leftcol = 0; @@ -7170,6 +7177,7 @@ copy_winopt(winopt_T *from, winopt_T *to) to->wo_fde_flags = from->wo_fde_flags; to->wo_fdt_flags = from->wo_fdt_flags; #endif + to->wo_whl = copy_option_val(from->wo_whl); #ifdef FEAT_EVAL // Copy the script context so that we know where the value was last set. @@ -7236,6 +7244,7 @@ check_winopt(winopt_T *wop UNUSED) check_string_option(&wop->wo_lcs); check_string_option(&wop->wo_fcs); check_string_option(&wop->wo_ve); + check_string_option(&wop->wo_whl); } /* @@ -7285,6 +7294,7 @@ clear_winopt(winopt_T *wop UNUSED) clear_string_option(&wop->wo_lcs); clear_string_option(&wop->wo_fcs); clear_string_option(&wop->wo_ve); + clear_string_option(&wop->wo_whl); } #ifdef FEAT_EVAL diff --git a/src/option.h b/src/option.h index 46b8daf09e..fddc3905cb 100644 --- a/src/option.h +++ b/src/option.h @@ -1389,6 +1389,7 @@ enum , WV_WFB , WV_WFH , WV_WFW + , WV_WHL , WV_WRAP #ifdef FEAT_SIGNS , WV_SCL diff --git a/src/optiondefs.h b/src/optiondefs.h index 6509434809..2a2b1c0da6 100644 --- a/src/optiondefs.h +++ b/src/optiondefs.h @@ -228,6 +228,7 @@ #define PV_WFB OPT_WIN(WV_WFB) #define PV_WFH OPT_WIN(WV_WFH) #define PV_WFW OPT_WIN(WV_WFW) +#define PV_WHL OPT_WIN(WV_WHL) #define PV_WRAP OPT_WIN(WV_WRAP) #define PV_CRBIND OPT_WIN(WV_CRBIND) #ifdef FEAT_CONCEAL @@ -2979,6 +2980,9 @@ static struct vimoption options[] = (char_u *)&p_wh, PV_NONE, did_set_winheight_helpheight, NULL, {(char_u *)1L, (char_u *)0L} SCTX_INIT}, + {"winhighlight", "whl", P_STRING|P_VI_DEF|P_RALL|P_ONECOMMA|P_NODUP|P_COLON, + (char_u *)VAR_WIN, PV_WHL, did_set_winhighlight, expand_set_winhighlight, + {(char_u *)"", (char_u *)NULL} SCTX_INIT}, {"winminheight", "wmh", P_NUM|P_VI_DEF, (char_u *)&p_wmh, PV_NONE, did_set_winminheight, NULL, {(char_u *)1L, (char_u *)0L} SCTX_INIT}, diff --git a/src/optionstr.c b/src/optionstr.c index d4287b46cc..7fb8bf548a 100644 --- a/src/optionstr.c +++ b/src/optionstr.c @@ -503,7 +503,6 @@ set_string_option_direct( #endif } -#if defined(FEAT_PROP_POPUP) || (defined(FEAT_DIFF) && defined(FEAT_FOLDING)) /* * Like set_string_option_direct(), but for a window-local option in "wp". * Blocks autocommands to avoid the old curwin becoming invalid. @@ -527,7 +526,6 @@ set_string_option_direct_in_win( curbuf = curwin->w_buffer; unblock_autocmds(); } -#endif #if defined(FEAT_PROP_POPUP) /* @@ -2815,6 +2813,63 @@ did_set_highlight(optset_T *args UNUSED) return NULL; } + static int +expand_hl_occasions( + optexpand_T *args, + int *numMatches, + char_u ***matches, + char_u prefix) +{ + char_u *p; + static char_u hl_flags[HLF_COUNT] = HL_FLAGS; + size_t i; + int count = 0; + + *matches = ALLOC_MULT(char_u *, HLF_COUNT + 1); + if (*matches == NULL) + return FAIL; + + // We still want to return the full option if it's requested. + if (args->oe_include_orig_val) + { + p = vim_strsave(args->oe_opt_value); + if (p == NULL) + { + VIM_CLEAR(*matches); + return FAIL; + } + (*matches)[count++] = p; + } + + for (i = 0; i < HLF_COUNT; i++) + { + p = alloc((prefix == NUL ? 1 : 2) + 1); + if (p == NULL) + { + if (count == 0) + { + VIM_CLEAR(*matches); + return FAIL; + } + else + break; + } + if (prefix == NUL) + sprintf((char *)p, "%c", hl_flags[i]); + else + sprintf((char *)p, "%c%c", prefix, hl_flags[i]); + (*matches)[count++] = p; + } + + if (count == 0) + { + VIM_CLEAR(*matches); + return FAIL; + } + *numMatches = count; + return OK; +} + /* * Expand 'highlight' option. */ @@ -2823,7 +2878,6 @@ expand_set_highlight(optexpand_T *args, int *numMatches, char_u ***matches) { char_u *p; expand_T *xp = args->oe_xp; - static char_u hl_flags[HLF_COUNT] = HL_FLAGS; size_t i; int count = 0; @@ -2838,49 +2892,9 @@ expand_set_highlight(optexpand_T *args, int *numMatches, char_u ***matches) } if (*xp->xp_pattern == NUL) - { // At beginning of a comma-separated list. Return the specific list of // supported occasions. - *matches = ALLOC_MULT(char_u *, HLF_COUNT + 1); - if (*matches == NULL) - return FAIL; - - // We still want to return the full option if it's requested. - if (args->oe_include_orig_val) - { - p = vim_strsave(args->oe_opt_value); - if (p == NULL) - { - VIM_CLEAR(*matches); - return FAIL; - } - (*matches)[count++] = p; - } - - for (i = 0; i < HLF_COUNT; i++) - { - p = vim_strnsave(&hl_flags[i], 1); - if (p == NULL) - { - if (count == 0) - { - VIM_CLEAR(*matches); - return FAIL; - } - else - break; - } - (*matches)[count++] = p; - } - - if (count == 0) - { - VIM_CLEAR(*matches); - return FAIL; - } - *numMatches = count; - return OK; - } + return expand_hl_occasions(args, numMatches, matches, NUL); // We are after the initial character (which indicates the occasion). We // already made sure we are not matching after a ':' above, so now we want @@ -4928,12 +4942,48 @@ expand_set_winaltkeys(optexpand_T *args, int *numMatches, char_u ***matches) char * did_set_wincolor(optset_T *args UNUSED) { -#ifdef FEAT_TERMINAL - term_update_wincolor(curwin); -#endif + update_wincolor(curwin, args->os_newval.string); return NULL; } +/* + * The 'winhighlight' option is changed + */ + char * +did_set_winhighlight(optset_T *args) +{ + return update_winhighlight(curwin, args->os_newval.string); +} + +/* + * Expand 'winhighlight' option. + */ + int +expand_set_winhighlight(optexpand_T *args, int *numMatches, char_u ***matches) +{ + expand_T *xp = args->oe_xp; + + if ((xp->xp_pattern > args->oe_set_arg && *(xp->xp_pattern-1) == ':') + || xp->xp_pattern == args->oe_set_arg || *(xp->xp_pattern-1) == ',') + { + // After a ':' or after a ',', or at the start, so expand highlight + // group name. + + // If starts with !, then expand 'highlight' occasions. + if (*xp->xp_pattern == '!') + return expand_hl_occasions(args, numMatches, matches, '!'); + else + return expand_set_opt_generic( + args, + get_highlight_name, + numMatches, + matches); + } + + VIM_CLEAR(*matches); + return FAIL; +} + int expand_set_wincolor(optexpand_T *args, int *numMatches, char_u ***matches) { diff --git a/src/popupmenu.c b/src/popupmenu.c index d316ba99ed..b8c72d44f8 100644 --- a/src/popupmenu.c +++ b/src/popupmenu.c @@ -905,6 +905,10 @@ pum_redraw(void) int last_isabbr = FALSE; int orig_attr = -1; int scroll_range = pum_size - pum_height; + bool override_success; + + // Use current window for highlight overrides when using 'winhighlight' + override_success = push_highlight_overrides(curwin->w_hl, curwin->w_hl_len); hlf_T hlfsNorm[3]; hlf_T hlfsSel[3]; @@ -1042,6 +1046,9 @@ pum_redraw(void) #ifdef FEAT_PROP_POPUP screen_zindex = 0; #endif + + if (override_success) + pop_highlight_overrides(); } #if defined(FEAT_PROP_POPUP) && defined(FEAT_QUICKFIX) diff --git a/src/popupwin.c b/src/popupwin.c index 399ab67ac3..7cd39b071c 100644 --- a/src/popupwin.c +++ b/src/popupwin.c @@ -826,11 +826,25 @@ apply_general_options(win_T *wp, dict_T *dict) str = dict_get_string(dict, "highlight", FALSE); if (str != NULL) { - set_string_option_direct_in_win(wp, (char_u *)"wincolor", -1, - str, OPT_FREE|OPT_LOCAL, 0); -#ifdef FEAT_TERMINAL - term_update_wincolor(wp); -#endif + char *errmsg = update_wincolor(wp, str); + + if (errmsg == NULL) + set_string_option_direct_in_win(wp, (char_u *)"wincolor", -1, + str, OPT_FREE|OPT_LOCAL, 0); + else + emsg(_(errmsg)); + } + + str = dict_get_string(dict, "highlights", FALSE); + if (str != NULL) + { + char *errmsg = update_winhighlight(wp, str); + + if (errmsg == NULL) + set_string_option_direct_in_win(wp, (char_u *)"winhighlight", -1, + str, OPT_FREE|OPT_LOCAL, 0); + else + emsg(_(errmsg)); } if (set_padding_border(dict, wp->w_popup_padding, "padding", 999) == FAIL || @@ -1894,11 +1908,18 @@ parse_popup_option(win_T *wp, int is_preview) { if (wp != NULL) { + char *errmsg; int c = *p; *p = NUL; - set_string_option_direct_in_win(wp, (char_u *)"wincolor", -1, - s + 10, OPT_FREE|OPT_LOCAL, 0); + + errmsg = update_wincolor(wp, s + 10); + if (errmsg == NULL) + set_string_option_direct_in_win(wp, (char_u *)"wincolor", + -1, s + 10, OPT_FREE|OPT_LOCAL, 0); + else + emsg(_(errmsg)); + *p = c; } } @@ -2218,9 +2239,14 @@ popup_update_color(win_T *wp, create_type_T type) { char *hiname = type == TYPE_MESSAGE_WIN ? "MessageWindow" : "PopupNotification"; - set_string_option_direct_in_win(wp, (char_u *)"wincolor", -1, - (char_u *)hiname, - OPT_FREE|OPT_LOCAL, 0); + char *errmsg; + + errmsg = update_wincolor(wp, (char_u *)hiname); + if (errmsg == NULL) + set_string_option_direct_in_win(wp, (char_u *)"wincolor", -1, + (char_u *)hiname, OPT_FREE|OPT_LOCAL, 0); + else + emsg(_(errmsg)); } /* @@ -3681,7 +3707,8 @@ f_popup_getoptions(typval_T *argvars, typval_T *rettv) (wp->w_popup_flags & POPF_OPACITY) ? 100 - wp->w_popup_blend : 100); dict_add_number(dict, "cursorline", (wp->w_popup_flags & POPF_CURSORLINE) != 0); - dict_add_string(dict, "highlight", wp->w_p_wcr); + dict_add_string(dict, "highlight", syn_id2name(hlf_get_id(wp, HLF_WIN))); + dict_add_string(dict, "highlights", wp->w_p_whl); if (wp->w_scrollbar_highlight != NULL) dict_add_string(dict, "scrollbarhighlight", wp->w_scrollbar_highlight); @@ -4494,7 +4521,7 @@ draw_opacity_padding_cell( if (enc_utf8) ScreenLinesUC[off] = 0; int popup_attr_val = - get_wcr_attr(screen_opacity_popup); + get_win_attr(screen_opacity_popup); int blend = screen_opacity_popup->w_popup_blend; ScreenAttrs[off] = hl_blend_attr(ScreenAttrs[off], popup_attr_val, blend, TRUE); @@ -4525,7 +4552,7 @@ draw_opacity_padding_cell( ScreenAttrs[off] = saved_screenattrs[save_off]; int popup_attr_val = - get_wcr_attr(screen_opacity_popup); + get_win_attr(screen_opacity_popup); int blend = screen_opacity_popup->w_popup_blend; ScreenAttrs[base_off] = hl_blend_attr( ScreenAttrs[base_off], @@ -4547,7 +4574,7 @@ draw_opacity_padding_cell( ScreenAttrs[off] = saved_screenattrs[save_off]; if (enc_utf8 && ScreenLinesUC != NULL) ScreenLinesUC[off] = 0; - int popup_attr_val = get_wcr_attr(screen_opacity_popup); + int popup_attr_val = get_win_attr(screen_opacity_popup); int blend = screen_opacity_popup->w_popup_blend; ScreenAttrs[off] = hl_blend_attr(ScreenAttrs[off], popup_attr_val, blend, TRUE); @@ -4567,7 +4594,7 @@ draw_opacity_padding_cell( ScreenLinesUC[base_off] = saved_screenlinesuc[base_save_off]; ScreenLinesUC[off] = saved_screenlinesuc[save_off]; - int popup_attr_val = get_wcr_attr(screen_opacity_popup); + int popup_attr_val = get_win_attr(screen_opacity_popup); int blend = screen_opacity_popup->w_popup_blend; ScreenAttrs[base_off] = hl_blend_attr(ScreenAttrs[base_off], popup_attr_val, blend, TRUE); @@ -4597,7 +4624,7 @@ draw_opacity_padding_cell( ScreenLinesUC[off] = 0; } - int popup_attr_val = get_wcr_attr(screen_opacity_popup); + int popup_attr_val = get_win_attr(screen_opacity_popup); int blend = screen_opacity_popup->w_popup_blend; ScreenAttrs[off] = hl_blend_attr(ScreenAttrs[off], popup_attr_val, blend, TRUE); @@ -4658,6 +4685,7 @@ update_popups(void (*win_update)(win_T *wp)) int sb_thumb_height = 0; int attr_scroll = 0; int attr_thumb = 0; + bool override_success; // hide the cursor until redrawing is done. cursor_off(); @@ -4690,6 +4718,8 @@ update_popups(void (*win_update)(win_T *wp)) int title_len = 0; int title_wincol; + override_success = push_highlight_overrides(wp->w_hl, wp->w_hl_len); + // This drawing uses the zindex of the popup window, so that it's on // top of the text but doesn't draw when another popup with higher // zindex is on top of the character. @@ -4858,7 +4888,7 @@ update_popups(void (*win_update)(win_T *wp)) total_width = popup_width(wp) - wp->w_popup_rightoff; total_height = popup_height(wp); - popup_attr = get_wcr_attr(wp); + popup_attr = get_win_attr(wp); if (wp->w_winrow + total_height > cmdline_row) wp->w_popup_flags |= POPF_ON_CMDLINE; @@ -5225,6 +5255,9 @@ update_popups(void (*win_update)(win_T *wp)) // if this was the message window popup may start the timer now may_start_message_win_timer(wp); #endif + + if (override_success) + pop_highlight_overrides(); } #ifdef FEAT_PROP_POPUP diff --git a/src/proto/highlight.pro b/src/proto/highlight.pro index 908765c217..a7691c88fc 100644 --- a/src/proto/highlight.pro +++ b/src/proto/highlight.pro @@ -48,4 +48,10 @@ int expand_highlight_group(char_u *pat, expand_T *xp, regmatch_T *rmp, char_u ** void free_highlight_fonts(void); void f_hlget(typval_T *argvars, typval_T *rettv); void f_hlset(typval_T *argvars, typval_T *rettv); +void update_highlight_overrides(hl_override_T *old, hl_override_T *new, int newlen); +bool push_highlight_overrides(hl_override_T *arr, int len); +void pop_highlight_overrides(void); +char *update_winhighlight(win_T *wp, char_u *opt); +int hlf_get_id(win_T *wp, int hlf); +char *update_wincolor(win_T *wp, char_u *opt); /* vim: set ft=c : */ diff --git a/src/proto/optionstr.pro b/src/proto/optionstr.pro index 7e55d3b199..e4e39e759c 100644 --- a/src/proto/optionstr.pro +++ b/src/proto/optionstr.pro @@ -207,6 +207,8 @@ int expand_set_wildoptions(optexpand_T *args, int *numMatches, char_u ***matches char *did_set_winaltkeys(optset_T *args); int expand_set_winaltkeys(optexpand_T *args, int *numMatches, char_u ***matches); char *did_set_wincolor(optset_T *args); +char *did_set_winhighlight(optset_T *args); +int expand_set_winhighlight(optexpand_T *args, int *numMatches, char_u ***matches); int expand_set_wincolor(optexpand_T *args, int *numMatches, char_u ***matches); char *did_set_string_option(int opt_idx, char_u **varp, char_u *oldval, char_u *value, char *errbuf, size_t errbuflen, int opt_flags, set_op_T op, int *value_checked); int check_ff_value(char_u *p); diff --git a/src/proto/screen.pro b/src/proto/screen.pro index cf7cd95f46..2dce886917 100644 --- a/src/proto/screen.pro +++ b/src/proto/screen.pro @@ -1,7 +1,7 @@ /* screen.c */ int conceal_cursor_line(win_T *wp); void conceal_check_cursor_line(int was_concealed); -int get_wcr_attr(win_T *wp); +int get_win_attr(win_T *wp); void win_draw_end(win_T *wp, int c1, int c2, int draw_margin, int row, int endrow, hlf_T hl); int compute_foldcolumn(win_T *wp, int col); size_t fill_foldcolumn(char_u *p, win_T *wp, int closed, linenr_T lnum); diff --git a/src/proto/terminal.pro b/src/proto/terminal.pro index dfa59cced1..5ae6b4ca61 100644 --- a/src/proto/terminal.pro +++ b/src/proto/terminal.pro @@ -35,9 +35,10 @@ int term_is_finished(buf_T *buf); int term_show_buffer(buf_T *buf); void term_change_in_curbuf(void); int term_get_attr(win_T *wp, linenr_T lnum, int col); -void term_reset_wincolor(win_T *wp); -void term_update_wincolor(win_T *wp); -void term_update_wincolor_all(void); +void term_reset_hlfwin(win_T *wp); +void term_update_hlfwin(win_T *wp); +void term_update_hlfwin_all(void); +void term_init_default_colors(term_T *term); void term_update_palette_all(void); void term_update_colors_all(void); char_u *term_get_status_text(term_T *term); diff --git a/src/screen.c b/src/screen.c index 716715558c..316b18b207 100644 --- a/src/screen.c +++ b/src/screen.c @@ -111,26 +111,31 @@ conceal_check_cursor_line(int was_concealed) #endif /* - * Get 'wincolor' attribute for window "wp". If not set and "wp" is a popup - * window then get the "Pmenu" highlight attribute. + * Get HLF_WIN attribute for window "wp". If not set and "wp" is a popup window + * then get the "Pmenu" highlight attribute. */ int -get_wcr_attr(win_T *wp) +get_win_attr(win_T *wp) { - int wcr_attr = 0; + int win_attr = wp->w_hlfwin_id; - if (*wp->w_p_wcr != NUL) - wcr_attr = syn_name2attr(wp->w_p_wcr); + if (win_attr != 0) + { + if (win_attr != -1) + win_attr = syn_id2attr(win_attr); + else + win_attr = 0; + } #ifdef FEAT_PROP_POPUP else if (WIN_IS_POPUP(wp)) { if (wp->w_popup_flags & POPF_INFO) - wcr_attr = HL_ATTR(HLF_PSI); // PmenuSel + win_attr = HL_ATTR(HLF_PSI); // PmenuSel else - wcr_attr = HL_ATTR(HLF_PNI); // Pmenu + win_attr = HL_ATTR(HLF_PNI); // Pmenu } #endif - return wcr_attr; + return win_attr; } /* @@ -184,9 +189,9 @@ win_draw_end( { int n = 0; int attr = HL_ATTR(hl); - int wcr_attr = get_wcr_attr(wp); + int win_attr = get_win_attr(wp); - attr = hl_combine_attr(wcr_attr, attr); + attr = hl_combine_attr(win_attr, attr); if (draw_margin) { @@ -196,19 +201,19 @@ win_draw_end( if (fdc > 0) // draw the fold column n = screen_fill_end(wp, ' ', ' ', n, fdc, - row, endrow, hl_combine_attr(wcr_attr, HL_ATTR(HLF_FC))); + row, endrow, hl_combine_attr(win_attr, HL_ATTR(HLF_FC))); #endif #ifdef FEAT_SIGNS if (signcolumn_on(wp)) // draw the sign column n = screen_fill_end(wp, ' ', ' ', n, 2, - row, endrow, hl_combine_attr(wcr_attr, HL_ATTR(HLF_SC))); + row, endrow, hl_combine_attr(win_attr, HL_ATTR(HLF_SC))); #endif if ((wp->w_p_nu || wp->w_p_rnu) && vim_strchr(p_cpo, CPO_NUMCOL) == NULL) // draw the number column n = screen_fill_end(wp, ' ', ' ', n, number_width(wp) + 1, - row, endrow, hl_combine_attr(wcr_attr, HL_ATTR(HLF_N))); + row, endrow, hl_combine_attr(win_attr, HL_ATTR(HLF_N))); } #ifdef FEAT_RIGHTLEFT @@ -658,7 +663,7 @@ screen_line( // Wide char doesn't fit at the edge. Replace with a // blended space so opacity is still applied. int char_attr = ScreenAttrs[off_from]; - int popup_attr = get_wcr_attr(screen_opacity_popup); + int popup_attr = get_win_attr(screen_opacity_popup); int combined = hl_combine_attr(popup_attr, char_attr); int blend = screen_opacity_popup->w_popup_blend; ScreenLines[off_to] = ' '; @@ -687,7 +692,7 @@ screen_line( // attribute (e.g. match highlight) so that its background // color is preserved on blank cells. int char_attr = ScreenAttrs[off_from]; - int popup_attr = get_wcr_attr(screen_opacity_popup); + int popup_attr = get_win_attr(screen_opacity_popup); int combined = hl_combine_attr(popup_attr, char_attr); int blend = screen_opacity_popup->w_popup_blend; ScreenAttrs[off_to] = hl_blend_attr(ScreenAttrs[off_to], @@ -712,7 +717,7 @@ screen_line( && (!enc_utf8 || ScreenLinesUC[off_to] == 0)) { int char_attr = ScreenAttrs[off_from]; - int popup_attr = get_wcr_attr(screen_opacity_popup); + int popup_attr = get_win_attr(screen_opacity_popup); int combined = hl_combine_attr(popup_attr, char_attr); int blend = screen_opacity_popup->w_popup_blend; ScreenLines[off_to] = ' '; @@ -869,7 +874,7 @@ skip_opacity: && screen_opacity_popup->w_popup_blend > 0) { int char_attr = ScreenAttrs[off_from]; - int popup_attr = get_wcr_attr(screen_opacity_popup); + int popup_attr = get_win_attr(screen_opacity_popup); int blend = screen_opacity_popup->w_popup_blend; // Combine popup window color with the character's own // attribute (e.g. syntax highlighting) so that the @@ -1747,7 +1752,6 @@ start_search_hl(void) end_search_hl(); // just in case it wasn't called before last_pat_prog(&screen_search_hl.rm); - screen_search_hl.attr = HL_ATTR(HLF_L); } /* @@ -2499,7 +2503,7 @@ screen_fill( goto skip_opacity_fill; } - int popup_attr = get_wcr_attr(screen_opacity_popup); + int popup_attr = get_win_attr(screen_opacity_popup); int blend = screen_opacity_popup->w_popup_blend; // Blend both foreground and background for padding area ScreenAttrs[off] = hl_blend_attr(ScreenAttrs[off], @@ -4559,9 +4563,9 @@ draw_tabline(void) int modified; int c; int len; - int attr_sel = HL_ATTR(HLF_TPS); - int attr_nosel = HL_ATTR(HLF_TP); - int attr_fill = HL_ATTR(HLF_TPF); + int attr_sel; + int attr_nosel; + int attr_fill; char_u *p; int room; int use_sep_chars = (t_colors < 8 @@ -4572,6 +4576,7 @@ draw_tabline(void) && !p_tgc #endif ); + bool override_success; #if defined(FEAT_TABPANEL) col = firstwin->w_wincol; @@ -4609,13 +4614,21 @@ draw_tabline(void) if (tabwidth < 6) tabwidth = 6; - attr = attr_nosel; tabcount = 0; for (tp = first_tabpage; tp != NULL && col < Columns - 4; tp = tp->tp_next) { scol = col; + override_success = push_highlight_overrides( + tp->tp_curwin->w_hl, tp->tp_curwin->w_hl_len); + + // Update them each time since highlight override might change them. + attr_sel = HL_ATTR(HLF_TPS); + attr_nosel = HL_ATTR(HLF_TP); + attr_fill = HL_ATTR(HLF_TPF); + attr = attr_nosel; + if (tp->tp_topframe == topframe) attr = attr_sel; if (use_sep_chars && col > 0) @@ -4697,6 +4710,9 @@ draw_tabline(void) ++tabcount; while (scol < col) TabPageIdxs[scol++] = tabcount; + + if (override_success) + pop_highlight_overrides(); } if (use_sep_chars) diff --git a/src/structs.h b/src/structs.h index 1fdc2ee1b9..b0b559e8a9 100644 --- a/src/structs.h +++ b/src/structs.h @@ -368,6 +368,8 @@ typedef struct sctx_T wo_script_ctx[WV_COUNT]; // SCTXs for window-local options # define w_p_script_ctx w_onebuf_opt.wo_script_ctx #endif + char_u *wo_whl; +#define w_p_whl w_onebuf_opt.wo_whl // 'winhighlight' } winopt_T; /* @@ -3949,6 +3951,17 @@ typedef struct int truncrl; } fill_chars_T; +/* + * Represents current highlight overrides (used by 'winhighlight' option). The + * highlight group with ID "from" will be overridden by the highlight group with + * ID "to" + */ +typedef struct +{ + int from; // If zero or negative then it is hlf_T enum + int to; // Same thing as "from" +} hl_override_T; + /* * Structure which contains all information that belongs to a window * @@ -4207,7 +4220,7 @@ struct window_S // column being used #endif #ifdef FEAT_TERMINAL - termcellcolor_T w_term_wincolor; // cache for term color of 'wincolor' + termcellcolor_T w_term_hlfwin; // cache for term color of HLF_WIN #endif /* @@ -4362,6 +4375,11 @@ struct window_S #ifdef FEAT_RUBY void *w_ruby_ref; #endif + + hl_override_T *w_hl; + int w_hl_len; + int w_hlfwin_id; // Cached HLF_WIN highlight group id, zero if none, + // or -1 if it was set to itself. }; /* diff --git a/src/terminal.c b/src/terminal.c index 02ca5d6d95..cea79dac6e 100644 --- a/src/terminal.c +++ b/src/terminal.c @@ -2184,10 +2184,6 @@ may_move_terminal_to_buffer(term_T *term, int redraw) <= term->tl_scrollback_scrolled) update_snapshot(term); - // Obtain the current background color. - vterm_state_get_default_colors(vterm_obtain_state(term->tl_vterm), - &term->tl_default_color.fg, &term->tl_default_color.bg); - if (redraw) { win_T *wp = NULL; @@ -2607,8 +2603,8 @@ term_get_highlight_id(term_T *term, win_T *wp) { char_u *name; - if (wp != NULL && *wp->w_p_wcr != NUL) - name = wp->w_p_wcr; + if (wp != NULL && wp->w_hlfwin_id != 0) + name = syn_id2name(wp->w_hlfwin_id); else if (term->tl_highlight_name != NULL) name = term->tl_highlight_name; else @@ -3179,12 +3175,12 @@ cell2attr( if (is_default_fg || is_default_bg) { - if (wp != NULL && *wp->w_p_wcr != NUL) + if (wp != NULL && wp->w_hlfwin_id != 0) { if (is_default_fg) - fg = &wp->w_term_wincolor.fg; + fg = &wp->w_term_hlfwin.fg; if (is_default_bg) - bg = &wp->w_term_wincolor.bg; + bg = &wp->w_term_hlfwin.bg; } else { @@ -4352,25 +4348,23 @@ get_vterm_color_from_synid(int id, VTermColor *fg, VTermColor *bg) } void -term_reset_wincolor(win_T *wp) +term_reset_hlfwin(win_T *wp) { - wp->w_term_wincolor.fg.type = VTERM_COLOR_INVALID | VTERM_COLOR_DEFAULT_FG; - wp->w_term_wincolor.bg.type = VTERM_COLOR_INVALID | VTERM_COLOR_DEFAULT_BG; + wp->w_term_hlfwin.fg.type = VTERM_COLOR_INVALID | VTERM_COLOR_DEFAULT_FG; + wp->w_term_hlfwin.bg.type = VTERM_COLOR_INVALID | VTERM_COLOR_DEFAULT_BG; } /* - * Cache the color of 'wincolor'. + * Cache the color of HLF_WIN. */ void -term_update_wincolor(win_T *wp) +term_update_hlfwin(win_T *wp) { - int id = 0; + int id = wp->w_hlfwin_id; - if (*wp->w_p_wcr != NUL) - id = syn_name2id(wp->w_p_wcr); - if (id == 0 || !get_vterm_color_from_synid(id, &wp->w_term_wincolor.fg, - &wp->w_term_wincolor.bg)) - term_reset_wincolor(wp); + if (id == 0 || !get_vterm_color_from_synid(id == -1 ? 0 : id, + &wp->w_term_hlfwin.fg, &wp->w_term_hlfwin.bg)) + term_reset_hlfwin(wp); } /* @@ -4378,20 +4372,20 @@ term_update_wincolor(win_T *wp) * or when any highlight is changed. */ void -term_update_wincolor_all(void) +term_update_hlfwin_all(void) { win_T *wp = NULL; int did_curwin = FALSE; while (for_all_windows_and_curwin(&wp, &did_curwin)) - term_update_wincolor(wp); + term_update_hlfwin(wp); } /* * Initialize term->tl_default_color from the environment. */ - static void -init_default_colors(term_T *term) + void +term_init_default_colors(term_T *term) { VTermColor *fg, *bg; int fgval, bgval; @@ -4960,7 +4954,7 @@ create_vterm(term_T *term, int rows, int cols) // TODO: depends on 'encoding'. vterm_set_utf8(vterm, 1); - init_default_colors(term); + term_init_default_colors(term); vterm_state_set_default_colors( state, @@ -5066,7 +5060,7 @@ term_update_colors_all(void) { if (term->tl_vterm == NULL) continue; - init_default_colors(term); + term_init_default_colors(term); vterm_state_set_default_colors( vterm_obtain_state(term->tl_vterm), &term->tl_default_color.fg, @@ -5821,7 +5815,7 @@ term_load_dump(typval_T *argvars, typval_T *rettv, int do_diff) VTermPos cursor_pos1; VTermPos cursor_pos2; - init_default_colors(term); + term_init_default_colors(term); rettv->vval.v_number = buf->b_fnum; diff --git a/src/testdir/dumps/Test_winhighlight_1.dump b/src/testdir/dumps/Test_winhighlight_1.dump new file mode 100644 index 0000000000..aa2760bd9b --- /dev/null +++ b/src/testdir/dumps/Test_winhighlight_1.dump @@ -0,0 +1,8 @@ +| +2&#ffffff0|2+2#e000e06&|++2#0000000&| |[|N|o| |N|a|m|e|]| | +8#0000001#e0e0e08|[|N|o| |N|a|m|e|]| @1|[|N|o| |N|a|m|e|]| | +1#0000000#ffffff0@37|X+8#0000001#e0e0e08 +>F+0#ffffff16#e000002|o|u|r| @32||+1#0000000#ffffff0|F+8&&|o|u|r| @32 +|F+0&&|i|v|e| @32||+1&&|F+0&&|i|v|e| @32 +|S|i|x| @33||+1&&|S+0&&|i|x| @33 +|~+0#4040ff13&| @35||+1#0000000&|~+0#4040ff13&| @35 +|~| @35||+1#0000000&|~+0#4040ff13&| @35 +|[+3#0000000&|N|o| |N|a|m|e|]| |[|+|]| @5|1|,|1| @11|A|l@1| |[+1&&|N|o| |N|a|m|e|]| |[|+|]| @5|1|,|1| @11|A|l@1 +|:+0&&|s|e|t|l|o|c|a|l| |w|h|l|=|C|u|r|s|o|r|L|i|n|e|:|E|r@1|o|r|M|s|g| @41 diff --git a/src/testdir/dumps/Test_winhighlight_10.dump b/src/testdir/dumps/Test_winhighlight_10.dump new file mode 100644 index 0000000000..7b42eba43d --- /dev/null +++ b/src/testdir/dumps/Test_winhighlight_10.dump @@ -0,0 +1,8 @@ +| +0#ffffff16#e000002|2+0#e000e06&|++0#ffffff16&| |[|N|o| |N|a|m|e|]| | +8#0000001#e0e0e08|[|N|o| |N|a|m|e|]| | +2#0000000#ffffff0|[|N|o| |N|a|m|e|]| | +1&&@37|X+8#0000001#e0e0e08 +> +8#0000000#ffffff0@74 +|~+0#4040ff13&| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|:+0#0000000&|t|a|b|n| |3| @49|0|,|0|-|1| @8|A|l@1| diff --git a/src/testdir/dumps/Test_winhighlight_11.dump b/src/testdir/dumps/Test_winhighlight_11.dump new file mode 100644 index 0000000000..3534418acf --- /dev/null +++ b/src/testdir/dumps/Test_winhighlight_11.dump @@ -0,0 +1,8 @@ +| +8#0000001#e0e0e08|2+8#e000e06&|++8#0000001&| |[|N|o| |N|a|m|e|]| @1|[|N|o| |N|a|m|e|]| | +2#0000000#ffffff0|[|N|o| |N|a|m|e|]| | +1&&@37|X+8#0000001#e0e0e08 +> +8#0000000#ffffff0@74 +|~+0#4040ff13&| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|:+0#0000000&|t|a|b|n| |3| @49|0|,|0|-|1| @8|A|l@1| diff --git a/src/testdir/dumps/Test_winhighlight_12.dump b/src/testdir/dumps/Test_winhighlight_12.dump new file mode 100644 index 0000000000..12c31ec117 --- /dev/null +++ b/src/testdir/dumps/Test_winhighlight_12.dump @@ -0,0 +1,8 @@ +| +2&#ffffff0|2+2#e000e06&|++2#0000000&| |[|N|o| |N|a|m|e|]| | +8#0000001#e0e0e08|[|N|o| |N|a|m|e|]| @1|[|N|o| |N|a|m|e|]| | +1#0000000#ffffff0@37|X+8#0000001#e0e0e08 +|w+8#0000000#ffffff0|N|e|x>t|w|N|e|x|t|F|o|u|r| @22||+1&&|w+8&&|N|e|x|t|w|N|e|x|t|F|o|u|r| @22 +|F+0&&|i|v|e| @32||+1&&|F+0&&|i|v|e| @32 +|S|i|x| @33||+1&&|S+0&&|i|x| @33 +|~+0#4040ff13&| @35||+1#0000000&|~+0#4040ff13&| @35 +|~| @35||+1#0000000&|~+0#4040ff13&| @35 +|[+0#ffffff16#e000002|N|o| |N|a|m|e|]| |[|+|]| @5|1|,|5| @11|A|l@1| |[+1#0000000#ffffff0|N|o| |N|a|m|e|]| |[|+|]| @5|1|,|5| @11|A|l@1 +|:+0&&|s|e|t|l|o|c|a|l| |w|h|l|=|S|t|a|t|u|s|L|i|n|e|:|E|r@1|o|r|M|s|g| @41 diff --git a/src/testdir/dumps/Test_winhighlight_13.dump b/src/testdir/dumps/Test_winhighlight_13.dump new file mode 100644 index 0000000000..ae3e7d3a1f --- /dev/null +++ b/src/testdir/dumps/Test_winhighlight_13.dump @@ -0,0 +1,8 @@ +| +2&#ffffff0|2+2#e000e06&|++2#0000000&| |[|N|o| |N|a|m|e|]| | +8#0000001#e0e0e08|[|N|o| |N|a|m|e|]| @1|[|N|o| |N|a|m|e|]| | +1#0000000#ffffff0@37|X+8#0000001#e0e0e08 +|w+0#0000000#ffffff0|N|e|x|t|w|N|e|x|t|F|o|u|r| @22||+1&&|w+8&&|N|e|x|t|w|N|e|x|t|F|o|u|r| @22 +|F+0&&|i|v|e| @32||+1&&|F+0&&|i|v|e| @32 +|S+8&&|i>x| @33||+1&&|S+0&&|i|x| @33 +|~+0#4040ff13&| @35||+1#0000000&|~+0#4040ff13&| @35 +|~| @35||+1#0000000&|~+0#4040ff13&| @35 +|[+0#ffffff16#e000002|N|o| |N|a|m|e|]| |[|+|]| @5|3|,|3| @11|A|l@1| |[+1#0000000#ffffff0|N|o| |N|a|m|e|]| |[|+|]| @5|1|,|5| @11|A|l@1 +|:+0&&|s|e|t|l|o|c|a|l| |w|h|l|=|S|t|a|t|u|s|L|i|n|e|:|E|r@1|o|r|M|s|g| @41 diff --git a/src/testdir/dumps/Test_winhighlight_13a.dump b/src/testdir/dumps/Test_winhighlight_13a.dump new file mode 100644 index 0000000000..4a20d46476 --- /dev/null +++ b/src/testdir/dumps/Test_winhighlight_13a.dump @@ -0,0 +1,8 @@ +| +2&#ffffff0|2+2#e000e06&|++2#0000000&| |[|N|o| |N|a|m|e|]| | +8#0000001#e0e0e08|[|N|o| |N|a|m|e|]| @1|[|N|o| |N|a|m|e|]| | +1#0000000#ffffff0@37|X+8#0000001#e0e0e08 +|w+0#0000000#ffffff0|N|e|x|t|w|N|e|x|t|F|o|u|r| @22||+1&&|w+8&&|N|e|x|t|w|N|e|x|t|F|o|u|r| @22 +|F+0&&|i|v|e| @32||+1&&|F+0&&|i|v|e| @32 +|S+8&&|i|x| @33||+1&&|S+0&&|i|x| @33 +|~+0#4040ff13&| @35||+1#0000000&|~+0#4040ff13&| @35 +|~| @35||+1#0000000&|~+0#4040ff13&| @35 +|[+0#ffffff16#e000002|N|o| |N|a|m|e|]| |[|+|]| @5|3|,|3| @11|A|l@1| |[+1#0000000#ffffff0|N|o| |N|a|m|e|]| |[|+|]| @5|1|,|5| @11|A|l@1 +|:+0&&> @73 diff --git a/src/testdir/dumps/Test_winhighlight_14.dump b/src/testdir/dumps/Test_winhighlight_14.dump new file mode 100644 index 0000000000..1ea869d656 --- /dev/null +++ b/src/testdir/dumps/Test_winhighlight_14.dump @@ -0,0 +1,8 @@ +| +2&#ffffff0|2+2#e000e06&|++2#0000000&| |[|N|o| |N|a|m|e|]| | +8#0000001#e0e0e08|[|N|o| |N|a|m|e|]| @1|[|N|o| |N|a|m|e|]| | +1#0000000#ffffff0@37|X+8#0000001#e0e0e08 +|w+0#0000000#ffffff0|N|e|x|t|w|N|e|x|t|F|o|u|r| @22||+1&&|w+8&&|N|e|x>t|w|N|e|x|t|F|o|u|r| @22 +|F+0&&|i|v|e| @32||+1&&|F+0&&|i|v|e| @32 +|S+8&&|i|x| @33||+1&&|S+0&&|i|x| @33 +|~+0#4040ff13&| @35||+1#0000000&|~+0#4040ff13&| @35 +|~| @35||+1#0000000&|~+0#4040ff13&| @35 +|[+1#0000000&|N|o| |N|a|m|e|]| |[|+|]| @5|3|,|3| @11|A|l@1| |[+3&&|N|o| |N|a|m|e|]| |[|+|]| @5|1|,|5| @11|A|l@1 +|:+0&&|w|i|n|c|m|d| |l| @65 diff --git a/src/testdir/dumps/Test_winhighlight_15.dump b/src/testdir/dumps/Test_winhighlight_15.dump new file mode 100644 index 0000000000..a90302a86f --- /dev/null +++ b/src/testdir/dumps/Test_winhighlight_15.dump @@ -0,0 +1,8 @@ +| +2&#ffffff0|2+2#e000e06&|++2#0000000&| |[|N|o| |N|a|m|e|]| | +8#0000001#e0e0e08|[|N|o| |N|a|m|e|]| @1|[|N|o| |N|a|m|e|]| | +1#0000000#ffffff0@37|X+8#0000001#e0e0e08 +|w+0#0000000#ffffff0|N|e|x|t|w|N|e|x|t|F|o|u|r| @22||+1&&|w+8#ffffff16#e000002|N|e|x>t|w|N|e|x|t|F|o|u|r| @22 +|F+0#0000000#ffffff0|i|v|e| @32||+1&&|F+0#ffffff16#e000002|i|v|e| @32 +|S+8#0000000#ffffff0|i|x| @33||+1&&|S+0#ffffff16#e000002|i|x| @33 +|~+0#4040ff13#ffffff0| @35||+1#0000000&|~+0#4040ff13#e000002| @35 +|~+0&#ffffff0| @35||+1#0000000&|~+0#4040ff13#e000002| @35 +|[+1#0000000#ffffff0|N|o| |N|a|m|e|]| |[|+|]| @5|3|,|3| @11|A|l@1| |[+3&&|N|o| |N|a|m|e|]| |[|+|]| @5|1|,|5| @11|A|l@1 +|:+0&&|s|e|t|l|o|c|a|l| |w|h|l|=|N|o|r|m|a|l|:|E|r@1|o|r|M|s|g| @45 diff --git a/src/testdir/dumps/Test_winhighlight_2.dump b/src/testdir/dumps/Test_winhighlight_2.dump new file mode 100644 index 0000000000..b84ef70531 --- /dev/null +++ b/src/testdir/dumps/Test_winhighlight_2.dump @@ -0,0 +1,8 @@ +| +2&#ffffff0|2+2#e000e06&|++2#0000000&| |[|N|o| |N|a|m|e|]| | +8#0000001#e0e0e08|[|N|o| |N|a|m|e|]| @1|[|N|o| |N|a|m|e|]| | +1#0000000#ffffff0@37|X+8#0000001#e0e0e08 +|F+0#ffffff16#e000002|o|u|r| @32||+1#0000000#ffffff0>F+8&&|o|u|r| @32 +|F+0&&|i|v|e| @32||+1&&|F+0&&|i|v|e| @32 +|S|i|x| @33||+1&&|S+0&&|i|x| @33 +|~+0#4040ff13&| @35||+1#0000000&|~+0#4040ff13&| @35 +|~| @35||+1#0000000&|~+0#4040ff13&| @35 +|[+1#0000000&|N|o| |N|a|m|e|]| |[|+|]| @5|1|,|1| @11|A|l@1| |[+3&&|N|o| |N|a|m|e|]| |[|+|]| @5|1|,|1| @11|A|l@1 +|:+0&&|w|i|n|c|m|d| |l| @65 diff --git a/src/testdir/dumps/Test_winhighlight_3.dump b/src/testdir/dumps/Test_winhighlight_3.dump new file mode 100644 index 0000000000..636db41a21 --- /dev/null +++ b/src/testdir/dumps/Test_winhighlight_3.dump @@ -0,0 +1,8 @@ +| +2&#ffffff0|2+2#e000e06&|++2#0000000&| |[|N|o| |N|a|m|e|]| | +8#0000001#e0e0e08|[|N|o| |N|a|m|e|]| @1|[|N|o| |N|a|m|e|]| | +1#0000000#ffffff0@37|X+8#0000001#e0e0e08 +>F+8#0000000#ffffff0|o|u|r| @32||+1&&|F+8&&|o|u|r| @32 +|F+0&&|i|v|e| @32||+1&&|F+0&&|i|v|e| @32 +|S|i|x| @33||+1&&|S+0&&|i|x| @33 +|~+0#4040ff13&| @35||+1#0000000&|~+0#4040ff13&| @35 +|~| @35||+1#0000000&|~+0#4040ff13&| @35 +|[+3#0000000&|N|o| |N|a|m|e|]| |[|+|]| @5|1|,|1| @11|A|l@1| |[+1&&|N|o| |N|a|m|e|]| |[|+|]| @5|1|,|1| @11|A|l@1 +|:+0&&|s|e|t|l|o|c|a|l| |w|h|l|=| @60 diff --git a/src/testdir/dumps/Test_winhighlight_6.dump b/src/testdir/dumps/Test_winhighlight_6.dump new file mode 100644 index 0000000000..f5753e1187 --- /dev/null +++ b/src/testdir/dumps/Test_winhighlight_6.dump @@ -0,0 +1,8 @@ +| +2&#ffffff0|2+2#e000e06&|++2#0000000&| |[|N|o| |N|a|m|e|]| | +8#0000001#e0e0e08|[|N|o| |N|a|m|e|]| @1|[|N|o| |N|a|m|e|]| | +1#0000000#ffffff0@37|X+8#0000001#e0e0e08 +|F+8#0000000#ffffff0|o|u|r| @32||+1&&>F+8&&|o|u|r| @32 +|F+0&&|i|v|e| @32||+1&&|F+0&&|i|v|e| @32 +|S|i|x| @33||+1&&|S+0&&|i|x| @33 +|~+0#4040ff13&| @35||+1#0000000&|~+0#4040ff13&| @35 +|~| @35||+1#0000000&|~+0#4040ff13&| @35 +|[+1#0000000&|N|o| |N|a|m|e|]| |[|+|]| @5|1|,|1| @11|A|l@1| |[+3&&|N|o| |N|a|m|e|]| |[|+|]| @5|1|,|1| @11|A|l@1 +|:+0&&|s|e|t|l|o|c|a|l| |w|h|l|=|V|e|r|t|S|p|l|i|t|:|E|r@1|o|r|M|s|g| @42 diff --git a/src/testdir/dumps/Test_winhighlight_7.dump b/src/testdir/dumps/Test_winhighlight_7.dump new file mode 100644 index 0000000000..3967f03ef7 --- /dev/null +++ b/src/testdir/dumps/Test_winhighlight_7.dump @@ -0,0 +1,8 @@ +| +2&#ffffff0|2+2#e000e06&|++2#0000000&| |[|N|o| |N|a|m|e|]| | +8#0000001#e0e0e08|[|N|o| |N|a|m|e|]| @1|[|N|o| |N|a|m|e|]| | +1#0000000#ffffff0@37|X+8#0000001#e0e0e08 +>F+8#0000000#ffffff0|o|u|r| @32||+0#ffffff16#e000002|F+8#0000000#ffffff0|o|u|r| @32 +|F+0&&|i|v|e| @32||+0#ffffff16#e000002|F+0#0000000#ffffff0|i|v|e| @32 +|S|i|x| @33||+0#ffffff16#e000002|S+0#0000000#ffffff0|i|x| @33 +|~+0#4040ff13&| @35||+0#ffffff16#e000002|~+0#4040ff13#ffffff0| @35 +|~| @35||+0#ffffff16#e000002|~+0#4040ff13#ffffff0| @35 +|[+3#0000000&|N|o| |N|a|m|e|]| |[|+|]| @5|1|,|1| @11|A|l@1| |[+1&&|N|o| |N|a|m|e|]| |[|+|]| @5|1|,|1| @11|A|l@1 +|:+0&&|s|e|t|l|o|c|a|l| |w|h|l|=|V|e|r|t|S|p|l|i|t|:|E|r@1|o|r|M|s|g| @42 diff --git a/src/testdir/dumps/Test_winhighlight_8.dump b/src/testdir/dumps/Test_winhighlight_8.dump new file mode 100644 index 0000000000..69568fc95c --- /dev/null +++ b/src/testdir/dumps/Test_winhighlight_8.dump @@ -0,0 +1,8 @@ +| +2&#ffffff0|2+2#e000e06&|++2#0000000&| |[|N|o| |N|a|m|e|]| | +8#0000001#e0e0e08|[|N|o| |N|a|m|e|]| @1|[|N|o| |N|a|m|e|]| | +1#0000000#ffffff0@37|X+8#0000001#e0e0e08 +|w+8#0000000#ffffff0|N|e|x|t>F|o|u|r| @27||+1&&|w+8&&|N|e|x|t|F|o|u|r| @27 +|w+0#0000001#e0e0e08|N|e|x|t| @9| +0#0000000#0000001| +0&#ffffff0@20||+1&&|F+0&&|i|v|e| @32 +|w+0#0000001#ffd7ff255|a+0#ffffff16#e000002|l@1| @10| +0#0000000#a8a8a8255| +0&#ffffff0@20||+1&&|S+0&&|i|x| @33 +|w+0#0000001#ffd7ff255|h+0#ffffff16#e000002|i|l|e| @9| +0#0000000#a8a8a8255| +0#4040ff13#ffffff0@20||+1#0000000&|~+0#4040ff13&| @35 +|w+0#0000001#ffd7ff255|i+0#ffffff16#e000002|n|c|m|d| @8| +0#0000000#a8a8a8255| +0#4040ff13#ffffff0@20||+1#0000000&|~+0#4040ff13&| @35 +|w+0#0000001#ffd7ff255|i+0#ffffff16#e000002|n|d|o| @9| +0#0000000#a8a8a8255| +3&#ffffff0@2|1|,|1| @11|A|l@1| |[+1&&|N|o| |N|a|m|e|]| |[|+|]| @5|1|,|1| @11|A|l@1 +|-+2&&@1| |C|o|m@1|a|n|d|-|l|i|n|e| |c|o|m|p|l|e|t|i|o|n| |(|^|V|^|N|^|P|)| |m+0#00e0003&|a|t|c|h| |1| |o|f| |1|5| +0#0000000&@25 diff --git a/src/testdir/dumps/Test_winhighlight_9.dump b/src/testdir/dumps/Test_winhighlight_9.dump new file mode 100644 index 0000000000..174531af71 --- /dev/null +++ b/src/testdir/dumps/Test_winhighlight_9.dump @@ -0,0 +1,8 @@ +| +2&#ffffff0|2+2#e000e06&|++2#0000000&| |[|N|o| |N|a|m|e|]| | +8#0000001#e0e0e08|[|N|o| |N|a|m|e|]| @1|[|N|o| |N|a|m|e|]| | +1#0000000#ffffff0@37|X+8#0000001#e0e0e08 +|w+8#0000000#ffffff0|N|e|x|t|w|N|e|x|t|F|o|u|r| @22||+1&&|w+8&&|N|e|x|t>w|N|e|x|t|F|o|u|r| @22 +|F+0&&|i|v|e| @32| +0#0000001#e0e0e08|w|N|e|x|t| @9| +0#0000000#0000001| +0&#ffffff0@20 +|S|i|x| @33| +0#0000001#ffd7ff255|w|a|l@1| @10| +0#0000000#a8a8a8255| +0&#ffffff0@20 +|~+0#4040ff13&| @35| +0#0000001#ffd7ff255|w|h|i|l|e| @9| +0#0000000#a8a8a8255| +0#4040ff13#ffffff0@20 +|~| @35| +0#0000001#ffd7ff255|w|i|n|c|m|d| @8| +0#0000000#a8a8a8255| +0#4040ff13#ffffff0@20 +|[+1#0000000&|N|o| |N|a|m|e|]| |[|+|]| @5|1|,|5| @11|A|l@1| +0#0000001#ffd7ff255|w|i|n|d|o| @9| +0#0000000#a8a8a8255| +3&#ffffff0@2|1|,|1| @11|A|l@1 +|-+2&&@1| |C|o|m@1|a|n|d|-|l|i|n|e| |c|o|m|p|l|e|t|i|o|n| |(|^|V|^|N|^|P|)| |m+0#00e0003&|a|t|c|h| |1| |o|f| |1|5| +0#0000000&@25 diff --git a/src/testdir/dumps/Test_winhighlight_copy_1.dump b/src/testdir/dumps/Test_winhighlight_copy_1.dump new file mode 100644 index 0000000000..1e61b6f829 --- /dev/null +++ b/src/testdir/dumps/Test_winhighlight_copy_1.dump @@ -0,0 +1,20 @@ +> +0#ffffff16#e000002@36||+1#0000000#ffffff0| +0#ffffff16#e000002@36 +|~+0#4040ff13#ffffff0| @35||+1#0000000&|~+0#4040ff13&| @35 +|~| @35||+1#0000000&|~+0#4040ff13&| @35 +|~| @35||+1#0000000&|~+0#4040ff13&| @35 +|~| @35||+1#0000000&|~+0#4040ff13&| @35 +|~| @35||+1#0000000&|~+0#4040ff13&| @35 +|~| @35||+1#0000000&|~+0#4040ff13&| @35 +|~| @35||+1#0000000&|~+0#4040ff13&| @35 +|~| @35||+1#0000000&|~+0#4040ff13&| @35 +|~| @35||+1#0000000&|~+0#4040ff13&| @35 +|~| @35||+1#0000000&|~+0#4040ff13&| @35 +|~| @35||+1#0000000&|~+0#4040ff13&| @35 +|~| @35||+1#0000000&|~+0#4040ff13&| @35 +|~| @35||+1#0000000&|~+0#4040ff13&| @35 +|~| @35||+1#0000000&|~+0#4040ff13&| @35 +|~| @35||+1#0000000&|~+0#4040ff13&| @35 +|~| @35||+1#0000000&|~+0#4040ff13&| @35 +|~| @35||+1#0000000&|~+0#4040ff13&| @35 +|[+3#0000000&|N|o| |N|a|m|e|]| @9|0|,|0|-|1| @9|A|l@1| |[+1&&|N|o| |N|a|m|e|]| @9|0|,|0|-|1| @9|A|l@1 +|:+0&&|v|s|p|l|i|t| @67 diff --git a/src/testdir/dumps/Test_winhighlight_hlsearch_1.dump b/src/testdir/dumps/Test_winhighlight_hlsearch_1.dump new file mode 100644 index 0000000000..65f3707588 --- /dev/null +++ b/src/testdir/dumps/Test_winhighlight_hlsearch_1.dump @@ -0,0 +1,20 @@ +|F+0&#ffffff0|o|u|r| @32||+1&&|F+0&&|o|u|r| @32 +|F|i+0#ffffff16#ff404010|v+0#0000000#ffffff0|e| @32||+1&&|F+0&&|i|v|e| @32 +|S|i+0#ffffff16#ff404010|x+0#0000000#ffffff0| @33||+1&&|S+0&&|i|x| @33 +|~+0#4040ff13&| @35||+1#0000000&|~+0#4040ff13&| @35 +|~| @35||+1#0000000&|~+0#4040ff13&| @35 +|~| @35||+1#0000000&|~+0#4040ff13&| @35 +|~| @35||+1#0000000&|~+0#4040ff13&| @35 +|~| @35||+1#0000000&|~+0#4040ff13&| @35 +|~| @35||+1#0000000&|~+0#4040ff13&| @35 +|~| @35||+1#0000000&|~+0#4040ff13&| @35 +|~| @35||+1#0000000&|~+0#4040ff13&| @35 +|~| @35||+1#0000000&|~+0#4040ff13&| @35 +|~| @35||+1#0000000&|~+0#4040ff13&| @35 +|~| @35||+1#0000000&|~+0#4040ff13&| @35 +|~| @35||+1#0000000&|~+0#4040ff13&| @35 +|~| @35||+1#0000000&|~+0#4040ff13&| @35 +|~| @35||+1#0000000&|~+0#4040ff13&| @35 +|~| @35||+1#0000000&|~+0#4040ff13&| @35 +|[+3#0000000&|N|o| |N|a|m|e|]| |[|+|]| @5|2|,|2| @11|A|l@1| |[+1&&|N|o| |N|a|m|e|]| |[|+|]| @5|1|,|1| @11|A|l@1 +|/+0&&|i> @72 diff --git a/src/testdir/dumps/Test_winhighlight_hlsearch_2.dump b/src/testdir/dumps/Test_winhighlight_hlsearch_2.dump new file mode 100644 index 0000000000..30d643854e --- /dev/null +++ b/src/testdir/dumps/Test_winhighlight_hlsearch_2.dump @@ -0,0 +1,20 @@ +|F+0&#ffffff0|o|u|r| @32||+1&&|F+0#ffffff16#ff404010|o+0#0000000#ffffff0|u|r| @32 +|F|i|v|e| @32||+1&&|F+0#ffffff16#ff404010|i+0#0000000#ffffff0|v|e| @32 +|S|i|x| @33||+1&&|S+0&&|i|x| @33 +|~+0#4040ff13&| @35||+1#0000000&|~+0#4040ff13&| @35 +|~| @35||+1#0000000&|~+0#4040ff13&| @35 +|~| @35||+1#0000000&|~+0#4040ff13&| @35 +|~| @35||+1#0000000&|~+0#4040ff13&| @35 +|~| @35||+1#0000000&|~+0#4040ff13&| @35 +|~| @35||+1#0000000&|~+0#4040ff13&| @35 +|~| @35||+1#0000000&|~+0#4040ff13&| @35 +|~| @35||+1#0000000&|~+0#4040ff13&| @35 +|~| @35||+1#0000000&|~+0#4040ff13&| @35 +|~| @35||+1#0000000&|~+0#4040ff13&| @35 +|~| @35||+1#0000000&|~+0#4040ff13&| @35 +|~| @35||+1#0000000&|~+0#4040ff13&| @35 +|~| @35||+1#0000000&|~+0#4040ff13&| @35 +|~| @35||+1#0000000&|~+0#4040ff13&| @35 +|~| @35||+1#0000000&|~+0#4040ff13&| @35 +|[+1#0000000&|N|o| |N|a|m|e|]| |[|+|]| @5|1|,|1| @11|A|l@1| |[+3&&|N|o| |N|a|m|e|]| |[|+|]| @5|2|,|1| @11|A|l@1 +|/+0&&|F> @72 diff --git a/src/testdir/dumps/Test_winhighlight_occasion_1.dump b/src/testdir/dumps/Test_winhighlight_occasion_1.dump new file mode 100644 index 0000000000..3ecbc1d3c5 --- /dev/null +++ b/src/testdir/dumps/Test_winhighlight_occasion_1.dump @@ -0,0 +1,20 @@ +>O+0#ffffff16#4040ff13|n|e| @71 +|T+0&#ff404010|w|o| @71 +|T|h|r|e@1| @69 +|~+0(ff4011| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|:+0#0000000#ffffff0|s|e|t|l|o|c|a|l| |w|h|l|=|!|(|:|A|,|!|.|:|B|,|S|t|a|t|u|s|L|i|n|e|:|!|~| @19|1|,|1| @10|A|l@1| diff --git a/src/testdir/dumps/Test_winhighlight_popupwin_1.dump b/src/testdir/dumps/Test_winhighlight_popupwin_1.dump new file mode 100644 index 0000000000..73e5d8ba49 --- /dev/null +++ b/src/testdir/dumps/Test_winhighlight_popupwin_1.dump @@ -0,0 +1,20 @@ +> +0&#ffffff0@74 +|~+0#4040ff13&| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @26|╔+0#ffffff16#ff404010|═@16|╗| +0#4040ff13#ffffff0@27 +|~| @26|║+0#ffffff16#ff404010| |i+0࿈ff13|n|t| +0&#ff404010|h|e|l@1|o| |=| |1+0#e000002&|0|;+0#ffffff16&| |║| +0#4040ff13#ffffff0@27 +|~| @26|╚+0#ffffff16#ff404010|═@16|╝| +0#4040ff13#ffffff0@27 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +| +0#0000000&@56|0|,|0|-|1| @8|A|l@1| diff --git a/src/testdir/dumps/Test_winhighlight_popupwin_2.dump b/src/testdir/dumps/Test_winhighlight_popupwin_2.dump new file mode 100644 index 0000000000..2aa8f554be --- /dev/null +++ b/src/testdir/dumps/Test_winhighlight_popupwin_2.dump @@ -0,0 +1,20 @@ +> +0&#ffffff0@74 +|~+0#4040ff13&| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @26|╔+0#0000001#ffd7ff255|═@16|╗| +0#4040ff13#ffffff0@27 +|~| @26|║+0#0000001#ffd7ff255| |i+0#00e0003&|n|t| +0#0000001&|h|e|l@1|o| |=| |1+0#e000002&|0|;+0#0000001&| |║| +0#4040ff13#ffffff0@27 +|~| @26|╚+0#0000001#ffd7ff255|═@16|╝| +0#4040ff13#ffffff0@27 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|:+0#0000000&|c|a|l@1| |w|i|n|_|e|x|e|c|u|t|e|(|g|:|i|d|,| |"|s|e|t| |w|h|l|=|"|)| @21|0|,|0|-|1| @8|A|l@1| diff --git a/src/testdir/dumps/Test_winhighlight_syntax_1.dump b/src/testdir/dumps/Test_winhighlight_syntax_1.dump new file mode 100644 index 0000000000..dacf136cff --- /dev/null +++ b/src/testdir/dumps/Test_winhighlight_syntax_1.dump @@ -0,0 +1,8 @@ +>O+0#ffffff16#e000002|n|e| +0#0000000#ffffff0|T+0#ffffff16#e000002|w|o| +0#0000000#ffffff0@67 +|O+0#ffffff16#e000002|n|e| +0#0000000#ffffff0@71 +|T+0#ffffff16#e000002|w|o| +0#0000000#ffffff0@71 +|T+0#ffffff16#e000002|h|r|e@1| +0#0000000#ffffff0@69 +|~+0#4040ff13&| @73 +|~| @73 +|~| @73 +|:+0#0000000&|s|e|t|l|o|c|a|l| |w|h|l|=|A|:|E|r@1|o|r|M|s|g| @32|1|,|1| @10|A|l@1| diff --git a/src/testdir/dumps/Test_winhighlight_syntax_2.dump b/src/testdir/dumps/Test_winhighlight_syntax_2.dump new file mode 100644 index 0000000000..691807c2c2 --- /dev/null +++ b/src/testdir/dumps/Test_winhighlight_syntax_2.dump @@ -0,0 +1,8 @@ +>O+0#ffffff16#4040ff13|n|e| +0#0000000#ffffff0|T+0#ffffff16#e000002|w|o| +0#0000000#ffffff0@67 +|O+0#ffffff16#4040ff13|n|e| +0#0000000#ffffff0@71 +|T+0#ffffff16#e000002|w|o| +0#0000000#ffffff0@71 +|T+0#ffffff16#e000002|h|r|e@1| +0#0000000#ffffff0@69 +|~+0#4040ff13&| @73 +|~| @73 +|~| @73 +|:+0#0000000&|s|e|t|l|o|c|a|l| |w|h|l|=|B|:|E|r@1|o|r|M|s|g| @32|1|,|1| @10|A|l@1| diff --git a/src/testdir/dumps/Test_winhighlight_syntax_3.dump b/src/testdir/dumps/Test_winhighlight_syntax_3.dump new file mode 100644 index 0000000000..77abcbd0f7 --- /dev/null +++ b/src/testdir/dumps/Test_winhighlight_syntax_3.dump @@ -0,0 +1,8 @@ +>O+0#ffffff16#4040ff13|n|e| +0#0000000#ffffff0|T+0#ffffff16#4040ff13|w|o| +0#0000000#ffffff0@67 +|O+0#ffffff16#4040ff13|n|e| +0#0000000#ffffff0@71 +|T+0#ffffff16#4040ff13|w|o| +0#0000000#ffffff0@71 +|T+0#ffffff16#e000002|h|r|e@1| +0#0000000#ffffff0@69 +|~+0#4040ff13&| @73 +|~| @73 +|~| @73 +|:+0#0000000&|s|e|t|l|o|c|a|l| |w|h|l|=|C|:|E|r@1|o|r|M|s|g| @32|1|,|1| @10|A|l@1| diff --git a/src/testdir/dumps/Test_winhighlight_term_1.dump b/src/testdir/dumps/Test_winhighlight_term_1.dump new file mode 100644 index 0000000000..18fffa5015 --- /dev/null +++ b/src/testdir/dumps/Test_winhighlight_term_1.dump @@ -0,0 +1,20 @@ +>>+0#ffffff16#e000002| @73 +|~+0#4040ff13#ffffff0| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|!+2#ffffff16#00e0003|s|h| |[|T|e|r|m|i|n|a|l|]| @42|1|,|1| @11|A|l@1 +| +0#0000000#ffffff0@74 +|~+0#4040ff13&| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|[+1#0000000&|N|o| |N|a|m|e|]| @47|0|,|0|-|1| @9|A|l@1 +|:+0&&|s|e|t|l|o|c|a|l| |w|h|l|=|T|e|r|m|i|n|a|l|:|E|r@1|o|r|M|s|g| @43 diff --git a/src/testdir/dumps/Test_winhighlight_term_2.dump b/src/testdir/dumps/Test_winhighlight_term_2.dump new file mode 100644 index 0000000000..33bd034ee6 --- /dev/null +++ b/src/testdir/dumps/Test_winhighlight_term_2.dump @@ -0,0 +1,20 @@ +|>+0#ffffff16#e000002> @73 +@75 +@75 +@75 +@75 +@75 +@75 +@75 +@75 +|!+2�e0003|s|h| |[|r|u|n@1|i|n|g|]| @43|1|,|1| @11|A|l@1 +| +0#0000000#ffffff0@74 +|~+0#4040ff13&| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|[+1#0000000&|N|o| |N|a|m|e|]| @47|0|,|0|-|1| @9|A|l@1 +|:+0&&|s|e|t|l|o|c|a|l| |w|h|l|=|T|e|r|m|i|n|a|l|:|E|r@1|o|r|M|s|g| @43 diff --git a/src/testdir/dumps/Test_winhighlight_term_3.dump b/src/testdir/dumps/Test_winhighlight_term_3.dump new file mode 100644 index 0000000000..e5760d0836 --- /dev/null +++ b/src/testdir/dumps/Test_winhighlight_term_3.dump @@ -0,0 +1,20 @@ +|>+0#ffffff16#e000002> @35||+1#0000000#ffffff0|>+0#ffffff16#e000002| @35 +@37||+1#0000000#ffffff0| +0#ffffff16#e000002@36 +@37||+1#0000000#ffffff0| +0#ffffff16#e000002@36 +@37||+1#0000000#ffffff0| +0#ffffff16#e000002@36 +@37||+1#0000000#ffffff0| +0#ffffff16#e000002@36 +@37||+1#0000000#ffffff0| +0#ffffff16#e000002@36 +@37||+1#0000000#ffffff0| +0#ffffff16#e000002@36 +@37||+1#0000000#ffffff0| +0#ffffff16#e000002@36 +@37||+1#0000000#ffffff0| +0#ffffff16#e000002@36 +|!+2�e0003|s|h| |[|r|u|n@1|i|n|g|]| @5|1|,|1| @11|A|l@1| |!+0&&|s|h| |[|r|u|n@1|i|n|g|]| @5|1|,|1| @11|A|l@1 +| +0#0000000#ffffff0@74 +|~+0#4040ff13&| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|[+1#0000000&|N|o| |N|a|m|e|]| @47|0|,|0|-|1| @9|A|l@1 +| +0&&@74 diff --git a/src/testdir/test_highlight.vim b/src/testdir/test_highlight.vim index c8d6e76abb..0cb6b5b102 100644 --- a/src/testdir/test_highlight.vim +++ b/src/testdir/test_highlight.vim @@ -1355,4 +1355,328 @@ func Test_hlset() call assert_true(hlget('hlg11')[0].cleared) endfunc +" Test for the 'winhighlight' option +func Test_winhighlight() + CheckScreendump + + let lines =<< trim END + set cursorline + call setline(1, ['Four', 'Five', 'Six']) + vsplit + tabnew + tabnew + tabfirst + END + call writefile(lines, 'Xtest_winhighlight', 'D') + + let buf = RunVimInTerminal('-S Xtest_winhighlight', {'rows': 8}) + call TermWait(buf) + + " Test that window highlight groups are actually local per window + call term_sendkeys(buf, "\:setlocal whl=CursorLine:ErrorMsg\") + call TermWait(buf) + + call VerifyScreenDump(buf, 'Test_winhighlight_1', {}) + + call term_sendkeys(buf, "\:wincmd l\") + call TermWait(buf) + + call VerifyScreenDump(buf, 'Test_winhighlight_2', {}) + + call term_sendkeys(buf, "\:wincmd h\\:setlocal whl=\") + call TermWait(buf) + + call VerifyScreenDump(buf, 'Test_winhighlight_3', {}) + + " Dump files 4 and 5 used to exist, but were removed later, too lazy to + " renumber the dump files... + + " Test that VertSplit in winhighlight only affects border if window that + " winhighlight is local to is on the left side of the separator/column + call term_sendkeys(buf, "\:wincmd l\") + call TermWait(buf) + + " Shouldn't affect separator + call term_sendkeys(buf, "\:setlocal whl=VertSplit:ErrorMsg\") + call TermWait(buf) + + call VerifyScreenDump(buf, 'Test_winhighlight_6', {}) + + call term_sendkeys(buf, "\:wincmd h\") + call TermWait(buf) + + " Should affect separator + call term_sendkeys(buf, "\:setlocal whl=VertSplit:ErrorMsg\") + call TermWait(buf) + + call VerifyScreenDump(buf, 'Test_winhighlight_7', {}) + + " Test that popup menu highlight is affected by current window only + call term_sendkeys(buf, "\:setlocal whl=Pmenu:ErrorMsg\iw\\") + call TermWait(buf) + + call VerifyScreenDump(buf, 'Test_winhighlight_8', {}) + + " Switch to other window (shouldn't be affected) + call term_sendkeys(buf, "\:wincmd l\iw\\") + call TermWait(buf) + + call VerifyScreenDump(buf, 'Test_winhighlight_9', {}) + + " Test that tabline highlight uses 'winhighlight' of last focused window in + " tabpage + call term_sendkeys(buf, "\:setlocal whl=TabLine:ErrorMsg\\:tabn 3\") + call TermWait(buf) + + call VerifyScreenDump(buf, 'Test_winhighlight_10', {}) + + " Make last focused window the other window, which should have no hightlight + " in tabline. + call term_sendkeys(buf, "\:tabn 1\\:wincmd h\\:tabn 3\") + call TermWait(buf) + + call VerifyScreenDump(buf, 'Test_winhighlight_11', {}) + + " Test if statusline is highlighted correctly local to window. + call term_sendkeys(buf, "\:tabn 1\\:set ruler\\:setlocal whl=StatusLine:ErrorMsg\") + call TermWait(buf) + + call VerifyScreenDump(buf, 'Test_winhighlight_12', {}) + + " Make status line change + call term_sendkeys(buf, "\jj") + call TermWait(buf) + + call VerifyScreenDump(buf, 'Test_winhighlight_13', {}) + + " Go into command line mode (status line should still have same highlight) + call term_sendkeys(buf, "\:") + call TermWait(buf) + + call VerifyScreenDump(buf, 'Test_winhighlight_13a', {}) + + " Go to next window (statusline highlighting for other window should stop) + call term_sendkeys(buf, "\\:wincmd l\") + call TermWait(buf) + + call VerifyScreenDump(buf, 'Test_winhighlight_14', {}) + + " Check that overridding Normal group maps to HLF_WIN in 'highlight'. + call term_sendkeys(buf, "\:setlocal whl=Normal:ErrorMsg\") + call TermWait(buf) + + call VerifyScreenDump(buf, 'Test_winhighlight_15', {}) + + " clean up + call StopVimInTerminal(buf) +endfunc + +" Test if 'hlsearch' highlighting works correctly with 'winhighlight' +func Test_winhighlight_hlsearch() + CheckScreendump + + let lines =<< trim END + vim9script + + hi A ctermbg=red ctermfg=white + hi B ctermbg=red ctermfg=white + hi link Search B + hi link IncSearch B + + autocmd CmdlineEnter [\/\?] { + setlocal whl=Search:A,IncSearch:B + hi clear Search + hi clear IncSearch + } + autocmd CmdlineLeave [\/\?] { + setlocal whl= + hi link Search B + hi link IncSearch B + } + + setline(1, ['One', 'Two', 'Three']) + vsplit + setline(1, ['Four', 'Five', 'Six']) + + set incsearch + set hlsearch + END + call writefile(lines, 'Xtest_winhighlight_hlsearch', 'D') + + let buf = RunVimInTerminal('-S Xtest_winhighlight_hlsearch', {'rows': 20}) + call TermWait(buf) + + call term_sendkeys(buf, "\/i") + call TermWait(buf) + + call VerifyScreenDump(buf, 'Test_winhighlight_hlsearch_1', {}) + + call term_sendkeys(buf, "\:wincmd l\") + call TermWait(buf) + + call term_sendkeys(buf, "\/F") + call TermWait(buf) + + call VerifyScreenDump(buf, 'Test_winhighlight_hlsearch_2', {}) + + call term_sendkeys(buf, "\") " Must exit search mode + + call StopVimInTerminal(buf) +endfunc + +" Test if syntax highlighting works correctly with 'winhighlight'. Also tests +" handling of highlight links. +func Test_winhighlight_syntax() + CheckScreendump + + let lines =<< trim END + vim9script + + hi A ctermbg=blue ctermfg=white + hi link B A + hi link C B + syntax match A display "One" + syntax match B display "Two" + syntax match C display "Three" + + setline(1, ["One Two", "One", "Two", "Three"]) + END + call writefile(lines, 'Xtest_winhighlight_syntax', 'D') + + let buf = RunVimInTerminal('-S Xtest_winhighlight_syntax', {'rows': 8}) + call TermWait(buf) + + " Since A is the root of the link chain, it should affect all + call term_sendkeys(buf, "\:setlocal whl=A:ErrorMsg\") + call TermWait(buf) + + call VerifyScreenDump(buf, 'Test_winhighlight_syntax_1', {}) + + " Since B is in the middle, B and C should be overridden, but not A + call term_sendkeys(buf, "\:setlocal whl=B:ErrorMsg\") + call TermWait(buf) + + call VerifyScreenDump(buf, 'Test_winhighlight_syntax_2', {}) + + " Since C is is last, it should only be overridden + call term_sendkeys(buf, "\:setlocal whl=C:ErrorMsg\") + call TermWait(buf) + + call VerifyScreenDump(buf, 'Test_winhighlight_syntax_3', {}) + + call term_sendkeys(buf, "\:setlocal whl=A:ErrorMsg,C:ErrorMsg\") + call TermWait(buf) + + call StopVimInTerminal(buf) +endfunc + +" Test if terminal is correctly highlighted using 'winhighlight' +func Test_winhighlight_term() + CheckScreendump + CheckUnix + + let lines =<< trim END + terminal sh + END + call writefile(lines, 'Xtest_winhighlight_term', 'D') + + let buf = RunVimInTerminal('-S Xtest_winhighlight_term', {'rows': 20, 'env': {'PS1': '>'}}) + call TermWait(buf) + + call term_sendkeys(buf, "\\\:setlocal whl=Terminal:ErrorMsg\") + call TermWait(buf) + + call VerifyScreenDump(buf, 'Test_winhighlight_term_1', {}) + + call term_sendkeys(buf, "i") + call TermWait(buf) + + call VerifyScreenDump(buf, 'Test_winhighlight_term_2', {}) + + " New terminal should have copied over winhighlight settings and updated + " accordingly. + call term_sendkeys(buf, "\\\:vsplit\i") + call TermWait(buf) + + call VerifyScreenDump(buf, 'Test_winhighlight_term_3', {}) + + call term_sendkeys(buf, "\\\:bw!\") + call TermWait(buf) + + call StopVimInTerminal(buf) +endfunc + +" Test if 'winhighlight' works correctly in popup windows +func Test_winhighlight_popupwin() + CheckScreendump + CheckUnix + + let lines =<< trim END + vim9script + + g:id = popup_dialog("int hello = 10;", {}) + + hi A ctermbg=red ctermfg=white + hi B ctermbg=blue ctermfg=white + + redraw! # Remove intro message + win_execute(g:id, "set filetype=c whl=Pmenu:A,cType:B") + END + call writefile(lines, 'Xtest_winhighlight_popupwin', 'D') + + let buf = RunVimInTerminal('-S Xtest_winhighlight_popupwin', {'rows': 20}) + call TermWait(buf) + + call VerifyScreenDump(buf, 'Test_winhighlight_popupwin_1', {}) + + call term_sendkeys(buf, "\:call win_execute(g:id, \"set whl=\")\") + call TermWait(buf) + + call VerifyScreenDump(buf, 'Test_winhighlight_popupwin_2', {}) + + call StopVimInTerminal(buf) +endfunc + +" Test that 'winhighlight' setting is copied over to new split window +func Test_winhighlight_copy() + CheckScreendump + + let buf = RunVimInTerminal('', {'rows': 20}) + call TermWait(buf) + + call term_sendkeys(buf, "\:setlocal cursorline whl=CursorLine:ErrorMsg\\:vsplit\") + call TermWait(buf) + + call VerifyScreenDump(buf, 'Test_winhighlight_copy_1', {}) + + call StopVimInTerminal(buf) +endfunc + +" Test if using a 'highlight' occasion instead of highlight group name works +" correctly. +func Test_winhighlight_occasion() + CheckScreendump + + let lines =<< trim END + highlight A ctermbg=red ctermfg=white + highlight B ctermbg=blue ctermfg=white + highlight EndOfBuffer ctermbg=green + + set cursorline + + call setline(1, ["One", "Two", "Three"]) + END + call writefile(lines, 'Xtest_winhighlight_occasion', 'D') + + let buf = RunVimInTerminal('-S Xtest_winhighlight_occasion', {'rows': 20}) + call TermWait(buf) + + call term_sendkeys(buf, "\:setlocal whl=!(:A,!.:B,StatusLine:!~\") + call TermWait(buf) + + call VerifyScreenDump(buf, 'Test_winhighlight_occasion_1', {}) + + call StopVimInTerminal(buf) +endfunc + " vim: shiftwidth=2 sts=2 expandtab diff --git a/src/testdir/test_options.vim b/src/testdir/test_options.vim index 58b7620c3e..dc1399793a 100644 --- a/src/testdir/test_options.vim +++ b/src/testdir/test_options.vim @@ -623,6 +623,11 @@ func Test_set_completion_string_values() call assert_equal('top', getcompletion('set printoptions=', 'cmdline')[0]) call assert_equal('SpecialKey', getcompletion('set wincolor=', 'cmdline')[0]) + call assert_equal('SpecialKey', getcompletion('set winhighlight=', 'cmdline')[0]) + call assert_equal('SpecialKey', getcompletion('set winhighlight=SpecialKey:', 'cmdline')[0]) + call assert_equal('SpecialKey', getcompletion('set winhighlight=SpecialKey:SpecialKey,', 'cmdline')[0]) + call assert_equal('!8', getcompletion('set winhighlight=SpecialKey:SpecialKey,!', 'cmdline')[0]) + call assert_equal('eol', getcompletion('set listchars+=', 'cmdline')[0]) call assert_equal(['multispace', 'leadmultispace'], getcompletion('set listchars+=', 'cmdline')[-2:]) call assert_equal(['tab', 'leadtab'], getcompletion('set listchars+=', 'cmdline')[5:6]) diff --git a/src/testdir/util/gen_opt_test.vim b/src/testdir/util/gen_opt_test.vim index 071a158ebd..0a010a9f4a 100644 --- a/src/testdir/util/gen_opt_test.vim +++ b/src/testdir/util/gen_opt_test.vim @@ -358,6 +358,9 @@ let test_values = { \ ['xxx', 'a4', 'full,full,full,full,full']], \ 'wildoptions': [['', 'tagfile', 'pum', 'fuzzy'], ['xxx']], \ 'winaltkeys': [['no', 'yes', 'menu'], ['', 'xxx']], + \ 'winhighlight': [['Search:Errormsg,Comment:String', 'Search:Comment', ''], + \ ['xxx', ',', 'Search:Comment,', 'Search:Errormsg,Comment:String,', + \ ':', 'Search:,', 'Search:']], \ "\ skipped options \ 'luadll': [[], []], diff --git a/src/version.c b/src/version.c index 2ef4469fe5..40ab10bfe4 100644 --- a/src/version.c +++ b/src/version.c @@ -734,6 +734,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 93, /**/ 92, /**/ diff --git a/src/vim.h b/src/vim.h index 1e75d8a2be..1a38606f7c 100644 --- a/src/vim.h +++ b/src/vim.h @@ -1593,6 +1593,7 @@ typedef enum , HLF_TPLS // tabpanel selected , HLF_TPLF // tabpanel filler , HLF_PRI // "preinsert" in 'completeopt' + , HLF_WIN // window colour , HLF_COUNT // MUST be the last one } hlf_T; @@ -1605,7 +1606,7 @@ typedef enum '+', '=', 'k', '<','[', ']', '{', '}', 'x', 'X', 'j', 'H', \ '*', '#', '_', '!', '.', 'o', 'q', \ 'z', 'Z', 'g', \ - '%', '^', '&', 'I'} + '%', '^', '&', 'I', '('} /* * Values for behaviour in spell_move_to diff --git a/src/window.c b/src/window.c index e8142ca202..bfca2c345a 100644 --- a/src/window.c +++ b/src/window.c @@ -1611,8 +1611,13 @@ win_init(win_T *newp, win_T *oldp, int flags UNUSED) #endif win_init_some(newp, oldp); + #ifdef FEAT_TERMINAL - term_update_wincolor(newp); + // Make sure to also handle highlight overrides copied over from oldp. + push_highlight_overrides(newp->w_hl, newp->w_hl_len); + if (newp->w_buffer->b_term != NULL) + term_init_default_colors(newp->w_buffer->b_term); + pop_highlight_overrides(); #endif } @@ -2522,7 +2527,7 @@ win_init_empty(win_T *wp) wp->w_s = &wp->w_buffer->b_s; #endif #ifdef FEAT_TERMINAL - term_reset_wincolor(wp); + term_reset_hlfwin(wp); #endif } @@ -5978,6 +5983,8 @@ win_free( ruby_window_free(wp); #endif + vim_free(wp->w_hl); + clear_winopt(&wp->w_onebuf_opt); clear_winopt(&wp->w_allbuf_opt);