xref: /vim-8.2.3635/src/highlight.c (revision 4ef18dcc)
1f9cc9f20SBram Moolenaar /* vi:set ts=8 sts=4 sw=4 noet:
2f9cc9f20SBram Moolenaar  *
3f9cc9f20SBram Moolenaar  * VIM - Vi IMproved	by Bram Moolenaar
4f9cc9f20SBram Moolenaar  *
5f9cc9f20SBram Moolenaar  * Do ":help uganda"  in Vim to read copying and usage conditions.
6f9cc9f20SBram Moolenaar  * Do ":help credits" in Vim to see a list of people who contributed.
7f9cc9f20SBram Moolenaar  * See README.txt for an overview of the Vim source code.
8f9cc9f20SBram Moolenaar  */
9f9cc9f20SBram Moolenaar 
10f9cc9f20SBram Moolenaar /*
1129b7d7a9SBram Moolenaar  * Highlighting stuff.
1229b7d7a9SBram Moolenaar  * Includes highlighting matches.
13f9cc9f20SBram Moolenaar  */
14f9cc9f20SBram Moolenaar 
15f9cc9f20SBram Moolenaar #include "vim.h"
16f9cc9f20SBram Moolenaar 
17f9cc9f20SBram Moolenaar #define SG_TERM		1	// term has been set
18f9cc9f20SBram Moolenaar #define SG_CTERM	2	// cterm has been set
19f9cc9f20SBram Moolenaar #define SG_GUI		4	// gui has been set
20f9cc9f20SBram Moolenaar #define SG_LINK		8	// link has been set
21f9cc9f20SBram Moolenaar 
22f9cc9f20SBram Moolenaar /*
23f9cc9f20SBram Moolenaar  * The "term", "cterm" and "gui" arguments can be any combination of the
24f9cc9f20SBram Moolenaar  * following names, separated by commas (but no spaces!).
25f9cc9f20SBram Moolenaar  */
26f9cc9f20SBram Moolenaar static char *(hl_name_table[]) =
27f9cc9f20SBram Moolenaar     {"bold", "standout", "underline", "undercurl",
28f9cc9f20SBram Moolenaar       "italic", "reverse", "inverse", "nocombine", "strikethrough", "NONE"};
29f9cc9f20SBram Moolenaar static int hl_attr_table[] =
30f9cc9f20SBram Moolenaar     {HL_BOLD, HL_STANDOUT, HL_UNDERLINE, HL_UNDERCURL, HL_ITALIC, HL_INVERSE, HL_INVERSE, HL_NOCOMBINE, HL_STRIKETHROUGH, 0};
31f9cc9f20SBram Moolenaar #define ATTR_COMBINE(attr_a, attr_b) ((((attr_b) & HL_NOCOMBINE) ? attr_b : (attr_a)) | (attr_b))
32f9cc9f20SBram Moolenaar 
332ac6e82aSBram Moolenaar /*
342ac6e82aSBram Moolenaar  * Structure that stores information about a highlight group.
352ac6e82aSBram Moolenaar  * The ID of a highlight group is also called group ID.  It is the index in
362ac6e82aSBram Moolenaar  * the highlight_ga array PLUS ONE.
372ac6e82aSBram Moolenaar  */
382ac6e82aSBram Moolenaar typedef struct
392ac6e82aSBram Moolenaar {
402ac6e82aSBram Moolenaar     char_u	*sg_name;	// highlight group name
412ac6e82aSBram Moolenaar     char_u	*sg_name_u;	// uppercase of sg_name
422ac6e82aSBram Moolenaar     int		sg_cleared;	// "hi clear" was used
432ac6e82aSBram Moolenaar // for normal terminals
442ac6e82aSBram Moolenaar     int		sg_term;	// "term=" highlighting attributes
452ac6e82aSBram Moolenaar     char_u	*sg_start;	// terminal string for start highl
462ac6e82aSBram Moolenaar     char_u	*sg_stop;	// terminal string for stop highl
472ac6e82aSBram Moolenaar     int		sg_term_attr;	// Screen attr for term mode
482ac6e82aSBram Moolenaar // for color terminals
492ac6e82aSBram Moolenaar     int		sg_cterm;	// "cterm=" highlighting attr
502ac6e82aSBram Moolenaar     int		sg_cterm_bold;	// bold attr was set for light color
512ac6e82aSBram Moolenaar     int		sg_cterm_fg;	// terminal fg color number + 1
522ac6e82aSBram Moolenaar     int		sg_cterm_bg;	// terminal bg color number + 1
532ac6e82aSBram Moolenaar     int		sg_cterm_attr;	// Screen attr for color term mode
542ac6e82aSBram Moolenaar // for when using the GUI
552ac6e82aSBram Moolenaar #if defined(FEAT_GUI) || defined(FEAT_TERMGUICOLORS)
562ac6e82aSBram Moolenaar     guicolor_T	sg_gui_fg;	// GUI foreground color handle
572ac6e82aSBram Moolenaar     guicolor_T	sg_gui_bg;	// GUI background color handle
582ac6e82aSBram Moolenaar #endif
592ac6e82aSBram Moolenaar #ifdef FEAT_GUI
602ac6e82aSBram Moolenaar     guicolor_T	sg_gui_sp;	// GUI special color handle
612ac6e82aSBram Moolenaar     GuiFont	sg_font;	// GUI font handle
622ac6e82aSBram Moolenaar #ifdef FEAT_XFONTSET
632ac6e82aSBram Moolenaar     GuiFontset	sg_fontset;	// GUI fontset handle
642ac6e82aSBram Moolenaar #endif
652ac6e82aSBram Moolenaar     char_u	*sg_font_name;  // GUI font or fontset name
662ac6e82aSBram Moolenaar     int		sg_gui_attr;    // Screen attr for GUI mode
672ac6e82aSBram Moolenaar #endif
682ac6e82aSBram Moolenaar #if defined(FEAT_GUI) || defined(FEAT_EVAL)
692ac6e82aSBram Moolenaar // Store the sp color name for the GUI or synIDattr()
702ac6e82aSBram Moolenaar     int		sg_gui;		// "gui=" highlighting attributes
712ac6e82aSBram Moolenaar     char_u	*sg_gui_fg_name;// GUI foreground color name
722ac6e82aSBram Moolenaar     char_u	*sg_gui_bg_name;// GUI background color name
732ac6e82aSBram Moolenaar     char_u	*sg_gui_sp_name;// GUI special color name
742ac6e82aSBram Moolenaar #endif
752ac6e82aSBram Moolenaar     int		sg_link;	// link to this highlight group ID
762ac6e82aSBram Moolenaar     int		sg_set;		// combination of SG_* flags
772ac6e82aSBram Moolenaar #ifdef FEAT_EVAL
782ac6e82aSBram Moolenaar     sctx_T	sg_script_ctx;	// script in which the group was last set
792ac6e82aSBram Moolenaar #endif
802ac6e82aSBram Moolenaar } hl_group_T;
812ac6e82aSBram Moolenaar 
822ac6e82aSBram Moolenaar // highlight groups for 'highlight' option
832ac6e82aSBram Moolenaar static garray_T highlight_ga;
842ac6e82aSBram Moolenaar #define HL_TABLE()	((hl_group_T *)((highlight_ga.ga_data)))
852ac6e82aSBram Moolenaar 
862ac6e82aSBram Moolenaar /*
872ac6e82aSBram Moolenaar  * An attribute number is the index in attr_table plus ATTR_OFF.
882ac6e82aSBram Moolenaar  */
892ac6e82aSBram Moolenaar #define ATTR_OFF (HL_ALL + 1)
902ac6e82aSBram Moolenaar 
91f9cc9f20SBram Moolenaar static void syn_unadd_group(void);
92f9cc9f20SBram Moolenaar static void set_hl_attr(int idx);
93f9cc9f20SBram Moolenaar static void highlight_list_one(int id);
94f9cc9f20SBram Moolenaar static int highlight_list_arg(int id, int didh, int type, int iarg, char_u *sarg, char *name);
95f9cc9f20SBram Moolenaar static int syn_add_group(char_u *name);
96f9cc9f20SBram Moolenaar static int hl_has_settings(int idx, int check_link);
97f9cc9f20SBram Moolenaar static void highlight_clear(int idx);
98f9cc9f20SBram Moolenaar 
99f9cc9f20SBram Moolenaar #if defined(FEAT_GUI) || defined(FEAT_TERMGUICOLORS)
100f9cc9f20SBram Moolenaar static void gui_do_one_color(int idx, int do_menu, int do_tooltip);
101f9cc9f20SBram Moolenaar #endif
102f9cc9f20SBram Moolenaar #ifdef FEAT_GUI
103f9cc9f20SBram Moolenaar static int  set_group_colors(char_u *name, guicolor_T *fgp, guicolor_T *bgp, int do_menu, int use_norm, int do_tooltip);
104f9cc9f20SBram Moolenaar static void hl_do_font(int idx, char_u *arg, int do_normal, int do_menu, int do_tooltip, int free_font);
105f9cc9f20SBram Moolenaar #endif
106f9cc9f20SBram Moolenaar 
107f9cc9f20SBram Moolenaar /*
108f9cc9f20SBram Moolenaar  * The default highlight groups.  These are compiled-in for fast startup and
109f9cc9f20SBram Moolenaar  * they still work when the runtime files can't be found.
110f9cc9f20SBram Moolenaar  * When making changes here, also change runtime/colors/default.vim!
111f9cc9f20SBram Moolenaar  * The #ifdefs are needed to reduce the amount of static data.  Helps to make
112f9cc9f20SBram Moolenaar  * the 16 bit DOS (museum) version compile.
113f9cc9f20SBram Moolenaar  */
114f9cc9f20SBram Moolenaar #if defined(FEAT_GUI) || defined(FEAT_EVAL)
115f9cc9f20SBram Moolenaar # define CENT(a, b) b
116f9cc9f20SBram Moolenaar #else
117f9cc9f20SBram Moolenaar # define CENT(a, b) a
118f9cc9f20SBram Moolenaar #endif
119f9cc9f20SBram Moolenaar static char *(highlight_init_both[]) = {
120f9cc9f20SBram Moolenaar     CENT("ErrorMsg term=standout ctermbg=DarkRed ctermfg=White",
121f9cc9f20SBram Moolenaar 	 "ErrorMsg term=standout ctermbg=DarkRed ctermfg=White guibg=Red guifg=White"),
122f9cc9f20SBram Moolenaar     CENT("IncSearch term=reverse cterm=reverse",
123f9cc9f20SBram Moolenaar 	 "IncSearch term=reverse cterm=reverse gui=reverse"),
124f9cc9f20SBram Moolenaar     CENT("ModeMsg term=bold cterm=bold",
125f9cc9f20SBram Moolenaar 	 "ModeMsg term=bold cterm=bold gui=bold"),
126f9cc9f20SBram Moolenaar     CENT("NonText term=bold ctermfg=Blue",
127f9cc9f20SBram Moolenaar 	 "NonText term=bold ctermfg=Blue gui=bold guifg=Blue"),
128f9cc9f20SBram Moolenaar     CENT("StatusLine term=reverse,bold cterm=reverse,bold",
129f9cc9f20SBram Moolenaar 	 "StatusLine term=reverse,bold cterm=reverse,bold gui=reverse,bold"),
130f9cc9f20SBram Moolenaar     CENT("StatusLineNC term=reverse cterm=reverse",
131f9cc9f20SBram Moolenaar 	 "StatusLineNC term=reverse cterm=reverse gui=reverse"),
132f9cc9f20SBram Moolenaar     "default link EndOfBuffer NonText",
133f9cc9f20SBram Moolenaar     CENT("VertSplit term=reverse cterm=reverse",
134f9cc9f20SBram Moolenaar 	 "VertSplit term=reverse cterm=reverse gui=reverse"),
135f9cc9f20SBram Moolenaar #ifdef FEAT_CLIPBOARD
136f9cc9f20SBram Moolenaar     CENT("VisualNOS term=underline,bold cterm=underline,bold",
137f9cc9f20SBram Moolenaar 	 "VisualNOS term=underline,bold cterm=underline,bold gui=underline,bold"),
138f9cc9f20SBram Moolenaar #endif
139f9cc9f20SBram Moolenaar #ifdef FEAT_DIFF
140f9cc9f20SBram Moolenaar     CENT("DiffText term=reverse cterm=bold ctermbg=Red",
141f9cc9f20SBram Moolenaar 	 "DiffText term=reverse cterm=bold ctermbg=Red gui=bold guibg=Red"),
142f9cc9f20SBram Moolenaar #endif
143f9cc9f20SBram Moolenaar #ifdef FEAT_INS_EXPAND
144f9cc9f20SBram Moolenaar     CENT("PmenuSbar ctermbg=Grey",
145f9cc9f20SBram Moolenaar 	 "PmenuSbar ctermbg=Grey guibg=Grey"),
146f9cc9f20SBram Moolenaar #endif
147f9cc9f20SBram Moolenaar     CENT("TabLineSel term=bold cterm=bold",
148f9cc9f20SBram Moolenaar 	 "TabLineSel term=bold cterm=bold gui=bold"),
149f9cc9f20SBram Moolenaar     CENT("TabLineFill term=reverse cterm=reverse",
150f9cc9f20SBram Moolenaar 	 "TabLineFill term=reverse cterm=reverse gui=reverse"),
151f9cc9f20SBram Moolenaar #ifdef FEAT_GUI
152f9cc9f20SBram Moolenaar     "Cursor guibg=fg guifg=bg",
153f9cc9f20SBram Moolenaar     "lCursor guibg=fg guifg=bg", // should be different, but what?
154f9cc9f20SBram Moolenaar #endif
155f9cc9f20SBram Moolenaar     "default link QuickFixLine Search",
156f9cc9f20SBram Moolenaar     CENT("Normal cterm=NONE", "Normal gui=NONE"),
157f9cc9f20SBram Moolenaar     NULL
158f9cc9f20SBram Moolenaar };
159f9cc9f20SBram Moolenaar 
160f9cc9f20SBram Moolenaar /* Default colors only used with a light background. */
161f9cc9f20SBram Moolenaar static char *(highlight_init_light[]) = {
162f9cc9f20SBram Moolenaar     CENT("Directory term=bold ctermfg=DarkBlue",
163f9cc9f20SBram Moolenaar 	 "Directory term=bold ctermfg=DarkBlue guifg=Blue"),
164f9cc9f20SBram Moolenaar     CENT("LineNr term=underline ctermfg=Brown",
165f9cc9f20SBram Moolenaar 	 "LineNr term=underline ctermfg=Brown guifg=Brown"),
166f9cc9f20SBram Moolenaar     CENT("CursorLineNr term=bold ctermfg=Brown",
167f9cc9f20SBram Moolenaar 	 "CursorLineNr term=bold ctermfg=Brown gui=bold guifg=Brown"),
168f9cc9f20SBram Moolenaar     CENT("MoreMsg term=bold ctermfg=DarkGreen",
169f9cc9f20SBram Moolenaar 	 "MoreMsg term=bold ctermfg=DarkGreen gui=bold guifg=SeaGreen"),
170f9cc9f20SBram Moolenaar     CENT("Question term=standout ctermfg=DarkGreen",
171f9cc9f20SBram Moolenaar 	 "Question term=standout ctermfg=DarkGreen gui=bold guifg=SeaGreen"),
172f9cc9f20SBram Moolenaar     CENT("Search term=reverse ctermbg=Yellow ctermfg=NONE",
173f9cc9f20SBram Moolenaar 	 "Search term=reverse ctermbg=Yellow ctermfg=NONE guibg=Yellow guifg=NONE"),
174f9cc9f20SBram Moolenaar #ifdef FEAT_SPELL
175f9cc9f20SBram Moolenaar     CENT("SpellBad term=reverse ctermbg=LightRed",
176f9cc9f20SBram Moolenaar 	 "SpellBad term=reverse ctermbg=LightRed guisp=Red gui=undercurl"),
177f9cc9f20SBram Moolenaar     CENT("SpellCap term=reverse ctermbg=LightBlue",
178f9cc9f20SBram Moolenaar 	 "SpellCap term=reverse ctermbg=LightBlue guisp=Blue gui=undercurl"),
179f9cc9f20SBram Moolenaar     CENT("SpellRare term=reverse ctermbg=LightMagenta",
180f9cc9f20SBram Moolenaar 	 "SpellRare term=reverse ctermbg=LightMagenta guisp=Magenta gui=undercurl"),
181f9cc9f20SBram Moolenaar     CENT("SpellLocal term=underline ctermbg=Cyan",
182f9cc9f20SBram Moolenaar 	 "SpellLocal term=underline ctermbg=Cyan guisp=DarkCyan gui=undercurl"),
183f9cc9f20SBram Moolenaar #endif
184f9cc9f20SBram Moolenaar #ifdef FEAT_INS_EXPAND
185f9cc9f20SBram Moolenaar     CENT("PmenuThumb ctermbg=Black",
186f9cc9f20SBram Moolenaar 	 "PmenuThumb ctermbg=Black guibg=Black"),
187f9cc9f20SBram Moolenaar     CENT("Pmenu ctermbg=LightMagenta ctermfg=Black",
188f9cc9f20SBram Moolenaar 	 "Pmenu ctermbg=LightMagenta ctermfg=Black guibg=LightMagenta"),
189f9cc9f20SBram Moolenaar     CENT("PmenuSel ctermbg=LightGrey ctermfg=Black",
190f9cc9f20SBram Moolenaar 	 "PmenuSel ctermbg=LightGrey ctermfg=Black guibg=Grey"),
191f9cc9f20SBram Moolenaar #endif
192f9cc9f20SBram Moolenaar     CENT("SpecialKey term=bold ctermfg=DarkBlue",
193f9cc9f20SBram Moolenaar 	 "SpecialKey term=bold ctermfg=DarkBlue guifg=Blue"),
194f9cc9f20SBram Moolenaar     CENT("Title term=bold ctermfg=DarkMagenta",
195f9cc9f20SBram Moolenaar 	 "Title term=bold ctermfg=DarkMagenta gui=bold guifg=Magenta"),
196f9cc9f20SBram Moolenaar     CENT("WarningMsg term=standout ctermfg=DarkRed",
197f9cc9f20SBram Moolenaar 	 "WarningMsg term=standout ctermfg=DarkRed guifg=Red"),
198f9cc9f20SBram Moolenaar #ifdef FEAT_WILDMENU
199f9cc9f20SBram Moolenaar     CENT("WildMenu term=standout ctermbg=Yellow ctermfg=Black",
200f9cc9f20SBram Moolenaar 	 "WildMenu term=standout ctermbg=Yellow ctermfg=Black guibg=Yellow guifg=Black"),
201f9cc9f20SBram Moolenaar #endif
202f9cc9f20SBram Moolenaar #ifdef FEAT_FOLDING
203f9cc9f20SBram Moolenaar     CENT("Folded term=standout ctermbg=Grey ctermfg=DarkBlue",
204f9cc9f20SBram Moolenaar 	 "Folded term=standout ctermbg=Grey ctermfg=DarkBlue guibg=LightGrey guifg=DarkBlue"),
205f9cc9f20SBram Moolenaar     CENT("FoldColumn term=standout ctermbg=Grey ctermfg=DarkBlue",
206f9cc9f20SBram Moolenaar 	 "FoldColumn term=standout ctermbg=Grey ctermfg=DarkBlue guibg=Grey guifg=DarkBlue"),
207f9cc9f20SBram Moolenaar #endif
208f9cc9f20SBram Moolenaar #ifdef FEAT_SIGNS
209f9cc9f20SBram Moolenaar     CENT("SignColumn term=standout ctermbg=Grey ctermfg=DarkBlue",
210f9cc9f20SBram Moolenaar 	 "SignColumn term=standout ctermbg=Grey ctermfg=DarkBlue guibg=Grey guifg=DarkBlue"),
211f9cc9f20SBram Moolenaar #endif
212f9cc9f20SBram Moolenaar     CENT("Visual term=reverse",
213f9cc9f20SBram Moolenaar 	 "Visual term=reverse guibg=LightGrey"),
214f9cc9f20SBram Moolenaar #ifdef FEAT_DIFF
215f9cc9f20SBram Moolenaar     CENT("DiffAdd term=bold ctermbg=LightBlue",
216f9cc9f20SBram Moolenaar 	 "DiffAdd term=bold ctermbg=LightBlue guibg=LightBlue"),
217f9cc9f20SBram Moolenaar     CENT("DiffChange term=bold ctermbg=LightMagenta",
218f9cc9f20SBram Moolenaar 	 "DiffChange term=bold ctermbg=LightMagenta guibg=LightMagenta"),
219f9cc9f20SBram Moolenaar     CENT("DiffDelete term=bold ctermfg=Blue ctermbg=LightCyan",
220f9cc9f20SBram Moolenaar 	 "DiffDelete term=bold ctermfg=Blue ctermbg=LightCyan gui=bold guifg=Blue guibg=LightCyan"),
221f9cc9f20SBram Moolenaar #endif
222f9cc9f20SBram Moolenaar     CENT("TabLine term=underline cterm=underline ctermfg=black ctermbg=LightGrey",
223f9cc9f20SBram Moolenaar 	 "TabLine term=underline cterm=underline ctermfg=black ctermbg=LightGrey gui=underline guibg=LightGrey"),
224f9cc9f20SBram Moolenaar #ifdef FEAT_SYN_HL
225f9cc9f20SBram Moolenaar     CENT("CursorColumn term=reverse ctermbg=LightGrey",
226f9cc9f20SBram Moolenaar 	 "CursorColumn term=reverse ctermbg=LightGrey guibg=Grey90"),
227f9cc9f20SBram Moolenaar     CENT("CursorLine term=underline cterm=underline",
228f9cc9f20SBram Moolenaar 	 "CursorLine term=underline cterm=underline guibg=Grey90"),
229f9cc9f20SBram Moolenaar     CENT("ColorColumn term=reverse ctermbg=LightRed",
230f9cc9f20SBram Moolenaar 	 "ColorColumn term=reverse ctermbg=LightRed guibg=LightRed"),
231f9cc9f20SBram Moolenaar #endif
232f9cc9f20SBram Moolenaar #ifdef FEAT_CONCEAL
233f9cc9f20SBram Moolenaar     CENT("Conceal ctermbg=DarkGrey ctermfg=LightGrey",
234f9cc9f20SBram Moolenaar 	 "Conceal ctermbg=DarkGrey ctermfg=LightGrey guibg=DarkGrey guifg=LightGrey"),
235f9cc9f20SBram Moolenaar #endif
236f9cc9f20SBram Moolenaar     CENT("MatchParen term=reverse ctermbg=Cyan",
237f9cc9f20SBram Moolenaar 	 "MatchParen term=reverse ctermbg=Cyan guibg=Cyan"),
238f9cc9f20SBram Moolenaar #ifdef FEAT_TERMINAL
239f9cc9f20SBram Moolenaar     CENT("StatusLineTerm term=reverse,bold cterm=bold ctermfg=White ctermbg=DarkGreen",
240f9cc9f20SBram Moolenaar 	 "StatusLineTerm term=reverse,bold cterm=bold ctermfg=White ctermbg=DarkGreen gui=bold guifg=bg guibg=DarkGreen"),
241f9cc9f20SBram Moolenaar     CENT("StatusLineTermNC term=reverse ctermfg=White ctermbg=DarkGreen",
242f9cc9f20SBram Moolenaar 	 "StatusLineTermNC term=reverse ctermfg=White ctermbg=DarkGreen guifg=bg guibg=DarkGreen"),
243f9cc9f20SBram Moolenaar #endif
244f9cc9f20SBram Moolenaar #ifdef FEAT_MENU
245f9cc9f20SBram Moolenaar     CENT("ToolbarLine term=underline ctermbg=LightGrey",
246f9cc9f20SBram Moolenaar 	 "ToolbarLine term=underline ctermbg=LightGrey guibg=LightGrey"),
247f9cc9f20SBram Moolenaar     CENT("ToolbarButton cterm=bold ctermfg=White ctermbg=DarkGrey",
248f9cc9f20SBram Moolenaar 	 "ToolbarButton cterm=bold ctermfg=White ctermbg=DarkGrey gui=bold guifg=White guibg=Grey40"),
249f9cc9f20SBram Moolenaar #endif
250f9cc9f20SBram Moolenaar     NULL
251f9cc9f20SBram Moolenaar };
252f9cc9f20SBram Moolenaar 
253f9cc9f20SBram Moolenaar /* Default colors only used with a dark background. */
254f9cc9f20SBram Moolenaar static char *(highlight_init_dark[]) = {
255f9cc9f20SBram Moolenaar     CENT("Directory term=bold ctermfg=LightCyan",
256f9cc9f20SBram Moolenaar 	 "Directory term=bold ctermfg=LightCyan guifg=Cyan"),
257f9cc9f20SBram Moolenaar     CENT("LineNr term=underline ctermfg=Yellow",
258f9cc9f20SBram Moolenaar 	 "LineNr term=underline ctermfg=Yellow guifg=Yellow"),
259f9cc9f20SBram Moolenaar     CENT("CursorLineNr term=bold ctermfg=Yellow",
260f9cc9f20SBram Moolenaar 	 "CursorLineNr term=bold ctermfg=Yellow gui=bold guifg=Yellow"),
261f9cc9f20SBram Moolenaar     CENT("MoreMsg term=bold ctermfg=LightGreen",
262f9cc9f20SBram Moolenaar 	 "MoreMsg term=bold ctermfg=LightGreen gui=bold guifg=SeaGreen"),
263f9cc9f20SBram Moolenaar     CENT("Question term=standout ctermfg=LightGreen",
264f9cc9f20SBram Moolenaar 	 "Question term=standout ctermfg=LightGreen gui=bold guifg=Green"),
265f9cc9f20SBram Moolenaar     CENT("Search term=reverse ctermbg=Yellow ctermfg=Black",
266f9cc9f20SBram Moolenaar 	 "Search term=reverse ctermbg=Yellow ctermfg=Black guibg=Yellow guifg=Black"),
267f9cc9f20SBram Moolenaar     CENT("SpecialKey term=bold ctermfg=LightBlue",
268f9cc9f20SBram Moolenaar 	 "SpecialKey term=bold ctermfg=LightBlue guifg=Cyan"),
269f9cc9f20SBram Moolenaar #ifdef FEAT_SPELL
270f9cc9f20SBram Moolenaar     CENT("SpellBad term=reverse ctermbg=Red",
271f9cc9f20SBram Moolenaar 	 "SpellBad term=reverse ctermbg=Red guisp=Red gui=undercurl"),
272f9cc9f20SBram Moolenaar     CENT("SpellCap term=reverse ctermbg=Blue",
273f9cc9f20SBram Moolenaar 	 "SpellCap term=reverse ctermbg=Blue guisp=Blue gui=undercurl"),
274f9cc9f20SBram Moolenaar     CENT("SpellRare term=reverse ctermbg=Magenta",
275f9cc9f20SBram Moolenaar 	 "SpellRare term=reverse ctermbg=Magenta guisp=Magenta gui=undercurl"),
276f9cc9f20SBram Moolenaar     CENT("SpellLocal term=underline ctermbg=Cyan",
277f9cc9f20SBram Moolenaar 	 "SpellLocal term=underline ctermbg=Cyan guisp=Cyan gui=undercurl"),
278f9cc9f20SBram Moolenaar #endif
279f9cc9f20SBram Moolenaar #ifdef FEAT_INS_EXPAND
280f9cc9f20SBram Moolenaar     CENT("PmenuThumb ctermbg=White",
281f9cc9f20SBram Moolenaar 	 "PmenuThumb ctermbg=White guibg=White"),
282f9cc9f20SBram Moolenaar     CENT("Pmenu ctermbg=Magenta ctermfg=Black",
283f9cc9f20SBram Moolenaar 	 "Pmenu ctermbg=Magenta ctermfg=Black guibg=Magenta"),
284f9cc9f20SBram Moolenaar     CENT("PmenuSel ctermbg=Black ctermfg=DarkGrey",
285f9cc9f20SBram Moolenaar 	 "PmenuSel ctermbg=Black ctermfg=DarkGrey guibg=DarkGrey"),
286f9cc9f20SBram Moolenaar #endif
287f9cc9f20SBram Moolenaar     CENT("Title term=bold ctermfg=LightMagenta",
288f9cc9f20SBram Moolenaar 	 "Title term=bold ctermfg=LightMagenta gui=bold guifg=Magenta"),
289f9cc9f20SBram Moolenaar     CENT("WarningMsg term=standout ctermfg=LightRed",
290f9cc9f20SBram Moolenaar 	 "WarningMsg term=standout ctermfg=LightRed guifg=Red"),
291f9cc9f20SBram Moolenaar #ifdef FEAT_WILDMENU
292f9cc9f20SBram Moolenaar     CENT("WildMenu term=standout ctermbg=Yellow ctermfg=Black",
293f9cc9f20SBram Moolenaar 	 "WildMenu term=standout ctermbg=Yellow ctermfg=Black guibg=Yellow guifg=Black"),
294f9cc9f20SBram Moolenaar #endif
295f9cc9f20SBram Moolenaar #ifdef FEAT_FOLDING
296f9cc9f20SBram Moolenaar     CENT("Folded term=standout ctermbg=DarkGrey ctermfg=Cyan",
297f9cc9f20SBram Moolenaar 	 "Folded term=standout ctermbg=DarkGrey ctermfg=Cyan guibg=DarkGrey guifg=Cyan"),
298f9cc9f20SBram Moolenaar     CENT("FoldColumn term=standout ctermbg=DarkGrey ctermfg=Cyan",
299f9cc9f20SBram Moolenaar 	 "FoldColumn term=standout ctermbg=DarkGrey ctermfg=Cyan guibg=Grey guifg=Cyan"),
300f9cc9f20SBram Moolenaar #endif
301f9cc9f20SBram Moolenaar #ifdef FEAT_SIGNS
302f9cc9f20SBram Moolenaar     CENT("SignColumn term=standout ctermbg=DarkGrey ctermfg=Cyan",
303f9cc9f20SBram Moolenaar 	 "SignColumn term=standout ctermbg=DarkGrey ctermfg=Cyan guibg=Grey guifg=Cyan"),
304f9cc9f20SBram Moolenaar #endif
305f9cc9f20SBram Moolenaar     CENT("Visual term=reverse",
306f9cc9f20SBram Moolenaar 	 "Visual term=reverse guibg=DarkGrey"),
307f9cc9f20SBram Moolenaar #ifdef FEAT_DIFF
308f9cc9f20SBram Moolenaar     CENT("DiffAdd term=bold ctermbg=DarkBlue",
309f9cc9f20SBram Moolenaar 	 "DiffAdd term=bold ctermbg=DarkBlue guibg=DarkBlue"),
310f9cc9f20SBram Moolenaar     CENT("DiffChange term=bold ctermbg=DarkMagenta",
311f9cc9f20SBram Moolenaar 	 "DiffChange term=bold ctermbg=DarkMagenta guibg=DarkMagenta"),
312f9cc9f20SBram Moolenaar     CENT("DiffDelete term=bold ctermfg=Blue ctermbg=DarkCyan",
313f9cc9f20SBram Moolenaar 	 "DiffDelete term=bold ctermfg=Blue ctermbg=DarkCyan gui=bold guifg=Blue guibg=DarkCyan"),
314f9cc9f20SBram Moolenaar #endif
315f9cc9f20SBram Moolenaar     CENT("TabLine term=underline cterm=underline ctermfg=white ctermbg=DarkGrey",
316f9cc9f20SBram Moolenaar 	 "TabLine term=underline cterm=underline ctermfg=white ctermbg=DarkGrey gui=underline guibg=DarkGrey"),
317f9cc9f20SBram Moolenaar #ifdef FEAT_SYN_HL
318f9cc9f20SBram Moolenaar     CENT("CursorColumn term=reverse ctermbg=DarkGrey",
319f9cc9f20SBram Moolenaar 	 "CursorColumn term=reverse ctermbg=DarkGrey guibg=Grey40"),
320f9cc9f20SBram Moolenaar     CENT("CursorLine term=underline cterm=underline",
321f9cc9f20SBram Moolenaar 	 "CursorLine term=underline cterm=underline guibg=Grey40"),
322f9cc9f20SBram Moolenaar     CENT("ColorColumn term=reverse ctermbg=DarkRed",
323f9cc9f20SBram Moolenaar 	 "ColorColumn term=reverse ctermbg=DarkRed guibg=DarkRed"),
324f9cc9f20SBram Moolenaar #endif
325f9cc9f20SBram Moolenaar     CENT("MatchParen term=reverse ctermbg=DarkCyan",
326f9cc9f20SBram Moolenaar 	 "MatchParen term=reverse ctermbg=DarkCyan guibg=DarkCyan"),
327f9cc9f20SBram Moolenaar #ifdef FEAT_CONCEAL
328f9cc9f20SBram Moolenaar     CENT("Conceal ctermbg=DarkGrey ctermfg=LightGrey",
329f9cc9f20SBram Moolenaar 	 "Conceal ctermbg=DarkGrey ctermfg=LightGrey guibg=DarkGrey guifg=LightGrey"),
330f9cc9f20SBram Moolenaar #endif
331f9cc9f20SBram Moolenaar #ifdef FEAT_TERMINAL
332f9cc9f20SBram Moolenaar     CENT("StatusLineTerm term=reverse,bold cterm=bold ctermfg=Black ctermbg=LightGreen",
333f9cc9f20SBram Moolenaar 	 "StatusLineTerm term=reverse,bold cterm=bold ctermfg=Black ctermbg=LightGreen gui=bold guifg=bg guibg=LightGreen"),
334f9cc9f20SBram Moolenaar     CENT("StatusLineTermNC term=reverse ctermfg=Black ctermbg=LightGreen",
335f9cc9f20SBram Moolenaar 	 "StatusLineTermNC term=reverse ctermfg=Black ctermbg=LightGreen guifg=bg guibg=LightGreen"),
336f9cc9f20SBram Moolenaar #endif
337f9cc9f20SBram Moolenaar #ifdef FEAT_MENU
338f9cc9f20SBram Moolenaar     CENT("ToolbarLine term=underline ctermbg=DarkGrey",
339f9cc9f20SBram Moolenaar 	 "ToolbarLine term=underline ctermbg=DarkGrey guibg=Grey50"),
340f9cc9f20SBram Moolenaar     CENT("ToolbarButton cterm=bold ctermfg=Black ctermbg=LightGrey",
341f9cc9f20SBram Moolenaar 	 "ToolbarButton cterm=bold ctermfg=Black ctermbg=LightGrey gui=bold guifg=Black guibg=LightGrey"),
342f9cc9f20SBram Moolenaar #endif
343f9cc9f20SBram Moolenaar     NULL
344f9cc9f20SBram Moolenaar };
345f9cc9f20SBram Moolenaar 
3462ac6e82aSBram Moolenaar /*
3472ac6e82aSBram Moolenaar  * Returns the number of highlight groups.
3482ac6e82aSBram Moolenaar  */
3492ac6e82aSBram Moolenaar     int
3502ac6e82aSBram Moolenaar highlight_num_groups(void)
3512ac6e82aSBram Moolenaar {
3522ac6e82aSBram Moolenaar     return highlight_ga.ga_len;
3532ac6e82aSBram Moolenaar }
3542ac6e82aSBram Moolenaar 
3552ac6e82aSBram Moolenaar /*
3562ac6e82aSBram Moolenaar  * Returns the name of a highlight group.
3572ac6e82aSBram Moolenaar  */
3582ac6e82aSBram Moolenaar     char_u *
3592ac6e82aSBram Moolenaar highlight_group_name(int id)
3602ac6e82aSBram Moolenaar {
3612ac6e82aSBram Moolenaar     return HL_TABLE()[id].sg_name;
3622ac6e82aSBram Moolenaar }
3632ac6e82aSBram Moolenaar 
3642ac6e82aSBram Moolenaar /*
3652ac6e82aSBram Moolenaar  * Returns the ID of the link to a highlight group.
3662ac6e82aSBram Moolenaar  */
3672ac6e82aSBram Moolenaar     int
3682ac6e82aSBram Moolenaar highlight_link_id(int id)
3692ac6e82aSBram Moolenaar {
3702ac6e82aSBram Moolenaar     return HL_TABLE()[id].sg_link;
3712ac6e82aSBram Moolenaar }
3722ac6e82aSBram Moolenaar 
373f9cc9f20SBram Moolenaar     void
374f9cc9f20SBram Moolenaar init_highlight(
375f9cc9f20SBram Moolenaar     int		both,	    // include groups where 'bg' doesn't matter
376f9cc9f20SBram Moolenaar     int		reset)	    // clear group first
377f9cc9f20SBram Moolenaar {
378f9cc9f20SBram Moolenaar     int		i;
379f9cc9f20SBram Moolenaar     char	**pp;
380f9cc9f20SBram Moolenaar     static int	had_both = FALSE;
381f9cc9f20SBram Moolenaar #ifdef FEAT_EVAL
382f9cc9f20SBram Moolenaar     char_u	*p;
383f9cc9f20SBram Moolenaar 
384f9cc9f20SBram Moolenaar     /*
385f9cc9f20SBram Moolenaar      * Try finding the color scheme file.  Used when a color file was loaded
386f9cc9f20SBram Moolenaar      * and 'background' or 't_Co' is changed.
387f9cc9f20SBram Moolenaar      */
388f9cc9f20SBram Moolenaar     p = get_var_value((char_u *)"g:colors_name");
389f9cc9f20SBram Moolenaar     if (p != NULL)
390f9cc9f20SBram Moolenaar     {
391f9cc9f20SBram Moolenaar 	// The value of g:colors_name could be freed when sourcing the script,
392f9cc9f20SBram Moolenaar 	// making "p" invalid, so copy it.
393f9cc9f20SBram Moolenaar 	char_u *copy_p = vim_strsave(p);
394f9cc9f20SBram Moolenaar 	int    r;
395f9cc9f20SBram Moolenaar 
396f9cc9f20SBram Moolenaar 	if (copy_p != NULL)
397f9cc9f20SBram Moolenaar 	{
398f9cc9f20SBram Moolenaar 	    r = load_colors(copy_p);
399f9cc9f20SBram Moolenaar 	    vim_free(copy_p);
400f9cc9f20SBram Moolenaar 	    if (r == OK)
401f9cc9f20SBram Moolenaar 		return;
402f9cc9f20SBram Moolenaar 	}
403f9cc9f20SBram Moolenaar     }
404f9cc9f20SBram Moolenaar 
405f9cc9f20SBram Moolenaar #endif
406f9cc9f20SBram Moolenaar 
407f9cc9f20SBram Moolenaar     /*
408f9cc9f20SBram Moolenaar      * Didn't use a color file, use the compiled-in colors.
409f9cc9f20SBram Moolenaar      */
410f9cc9f20SBram Moolenaar     if (both)
411f9cc9f20SBram Moolenaar     {
412f9cc9f20SBram Moolenaar 	had_both = TRUE;
413f9cc9f20SBram Moolenaar 	pp = highlight_init_both;
414f9cc9f20SBram Moolenaar 	for (i = 0; pp[i] != NULL; ++i)
415f9cc9f20SBram Moolenaar 	    do_highlight((char_u *)pp[i], reset, TRUE);
416f9cc9f20SBram Moolenaar     }
417f9cc9f20SBram Moolenaar     else if (!had_both)
418f9cc9f20SBram Moolenaar 	// Don't do anything before the call with both == TRUE from main().
419f9cc9f20SBram Moolenaar 	// Not everything has been setup then, and that call will overrule
420f9cc9f20SBram Moolenaar 	// everything anyway.
421f9cc9f20SBram Moolenaar 	return;
422f9cc9f20SBram Moolenaar 
423f9cc9f20SBram Moolenaar     if (*p_bg == 'l')
424f9cc9f20SBram Moolenaar 	pp = highlight_init_light;
425f9cc9f20SBram Moolenaar     else
426f9cc9f20SBram Moolenaar 	pp = highlight_init_dark;
427f9cc9f20SBram Moolenaar     for (i = 0; pp[i] != NULL; ++i)
428f9cc9f20SBram Moolenaar 	do_highlight((char_u *)pp[i], reset, TRUE);
429f9cc9f20SBram Moolenaar 
430f9cc9f20SBram Moolenaar     // Reverse looks ugly, but grey may not work for 8 colors.  Thus let it
431f9cc9f20SBram Moolenaar     // depend on the number of colors available.
432f9cc9f20SBram Moolenaar     // With 8 colors brown is equal to yellow, need to use black for Search fg
433f9cc9f20SBram Moolenaar     // to avoid Statement highlighted text disappears.
434f9cc9f20SBram Moolenaar     // Clear the attributes, needed when changing the t_Co value.
435f9cc9f20SBram Moolenaar     if (t_colors > 8)
436f9cc9f20SBram Moolenaar 	do_highlight((char_u *)(*p_bg == 'l'
437f9cc9f20SBram Moolenaar 		    ? "Visual cterm=NONE ctermbg=LightGrey"
438f9cc9f20SBram Moolenaar 		    : "Visual cterm=NONE ctermbg=DarkGrey"), FALSE, TRUE);
439f9cc9f20SBram Moolenaar     else
440f9cc9f20SBram Moolenaar     {
441f9cc9f20SBram Moolenaar 	do_highlight((char_u *)"Visual cterm=reverse ctermbg=NONE",
442f9cc9f20SBram Moolenaar 								 FALSE, TRUE);
443f9cc9f20SBram Moolenaar 	if (*p_bg == 'l')
444f9cc9f20SBram Moolenaar 	    do_highlight((char_u *)"Search ctermfg=black", FALSE, TRUE);
445f9cc9f20SBram Moolenaar     }
446f9cc9f20SBram Moolenaar 
447f9cc9f20SBram Moolenaar #ifdef FEAT_SYN_HL
448f9cc9f20SBram Moolenaar     /*
449f9cc9f20SBram Moolenaar      * If syntax highlighting is enabled load the highlighting for it.
450f9cc9f20SBram Moolenaar      */
451f9cc9f20SBram Moolenaar     if (get_var_value((char_u *)"g:syntax_on") != NULL)
452f9cc9f20SBram Moolenaar     {
453f9cc9f20SBram Moolenaar 	static int	recursive = 0;
454f9cc9f20SBram Moolenaar 
455f9cc9f20SBram Moolenaar 	if (recursive >= 5)
456f9cc9f20SBram Moolenaar 	    emsg(_("E679: recursive loop loading syncolor.vim"));
457f9cc9f20SBram Moolenaar 	else
458f9cc9f20SBram Moolenaar 	{
459f9cc9f20SBram Moolenaar 	    ++recursive;
460f9cc9f20SBram Moolenaar 	    (void)source_runtime((char_u *)"syntax/syncolor.vim", DIP_ALL);
461f9cc9f20SBram Moolenaar 	    --recursive;
462f9cc9f20SBram Moolenaar 	}
463f9cc9f20SBram Moolenaar     }
464f9cc9f20SBram Moolenaar #endif
465f9cc9f20SBram Moolenaar }
466f9cc9f20SBram Moolenaar 
467f9cc9f20SBram Moolenaar /*
468f9cc9f20SBram Moolenaar  * Load color file "name".
469f9cc9f20SBram Moolenaar  * Return OK for success, FAIL for failure.
470f9cc9f20SBram Moolenaar  */
471f9cc9f20SBram Moolenaar     int
472f9cc9f20SBram Moolenaar load_colors(char_u *name)
473f9cc9f20SBram Moolenaar {
474f9cc9f20SBram Moolenaar     char_u	*buf;
475f9cc9f20SBram Moolenaar     int		retval = FAIL;
476f9cc9f20SBram Moolenaar     static int	recursive = FALSE;
477f9cc9f20SBram Moolenaar 
478f9cc9f20SBram Moolenaar     // When being called recursively, this is probably because setting
479f9cc9f20SBram Moolenaar     // 'background' caused the highlighting to be reloaded.  This means it is
480f9cc9f20SBram Moolenaar     // working, thus we should return OK.
481f9cc9f20SBram Moolenaar     if (recursive)
482f9cc9f20SBram Moolenaar 	return OK;
483f9cc9f20SBram Moolenaar 
484f9cc9f20SBram Moolenaar     recursive = TRUE;
485f9cc9f20SBram Moolenaar     buf = alloc(STRLEN(name) + 12);
486f9cc9f20SBram Moolenaar     if (buf != NULL)
487f9cc9f20SBram Moolenaar     {
488f9cc9f20SBram Moolenaar 	apply_autocmds(EVENT_COLORSCHEMEPRE, name,
489f9cc9f20SBram Moolenaar 					       curbuf->b_fname, FALSE, curbuf);
490f9cc9f20SBram Moolenaar 	sprintf((char *)buf, "colors/%s.vim", name);
491f9cc9f20SBram Moolenaar 	retval = source_runtime(buf, DIP_START + DIP_OPT);
492f9cc9f20SBram Moolenaar 	vim_free(buf);
493f9cc9f20SBram Moolenaar 	apply_autocmds(EVENT_COLORSCHEME, name, curbuf->b_fname, FALSE, curbuf);
494f9cc9f20SBram Moolenaar     }
495f9cc9f20SBram Moolenaar     recursive = FALSE;
496f9cc9f20SBram Moolenaar 
497f9cc9f20SBram Moolenaar     return retval;
498f9cc9f20SBram Moolenaar }
499f9cc9f20SBram Moolenaar 
500f9cc9f20SBram Moolenaar static char *(color_names[28]) = {
501f9cc9f20SBram Moolenaar 	    "Black", "DarkBlue", "DarkGreen", "DarkCyan",
502f9cc9f20SBram Moolenaar 	    "DarkRed", "DarkMagenta", "Brown", "DarkYellow",
503f9cc9f20SBram Moolenaar 	    "Gray", "Grey", "LightGray", "LightGrey",
504f9cc9f20SBram Moolenaar 	    "DarkGray", "DarkGrey",
505f9cc9f20SBram Moolenaar 	    "Blue", "LightBlue", "Green", "LightGreen",
506f9cc9f20SBram Moolenaar 	    "Cyan", "LightCyan", "Red", "LightRed", "Magenta",
507f9cc9f20SBram Moolenaar 	    "LightMagenta", "Yellow", "LightYellow", "White", "NONE"};
508f9cc9f20SBram Moolenaar 	    // indices:
509f9cc9f20SBram Moolenaar 	    // 0, 1, 2, 3,
510f9cc9f20SBram Moolenaar 	    // 4, 5, 6, 7,
511f9cc9f20SBram Moolenaar 	    // 8, 9, 10, 11,
512f9cc9f20SBram Moolenaar 	    // 12, 13,
513f9cc9f20SBram Moolenaar 	    // 14, 15, 16, 17,
514f9cc9f20SBram Moolenaar 	    // 18, 19, 20, 21, 22,
515f9cc9f20SBram Moolenaar 	    // 23, 24, 25, 26, 27
516f9cc9f20SBram Moolenaar static int color_numbers_16[28] = {0, 1, 2, 3,
517f9cc9f20SBram Moolenaar 				 4, 5, 6, 6,
518f9cc9f20SBram Moolenaar 				 7, 7, 7, 7,
519f9cc9f20SBram Moolenaar 				 8, 8,
520f9cc9f20SBram Moolenaar 				 9, 9, 10, 10,
521f9cc9f20SBram Moolenaar 				 11, 11, 12, 12, 13,
522f9cc9f20SBram Moolenaar 				 13, 14, 14, 15, -1};
523f9cc9f20SBram Moolenaar // for xterm with 88 colors...
524f9cc9f20SBram Moolenaar static int color_numbers_88[28] = {0, 4, 2, 6,
525f9cc9f20SBram Moolenaar 				 1, 5, 32, 72,
526f9cc9f20SBram Moolenaar 				 84, 84, 7, 7,
527f9cc9f20SBram Moolenaar 				 82, 82,
528f9cc9f20SBram Moolenaar 				 12, 43, 10, 61,
529f9cc9f20SBram Moolenaar 				 14, 63, 9, 74, 13,
530f9cc9f20SBram Moolenaar 				 75, 11, 78, 15, -1};
531f9cc9f20SBram Moolenaar // for xterm with 256 colors...
532f9cc9f20SBram Moolenaar static int color_numbers_256[28] = {0, 4, 2, 6,
533f9cc9f20SBram Moolenaar 				 1, 5, 130, 130,
534f9cc9f20SBram Moolenaar 				 248, 248, 7, 7,
535f9cc9f20SBram Moolenaar 				 242, 242,
536f9cc9f20SBram Moolenaar 				 12, 81, 10, 121,
537f9cc9f20SBram Moolenaar 				 14, 159, 9, 224, 13,
538f9cc9f20SBram Moolenaar 				 225, 11, 229, 15, -1};
539f9cc9f20SBram Moolenaar // for terminals with less than 16 colors...
540f9cc9f20SBram Moolenaar static int color_numbers_8[28] = {0, 4, 2, 6,
541f9cc9f20SBram Moolenaar 				 1, 5, 3, 3,
542f9cc9f20SBram Moolenaar 				 7, 7, 7, 7,
543f9cc9f20SBram Moolenaar 				 0+8, 0+8,
544f9cc9f20SBram Moolenaar 				 4+8, 4+8, 2+8, 2+8,
545f9cc9f20SBram Moolenaar 				 6+8, 6+8, 1+8, 1+8, 5+8,
546f9cc9f20SBram Moolenaar 				 5+8, 3+8, 3+8, 7+8, -1};
547f9cc9f20SBram Moolenaar 
548f9cc9f20SBram Moolenaar /*
549f9cc9f20SBram Moolenaar  * Lookup the "cterm" value to be used for color with index "idx" in
550f9cc9f20SBram Moolenaar  * color_names[].
551f9cc9f20SBram Moolenaar  * "boldp" will be set to TRUE or FALSE for a foreground color when using 8
552f9cc9f20SBram Moolenaar  * colors, otherwise it will be unchanged.
553f9cc9f20SBram Moolenaar  */
554f9cc9f20SBram Moolenaar     int
555f9cc9f20SBram Moolenaar lookup_color(int idx, int foreground, int *boldp)
556f9cc9f20SBram Moolenaar {
557f9cc9f20SBram Moolenaar     int		color = color_numbers_16[idx];
558f9cc9f20SBram Moolenaar     char_u	*p;
559f9cc9f20SBram Moolenaar 
560f9cc9f20SBram Moolenaar     // Use the _16 table to check if it's a valid color name.
561f9cc9f20SBram Moolenaar     if (color < 0)
562f9cc9f20SBram Moolenaar 	return -1;
563f9cc9f20SBram Moolenaar 
564f9cc9f20SBram Moolenaar     if (t_colors == 8)
565f9cc9f20SBram Moolenaar     {
566f9cc9f20SBram Moolenaar 	// t_Co is 8: use the 8 colors table
567f9cc9f20SBram Moolenaar #if defined(__QNXNTO__)
568f9cc9f20SBram Moolenaar 	color = color_numbers_8_qansi[idx];
569f9cc9f20SBram Moolenaar #else
570f9cc9f20SBram Moolenaar 	color = color_numbers_8[idx];
571f9cc9f20SBram Moolenaar #endif
572f9cc9f20SBram Moolenaar 	if (foreground)
573f9cc9f20SBram Moolenaar 	{
574f9cc9f20SBram Moolenaar 	    // set/reset bold attribute to get light foreground
575f9cc9f20SBram Moolenaar 	    // colors (on some terminals, e.g. "linux")
576f9cc9f20SBram Moolenaar 	    if (color & 8)
577f9cc9f20SBram Moolenaar 		*boldp = TRUE;
578f9cc9f20SBram Moolenaar 	    else
579f9cc9f20SBram Moolenaar 		*boldp = FALSE;
580f9cc9f20SBram Moolenaar 	}
581f9cc9f20SBram Moolenaar 	color &= 7;	// truncate to 8 colors
582f9cc9f20SBram Moolenaar     }
583f9cc9f20SBram Moolenaar     else if (t_colors == 16 || t_colors == 88
584f9cc9f20SBram Moolenaar 					   || t_colors >= 256)
585f9cc9f20SBram Moolenaar     {
586f9cc9f20SBram Moolenaar 	/*
587f9cc9f20SBram Moolenaar 	 * Guess: if the termcap entry ends in 'm', it is
588f9cc9f20SBram Moolenaar 	 * probably an xterm-like terminal.  Use the changed
589f9cc9f20SBram Moolenaar 	 * order for colors.
590f9cc9f20SBram Moolenaar 	 */
591f9cc9f20SBram Moolenaar 	if (*T_CAF != NUL)
592f9cc9f20SBram Moolenaar 	    p = T_CAF;
593f9cc9f20SBram Moolenaar 	else
594f9cc9f20SBram Moolenaar 	    p = T_CSF;
595f9cc9f20SBram Moolenaar 	if (*p != NUL && (t_colors > 256
596f9cc9f20SBram Moolenaar 			      || *(p + STRLEN(p) - 1) == 'm'))
597f9cc9f20SBram Moolenaar 	{
598f9cc9f20SBram Moolenaar 	    if (t_colors == 88)
599f9cc9f20SBram Moolenaar 		color = color_numbers_88[idx];
600f9cc9f20SBram Moolenaar 	    else if (t_colors >= 256)
601f9cc9f20SBram Moolenaar 		color = color_numbers_256[idx];
602f9cc9f20SBram Moolenaar 	    else
603f9cc9f20SBram Moolenaar 		color = color_numbers_8[idx];
604f9cc9f20SBram Moolenaar 	}
605f9cc9f20SBram Moolenaar #ifdef FEAT_TERMRESPONSE
606f9cc9f20SBram Moolenaar 	if (t_colors >= 256 && color == 15 && is_mac_terminal)
607f9cc9f20SBram Moolenaar 	    // Terminal.app has a bug: 15 is light grey. Use white
608f9cc9f20SBram Moolenaar 	    // from the color cube instead.
609f9cc9f20SBram Moolenaar 	    color = 231;
610f9cc9f20SBram Moolenaar #endif
611f9cc9f20SBram Moolenaar     }
612f9cc9f20SBram Moolenaar     return color;
613f9cc9f20SBram Moolenaar }
614f9cc9f20SBram Moolenaar 
615f9cc9f20SBram Moolenaar /*
616f9cc9f20SBram Moolenaar  * Handle the ":highlight .." command.
617f9cc9f20SBram Moolenaar  * When using ":hi clear" this is called recursively for each group with
618f9cc9f20SBram Moolenaar  * "forceit" and "init" both TRUE.
619f9cc9f20SBram Moolenaar  */
620f9cc9f20SBram Moolenaar     void
621f9cc9f20SBram Moolenaar do_highlight(
622f9cc9f20SBram Moolenaar     char_u	*line,
623f9cc9f20SBram Moolenaar     int		forceit,
624f9cc9f20SBram Moolenaar     int		init)	    // TRUE when called for initializing
625f9cc9f20SBram Moolenaar {
626f9cc9f20SBram Moolenaar     char_u	*name_end;
627f9cc9f20SBram Moolenaar     char_u	*p;
628f9cc9f20SBram Moolenaar     char_u	*linep;
629f9cc9f20SBram Moolenaar     char_u	*key_start;
630f9cc9f20SBram Moolenaar     char_u	*arg_start;
631f9cc9f20SBram Moolenaar     char_u	*key = NULL, *arg = NULL;
632f9cc9f20SBram Moolenaar     long	i;
633f9cc9f20SBram Moolenaar     int		off;
634f9cc9f20SBram Moolenaar     int		len;
635f9cc9f20SBram Moolenaar     int		attr;
636f9cc9f20SBram Moolenaar     int		id;
637f9cc9f20SBram Moolenaar     int		idx;
638f9cc9f20SBram Moolenaar     hl_group_T	item_before;
639f9cc9f20SBram Moolenaar     int		did_change = FALSE;
640f9cc9f20SBram Moolenaar     int		dodefault = FALSE;
641f9cc9f20SBram Moolenaar     int		doclear = FALSE;
642f9cc9f20SBram Moolenaar     int		dolink = FALSE;
643f9cc9f20SBram Moolenaar     int		error = FALSE;
644f9cc9f20SBram Moolenaar     int		color;
645f9cc9f20SBram Moolenaar     int		is_normal_group = FALSE;	// "Normal" group
646f9cc9f20SBram Moolenaar #ifdef FEAT_TERMINAL
647f9cc9f20SBram Moolenaar     int		is_terminal_group = FALSE;	// "Terminal" group
648f9cc9f20SBram Moolenaar #endif
649f9cc9f20SBram Moolenaar #ifdef FEAT_GUI_X11
650f9cc9f20SBram Moolenaar     int		is_menu_group = FALSE;		// "Menu" group
651f9cc9f20SBram Moolenaar     int		is_scrollbar_group = FALSE;	// "Scrollbar" group
652f9cc9f20SBram Moolenaar     int		is_tooltip_group = FALSE;	// "Tooltip" group
653f9cc9f20SBram Moolenaar     int		do_colors = FALSE;		// need to update colors?
654f9cc9f20SBram Moolenaar #else
655f9cc9f20SBram Moolenaar # define is_menu_group 0
656f9cc9f20SBram Moolenaar # define is_tooltip_group 0
657f9cc9f20SBram Moolenaar #endif
658f9cc9f20SBram Moolenaar #if defined(FEAT_GUI) || defined(FEAT_TERMGUICOLORS)
659f9cc9f20SBram Moolenaar     int		did_highlight_changed = FALSE;
660f9cc9f20SBram Moolenaar #endif
661f9cc9f20SBram Moolenaar 
662f9cc9f20SBram Moolenaar     /*
663f9cc9f20SBram Moolenaar      * If no argument, list current highlighting.
664f9cc9f20SBram Moolenaar      */
665f9cc9f20SBram Moolenaar     if (ends_excmd(*line))
666f9cc9f20SBram Moolenaar     {
667f9cc9f20SBram Moolenaar 	for (i = 1; i <= highlight_ga.ga_len && !got_int; ++i)
668f9cc9f20SBram Moolenaar 	    // TODO: only call when the group has attributes set
669f9cc9f20SBram Moolenaar 	    highlight_list_one((int)i);
670f9cc9f20SBram Moolenaar 	return;
671f9cc9f20SBram Moolenaar     }
672f9cc9f20SBram Moolenaar 
673f9cc9f20SBram Moolenaar     /*
674f9cc9f20SBram Moolenaar      * Isolate the name.
675f9cc9f20SBram Moolenaar      */
676f9cc9f20SBram Moolenaar     name_end = skiptowhite(line);
677f9cc9f20SBram Moolenaar     linep = skipwhite(name_end);
678f9cc9f20SBram Moolenaar 
679f9cc9f20SBram Moolenaar     /*
680f9cc9f20SBram Moolenaar      * Check for "default" argument.
681f9cc9f20SBram Moolenaar      */
682f9cc9f20SBram Moolenaar     if (STRNCMP(line, "default", name_end - line) == 0)
683f9cc9f20SBram Moolenaar     {
684f9cc9f20SBram Moolenaar 	dodefault = TRUE;
685f9cc9f20SBram Moolenaar 	line = linep;
686f9cc9f20SBram Moolenaar 	name_end = skiptowhite(line);
687f9cc9f20SBram Moolenaar 	linep = skipwhite(name_end);
688f9cc9f20SBram Moolenaar     }
689f9cc9f20SBram Moolenaar 
690f9cc9f20SBram Moolenaar     /*
691f9cc9f20SBram Moolenaar      * Check for "clear" or "link" argument.
692f9cc9f20SBram Moolenaar      */
693f9cc9f20SBram Moolenaar     if (STRNCMP(line, "clear", name_end - line) == 0)
694f9cc9f20SBram Moolenaar 	doclear = TRUE;
695f9cc9f20SBram Moolenaar     if (STRNCMP(line, "link", name_end - line) == 0)
696f9cc9f20SBram Moolenaar 	dolink = TRUE;
697f9cc9f20SBram Moolenaar 
698f9cc9f20SBram Moolenaar     /*
699f9cc9f20SBram Moolenaar      * ":highlight {group-name}": list highlighting for one group.
700f9cc9f20SBram Moolenaar      */
701f9cc9f20SBram Moolenaar     if (!doclear && !dolink && ends_excmd(*linep))
702f9cc9f20SBram Moolenaar     {
703f9cc9f20SBram Moolenaar 	id = syn_namen2id(line, (int)(name_end - line));
704f9cc9f20SBram Moolenaar 	if (id == 0)
705f9cc9f20SBram Moolenaar 	    semsg(_("E411: highlight group not found: %s"), line);
706f9cc9f20SBram Moolenaar 	else
707f9cc9f20SBram Moolenaar 	    highlight_list_one(id);
708f9cc9f20SBram Moolenaar 	return;
709f9cc9f20SBram Moolenaar     }
710f9cc9f20SBram Moolenaar 
711f9cc9f20SBram Moolenaar     /*
712f9cc9f20SBram Moolenaar      * Handle ":highlight link {from} {to}" command.
713f9cc9f20SBram Moolenaar      */
714f9cc9f20SBram Moolenaar     if (dolink)
715f9cc9f20SBram Moolenaar     {
716f9cc9f20SBram Moolenaar 	char_u	    *from_start = linep;
717f9cc9f20SBram Moolenaar 	char_u	    *from_end;
718f9cc9f20SBram Moolenaar 	char_u	    *to_start;
719f9cc9f20SBram Moolenaar 	char_u	    *to_end;
720f9cc9f20SBram Moolenaar 	int	    from_id;
721f9cc9f20SBram Moolenaar 	int	    to_id;
722f9cc9f20SBram Moolenaar 
723f9cc9f20SBram Moolenaar 	from_end = skiptowhite(from_start);
724f9cc9f20SBram Moolenaar 	to_start = skipwhite(from_end);
725f9cc9f20SBram Moolenaar 	to_end	 = skiptowhite(to_start);
726f9cc9f20SBram Moolenaar 
727f9cc9f20SBram Moolenaar 	if (ends_excmd(*from_start) || ends_excmd(*to_start))
728f9cc9f20SBram Moolenaar 	{
729f9cc9f20SBram Moolenaar 	    semsg(_("E412: Not enough arguments: \":highlight link %s\""),
730f9cc9f20SBram Moolenaar 								  from_start);
731f9cc9f20SBram Moolenaar 	    return;
732f9cc9f20SBram Moolenaar 	}
733f9cc9f20SBram Moolenaar 
734f9cc9f20SBram Moolenaar 	if (!ends_excmd(*skipwhite(to_end)))
735f9cc9f20SBram Moolenaar 	{
736f9cc9f20SBram Moolenaar 	    semsg(_("E413: Too many arguments: \":highlight link %s\""), from_start);
737f9cc9f20SBram Moolenaar 	    return;
738f9cc9f20SBram Moolenaar 	}
739f9cc9f20SBram Moolenaar 
740f9cc9f20SBram Moolenaar 	from_id = syn_check_group(from_start, (int)(from_end - from_start));
741f9cc9f20SBram Moolenaar 	if (STRNCMP(to_start, "NONE", 4) == 0)
742f9cc9f20SBram Moolenaar 	    to_id = 0;
743f9cc9f20SBram Moolenaar 	else
744f9cc9f20SBram Moolenaar 	    to_id = syn_check_group(to_start, (int)(to_end - to_start));
745f9cc9f20SBram Moolenaar 
746f9cc9f20SBram Moolenaar 	if (from_id > 0 && (!init || HL_TABLE()[from_id - 1].sg_set == 0))
747f9cc9f20SBram Moolenaar 	{
748f9cc9f20SBram Moolenaar 	    /*
749f9cc9f20SBram Moolenaar 	     * Don't allow a link when there already is some highlighting
750f9cc9f20SBram Moolenaar 	     * for the group, unless '!' is used
751f9cc9f20SBram Moolenaar 	     */
752f9cc9f20SBram Moolenaar 	    if (to_id > 0 && !forceit && !init
753f9cc9f20SBram Moolenaar 				   && hl_has_settings(from_id - 1, dodefault))
754f9cc9f20SBram Moolenaar 	    {
755f9cc9f20SBram Moolenaar 		if (sourcing_name == NULL && !dodefault)
756f9cc9f20SBram Moolenaar 		    emsg(_("E414: group has settings, highlight link ignored"));
757f9cc9f20SBram Moolenaar 	    }
758f9cc9f20SBram Moolenaar 	    else if (HL_TABLE()[from_id - 1].sg_link != to_id
759f9cc9f20SBram Moolenaar #ifdef FEAT_EVAL
760f9cc9f20SBram Moolenaar 		    || HL_TABLE()[from_id - 1].sg_script_ctx.sc_sid
761f9cc9f20SBram Moolenaar 							 != current_sctx.sc_sid
762f9cc9f20SBram Moolenaar #endif
763f9cc9f20SBram Moolenaar 		    || HL_TABLE()[from_id - 1].sg_cleared)
764f9cc9f20SBram Moolenaar 	    {
765f9cc9f20SBram Moolenaar 		if (!init)
766f9cc9f20SBram Moolenaar 		    HL_TABLE()[from_id - 1].sg_set |= SG_LINK;
767f9cc9f20SBram Moolenaar 		HL_TABLE()[from_id - 1].sg_link = to_id;
768f9cc9f20SBram Moolenaar #ifdef FEAT_EVAL
769f9cc9f20SBram Moolenaar 		HL_TABLE()[from_id - 1].sg_script_ctx = current_sctx;
770f9cc9f20SBram Moolenaar 		HL_TABLE()[from_id - 1].sg_script_ctx.sc_lnum += sourcing_lnum;
771f9cc9f20SBram Moolenaar #endif
772f9cc9f20SBram Moolenaar 		HL_TABLE()[from_id - 1].sg_cleared = FALSE;
773f9cc9f20SBram Moolenaar 		redraw_all_later(SOME_VALID);
774f9cc9f20SBram Moolenaar 
775f9cc9f20SBram Moolenaar 		// Only call highlight_changed() once after multiple changes.
776f9cc9f20SBram Moolenaar 		need_highlight_changed = TRUE;
777f9cc9f20SBram Moolenaar 	    }
778f9cc9f20SBram Moolenaar 	}
779f9cc9f20SBram Moolenaar 
780f9cc9f20SBram Moolenaar 	return;
781f9cc9f20SBram Moolenaar     }
782f9cc9f20SBram Moolenaar 
783f9cc9f20SBram Moolenaar     if (doclear)
784f9cc9f20SBram Moolenaar     {
785f9cc9f20SBram Moolenaar 	/*
786f9cc9f20SBram Moolenaar 	 * ":highlight clear [group]" command.
787f9cc9f20SBram Moolenaar 	 */
788f9cc9f20SBram Moolenaar 	line = linep;
789f9cc9f20SBram Moolenaar 	if (ends_excmd(*line))
790f9cc9f20SBram Moolenaar 	{
791f9cc9f20SBram Moolenaar #ifdef FEAT_GUI
792f9cc9f20SBram Moolenaar 	    // First, we do not destroy the old values, but allocate the new
793f9cc9f20SBram Moolenaar 	    // ones and update the display. THEN we destroy the old values.
794f9cc9f20SBram Moolenaar 	    // If we destroy the old values first, then the old values
795f9cc9f20SBram Moolenaar 	    // (such as GuiFont's or GuiFontset's) will still be displayed but
796f9cc9f20SBram Moolenaar 	    // invalid because they were free'd.
797f9cc9f20SBram Moolenaar 	    if (gui.in_use)
798f9cc9f20SBram Moolenaar 	    {
799f9cc9f20SBram Moolenaar # ifdef FEAT_BEVAL_TIP
800f9cc9f20SBram Moolenaar 		gui_init_tooltip_font();
801f9cc9f20SBram Moolenaar # endif
802f9cc9f20SBram Moolenaar # if defined(FEAT_MENU) && (defined(FEAT_GUI_ATHENA) || defined(FEAT_GUI_MOTIF))
803f9cc9f20SBram Moolenaar 		gui_init_menu_font();
804f9cc9f20SBram Moolenaar # endif
805f9cc9f20SBram Moolenaar 	    }
806f9cc9f20SBram Moolenaar # if defined(FEAT_GUI_MSWIN) || defined(FEAT_GUI_X11)
807f9cc9f20SBram Moolenaar 	    gui_mch_def_colors();
808f9cc9f20SBram Moolenaar # endif
809f9cc9f20SBram Moolenaar # ifdef FEAT_GUI_X11
810f9cc9f20SBram Moolenaar #  ifdef FEAT_MENU
811f9cc9f20SBram Moolenaar 
812f9cc9f20SBram Moolenaar 	    // This only needs to be done when there is no Menu highlight
813f9cc9f20SBram Moolenaar 	    // group defined by default, which IS currently the case.
814f9cc9f20SBram Moolenaar 	    gui_mch_new_menu_colors();
815f9cc9f20SBram Moolenaar #  endif
816f9cc9f20SBram Moolenaar 	    if (gui.in_use)
817f9cc9f20SBram Moolenaar 	    {
818f9cc9f20SBram Moolenaar 		gui_new_scrollbar_colors();
819f9cc9f20SBram Moolenaar #  ifdef FEAT_BEVAL_GUI
820f9cc9f20SBram Moolenaar 		gui_mch_new_tooltip_colors();
821f9cc9f20SBram Moolenaar #  endif
822f9cc9f20SBram Moolenaar #  ifdef FEAT_MENU
823f9cc9f20SBram Moolenaar 		gui_mch_new_menu_font();
824f9cc9f20SBram Moolenaar #  endif
825f9cc9f20SBram Moolenaar 	    }
826f9cc9f20SBram Moolenaar # endif
827f9cc9f20SBram Moolenaar 
828f9cc9f20SBram Moolenaar 	    // Ok, we're done allocating the new default graphics items.
829f9cc9f20SBram Moolenaar 	    // The screen should already be refreshed at this point.
830f9cc9f20SBram Moolenaar 	    // It is now Ok to clear out the old data.
831f9cc9f20SBram Moolenaar #endif
832f9cc9f20SBram Moolenaar #ifdef FEAT_EVAL
833f9cc9f20SBram Moolenaar 	    do_unlet((char_u *)"colors_name", TRUE);
834f9cc9f20SBram Moolenaar #endif
835f9cc9f20SBram Moolenaar 	    restore_cterm_colors();
836f9cc9f20SBram Moolenaar 
837f9cc9f20SBram Moolenaar 	    /*
838f9cc9f20SBram Moolenaar 	     * Clear all default highlight groups and load the defaults.
839f9cc9f20SBram Moolenaar 	     */
840f9cc9f20SBram Moolenaar 	    for (idx = 0; idx < highlight_ga.ga_len; ++idx)
841f9cc9f20SBram Moolenaar 		highlight_clear(idx);
842f9cc9f20SBram Moolenaar 	    init_highlight(TRUE, TRUE);
843f9cc9f20SBram Moolenaar #if defined(FEAT_GUI) || defined(FEAT_TERMGUICOLORS)
844f9cc9f20SBram Moolenaar 	    if (USE_24BIT)
845f9cc9f20SBram Moolenaar 		highlight_gui_started();
846f9cc9f20SBram Moolenaar 	    else
847f9cc9f20SBram Moolenaar #endif
848f9cc9f20SBram Moolenaar 		highlight_changed();
849f9cc9f20SBram Moolenaar 	    redraw_later_clear();
850f9cc9f20SBram Moolenaar 	    return;
851f9cc9f20SBram Moolenaar 	}
852f9cc9f20SBram Moolenaar 	name_end = skiptowhite(line);
853f9cc9f20SBram Moolenaar 	linep = skipwhite(name_end);
854f9cc9f20SBram Moolenaar     }
855f9cc9f20SBram Moolenaar 
856f9cc9f20SBram Moolenaar     /*
857f9cc9f20SBram Moolenaar      * Find the group name in the table.  If it does not exist yet, add it.
858f9cc9f20SBram Moolenaar      */
859f9cc9f20SBram Moolenaar     id = syn_check_group(line, (int)(name_end - line));
860f9cc9f20SBram Moolenaar     if (id == 0)			// failed (out of memory)
861f9cc9f20SBram Moolenaar 	return;
862f9cc9f20SBram Moolenaar     idx = id - 1;			// index is ID minus one
863f9cc9f20SBram Moolenaar 
864f9cc9f20SBram Moolenaar     // Return if "default" was used and the group already has settings.
865f9cc9f20SBram Moolenaar     if (dodefault && hl_has_settings(idx, TRUE))
866f9cc9f20SBram Moolenaar 	return;
867f9cc9f20SBram Moolenaar 
868f9cc9f20SBram Moolenaar     // Make a copy so we can check if any attribute actually changed.
869f9cc9f20SBram Moolenaar     item_before = HL_TABLE()[idx];
870f9cc9f20SBram Moolenaar 
871f9cc9f20SBram Moolenaar     if (STRCMP(HL_TABLE()[idx].sg_name_u, "NORMAL") == 0)
872f9cc9f20SBram Moolenaar 	is_normal_group = TRUE;
873f9cc9f20SBram Moolenaar #ifdef FEAT_TERMINAL
874f9cc9f20SBram Moolenaar     else if (STRCMP(HL_TABLE()[idx].sg_name_u, "TERMINAL") == 0)
875f9cc9f20SBram Moolenaar 	is_terminal_group = TRUE;
876f9cc9f20SBram Moolenaar #endif
877f9cc9f20SBram Moolenaar #ifdef FEAT_GUI_X11
878f9cc9f20SBram Moolenaar     else if (STRCMP(HL_TABLE()[idx].sg_name_u, "MENU") == 0)
879f9cc9f20SBram Moolenaar 	is_menu_group = TRUE;
880f9cc9f20SBram Moolenaar     else if (STRCMP(HL_TABLE()[idx].sg_name_u, "SCROLLBAR") == 0)
881f9cc9f20SBram Moolenaar 	is_scrollbar_group = TRUE;
882f9cc9f20SBram Moolenaar     else if (STRCMP(HL_TABLE()[idx].sg_name_u, "TOOLTIP") == 0)
883f9cc9f20SBram Moolenaar 	is_tooltip_group = TRUE;
884f9cc9f20SBram Moolenaar #endif
885f9cc9f20SBram Moolenaar 
886f9cc9f20SBram Moolenaar     // Clear the highlighting for ":hi clear {group}" and ":hi clear".
887f9cc9f20SBram Moolenaar     if (doclear || (forceit && init))
888f9cc9f20SBram Moolenaar     {
889f9cc9f20SBram Moolenaar 	highlight_clear(idx);
890f9cc9f20SBram Moolenaar 	if (!doclear)
891f9cc9f20SBram Moolenaar 	    HL_TABLE()[idx].sg_set = 0;
892f9cc9f20SBram Moolenaar     }
893f9cc9f20SBram Moolenaar 
894f9cc9f20SBram Moolenaar     if (!doclear)
895f9cc9f20SBram Moolenaar       while (!ends_excmd(*linep))
896f9cc9f20SBram Moolenaar       {
897f9cc9f20SBram Moolenaar 	key_start = linep;
898f9cc9f20SBram Moolenaar 	if (*linep == '=')
899f9cc9f20SBram Moolenaar 	{
900f9cc9f20SBram Moolenaar 	    semsg(_("E415: unexpected equal sign: %s"), key_start);
901f9cc9f20SBram Moolenaar 	    error = TRUE;
902f9cc9f20SBram Moolenaar 	    break;
903f9cc9f20SBram Moolenaar 	}
904f9cc9f20SBram Moolenaar 
905f9cc9f20SBram Moolenaar 	/*
906f9cc9f20SBram Moolenaar 	 * Isolate the key ("term", "ctermfg", "ctermbg", "font", "guifg" or
907f9cc9f20SBram Moolenaar 	 * "guibg").
908f9cc9f20SBram Moolenaar 	 */
909f9cc9f20SBram Moolenaar 	while (*linep && !VIM_ISWHITE(*linep) && *linep != '=')
910f9cc9f20SBram Moolenaar 	    ++linep;
911f9cc9f20SBram Moolenaar 	vim_free(key);
912f9cc9f20SBram Moolenaar 	key = vim_strnsave_up(key_start, (int)(linep - key_start));
913f9cc9f20SBram Moolenaar 	if (key == NULL)
914f9cc9f20SBram Moolenaar 	{
915f9cc9f20SBram Moolenaar 	    error = TRUE;
916f9cc9f20SBram Moolenaar 	    break;
917f9cc9f20SBram Moolenaar 	}
918f9cc9f20SBram Moolenaar 	linep = skipwhite(linep);
919f9cc9f20SBram Moolenaar 
920f9cc9f20SBram Moolenaar 	if (STRCMP(key, "NONE") == 0)
921f9cc9f20SBram Moolenaar 	{
922f9cc9f20SBram Moolenaar 	    if (!init || HL_TABLE()[idx].sg_set == 0)
923f9cc9f20SBram Moolenaar 	    {
924f9cc9f20SBram Moolenaar 		if (!init)
925f9cc9f20SBram Moolenaar 		    HL_TABLE()[idx].sg_set |= SG_TERM+SG_CTERM+SG_GUI;
926f9cc9f20SBram Moolenaar 		highlight_clear(idx);
927f9cc9f20SBram Moolenaar 	    }
928f9cc9f20SBram Moolenaar 	    continue;
929f9cc9f20SBram Moolenaar 	}
930f9cc9f20SBram Moolenaar 
931f9cc9f20SBram Moolenaar 	/*
932f9cc9f20SBram Moolenaar 	 * Check for the equal sign.
933f9cc9f20SBram Moolenaar 	 */
934f9cc9f20SBram Moolenaar 	if (*linep != '=')
935f9cc9f20SBram Moolenaar 	{
936f9cc9f20SBram Moolenaar 	    semsg(_("E416: missing equal sign: %s"), key_start);
937f9cc9f20SBram Moolenaar 	    error = TRUE;
938f9cc9f20SBram Moolenaar 	    break;
939f9cc9f20SBram Moolenaar 	}
940f9cc9f20SBram Moolenaar 	++linep;
941f9cc9f20SBram Moolenaar 
942f9cc9f20SBram Moolenaar 	/*
943f9cc9f20SBram Moolenaar 	 * Isolate the argument.
944f9cc9f20SBram Moolenaar 	 */
945f9cc9f20SBram Moolenaar 	linep = skipwhite(linep);
946f9cc9f20SBram Moolenaar 	if (*linep == '\'')		// guifg='color name'
947f9cc9f20SBram Moolenaar 	{
948f9cc9f20SBram Moolenaar 	    arg_start = ++linep;
949f9cc9f20SBram Moolenaar 	    linep = vim_strchr(linep, '\'');
950f9cc9f20SBram Moolenaar 	    if (linep == NULL)
951f9cc9f20SBram Moolenaar 	    {
952f9cc9f20SBram Moolenaar 		semsg(_(e_invarg2), key_start);
953f9cc9f20SBram Moolenaar 		error = TRUE;
954f9cc9f20SBram Moolenaar 		break;
955f9cc9f20SBram Moolenaar 	    }
956f9cc9f20SBram Moolenaar 	}
957f9cc9f20SBram Moolenaar 	else
958f9cc9f20SBram Moolenaar 	{
959f9cc9f20SBram Moolenaar 	    arg_start = linep;
960f9cc9f20SBram Moolenaar 	    linep = skiptowhite(linep);
961f9cc9f20SBram Moolenaar 	}
962f9cc9f20SBram Moolenaar 	if (linep == arg_start)
963f9cc9f20SBram Moolenaar 	{
964f9cc9f20SBram Moolenaar 	    semsg(_("E417: missing argument: %s"), key_start);
965f9cc9f20SBram Moolenaar 	    error = TRUE;
966f9cc9f20SBram Moolenaar 	    break;
967f9cc9f20SBram Moolenaar 	}
968f9cc9f20SBram Moolenaar 	vim_free(arg);
969f9cc9f20SBram Moolenaar 	arg = vim_strnsave(arg_start, (int)(linep - arg_start));
970f9cc9f20SBram Moolenaar 	if (arg == NULL)
971f9cc9f20SBram Moolenaar 	{
972f9cc9f20SBram Moolenaar 	    error = TRUE;
973f9cc9f20SBram Moolenaar 	    break;
974f9cc9f20SBram Moolenaar 	}
975f9cc9f20SBram Moolenaar 	if (*linep == '\'')
976f9cc9f20SBram Moolenaar 	    ++linep;
977f9cc9f20SBram Moolenaar 
978f9cc9f20SBram Moolenaar 	/*
979f9cc9f20SBram Moolenaar 	 * Store the argument.
980f9cc9f20SBram Moolenaar 	 */
981f9cc9f20SBram Moolenaar 	if (  STRCMP(key, "TERM") == 0
982f9cc9f20SBram Moolenaar 		|| STRCMP(key, "CTERM") == 0
983f9cc9f20SBram Moolenaar 		|| STRCMP(key, "GUI") == 0)
984f9cc9f20SBram Moolenaar 	{
985f9cc9f20SBram Moolenaar 	    attr = 0;
986f9cc9f20SBram Moolenaar 	    off = 0;
987f9cc9f20SBram Moolenaar 	    while (arg[off] != NUL)
988f9cc9f20SBram Moolenaar 	    {
989f9cc9f20SBram Moolenaar 		for (i = sizeof(hl_attr_table) / sizeof(int); --i >= 0; )
990f9cc9f20SBram Moolenaar 		{
991f9cc9f20SBram Moolenaar 		    len = (int)STRLEN(hl_name_table[i]);
992f9cc9f20SBram Moolenaar 		    if (STRNICMP(arg + off, hl_name_table[i], len) == 0)
993f9cc9f20SBram Moolenaar 		    {
994f9cc9f20SBram Moolenaar 			attr |= hl_attr_table[i];
995f9cc9f20SBram Moolenaar 			off += len;
996f9cc9f20SBram Moolenaar 			break;
997f9cc9f20SBram Moolenaar 		    }
998f9cc9f20SBram Moolenaar 		}
999f9cc9f20SBram Moolenaar 		if (i < 0)
1000f9cc9f20SBram Moolenaar 		{
1001f9cc9f20SBram Moolenaar 		    semsg(_("E418: Illegal value: %s"), arg);
1002f9cc9f20SBram Moolenaar 		    error = TRUE;
1003f9cc9f20SBram Moolenaar 		    break;
1004f9cc9f20SBram Moolenaar 		}
1005f9cc9f20SBram Moolenaar 		if (arg[off] == ',')		// another one follows
1006f9cc9f20SBram Moolenaar 		    ++off;
1007f9cc9f20SBram Moolenaar 	    }
1008f9cc9f20SBram Moolenaar 	    if (error)
1009f9cc9f20SBram Moolenaar 		break;
1010f9cc9f20SBram Moolenaar 	    if (*key == 'T')
1011f9cc9f20SBram Moolenaar 	    {
1012f9cc9f20SBram Moolenaar 		if (!init || !(HL_TABLE()[idx].sg_set & SG_TERM))
1013f9cc9f20SBram Moolenaar 		{
1014f9cc9f20SBram Moolenaar 		    if (!init)
1015f9cc9f20SBram Moolenaar 			HL_TABLE()[idx].sg_set |= SG_TERM;
1016f9cc9f20SBram Moolenaar 		    HL_TABLE()[idx].sg_term = attr;
1017f9cc9f20SBram Moolenaar 		}
1018f9cc9f20SBram Moolenaar 	    }
1019f9cc9f20SBram Moolenaar 	    else if (*key == 'C')
1020f9cc9f20SBram Moolenaar 	    {
1021f9cc9f20SBram Moolenaar 		if (!init || !(HL_TABLE()[idx].sg_set & SG_CTERM))
1022f9cc9f20SBram Moolenaar 		{
1023f9cc9f20SBram Moolenaar 		    if (!init)
1024f9cc9f20SBram Moolenaar 			HL_TABLE()[idx].sg_set |= SG_CTERM;
1025f9cc9f20SBram Moolenaar 		    HL_TABLE()[idx].sg_cterm = attr;
1026f9cc9f20SBram Moolenaar 		    HL_TABLE()[idx].sg_cterm_bold = FALSE;
1027f9cc9f20SBram Moolenaar 		}
1028f9cc9f20SBram Moolenaar 	    }
1029f9cc9f20SBram Moolenaar #if defined(FEAT_GUI) || defined(FEAT_EVAL)
1030f9cc9f20SBram Moolenaar 	    else
1031f9cc9f20SBram Moolenaar 	    {
1032f9cc9f20SBram Moolenaar 		if (!init || !(HL_TABLE()[idx].sg_set & SG_GUI))
1033f9cc9f20SBram Moolenaar 		{
1034f9cc9f20SBram Moolenaar 		    if (!init)
1035f9cc9f20SBram Moolenaar 			HL_TABLE()[idx].sg_set |= SG_GUI;
1036f9cc9f20SBram Moolenaar 		    HL_TABLE()[idx].sg_gui = attr;
1037f9cc9f20SBram Moolenaar 		}
1038f9cc9f20SBram Moolenaar 	    }
1039f9cc9f20SBram Moolenaar #endif
1040f9cc9f20SBram Moolenaar 	}
1041f9cc9f20SBram Moolenaar 	else if (STRCMP(key, "FONT") == 0)
1042f9cc9f20SBram Moolenaar 	{
1043f9cc9f20SBram Moolenaar 	    // in non-GUI fonts are simply ignored
1044f9cc9f20SBram Moolenaar #ifdef FEAT_GUI
1045f9cc9f20SBram Moolenaar 	    if (HL_TABLE()[idx].sg_font_name != NULL
1046f9cc9f20SBram Moolenaar 			     && STRCMP(HL_TABLE()[idx].sg_font_name, arg) == 0)
1047f9cc9f20SBram Moolenaar 	    {
1048f9cc9f20SBram Moolenaar 		// Font name didn't change, ignore.
1049f9cc9f20SBram Moolenaar 	    }
1050f9cc9f20SBram Moolenaar 	    else if (!gui.shell_created)
1051f9cc9f20SBram Moolenaar 	    {
1052f9cc9f20SBram Moolenaar 		// GUI not started yet, always accept the name.
1053f9cc9f20SBram Moolenaar 		vim_free(HL_TABLE()[idx].sg_font_name);
1054f9cc9f20SBram Moolenaar 		HL_TABLE()[idx].sg_font_name = vim_strsave(arg);
1055f9cc9f20SBram Moolenaar 		did_change = TRUE;
1056f9cc9f20SBram Moolenaar 	    }
1057f9cc9f20SBram Moolenaar 	    else
1058f9cc9f20SBram Moolenaar 	    {
1059f9cc9f20SBram Moolenaar 		GuiFont temp_sg_font = HL_TABLE()[idx].sg_font;
1060f9cc9f20SBram Moolenaar # ifdef FEAT_XFONTSET
1061f9cc9f20SBram Moolenaar 		GuiFontset temp_sg_fontset = HL_TABLE()[idx].sg_fontset;
1062f9cc9f20SBram Moolenaar # endif
1063f9cc9f20SBram Moolenaar 		// First, save the current font/fontset.
1064f9cc9f20SBram Moolenaar 		// Then try to allocate the font/fontset.
1065f9cc9f20SBram Moolenaar 		// If the allocation fails, HL_TABLE()[idx].sg_font OR
1066f9cc9f20SBram Moolenaar 		// sg_fontset will be set to NOFONT or NOFONTSET respectively.
1067f9cc9f20SBram Moolenaar 
1068f9cc9f20SBram Moolenaar 		HL_TABLE()[idx].sg_font = NOFONT;
1069f9cc9f20SBram Moolenaar # ifdef FEAT_XFONTSET
1070f9cc9f20SBram Moolenaar 		HL_TABLE()[idx].sg_fontset = NOFONTSET;
1071f9cc9f20SBram Moolenaar # endif
1072f9cc9f20SBram Moolenaar 		hl_do_font(idx, arg, is_normal_group, is_menu_group,
1073f9cc9f20SBram Moolenaar 						     is_tooltip_group, FALSE);
1074f9cc9f20SBram Moolenaar 
1075f9cc9f20SBram Moolenaar # ifdef FEAT_XFONTSET
1076f9cc9f20SBram Moolenaar 		if (HL_TABLE()[idx].sg_fontset != NOFONTSET)
1077f9cc9f20SBram Moolenaar 		{
1078f9cc9f20SBram Moolenaar 		    // New fontset was accepted. Free the old one, if there
1079f9cc9f20SBram Moolenaar 		    // was one.
1080f9cc9f20SBram Moolenaar 		    gui_mch_free_fontset(temp_sg_fontset);
1081f9cc9f20SBram Moolenaar 		    vim_free(HL_TABLE()[idx].sg_font_name);
1082f9cc9f20SBram Moolenaar 		    HL_TABLE()[idx].sg_font_name = vim_strsave(arg);
1083f9cc9f20SBram Moolenaar 		    did_change = TRUE;
1084f9cc9f20SBram Moolenaar 		}
1085f9cc9f20SBram Moolenaar 		else
1086f9cc9f20SBram Moolenaar 		    HL_TABLE()[idx].sg_fontset = temp_sg_fontset;
1087f9cc9f20SBram Moolenaar # endif
1088f9cc9f20SBram Moolenaar 		if (HL_TABLE()[idx].sg_font != NOFONT)
1089f9cc9f20SBram Moolenaar 		{
1090f9cc9f20SBram Moolenaar 		    // New font was accepted. Free the old one, if there was
1091f9cc9f20SBram Moolenaar 		    // one.
1092f9cc9f20SBram Moolenaar 		    gui_mch_free_font(temp_sg_font);
1093f9cc9f20SBram Moolenaar 		    vim_free(HL_TABLE()[idx].sg_font_name);
1094f9cc9f20SBram Moolenaar 		    HL_TABLE()[idx].sg_font_name = vim_strsave(arg);
1095f9cc9f20SBram Moolenaar 		    did_change = TRUE;
1096f9cc9f20SBram Moolenaar 		}
1097f9cc9f20SBram Moolenaar 		else
1098f9cc9f20SBram Moolenaar 		    HL_TABLE()[idx].sg_font = temp_sg_font;
1099f9cc9f20SBram Moolenaar 	    }
1100f9cc9f20SBram Moolenaar #endif
1101f9cc9f20SBram Moolenaar 	}
1102f9cc9f20SBram Moolenaar 	else if (STRCMP(key, "CTERMFG") == 0 || STRCMP(key, "CTERMBG") == 0)
1103f9cc9f20SBram Moolenaar 	{
1104f9cc9f20SBram Moolenaar 	  if (!init || !(HL_TABLE()[idx].sg_set & SG_CTERM))
1105f9cc9f20SBram Moolenaar 	  {
1106f9cc9f20SBram Moolenaar 	    if (!init)
1107f9cc9f20SBram Moolenaar 		HL_TABLE()[idx].sg_set |= SG_CTERM;
1108f9cc9f20SBram Moolenaar 
1109f9cc9f20SBram Moolenaar 	    // When setting the foreground color, and previously the "bold"
1110f9cc9f20SBram Moolenaar 	    // flag was set for a light color, reset it now
1111f9cc9f20SBram Moolenaar 	    if (key[5] == 'F' && HL_TABLE()[idx].sg_cterm_bold)
1112f9cc9f20SBram Moolenaar 	    {
1113f9cc9f20SBram Moolenaar 		HL_TABLE()[idx].sg_cterm &= ~HL_BOLD;
1114f9cc9f20SBram Moolenaar 		HL_TABLE()[idx].sg_cterm_bold = FALSE;
1115f9cc9f20SBram Moolenaar 	    }
1116f9cc9f20SBram Moolenaar 
1117f9cc9f20SBram Moolenaar 	    if (VIM_ISDIGIT(*arg))
1118f9cc9f20SBram Moolenaar 		color = atoi((char *)arg);
1119f9cc9f20SBram Moolenaar 	    else if (STRICMP(arg, "fg") == 0)
1120f9cc9f20SBram Moolenaar 	    {
1121f9cc9f20SBram Moolenaar 		if (cterm_normal_fg_color)
1122f9cc9f20SBram Moolenaar 		    color = cterm_normal_fg_color - 1;
1123f9cc9f20SBram Moolenaar 		else
1124f9cc9f20SBram Moolenaar 		{
1125f9cc9f20SBram Moolenaar 		    emsg(_("E419: FG color unknown"));
1126f9cc9f20SBram Moolenaar 		    error = TRUE;
1127f9cc9f20SBram Moolenaar 		    break;
1128f9cc9f20SBram Moolenaar 		}
1129f9cc9f20SBram Moolenaar 	    }
1130f9cc9f20SBram Moolenaar 	    else if (STRICMP(arg, "bg") == 0)
1131f9cc9f20SBram Moolenaar 	    {
1132f9cc9f20SBram Moolenaar 		if (cterm_normal_bg_color > 0)
1133f9cc9f20SBram Moolenaar 		    color = cterm_normal_bg_color - 1;
1134f9cc9f20SBram Moolenaar 		else
1135f9cc9f20SBram Moolenaar 		{
1136f9cc9f20SBram Moolenaar 		    emsg(_("E420: BG color unknown"));
1137f9cc9f20SBram Moolenaar 		    error = TRUE;
1138f9cc9f20SBram Moolenaar 		    break;
1139f9cc9f20SBram Moolenaar 		}
1140f9cc9f20SBram Moolenaar 	    }
1141f9cc9f20SBram Moolenaar 	    else
1142f9cc9f20SBram Moolenaar 	    {
1143f9cc9f20SBram Moolenaar 		int bold = MAYBE;
1144f9cc9f20SBram Moolenaar 
1145f9cc9f20SBram Moolenaar #if defined(__QNXNTO__)
1146f9cc9f20SBram Moolenaar 		static int *color_numbers_8_qansi = color_numbers_8;
1147f9cc9f20SBram Moolenaar 		// On qnx, the 8 & 16 color arrays are the same
1148f9cc9f20SBram Moolenaar 		if (STRNCMP(T_NAME, "qansi", 5) == 0)
1149f9cc9f20SBram Moolenaar 		    color_numbers_8_qansi = color_numbers_16;
1150f9cc9f20SBram Moolenaar #endif
1151f9cc9f20SBram Moolenaar 
1152f9cc9f20SBram Moolenaar 		// reduce calls to STRICMP a bit, it can be slow
1153f9cc9f20SBram Moolenaar 		off = TOUPPER_ASC(*arg);
1154f9cc9f20SBram Moolenaar 		for (i = (sizeof(color_names) / sizeof(char *)); --i >= 0; )
1155f9cc9f20SBram Moolenaar 		    if (off == color_names[i][0]
1156f9cc9f20SBram Moolenaar 				 && STRICMP(arg + 1, color_names[i] + 1) == 0)
1157f9cc9f20SBram Moolenaar 			break;
1158f9cc9f20SBram Moolenaar 		if (i < 0)
1159f9cc9f20SBram Moolenaar 		{
1160f9cc9f20SBram Moolenaar 		    semsg(_("E421: Color name or number not recognized: %s"), key_start);
1161f9cc9f20SBram Moolenaar 		    error = TRUE;
1162f9cc9f20SBram Moolenaar 		    break;
1163f9cc9f20SBram Moolenaar 		}
1164f9cc9f20SBram Moolenaar 
1165f9cc9f20SBram Moolenaar 		color = lookup_color(i, key[5] == 'F', &bold);
1166f9cc9f20SBram Moolenaar 
1167f9cc9f20SBram Moolenaar 		// set/reset bold attribute to get light foreground
1168f9cc9f20SBram Moolenaar 		// colors (on some terminals, e.g. "linux")
1169f9cc9f20SBram Moolenaar 		if (bold == TRUE)
1170f9cc9f20SBram Moolenaar 		{
1171f9cc9f20SBram Moolenaar 		    HL_TABLE()[idx].sg_cterm |= HL_BOLD;
1172f9cc9f20SBram Moolenaar 		    HL_TABLE()[idx].sg_cterm_bold = TRUE;
1173f9cc9f20SBram Moolenaar 		}
1174f9cc9f20SBram Moolenaar 		else if (bold == FALSE)
1175f9cc9f20SBram Moolenaar 		    HL_TABLE()[idx].sg_cterm &= ~HL_BOLD;
1176f9cc9f20SBram Moolenaar 	    }
1177f9cc9f20SBram Moolenaar 
1178f9cc9f20SBram Moolenaar 	    // Add one to the argument, to avoid zero.  Zero is used for
1179f9cc9f20SBram Moolenaar 	    // "NONE", then "color" is -1.
1180f9cc9f20SBram Moolenaar 	    if (key[5] == 'F')
1181f9cc9f20SBram Moolenaar 	    {
1182f9cc9f20SBram Moolenaar 		HL_TABLE()[idx].sg_cterm_fg = color + 1;
1183f9cc9f20SBram Moolenaar 		if (is_normal_group)
1184f9cc9f20SBram Moolenaar 		{
1185f9cc9f20SBram Moolenaar 		    cterm_normal_fg_color = color + 1;
1186f9cc9f20SBram Moolenaar 		    cterm_normal_fg_bold = (HL_TABLE()[idx].sg_cterm & HL_BOLD);
1187f9cc9f20SBram Moolenaar #ifdef FEAT_GUI
1188f9cc9f20SBram Moolenaar 		    // Don't do this if the GUI is used.
1189f9cc9f20SBram Moolenaar 		    if (!gui.in_use && !gui.starting)
1190f9cc9f20SBram Moolenaar #endif
1191f9cc9f20SBram Moolenaar 		    {
1192f9cc9f20SBram Moolenaar 			must_redraw = CLEAR;
1193f9cc9f20SBram Moolenaar 			if (termcap_active && color >= 0)
1194f9cc9f20SBram Moolenaar 			    term_fg_color(color);
1195f9cc9f20SBram Moolenaar 		    }
1196f9cc9f20SBram Moolenaar 		}
1197f9cc9f20SBram Moolenaar 	    }
1198f9cc9f20SBram Moolenaar 	    else
1199f9cc9f20SBram Moolenaar 	    {
1200f9cc9f20SBram Moolenaar 		HL_TABLE()[idx].sg_cterm_bg = color + 1;
1201f9cc9f20SBram Moolenaar 		if (is_normal_group)
1202f9cc9f20SBram Moolenaar 		{
1203f9cc9f20SBram Moolenaar 		    cterm_normal_bg_color = color + 1;
1204f9cc9f20SBram Moolenaar #ifdef FEAT_GUI
1205f9cc9f20SBram Moolenaar 		    // Don't mess with 'background' if the GUI is used.
1206f9cc9f20SBram Moolenaar 		    if (!gui.in_use && !gui.starting)
1207f9cc9f20SBram Moolenaar #endif
1208f9cc9f20SBram Moolenaar 		    {
1209f9cc9f20SBram Moolenaar 			must_redraw = CLEAR;
1210f9cc9f20SBram Moolenaar 			if (color >= 0)
1211f9cc9f20SBram Moolenaar 			{
1212f9cc9f20SBram Moolenaar 			    int dark = -1;
1213f9cc9f20SBram Moolenaar 
1214f9cc9f20SBram Moolenaar 			    if (termcap_active)
1215f9cc9f20SBram Moolenaar 				term_bg_color(color);
1216f9cc9f20SBram Moolenaar 			    if (t_colors < 16)
1217f9cc9f20SBram Moolenaar 				dark = (color == 0 || color == 4);
1218f9cc9f20SBram Moolenaar 			    // Limit the heuristic to the standard 16 colors
1219f9cc9f20SBram Moolenaar 			    else if (color < 16)
1220f9cc9f20SBram Moolenaar 				dark = (color < 7 || color == 8);
1221f9cc9f20SBram Moolenaar 			    // Set the 'background' option if the value is
1222f9cc9f20SBram Moolenaar 			    // wrong.
1223f9cc9f20SBram Moolenaar 			    if (dark != -1
1224f9cc9f20SBram Moolenaar 				    && dark != (*p_bg == 'd')
1225f9cc9f20SBram Moolenaar 				    && !option_was_set((char_u *)"bg"))
1226f9cc9f20SBram Moolenaar 			    {
1227f9cc9f20SBram Moolenaar 				set_option_value((char_u *)"bg", 0L,
1228f9cc9f20SBram Moolenaar 				       (char_u *)(dark ? "dark" : "light"), 0);
1229f9cc9f20SBram Moolenaar 				reset_option_was_set((char_u *)"bg");
1230f9cc9f20SBram Moolenaar 			    }
1231f9cc9f20SBram Moolenaar 			}
1232f9cc9f20SBram Moolenaar 		    }
1233f9cc9f20SBram Moolenaar 		}
1234f9cc9f20SBram Moolenaar 	    }
1235f9cc9f20SBram Moolenaar 	  }
1236f9cc9f20SBram Moolenaar 	}
1237f9cc9f20SBram Moolenaar 	else if (STRCMP(key, "GUIFG") == 0)
1238f9cc9f20SBram Moolenaar 	{
1239f9cc9f20SBram Moolenaar #if defined(FEAT_GUI) || defined(FEAT_EVAL)
1240f9cc9f20SBram Moolenaar 	    char_u **namep = &HL_TABLE()[idx].sg_gui_fg_name;
1241f9cc9f20SBram Moolenaar 
1242f9cc9f20SBram Moolenaar 	    if (!init || !(HL_TABLE()[idx].sg_set & SG_GUI))
1243f9cc9f20SBram Moolenaar 	    {
1244f9cc9f20SBram Moolenaar 		if (!init)
1245f9cc9f20SBram Moolenaar 		    HL_TABLE()[idx].sg_set |= SG_GUI;
1246f9cc9f20SBram Moolenaar 
1247f9cc9f20SBram Moolenaar # if defined(FEAT_GUI) || defined(FEAT_TERMGUICOLORS)
1248f9cc9f20SBram Moolenaar 		// In GUI guifg colors are only used when recognized
1249f9cc9f20SBram Moolenaar 		i = color_name2handle(arg);
1250f9cc9f20SBram Moolenaar 		if (i != INVALCOLOR || STRCMP(arg, "NONE") == 0 || !USE_24BIT)
1251f9cc9f20SBram Moolenaar 		{
1252f9cc9f20SBram Moolenaar 		    HL_TABLE()[idx].sg_gui_fg = i;
1253f9cc9f20SBram Moolenaar # endif
1254f9cc9f20SBram Moolenaar 		    if (*namep == NULL || STRCMP(*namep, arg) != 0)
1255f9cc9f20SBram Moolenaar 		    {
1256f9cc9f20SBram Moolenaar 			vim_free(*namep);
1257f9cc9f20SBram Moolenaar 			if (STRCMP(arg, "NONE") != 0)
1258f9cc9f20SBram Moolenaar 			    *namep = vim_strsave(arg);
1259f9cc9f20SBram Moolenaar 			else
1260f9cc9f20SBram Moolenaar 			    *namep = NULL;
1261f9cc9f20SBram Moolenaar 			did_change = TRUE;
1262f9cc9f20SBram Moolenaar 		    }
1263f9cc9f20SBram Moolenaar # if defined(FEAT_GUI) || defined(FEAT_TERMGUICOLORS)
1264f9cc9f20SBram Moolenaar #  ifdef FEAT_GUI_X11
1265f9cc9f20SBram Moolenaar 		    if (is_menu_group && gui.menu_fg_pixel != i)
1266f9cc9f20SBram Moolenaar 		    {
1267f9cc9f20SBram Moolenaar 			gui.menu_fg_pixel = i;
1268f9cc9f20SBram Moolenaar 			do_colors = TRUE;
1269f9cc9f20SBram Moolenaar 		    }
1270f9cc9f20SBram Moolenaar 		    if (is_scrollbar_group && gui.scroll_fg_pixel != i)
1271f9cc9f20SBram Moolenaar 		    {
1272f9cc9f20SBram Moolenaar 			gui.scroll_fg_pixel = i;
1273f9cc9f20SBram Moolenaar 			do_colors = TRUE;
1274f9cc9f20SBram Moolenaar 		    }
1275f9cc9f20SBram Moolenaar #   ifdef FEAT_BEVAL_GUI
1276f9cc9f20SBram Moolenaar 		    if (is_tooltip_group && gui.tooltip_fg_pixel != i)
1277f9cc9f20SBram Moolenaar 		    {
1278f9cc9f20SBram Moolenaar 			gui.tooltip_fg_pixel = i;
1279f9cc9f20SBram Moolenaar 			do_colors = TRUE;
1280f9cc9f20SBram Moolenaar 		    }
1281f9cc9f20SBram Moolenaar #   endif
1282f9cc9f20SBram Moolenaar #  endif
1283f9cc9f20SBram Moolenaar 		}
1284f9cc9f20SBram Moolenaar # endif
1285f9cc9f20SBram Moolenaar 	    }
1286f9cc9f20SBram Moolenaar #endif
1287f9cc9f20SBram Moolenaar 	}
1288f9cc9f20SBram Moolenaar 	else if (STRCMP(key, "GUIBG") == 0)
1289f9cc9f20SBram Moolenaar 	{
1290f9cc9f20SBram Moolenaar #if defined(FEAT_GUI) || defined(FEAT_EVAL)
1291f9cc9f20SBram Moolenaar 	    char_u **namep = &HL_TABLE()[idx].sg_gui_bg_name;
1292f9cc9f20SBram Moolenaar 
1293f9cc9f20SBram Moolenaar 	    if (!init || !(HL_TABLE()[idx].sg_set & SG_GUI))
1294f9cc9f20SBram Moolenaar 	    {
1295f9cc9f20SBram Moolenaar 		if (!init)
1296f9cc9f20SBram Moolenaar 		    HL_TABLE()[idx].sg_set |= SG_GUI;
1297f9cc9f20SBram Moolenaar 
1298f9cc9f20SBram Moolenaar # if defined(FEAT_GUI) || defined(FEAT_TERMGUICOLORS)
1299f9cc9f20SBram Moolenaar 		// In GUI guifg colors are only used when recognized
1300f9cc9f20SBram Moolenaar 		i = color_name2handle(arg);
1301f9cc9f20SBram Moolenaar 		if (i != INVALCOLOR || STRCMP(arg, "NONE") == 0 || !USE_24BIT)
1302f9cc9f20SBram Moolenaar 		{
1303f9cc9f20SBram Moolenaar 		    HL_TABLE()[idx].sg_gui_bg = i;
1304f9cc9f20SBram Moolenaar # endif
1305f9cc9f20SBram Moolenaar 		    if (*namep == NULL || STRCMP(*namep, arg) != 0)
1306f9cc9f20SBram Moolenaar 		    {
1307f9cc9f20SBram Moolenaar 			vim_free(*namep);
1308f9cc9f20SBram Moolenaar 			if (STRCMP(arg, "NONE") != 0)
1309f9cc9f20SBram Moolenaar 			    *namep = vim_strsave(arg);
1310f9cc9f20SBram Moolenaar 			else
1311f9cc9f20SBram Moolenaar 			    *namep = NULL;
1312f9cc9f20SBram Moolenaar 			did_change = TRUE;
1313f9cc9f20SBram Moolenaar 		    }
1314f9cc9f20SBram Moolenaar # if defined(FEAT_GUI) || defined(FEAT_TERMGUICOLORS)
1315f9cc9f20SBram Moolenaar #  ifdef FEAT_GUI_X11
1316f9cc9f20SBram Moolenaar 		    if (is_menu_group && gui.menu_bg_pixel != i)
1317f9cc9f20SBram Moolenaar 		    {
1318f9cc9f20SBram Moolenaar 			gui.menu_bg_pixel = i;
1319f9cc9f20SBram Moolenaar 			do_colors = TRUE;
1320f9cc9f20SBram Moolenaar 		    }
1321f9cc9f20SBram Moolenaar 		    if (is_scrollbar_group && gui.scroll_bg_pixel != i)
1322f9cc9f20SBram Moolenaar 		    {
1323f9cc9f20SBram Moolenaar 			gui.scroll_bg_pixel = i;
1324f9cc9f20SBram Moolenaar 			do_colors = TRUE;
1325f9cc9f20SBram Moolenaar 		    }
1326f9cc9f20SBram Moolenaar #   ifdef FEAT_BEVAL_GUI
1327f9cc9f20SBram Moolenaar 		    if (is_tooltip_group && gui.tooltip_bg_pixel != i)
1328f9cc9f20SBram Moolenaar 		    {
1329f9cc9f20SBram Moolenaar 			gui.tooltip_bg_pixel = i;
1330f9cc9f20SBram Moolenaar 			do_colors = TRUE;
1331f9cc9f20SBram Moolenaar 		    }
1332f9cc9f20SBram Moolenaar #   endif
1333f9cc9f20SBram Moolenaar #  endif
1334f9cc9f20SBram Moolenaar 		}
1335f9cc9f20SBram Moolenaar # endif
1336f9cc9f20SBram Moolenaar 	    }
1337f9cc9f20SBram Moolenaar #endif
1338f9cc9f20SBram Moolenaar 	}
1339f9cc9f20SBram Moolenaar 	else if (STRCMP(key, "GUISP") == 0)
1340f9cc9f20SBram Moolenaar 	{
1341f9cc9f20SBram Moolenaar #if defined(FEAT_GUI) || defined(FEAT_EVAL)
1342f9cc9f20SBram Moolenaar 	    char_u **namep = &HL_TABLE()[idx].sg_gui_sp_name;
1343f9cc9f20SBram Moolenaar 
1344f9cc9f20SBram Moolenaar 	    if (!init || !(HL_TABLE()[idx].sg_set & SG_GUI))
1345f9cc9f20SBram Moolenaar 	    {
1346f9cc9f20SBram Moolenaar 		if (!init)
1347f9cc9f20SBram Moolenaar 		    HL_TABLE()[idx].sg_set |= SG_GUI;
1348f9cc9f20SBram Moolenaar 
1349f9cc9f20SBram Moolenaar # ifdef FEAT_GUI
1350f9cc9f20SBram Moolenaar 		i = color_name2handle(arg);
1351f9cc9f20SBram Moolenaar 		if (i != INVALCOLOR || STRCMP(arg, "NONE") == 0 || !gui.in_use)
1352f9cc9f20SBram Moolenaar 		{
1353f9cc9f20SBram Moolenaar 		    HL_TABLE()[idx].sg_gui_sp = i;
1354f9cc9f20SBram Moolenaar # endif
1355f9cc9f20SBram Moolenaar 		    if (*namep == NULL || STRCMP(*namep, arg) != 0)
1356f9cc9f20SBram Moolenaar 		    {
1357f9cc9f20SBram Moolenaar 			vim_free(*namep);
1358f9cc9f20SBram Moolenaar 			if (STRCMP(arg, "NONE") != 0)
1359f9cc9f20SBram Moolenaar 			    *namep = vim_strsave(arg);
1360f9cc9f20SBram Moolenaar 			else
1361f9cc9f20SBram Moolenaar 			    *namep = NULL;
1362f9cc9f20SBram Moolenaar 			did_change = TRUE;
1363f9cc9f20SBram Moolenaar 		    }
1364f9cc9f20SBram Moolenaar # ifdef FEAT_GUI
1365f9cc9f20SBram Moolenaar 		}
1366f9cc9f20SBram Moolenaar # endif
1367f9cc9f20SBram Moolenaar 	    }
1368f9cc9f20SBram Moolenaar #endif
1369f9cc9f20SBram Moolenaar 	}
1370f9cc9f20SBram Moolenaar 	else if (STRCMP(key, "START") == 0 || STRCMP(key, "STOP") == 0)
1371f9cc9f20SBram Moolenaar 	{
1372f9cc9f20SBram Moolenaar 	    char_u	buf[100];
1373f9cc9f20SBram Moolenaar 	    char_u	*tname;
1374f9cc9f20SBram Moolenaar 
1375f9cc9f20SBram Moolenaar 	    if (!init)
1376f9cc9f20SBram Moolenaar 		HL_TABLE()[idx].sg_set |= SG_TERM;
1377f9cc9f20SBram Moolenaar 
1378f9cc9f20SBram Moolenaar 	    /*
1379f9cc9f20SBram Moolenaar 	     * The "start" and "stop"  arguments can be a literal escape
1380f9cc9f20SBram Moolenaar 	     * sequence, or a comma separated list of terminal codes.
1381f9cc9f20SBram Moolenaar 	     */
1382f9cc9f20SBram Moolenaar 	    if (STRNCMP(arg, "t_", 2) == 0)
1383f9cc9f20SBram Moolenaar 	    {
1384f9cc9f20SBram Moolenaar 		off = 0;
1385f9cc9f20SBram Moolenaar 		buf[0] = 0;
1386f9cc9f20SBram Moolenaar 		while (arg[off] != NUL)
1387f9cc9f20SBram Moolenaar 		{
1388f9cc9f20SBram Moolenaar 		    // Isolate one termcap name
1389f9cc9f20SBram Moolenaar 		    for (len = 0; arg[off + len] &&
1390f9cc9f20SBram Moolenaar 						 arg[off + len] != ','; ++len)
1391f9cc9f20SBram Moolenaar 			;
1392f9cc9f20SBram Moolenaar 		    tname = vim_strnsave(arg + off, len);
1393f9cc9f20SBram Moolenaar 		    if (tname == NULL)		// out of memory
1394f9cc9f20SBram Moolenaar 		    {
1395f9cc9f20SBram Moolenaar 			error = TRUE;
1396f9cc9f20SBram Moolenaar 			break;
1397f9cc9f20SBram Moolenaar 		    }
1398f9cc9f20SBram Moolenaar 		    // lookup the escape sequence for the item
1399f9cc9f20SBram Moolenaar 		    p = get_term_code(tname);
1400f9cc9f20SBram Moolenaar 		    vim_free(tname);
1401f9cc9f20SBram Moolenaar 		    if (p == NULL)	    // ignore non-existing things
1402f9cc9f20SBram Moolenaar 			p = (char_u *)"";
1403f9cc9f20SBram Moolenaar 
1404f9cc9f20SBram Moolenaar 		    // Append it to the already found stuff
1405f9cc9f20SBram Moolenaar 		    if ((int)(STRLEN(buf) + STRLEN(p)) >= 99)
1406f9cc9f20SBram Moolenaar 		    {
1407f9cc9f20SBram Moolenaar 			semsg(_("E422: terminal code too long: %s"), arg);
1408f9cc9f20SBram Moolenaar 			error = TRUE;
1409f9cc9f20SBram Moolenaar 			break;
1410f9cc9f20SBram Moolenaar 		    }
1411f9cc9f20SBram Moolenaar 		    STRCAT(buf, p);
1412f9cc9f20SBram Moolenaar 
1413f9cc9f20SBram Moolenaar 		    // Advance to the next item
1414f9cc9f20SBram Moolenaar 		    off += len;
1415f9cc9f20SBram Moolenaar 		    if (arg[off] == ',')	    // another one follows
1416f9cc9f20SBram Moolenaar 			++off;
1417f9cc9f20SBram Moolenaar 		}
1418f9cc9f20SBram Moolenaar 	    }
1419f9cc9f20SBram Moolenaar 	    else
1420f9cc9f20SBram Moolenaar 	    {
1421f9cc9f20SBram Moolenaar 		/*
1422f9cc9f20SBram Moolenaar 		 * Copy characters from arg[] to buf[], translating <> codes.
1423f9cc9f20SBram Moolenaar 		 */
1424f9cc9f20SBram Moolenaar 		for (p = arg, off = 0; off < 100 - 6 && *p; )
1425f9cc9f20SBram Moolenaar 		{
1426f9cc9f20SBram Moolenaar 		    len = trans_special(&p, buf + off, FALSE, FALSE);
1427f9cc9f20SBram Moolenaar 		    if (len > 0)	    // recognized special char
1428f9cc9f20SBram Moolenaar 			off += len;
1429f9cc9f20SBram Moolenaar 		    else		    // copy as normal char
1430f9cc9f20SBram Moolenaar 			buf[off++] = *p++;
1431f9cc9f20SBram Moolenaar 		}
1432f9cc9f20SBram Moolenaar 		buf[off] = NUL;
1433f9cc9f20SBram Moolenaar 	    }
1434f9cc9f20SBram Moolenaar 	    if (error)
1435f9cc9f20SBram Moolenaar 		break;
1436f9cc9f20SBram Moolenaar 
1437f9cc9f20SBram Moolenaar 	    if (STRCMP(buf, "NONE") == 0)	// resetting the value
1438f9cc9f20SBram Moolenaar 		p = NULL;
1439f9cc9f20SBram Moolenaar 	    else
1440f9cc9f20SBram Moolenaar 		p = vim_strsave(buf);
1441f9cc9f20SBram Moolenaar 	    if (key[2] == 'A')
1442f9cc9f20SBram Moolenaar 	    {
1443f9cc9f20SBram Moolenaar 		vim_free(HL_TABLE()[idx].sg_start);
1444f9cc9f20SBram Moolenaar 		HL_TABLE()[idx].sg_start = p;
1445f9cc9f20SBram Moolenaar 	    }
1446f9cc9f20SBram Moolenaar 	    else
1447f9cc9f20SBram Moolenaar 	    {
1448f9cc9f20SBram Moolenaar 		vim_free(HL_TABLE()[idx].sg_stop);
1449f9cc9f20SBram Moolenaar 		HL_TABLE()[idx].sg_stop = p;
1450f9cc9f20SBram Moolenaar 	    }
1451f9cc9f20SBram Moolenaar 	}
1452f9cc9f20SBram Moolenaar 	else
1453f9cc9f20SBram Moolenaar 	{
1454f9cc9f20SBram Moolenaar 	    semsg(_("E423: Illegal argument: %s"), key_start);
1455f9cc9f20SBram Moolenaar 	    error = TRUE;
1456f9cc9f20SBram Moolenaar 	    break;
1457f9cc9f20SBram Moolenaar 	}
1458f9cc9f20SBram Moolenaar 	HL_TABLE()[idx].sg_cleared = FALSE;
1459f9cc9f20SBram Moolenaar 
1460f9cc9f20SBram Moolenaar 	/*
1461f9cc9f20SBram Moolenaar 	 * When highlighting has been given for a group, don't link it.
1462f9cc9f20SBram Moolenaar 	 */
1463f9cc9f20SBram Moolenaar 	if (!init || !(HL_TABLE()[idx].sg_set & SG_LINK))
1464f9cc9f20SBram Moolenaar 	    HL_TABLE()[idx].sg_link = 0;
1465f9cc9f20SBram Moolenaar 
1466f9cc9f20SBram Moolenaar 	/*
1467f9cc9f20SBram Moolenaar 	 * Continue with next argument.
1468f9cc9f20SBram Moolenaar 	 */
1469f9cc9f20SBram Moolenaar 	linep = skipwhite(linep);
1470f9cc9f20SBram Moolenaar       }
1471f9cc9f20SBram Moolenaar 
1472f9cc9f20SBram Moolenaar     /*
1473f9cc9f20SBram Moolenaar      * If there is an error, and it's a new entry, remove it from the table.
1474f9cc9f20SBram Moolenaar      */
1475f9cc9f20SBram Moolenaar     if (error && idx == highlight_ga.ga_len)
1476f9cc9f20SBram Moolenaar 	syn_unadd_group();
1477f9cc9f20SBram Moolenaar     else
1478f9cc9f20SBram Moolenaar     {
1479f9cc9f20SBram Moolenaar 	if (is_normal_group)
1480f9cc9f20SBram Moolenaar 	{
1481f9cc9f20SBram Moolenaar 	    HL_TABLE()[idx].sg_term_attr = 0;
1482f9cc9f20SBram Moolenaar 	    HL_TABLE()[idx].sg_cterm_attr = 0;
1483f9cc9f20SBram Moolenaar #ifdef FEAT_GUI
1484f9cc9f20SBram Moolenaar 	    HL_TABLE()[idx].sg_gui_attr = 0;
1485f9cc9f20SBram Moolenaar 	    /*
1486f9cc9f20SBram Moolenaar 	     * Need to update all groups, because they might be using "bg"
1487f9cc9f20SBram Moolenaar 	     * and/or "fg", which have been changed now.
1488f9cc9f20SBram Moolenaar 	     */
1489f9cc9f20SBram Moolenaar #endif
1490f9cc9f20SBram Moolenaar #if defined(FEAT_GUI) || defined(FEAT_TERMGUICOLORS)
1491f9cc9f20SBram Moolenaar 	    if (USE_24BIT)
1492f9cc9f20SBram Moolenaar 	    {
1493f9cc9f20SBram Moolenaar 		highlight_gui_started();
1494f9cc9f20SBram Moolenaar 		did_highlight_changed = TRUE;
1495f9cc9f20SBram Moolenaar 		redraw_all_later(NOT_VALID);
1496f9cc9f20SBram Moolenaar 	    }
1497f9cc9f20SBram Moolenaar #endif
1498f9cc9f20SBram Moolenaar 	}
1499f9cc9f20SBram Moolenaar #ifdef FEAT_TERMINAL
1500f9cc9f20SBram Moolenaar 	else if (is_terminal_group)
1501f9cc9f20SBram Moolenaar 	    set_terminal_default_colors(
1502f9cc9f20SBram Moolenaar 		    HL_TABLE()[idx].sg_cterm_fg, HL_TABLE()[idx].sg_cterm_bg);
1503f9cc9f20SBram Moolenaar #endif
1504f9cc9f20SBram Moolenaar #ifdef FEAT_GUI_X11
1505f9cc9f20SBram Moolenaar # ifdef FEAT_MENU
1506f9cc9f20SBram Moolenaar 	else if (is_menu_group)
1507f9cc9f20SBram Moolenaar 	{
1508f9cc9f20SBram Moolenaar 	    if (gui.in_use && do_colors)
1509f9cc9f20SBram Moolenaar 		gui_mch_new_menu_colors();
1510f9cc9f20SBram Moolenaar 	}
1511f9cc9f20SBram Moolenaar # endif
1512f9cc9f20SBram Moolenaar 	else if (is_scrollbar_group)
1513f9cc9f20SBram Moolenaar 	{
1514f9cc9f20SBram Moolenaar 	    if (gui.in_use && do_colors)
1515f9cc9f20SBram Moolenaar 		gui_new_scrollbar_colors();
1516f9cc9f20SBram Moolenaar 	    else
1517f9cc9f20SBram Moolenaar 		set_hl_attr(idx);
1518f9cc9f20SBram Moolenaar 	}
1519f9cc9f20SBram Moolenaar # ifdef FEAT_BEVAL_GUI
1520f9cc9f20SBram Moolenaar 	else if (is_tooltip_group)
1521f9cc9f20SBram Moolenaar 	{
1522f9cc9f20SBram Moolenaar 	    if (gui.in_use && do_colors)
1523f9cc9f20SBram Moolenaar 		gui_mch_new_tooltip_colors();
1524f9cc9f20SBram Moolenaar 	}
1525f9cc9f20SBram Moolenaar # endif
1526f9cc9f20SBram Moolenaar #endif
1527f9cc9f20SBram Moolenaar 	else
1528f9cc9f20SBram Moolenaar 	    set_hl_attr(idx);
1529f9cc9f20SBram Moolenaar #ifdef FEAT_EVAL
1530f9cc9f20SBram Moolenaar 	HL_TABLE()[idx].sg_script_ctx = current_sctx;
1531f9cc9f20SBram Moolenaar 	HL_TABLE()[idx].sg_script_ctx.sc_lnum += sourcing_lnum;
1532f9cc9f20SBram Moolenaar #endif
1533f9cc9f20SBram Moolenaar     }
1534f9cc9f20SBram Moolenaar 
1535f9cc9f20SBram Moolenaar     vim_free(key);
1536f9cc9f20SBram Moolenaar     vim_free(arg);
1537f9cc9f20SBram Moolenaar 
1538f9cc9f20SBram Moolenaar     // Only call highlight_changed() once, after a sequence of highlight
1539f9cc9f20SBram Moolenaar     // commands, and only if an attribute actually changed.
1540f9cc9f20SBram Moolenaar     if ((did_change
1541f9cc9f20SBram Moolenaar 	   || memcmp(&HL_TABLE()[idx], &item_before, sizeof(item_before)) != 0)
1542f9cc9f20SBram Moolenaar #if defined(FEAT_GUI) || defined(FEAT_TERMGUICOLORS)
1543f9cc9f20SBram Moolenaar 	    && !did_highlight_changed
1544f9cc9f20SBram Moolenaar #endif
1545f9cc9f20SBram Moolenaar        )
1546f9cc9f20SBram Moolenaar     {
1547f9cc9f20SBram Moolenaar 	// Do not trigger a redraw when highlighting is changed while
1548f9cc9f20SBram Moolenaar 	// redrawing.  This may happen when evaluating 'statusline' changes the
1549f9cc9f20SBram Moolenaar 	// StatusLine group.
1550f9cc9f20SBram Moolenaar 	if (!updating_screen)
1551f9cc9f20SBram Moolenaar 	    redraw_all_later(NOT_VALID);
1552f9cc9f20SBram Moolenaar 	need_highlight_changed = TRUE;
1553f9cc9f20SBram Moolenaar     }
1554f9cc9f20SBram Moolenaar }
1555f9cc9f20SBram Moolenaar 
1556f9cc9f20SBram Moolenaar #if defined(EXITFREE) || defined(PROTO)
1557f9cc9f20SBram Moolenaar     void
1558f9cc9f20SBram Moolenaar free_highlight(void)
1559f9cc9f20SBram Moolenaar {
1560f9cc9f20SBram Moolenaar     int	    i;
1561f9cc9f20SBram Moolenaar 
1562f9cc9f20SBram Moolenaar     for (i = 0; i < highlight_ga.ga_len; ++i)
1563f9cc9f20SBram Moolenaar     {
1564f9cc9f20SBram Moolenaar 	highlight_clear(i);
1565f9cc9f20SBram Moolenaar 	vim_free(HL_TABLE()[i].sg_name);
1566f9cc9f20SBram Moolenaar 	vim_free(HL_TABLE()[i].sg_name_u);
1567f9cc9f20SBram Moolenaar     }
1568f9cc9f20SBram Moolenaar     ga_clear(&highlight_ga);
1569f9cc9f20SBram Moolenaar }
1570f9cc9f20SBram Moolenaar #endif
1571f9cc9f20SBram Moolenaar 
1572f9cc9f20SBram Moolenaar /*
1573f9cc9f20SBram Moolenaar  * Reset the cterm colors to what they were before Vim was started, if
1574f9cc9f20SBram Moolenaar  * possible.  Otherwise reset them to zero.
1575f9cc9f20SBram Moolenaar  */
1576f9cc9f20SBram Moolenaar     void
1577f9cc9f20SBram Moolenaar restore_cterm_colors(void)
1578f9cc9f20SBram Moolenaar {
1579f9cc9f20SBram Moolenaar #if defined(MSWIN) && !defined(FEAT_GUI_MSWIN)
1580f9cc9f20SBram Moolenaar     // Since t_me has been set, this probably means that the user
1581f9cc9f20SBram Moolenaar     // wants to use this as default colors.  Need to reset default
1582f9cc9f20SBram Moolenaar     // background/foreground colors.
1583f9cc9f20SBram Moolenaar     mch_set_normal_colors();
1584f9cc9f20SBram Moolenaar #else
1585f9cc9f20SBram Moolenaar # ifdef VIMDLL
1586f9cc9f20SBram Moolenaar     if (!gui.in_use)
1587f9cc9f20SBram Moolenaar     {
1588f9cc9f20SBram Moolenaar 	mch_set_normal_colors();
1589f9cc9f20SBram Moolenaar 	return;
1590f9cc9f20SBram Moolenaar     }
1591f9cc9f20SBram Moolenaar # endif
1592f9cc9f20SBram Moolenaar     cterm_normal_fg_color = 0;
1593f9cc9f20SBram Moolenaar     cterm_normal_fg_bold = 0;
1594f9cc9f20SBram Moolenaar     cterm_normal_bg_color = 0;
1595f9cc9f20SBram Moolenaar # ifdef FEAT_TERMGUICOLORS
1596f9cc9f20SBram Moolenaar     cterm_normal_fg_gui_color = INVALCOLOR;
1597f9cc9f20SBram Moolenaar     cterm_normal_bg_gui_color = INVALCOLOR;
1598f9cc9f20SBram Moolenaar # endif
1599f9cc9f20SBram Moolenaar #endif
1600f9cc9f20SBram Moolenaar }
1601f9cc9f20SBram Moolenaar 
1602f9cc9f20SBram Moolenaar /*
1603f9cc9f20SBram Moolenaar  * Return TRUE if highlight group "idx" has any settings.
1604f9cc9f20SBram Moolenaar  * When "check_link" is TRUE also check for an existing link.
1605f9cc9f20SBram Moolenaar  */
1606f9cc9f20SBram Moolenaar     static int
1607f9cc9f20SBram Moolenaar hl_has_settings(int idx, int check_link)
1608f9cc9f20SBram Moolenaar {
1609f9cc9f20SBram Moolenaar     return (   HL_TABLE()[idx].sg_term_attr != 0
1610f9cc9f20SBram Moolenaar 	    || HL_TABLE()[idx].sg_cterm_attr != 0
1611f9cc9f20SBram Moolenaar 	    || HL_TABLE()[idx].sg_cterm_fg != 0
1612f9cc9f20SBram Moolenaar 	    || HL_TABLE()[idx].sg_cterm_bg != 0
1613f9cc9f20SBram Moolenaar #ifdef FEAT_GUI
1614f9cc9f20SBram Moolenaar 	    || HL_TABLE()[idx].sg_gui_attr != 0
1615f9cc9f20SBram Moolenaar 	    || HL_TABLE()[idx].sg_gui_fg_name != NULL
1616f9cc9f20SBram Moolenaar 	    || HL_TABLE()[idx].sg_gui_bg_name != NULL
1617f9cc9f20SBram Moolenaar 	    || HL_TABLE()[idx].sg_gui_sp_name != NULL
1618f9cc9f20SBram Moolenaar 	    || HL_TABLE()[idx].sg_font_name != NULL
1619f9cc9f20SBram Moolenaar #endif
1620f9cc9f20SBram Moolenaar 	    || (check_link && (HL_TABLE()[idx].sg_set & SG_LINK)));
1621f9cc9f20SBram Moolenaar }
1622f9cc9f20SBram Moolenaar 
1623f9cc9f20SBram Moolenaar /*
1624f9cc9f20SBram Moolenaar  * Clear highlighting for one group.
1625f9cc9f20SBram Moolenaar  */
1626f9cc9f20SBram Moolenaar     static void
1627f9cc9f20SBram Moolenaar highlight_clear(int idx)
1628f9cc9f20SBram Moolenaar {
1629f9cc9f20SBram Moolenaar     HL_TABLE()[idx].sg_cleared = TRUE;
1630f9cc9f20SBram Moolenaar 
1631f9cc9f20SBram Moolenaar     HL_TABLE()[idx].sg_term = 0;
1632f9cc9f20SBram Moolenaar     VIM_CLEAR(HL_TABLE()[idx].sg_start);
1633f9cc9f20SBram Moolenaar     VIM_CLEAR(HL_TABLE()[idx].sg_stop);
1634f9cc9f20SBram Moolenaar     HL_TABLE()[idx].sg_term_attr = 0;
1635f9cc9f20SBram Moolenaar     HL_TABLE()[idx].sg_cterm = 0;
1636f9cc9f20SBram Moolenaar     HL_TABLE()[idx].sg_cterm_bold = FALSE;
1637f9cc9f20SBram Moolenaar     HL_TABLE()[idx].sg_cterm_fg = 0;
1638f9cc9f20SBram Moolenaar     HL_TABLE()[idx].sg_cterm_bg = 0;
1639f9cc9f20SBram Moolenaar     HL_TABLE()[idx].sg_cterm_attr = 0;
1640f9cc9f20SBram Moolenaar #if defined(FEAT_GUI) || defined(FEAT_EVAL)
1641f9cc9f20SBram Moolenaar     HL_TABLE()[idx].sg_gui = 0;
1642f9cc9f20SBram Moolenaar     VIM_CLEAR(HL_TABLE()[idx].sg_gui_fg_name);
1643f9cc9f20SBram Moolenaar     VIM_CLEAR(HL_TABLE()[idx].sg_gui_bg_name);
1644f9cc9f20SBram Moolenaar     VIM_CLEAR(HL_TABLE()[idx].sg_gui_sp_name);
1645f9cc9f20SBram Moolenaar #endif
1646f9cc9f20SBram Moolenaar #if defined(FEAT_GUI) || defined(FEAT_TERMGUICOLORS)
1647f9cc9f20SBram Moolenaar     HL_TABLE()[idx].sg_gui_fg = INVALCOLOR;
1648f9cc9f20SBram Moolenaar     HL_TABLE()[idx].sg_gui_bg = INVALCOLOR;
1649f9cc9f20SBram Moolenaar #endif
1650f9cc9f20SBram Moolenaar #ifdef FEAT_GUI
1651f9cc9f20SBram Moolenaar     HL_TABLE()[idx].sg_gui_sp = INVALCOLOR;
1652f9cc9f20SBram Moolenaar     gui_mch_free_font(HL_TABLE()[idx].sg_font);
1653f9cc9f20SBram Moolenaar     HL_TABLE()[idx].sg_font = NOFONT;
1654f9cc9f20SBram Moolenaar # ifdef FEAT_XFONTSET
1655f9cc9f20SBram Moolenaar     gui_mch_free_fontset(HL_TABLE()[idx].sg_fontset);
1656f9cc9f20SBram Moolenaar     HL_TABLE()[idx].sg_fontset = NOFONTSET;
1657f9cc9f20SBram Moolenaar # endif
1658f9cc9f20SBram Moolenaar     VIM_CLEAR(HL_TABLE()[idx].sg_font_name);
1659f9cc9f20SBram Moolenaar     HL_TABLE()[idx].sg_gui_attr = 0;
1660f9cc9f20SBram Moolenaar #endif
1661f9cc9f20SBram Moolenaar #ifdef FEAT_EVAL
1662f9cc9f20SBram Moolenaar     // Clear the script ID only when there is no link, since that is not
1663f9cc9f20SBram Moolenaar     // cleared.
1664f9cc9f20SBram Moolenaar     if (HL_TABLE()[idx].sg_link == 0)
1665f9cc9f20SBram Moolenaar     {
1666f9cc9f20SBram Moolenaar 	HL_TABLE()[idx].sg_script_ctx.sc_sid = 0;
1667f9cc9f20SBram Moolenaar 	HL_TABLE()[idx].sg_script_ctx.sc_lnum = 0;
1668f9cc9f20SBram Moolenaar     }
1669f9cc9f20SBram Moolenaar #endif
1670f9cc9f20SBram Moolenaar }
1671f9cc9f20SBram Moolenaar 
1672f9cc9f20SBram Moolenaar #if defined(FEAT_GUI) || defined(FEAT_TERMGUICOLORS) || defined(PROTO)
1673f9cc9f20SBram Moolenaar /*
1674f9cc9f20SBram Moolenaar  * Set the normal foreground and background colors according to the "Normal"
1675f9cc9f20SBram Moolenaar  * highlighting group.  For X11 also set "Menu", "Scrollbar", and
1676f9cc9f20SBram Moolenaar  * "Tooltip" colors.
1677f9cc9f20SBram Moolenaar  */
1678f9cc9f20SBram Moolenaar     void
1679f9cc9f20SBram Moolenaar set_normal_colors(void)
1680f9cc9f20SBram Moolenaar {
1681f9cc9f20SBram Moolenaar # ifdef FEAT_GUI
1682f9cc9f20SBram Moolenaar #  ifdef FEAT_TERMGUICOLORS
1683f9cc9f20SBram Moolenaar     if (gui.in_use)
1684f9cc9f20SBram Moolenaar #  endif
1685f9cc9f20SBram Moolenaar     {
1686f9cc9f20SBram Moolenaar 	if (set_group_colors((char_u *)"Normal",
1687f9cc9f20SBram Moolenaar 				 &gui.norm_pixel, &gui.back_pixel,
1688f9cc9f20SBram Moolenaar 				 FALSE, TRUE, FALSE))
1689f9cc9f20SBram Moolenaar 	{
1690f9cc9f20SBram Moolenaar 	    gui_mch_new_colors();
1691f9cc9f20SBram Moolenaar 	    must_redraw = CLEAR;
1692f9cc9f20SBram Moolenaar 	}
1693f9cc9f20SBram Moolenaar #  ifdef FEAT_GUI_X11
1694f9cc9f20SBram Moolenaar 	if (set_group_colors((char_u *)"Menu",
1695f9cc9f20SBram Moolenaar 			     &gui.menu_fg_pixel, &gui.menu_bg_pixel,
1696f9cc9f20SBram Moolenaar 			     TRUE, FALSE, FALSE))
1697f9cc9f20SBram Moolenaar 	{
1698f9cc9f20SBram Moolenaar #   ifdef FEAT_MENU
1699f9cc9f20SBram Moolenaar 	    gui_mch_new_menu_colors();
1700f9cc9f20SBram Moolenaar #   endif
1701f9cc9f20SBram Moolenaar 	    must_redraw = CLEAR;
1702f9cc9f20SBram Moolenaar 	}
1703f9cc9f20SBram Moolenaar #   ifdef FEAT_BEVAL_GUI
1704f9cc9f20SBram Moolenaar 	if (set_group_colors((char_u *)"Tooltip",
1705f9cc9f20SBram Moolenaar 			     &gui.tooltip_fg_pixel, &gui.tooltip_bg_pixel,
1706f9cc9f20SBram Moolenaar 			     FALSE, FALSE, TRUE))
1707f9cc9f20SBram Moolenaar 	{
1708f9cc9f20SBram Moolenaar #    ifdef FEAT_TOOLBAR
1709f9cc9f20SBram Moolenaar 	    gui_mch_new_tooltip_colors();
1710f9cc9f20SBram Moolenaar #    endif
1711f9cc9f20SBram Moolenaar 	    must_redraw = CLEAR;
1712f9cc9f20SBram Moolenaar 	}
1713f9cc9f20SBram Moolenaar #   endif
1714f9cc9f20SBram Moolenaar 	if (set_group_colors((char_u *)"Scrollbar",
1715f9cc9f20SBram Moolenaar 			&gui.scroll_fg_pixel, &gui.scroll_bg_pixel,
1716f9cc9f20SBram Moolenaar 			FALSE, FALSE, FALSE))
1717f9cc9f20SBram Moolenaar 	{
1718f9cc9f20SBram Moolenaar 	    gui_new_scrollbar_colors();
1719f9cc9f20SBram Moolenaar 	    must_redraw = CLEAR;
1720f9cc9f20SBram Moolenaar 	}
1721f9cc9f20SBram Moolenaar #  endif
1722f9cc9f20SBram Moolenaar     }
1723f9cc9f20SBram Moolenaar # endif
1724f9cc9f20SBram Moolenaar # ifdef FEAT_TERMGUICOLORS
1725f9cc9f20SBram Moolenaar #  ifdef FEAT_GUI
1726f9cc9f20SBram Moolenaar     else
1727f9cc9f20SBram Moolenaar #  endif
1728f9cc9f20SBram Moolenaar     {
1729f9cc9f20SBram Moolenaar 	int		idx;
1730f9cc9f20SBram Moolenaar 
1731f9cc9f20SBram Moolenaar 	idx = syn_name2id((char_u *)"Normal") - 1;
1732f9cc9f20SBram Moolenaar 	if (idx >= 0)
1733f9cc9f20SBram Moolenaar 	{
1734f9cc9f20SBram Moolenaar 	    gui_do_one_color(idx, FALSE, FALSE);
1735f9cc9f20SBram Moolenaar 
1736f9cc9f20SBram Moolenaar 	    // If the normal fg or bg color changed a complete redraw is
1737f9cc9f20SBram Moolenaar 	    // required.
1738f9cc9f20SBram Moolenaar 	    if (cterm_normal_fg_gui_color != HL_TABLE()[idx].sg_gui_fg
1739f9cc9f20SBram Moolenaar 		    || cterm_normal_bg_gui_color != HL_TABLE()[idx].sg_gui_bg)
1740f9cc9f20SBram Moolenaar 	    {
1741f9cc9f20SBram Moolenaar 		// if the GUI color is INVALCOLOR then we use the default cterm
1742f9cc9f20SBram Moolenaar 		// color
1743f9cc9f20SBram Moolenaar 		cterm_normal_fg_gui_color = HL_TABLE()[idx].sg_gui_fg;
1744f9cc9f20SBram Moolenaar 		cterm_normal_bg_gui_color = HL_TABLE()[idx].sg_gui_bg;
1745f9cc9f20SBram Moolenaar 		must_redraw = CLEAR;
1746f9cc9f20SBram Moolenaar 	    }
1747f9cc9f20SBram Moolenaar 	}
1748f9cc9f20SBram Moolenaar     }
1749f9cc9f20SBram Moolenaar # endif
1750f9cc9f20SBram Moolenaar }
1751f9cc9f20SBram Moolenaar #endif
1752f9cc9f20SBram Moolenaar 
1753f9cc9f20SBram Moolenaar #if defined(FEAT_GUI) || defined(PROTO)
1754f9cc9f20SBram Moolenaar /*
1755f9cc9f20SBram Moolenaar  * Set the colors for "Normal", "Menu", "Tooltip" or "Scrollbar".
1756f9cc9f20SBram Moolenaar  */
1757f9cc9f20SBram Moolenaar     static int
1758f9cc9f20SBram Moolenaar set_group_colors(
1759f9cc9f20SBram Moolenaar     char_u	*name,
1760f9cc9f20SBram Moolenaar     guicolor_T	*fgp,
1761f9cc9f20SBram Moolenaar     guicolor_T	*bgp,
1762f9cc9f20SBram Moolenaar     int		do_menu,
1763f9cc9f20SBram Moolenaar     int		use_norm,
1764f9cc9f20SBram Moolenaar     int		do_tooltip)
1765f9cc9f20SBram Moolenaar {
1766f9cc9f20SBram Moolenaar     int		idx;
1767f9cc9f20SBram Moolenaar 
1768f9cc9f20SBram Moolenaar     idx = syn_name2id(name) - 1;
1769f9cc9f20SBram Moolenaar     if (idx >= 0)
1770f9cc9f20SBram Moolenaar     {
1771f9cc9f20SBram Moolenaar 	gui_do_one_color(idx, do_menu, do_tooltip);
1772f9cc9f20SBram Moolenaar 
1773f9cc9f20SBram Moolenaar 	if (HL_TABLE()[idx].sg_gui_fg != INVALCOLOR)
1774f9cc9f20SBram Moolenaar 	    *fgp = HL_TABLE()[idx].sg_gui_fg;
1775f9cc9f20SBram Moolenaar 	else if (use_norm)
1776f9cc9f20SBram Moolenaar 	    *fgp = gui.def_norm_pixel;
1777f9cc9f20SBram Moolenaar 	if (HL_TABLE()[idx].sg_gui_bg != INVALCOLOR)
1778f9cc9f20SBram Moolenaar 	    *bgp = HL_TABLE()[idx].sg_gui_bg;
1779f9cc9f20SBram Moolenaar 	else if (use_norm)
1780f9cc9f20SBram Moolenaar 	    *bgp = gui.def_back_pixel;
1781f9cc9f20SBram Moolenaar 	return TRUE;
1782f9cc9f20SBram Moolenaar     }
1783f9cc9f20SBram Moolenaar     return FALSE;
1784f9cc9f20SBram Moolenaar }
1785f9cc9f20SBram Moolenaar 
1786f9cc9f20SBram Moolenaar /*
1787f9cc9f20SBram Moolenaar  * Get the font of the "Normal" group.
1788f9cc9f20SBram Moolenaar  * Returns "" when it's not found or not set.
1789f9cc9f20SBram Moolenaar  */
1790f9cc9f20SBram Moolenaar     char_u *
1791f9cc9f20SBram Moolenaar hl_get_font_name(void)
1792f9cc9f20SBram Moolenaar {
1793f9cc9f20SBram Moolenaar     int		id;
1794f9cc9f20SBram Moolenaar     char_u	*s;
1795f9cc9f20SBram Moolenaar 
1796f9cc9f20SBram Moolenaar     id = syn_name2id((char_u *)"Normal");
1797f9cc9f20SBram Moolenaar     if (id > 0)
1798f9cc9f20SBram Moolenaar     {
1799f9cc9f20SBram Moolenaar 	s = HL_TABLE()[id - 1].sg_font_name;
1800f9cc9f20SBram Moolenaar 	if (s != NULL)
1801f9cc9f20SBram Moolenaar 	    return s;
1802f9cc9f20SBram Moolenaar     }
1803f9cc9f20SBram Moolenaar     return (char_u *)"";
1804f9cc9f20SBram Moolenaar }
1805f9cc9f20SBram Moolenaar 
1806f9cc9f20SBram Moolenaar /*
1807f9cc9f20SBram Moolenaar  * Set font for "Normal" group.  Called by gui_mch_init_font() when a font has
1808f9cc9f20SBram Moolenaar  * actually chosen to be used.
1809f9cc9f20SBram Moolenaar  */
1810f9cc9f20SBram Moolenaar     void
1811f9cc9f20SBram Moolenaar hl_set_font_name(char_u *font_name)
1812f9cc9f20SBram Moolenaar {
1813f9cc9f20SBram Moolenaar     int	    id;
1814f9cc9f20SBram Moolenaar 
1815f9cc9f20SBram Moolenaar     id = syn_name2id((char_u *)"Normal");
1816f9cc9f20SBram Moolenaar     if (id > 0)
1817f9cc9f20SBram Moolenaar     {
1818f9cc9f20SBram Moolenaar 	vim_free(HL_TABLE()[id - 1].sg_font_name);
1819f9cc9f20SBram Moolenaar 	HL_TABLE()[id - 1].sg_font_name = vim_strsave(font_name);
1820f9cc9f20SBram Moolenaar     }
1821f9cc9f20SBram Moolenaar }
1822f9cc9f20SBram Moolenaar 
1823f9cc9f20SBram Moolenaar /*
1824f9cc9f20SBram Moolenaar  * Set background color for "Normal" group.  Called by gui_set_bg_color()
1825f9cc9f20SBram Moolenaar  * when the color is known.
1826f9cc9f20SBram Moolenaar  */
1827f9cc9f20SBram Moolenaar     void
1828f9cc9f20SBram Moolenaar hl_set_bg_color_name(
1829f9cc9f20SBram Moolenaar     char_u  *name)	    // must have been allocated
1830f9cc9f20SBram Moolenaar {
1831f9cc9f20SBram Moolenaar     int	    id;
1832f9cc9f20SBram Moolenaar 
1833f9cc9f20SBram Moolenaar     if (name != NULL)
1834f9cc9f20SBram Moolenaar     {
1835f9cc9f20SBram Moolenaar 	id = syn_name2id((char_u *)"Normal");
1836f9cc9f20SBram Moolenaar 	if (id > 0)
1837f9cc9f20SBram Moolenaar 	{
1838f9cc9f20SBram Moolenaar 	    vim_free(HL_TABLE()[id - 1].sg_gui_bg_name);
1839f9cc9f20SBram Moolenaar 	    HL_TABLE()[id - 1].sg_gui_bg_name = name;
1840f9cc9f20SBram Moolenaar 	}
1841f9cc9f20SBram Moolenaar     }
1842f9cc9f20SBram Moolenaar }
1843f9cc9f20SBram Moolenaar 
1844f9cc9f20SBram Moolenaar /*
1845f9cc9f20SBram Moolenaar  * Set foreground color for "Normal" group.  Called by gui_set_fg_color()
1846f9cc9f20SBram Moolenaar  * when the color is known.
1847f9cc9f20SBram Moolenaar  */
1848f9cc9f20SBram Moolenaar     void
1849f9cc9f20SBram Moolenaar hl_set_fg_color_name(
1850f9cc9f20SBram Moolenaar     char_u  *name)	    // must have been allocated
1851f9cc9f20SBram Moolenaar {
1852f9cc9f20SBram Moolenaar     int	    id;
1853f9cc9f20SBram Moolenaar 
1854f9cc9f20SBram Moolenaar     if (name != NULL)
1855f9cc9f20SBram Moolenaar     {
1856f9cc9f20SBram Moolenaar 	id = syn_name2id((char_u *)"Normal");
1857f9cc9f20SBram Moolenaar 	if (id > 0)
1858f9cc9f20SBram Moolenaar 	{
1859f9cc9f20SBram Moolenaar 	    vim_free(HL_TABLE()[id - 1].sg_gui_fg_name);
1860f9cc9f20SBram Moolenaar 	    HL_TABLE()[id - 1].sg_gui_fg_name = name;
1861f9cc9f20SBram Moolenaar 	}
1862f9cc9f20SBram Moolenaar     }
1863f9cc9f20SBram Moolenaar }
1864f9cc9f20SBram Moolenaar 
1865f9cc9f20SBram Moolenaar /*
1866f9cc9f20SBram Moolenaar  * Return the handle for a font name.
1867f9cc9f20SBram Moolenaar  * Returns NOFONT when failed.
1868f9cc9f20SBram Moolenaar  */
1869f9cc9f20SBram Moolenaar     static GuiFont
1870f9cc9f20SBram Moolenaar font_name2handle(char_u *name)
1871f9cc9f20SBram Moolenaar {
1872f9cc9f20SBram Moolenaar     if (STRCMP(name, "NONE") == 0)
1873f9cc9f20SBram Moolenaar 	return NOFONT;
1874f9cc9f20SBram Moolenaar 
1875f9cc9f20SBram Moolenaar     return gui_mch_get_font(name, TRUE);
1876f9cc9f20SBram Moolenaar }
1877f9cc9f20SBram Moolenaar 
1878f9cc9f20SBram Moolenaar # ifdef FEAT_XFONTSET
1879f9cc9f20SBram Moolenaar /*
1880f9cc9f20SBram Moolenaar  * Return the handle for a fontset name.
1881f9cc9f20SBram Moolenaar  * Returns NOFONTSET when failed.
1882f9cc9f20SBram Moolenaar  */
1883f9cc9f20SBram Moolenaar     static GuiFontset
1884f9cc9f20SBram Moolenaar fontset_name2handle(char_u *name, int fixed_width)
1885f9cc9f20SBram Moolenaar {
1886f9cc9f20SBram Moolenaar     if (STRCMP(name, "NONE") == 0)
1887f9cc9f20SBram Moolenaar 	return NOFONTSET;
1888f9cc9f20SBram Moolenaar 
1889f9cc9f20SBram Moolenaar     return gui_mch_get_fontset(name, TRUE, fixed_width);
1890f9cc9f20SBram Moolenaar }
1891f9cc9f20SBram Moolenaar # endif
1892f9cc9f20SBram Moolenaar 
1893f9cc9f20SBram Moolenaar /*
1894f9cc9f20SBram Moolenaar  * Get the font or fontset for one highlight group.
1895f9cc9f20SBram Moolenaar  */
1896f9cc9f20SBram Moolenaar     static void
1897f9cc9f20SBram Moolenaar hl_do_font(
1898f9cc9f20SBram Moolenaar     int		idx,
1899f9cc9f20SBram Moolenaar     char_u	*arg,
1900f9cc9f20SBram Moolenaar     int		do_normal,		// set normal font
1901f9cc9f20SBram Moolenaar     int		do_menu UNUSED,		// set menu font
1902f9cc9f20SBram Moolenaar     int		do_tooltip UNUSED,	// set tooltip font
1903f9cc9f20SBram Moolenaar     int		free_font)		// free current font/fontset
1904f9cc9f20SBram Moolenaar {
1905f9cc9f20SBram Moolenaar # ifdef FEAT_XFONTSET
1906f9cc9f20SBram Moolenaar     // If 'guifontset' is not empty, first try using the name as a
1907f9cc9f20SBram Moolenaar     // fontset.  If that doesn't work, use it as a font name.
1908f9cc9f20SBram Moolenaar     if (*p_guifontset != NUL
1909f9cc9f20SBram Moolenaar #  ifdef FONTSET_ALWAYS
1910f9cc9f20SBram Moolenaar 	|| do_menu
1911f9cc9f20SBram Moolenaar #  endif
1912f9cc9f20SBram Moolenaar #  ifdef FEAT_BEVAL_TIP
1913f9cc9f20SBram Moolenaar 	// In Athena & Motif, the Tooltip highlight group is always a fontset
1914f9cc9f20SBram Moolenaar 	|| do_tooltip
1915f9cc9f20SBram Moolenaar #  endif
1916f9cc9f20SBram Moolenaar 	    )
1917f9cc9f20SBram Moolenaar     {
1918f9cc9f20SBram Moolenaar 	if (free_font)
1919f9cc9f20SBram Moolenaar 	    gui_mch_free_fontset(HL_TABLE()[idx].sg_fontset);
1920f9cc9f20SBram Moolenaar 	HL_TABLE()[idx].sg_fontset = fontset_name2handle(arg, 0
1921f9cc9f20SBram Moolenaar #  ifdef FONTSET_ALWAYS
1922f9cc9f20SBram Moolenaar 		|| do_menu
1923f9cc9f20SBram Moolenaar #  endif
1924f9cc9f20SBram Moolenaar #  ifdef FEAT_BEVAL_TIP
1925f9cc9f20SBram Moolenaar 		|| do_tooltip
1926f9cc9f20SBram Moolenaar #  endif
1927f9cc9f20SBram Moolenaar 		);
1928f9cc9f20SBram Moolenaar     }
1929f9cc9f20SBram Moolenaar     if (HL_TABLE()[idx].sg_fontset != NOFONTSET)
1930f9cc9f20SBram Moolenaar     {
1931f9cc9f20SBram Moolenaar 	// If it worked and it's the Normal group, use it as the normal
1932f9cc9f20SBram Moolenaar 	// fontset.  Same for the Menu group.
1933f9cc9f20SBram Moolenaar 	if (do_normal)
1934f9cc9f20SBram Moolenaar 	    gui_init_font(arg, TRUE);
1935f9cc9f20SBram Moolenaar #   if (defined(FEAT_GUI_MOTIF) || defined(FEAT_GUI_ATHENA)) && defined(FEAT_MENU)
1936f9cc9f20SBram Moolenaar 	if (do_menu)
1937f9cc9f20SBram Moolenaar 	{
1938f9cc9f20SBram Moolenaar #    ifdef FONTSET_ALWAYS
1939f9cc9f20SBram Moolenaar 	    gui.menu_fontset = HL_TABLE()[idx].sg_fontset;
1940f9cc9f20SBram Moolenaar #    else
1941f9cc9f20SBram Moolenaar 	    // YIKES!  This is a bug waiting to crash the program
1942f9cc9f20SBram Moolenaar 	    gui.menu_font = HL_TABLE()[idx].sg_fontset;
1943f9cc9f20SBram Moolenaar #    endif
1944f9cc9f20SBram Moolenaar 	    gui_mch_new_menu_font();
1945f9cc9f20SBram Moolenaar 	}
1946f9cc9f20SBram Moolenaar #    ifdef FEAT_BEVAL_GUI
1947f9cc9f20SBram Moolenaar 	if (do_tooltip)
1948f9cc9f20SBram Moolenaar 	{
1949f9cc9f20SBram Moolenaar 	    // The Athena widget set cannot currently handle switching between
1950f9cc9f20SBram Moolenaar 	    // displaying a single font and a fontset.
1951f9cc9f20SBram Moolenaar 	    // If the XtNinternational resource is set to True at widget
1952f9cc9f20SBram Moolenaar 	    // creation, then a fontset is always used, otherwise an
1953f9cc9f20SBram Moolenaar 	    // XFontStruct is used.
1954f9cc9f20SBram Moolenaar 	    gui.tooltip_fontset = (XFontSet)HL_TABLE()[idx].sg_fontset;
1955f9cc9f20SBram Moolenaar 	    gui_mch_new_tooltip_font();
1956f9cc9f20SBram Moolenaar 	}
1957f9cc9f20SBram Moolenaar #    endif
1958f9cc9f20SBram Moolenaar #   endif
1959f9cc9f20SBram Moolenaar     }
1960f9cc9f20SBram Moolenaar     else
1961f9cc9f20SBram Moolenaar # endif
1962f9cc9f20SBram Moolenaar     {
1963f9cc9f20SBram Moolenaar 	if (free_font)
1964f9cc9f20SBram Moolenaar 	    gui_mch_free_font(HL_TABLE()[idx].sg_font);
1965f9cc9f20SBram Moolenaar 	HL_TABLE()[idx].sg_font = font_name2handle(arg);
1966f9cc9f20SBram Moolenaar 	// If it worked and it's the Normal group, use it as the
1967f9cc9f20SBram Moolenaar 	// normal font.  Same for the Menu group.
1968f9cc9f20SBram Moolenaar 	if (HL_TABLE()[idx].sg_font != NOFONT)
1969f9cc9f20SBram Moolenaar 	{
1970f9cc9f20SBram Moolenaar 	    if (do_normal)
1971f9cc9f20SBram Moolenaar 		gui_init_font(arg, FALSE);
1972f9cc9f20SBram Moolenaar #ifndef FONTSET_ALWAYS
1973f9cc9f20SBram Moolenaar # if (defined(FEAT_GUI_MOTIF) || defined(FEAT_GUI_ATHENA)) && defined(FEAT_MENU)
1974f9cc9f20SBram Moolenaar 	    if (do_menu)
1975f9cc9f20SBram Moolenaar 	    {
1976f9cc9f20SBram Moolenaar 		gui.menu_font = HL_TABLE()[idx].sg_font;
1977f9cc9f20SBram Moolenaar 		gui_mch_new_menu_font();
1978f9cc9f20SBram Moolenaar 	    }
1979f9cc9f20SBram Moolenaar # endif
1980f9cc9f20SBram Moolenaar #endif
1981f9cc9f20SBram Moolenaar 	}
1982f9cc9f20SBram Moolenaar     }
1983f9cc9f20SBram Moolenaar }
1984f9cc9f20SBram Moolenaar 
1985f9cc9f20SBram Moolenaar #endif // FEAT_GUI
1986f9cc9f20SBram Moolenaar 
1987f9cc9f20SBram Moolenaar #if defined(FEAT_GUI) || defined(FEAT_TERMGUICOLORS) || defined(PROTO)
1988f9cc9f20SBram Moolenaar /*
1989f9cc9f20SBram Moolenaar  * Return the handle for a color name.
1990f9cc9f20SBram Moolenaar  * Returns INVALCOLOR when failed.
1991f9cc9f20SBram Moolenaar  */
1992f9cc9f20SBram Moolenaar     guicolor_T
1993f9cc9f20SBram Moolenaar color_name2handle(char_u *name)
1994f9cc9f20SBram Moolenaar {
1995f9cc9f20SBram Moolenaar     if (STRCMP(name, "NONE") == 0)
1996f9cc9f20SBram Moolenaar 	return INVALCOLOR;
1997f9cc9f20SBram Moolenaar 
1998f9cc9f20SBram Moolenaar     if (STRICMP(name, "fg") == 0 || STRICMP(name, "foreground") == 0)
1999f9cc9f20SBram Moolenaar     {
2000f9cc9f20SBram Moolenaar #if defined(FEAT_TERMGUICOLORS) && defined(FEAT_GUI)
2001f9cc9f20SBram Moolenaar 	if (gui.in_use)
2002f9cc9f20SBram Moolenaar #endif
2003f9cc9f20SBram Moolenaar #ifdef FEAT_GUI
2004f9cc9f20SBram Moolenaar 	    return gui.norm_pixel;
2005f9cc9f20SBram Moolenaar #endif
2006f9cc9f20SBram Moolenaar #ifdef FEAT_TERMGUICOLORS
2007f9cc9f20SBram Moolenaar 	if (cterm_normal_fg_gui_color != INVALCOLOR)
2008f9cc9f20SBram Moolenaar 	    return cterm_normal_fg_gui_color;
2009f9cc9f20SBram Moolenaar 	// Guess that the foreground is black or white.
2010f9cc9f20SBram Moolenaar 	return GUI_GET_COLOR((char_u *)(*p_bg == 'l' ? "black" : "white"));
2011f9cc9f20SBram Moolenaar #endif
2012f9cc9f20SBram Moolenaar     }
2013f9cc9f20SBram Moolenaar     if (STRICMP(name, "bg") == 0 || STRICMP(name, "background") == 0)
2014f9cc9f20SBram Moolenaar     {
2015f9cc9f20SBram Moolenaar #if defined(FEAT_TERMGUICOLORS) && defined(FEAT_GUI)
2016f9cc9f20SBram Moolenaar 	if (gui.in_use)
2017f9cc9f20SBram Moolenaar #endif
2018f9cc9f20SBram Moolenaar #ifdef FEAT_GUI
2019f9cc9f20SBram Moolenaar 	    return gui.back_pixel;
2020f9cc9f20SBram Moolenaar #endif
2021f9cc9f20SBram Moolenaar #ifdef FEAT_TERMGUICOLORS
2022f9cc9f20SBram Moolenaar 	if (cterm_normal_bg_gui_color != INVALCOLOR)
2023f9cc9f20SBram Moolenaar 	    return cterm_normal_bg_gui_color;
2024f9cc9f20SBram Moolenaar 	// Guess that the background is white or black.
2025f9cc9f20SBram Moolenaar 	return GUI_GET_COLOR((char_u *)(*p_bg == 'l' ? "white" : "black"));
2026f9cc9f20SBram Moolenaar #endif
2027f9cc9f20SBram Moolenaar     }
2028f9cc9f20SBram Moolenaar 
2029f9cc9f20SBram Moolenaar     return GUI_GET_COLOR(name);
2030f9cc9f20SBram Moolenaar }
2031f9cc9f20SBram Moolenaar #endif
2032f9cc9f20SBram Moolenaar 
2033f9cc9f20SBram Moolenaar /*
2034f9cc9f20SBram Moolenaar  * Table with the specifications for an attribute number.
2035f9cc9f20SBram Moolenaar  * Note that this table is used by ALL buffers.  This is required because the
2036f9cc9f20SBram Moolenaar  * GUI can redraw at any time for any buffer.
2037f9cc9f20SBram Moolenaar  */
2038f9cc9f20SBram Moolenaar static garray_T	term_attr_table = {0, 0, 0, 0, NULL};
2039f9cc9f20SBram Moolenaar 
2040f9cc9f20SBram Moolenaar #define TERM_ATTR_ENTRY(idx) ((attrentry_T *)term_attr_table.ga_data)[idx]
2041f9cc9f20SBram Moolenaar 
2042f9cc9f20SBram Moolenaar static garray_T	cterm_attr_table = {0, 0, 0, 0, NULL};
2043f9cc9f20SBram Moolenaar 
2044f9cc9f20SBram Moolenaar #define CTERM_ATTR_ENTRY(idx) ((attrentry_T *)cterm_attr_table.ga_data)[idx]
2045f9cc9f20SBram Moolenaar 
2046f9cc9f20SBram Moolenaar #ifdef FEAT_GUI
2047f9cc9f20SBram Moolenaar static garray_T	gui_attr_table = {0, 0, 0, 0, NULL};
2048f9cc9f20SBram Moolenaar 
2049f9cc9f20SBram Moolenaar #define GUI_ATTR_ENTRY(idx) ((attrentry_T *)gui_attr_table.ga_data)[idx]
2050f9cc9f20SBram Moolenaar #endif
2051f9cc9f20SBram Moolenaar 
2052f9cc9f20SBram Moolenaar /*
2053f9cc9f20SBram Moolenaar  * Return the attr number for a set of colors and font.
2054f9cc9f20SBram Moolenaar  * Add a new entry to the term_attr_table, cterm_attr_table or gui_attr_table
2055f9cc9f20SBram Moolenaar  * if the combination is new.
2056f9cc9f20SBram Moolenaar  * Return 0 for error (no more room).
2057f9cc9f20SBram Moolenaar  */
2058f9cc9f20SBram Moolenaar     static int
2059f9cc9f20SBram Moolenaar get_attr_entry(garray_T *table, attrentry_T *aep)
2060f9cc9f20SBram Moolenaar {
2061f9cc9f20SBram Moolenaar     int		i;
2062f9cc9f20SBram Moolenaar     attrentry_T	*taep;
2063f9cc9f20SBram Moolenaar     static int	recursive = FALSE;
2064f9cc9f20SBram Moolenaar 
2065f9cc9f20SBram Moolenaar     /*
2066f9cc9f20SBram Moolenaar      * Init the table, in case it wasn't done yet.
2067f9cc9f20SBram Moolenaar      */
2068f9cc9f20SBram Moolenaar     table->ga_itemsize = sizeof(attrentry_T);
2069f9cc9f20SBram Moolenaar     table->ga_growsize = 7;
2070f9cc9f20SBram Moolenaar 
2071f9cc9f20SBram Moolenaar     /*
2072f9cc9f20SBram Moolenaar      * Try to find an entry with the same specifications.
2073f9cc9f20SBram Moolenaar      */
2074f9cc9f20SBram Moolenaar     for (i = 0; i < table->ga_len; ++i)
2075f9cc9f20SBram Moolenaar     {
2076f9cc9f20SBram Moolenaar 	taep = &(((attrentry_T *)table->ga_data)[i]);
2077f9cc9f20SBram Moolenaar 	if (	   aep->ae_attr == taep->ae_attr
2078f9cc9f20SBram Moolenaar 		&& (
2079f9cc9f20SBram Moolenaar #ifdef FEAT_GUI
2080f9cc9f20SBram Moolenaar 		       (table == &gui_attr_table
2081f9cc9f20SBram Moolenaar 			&& (aep->ae_u.gui.fg_color == taep->ae_u.gui.fg_color
2082f9cc9f20SBram Moolenaar 			    && aep->ae_u.gui.bg_color
2083f9cc9f20SBram Moolenaar 						    == taep->ae_u.gui.bg_color
2084f9cc9f20SBram Moolenaar 			    && aep->ae_u.gui.sp_color
2085f9cc9f20SBram Moolenaar 						    == taep->ae_u.gui.sp_color
2086f9cc9f20SBram Moolenaar 			    && aep->ae_u.gui.font == taep->ae_u.gui.font
2087f9cc9f20SBram Moolenaar #  ifdef FEAT_XFONTSET
2088f9cc9f20SBram Moolenaar 			    && aep->ae_u.gui.fontset == taep->ae_u.gui.fontset
2089f9cc9f20SBram Moolenaar #  endif
2090f9cc9f20SBram Moolenaar 			    ))
2091f9cc9f20SBram Moolenaar 		    ||
2092f9cc9f20SBram Moolenaar #endif
2093f9cc9f20SBram Moolenaar 		       (table == &term_attr_table
2094f9cc9f20SBram Moolenaar 			&& (aep->ae_u.term.start == NULL)
2095f9cc9f20SBram Moolenaar 					    == (taep->ae_u.term.start == NULL)
2096f9cc9f20SBram Moolenaar 			&& (aep->ae_u.term.start == NULL
2097f9cc9f20SBram Moolenaar 			    || STRCMP(aep->ae_u.term.start,
2098f9cc9f20SBram Moolenaar 						  taep->ae_u.term.start) == 0)
2099f9cc9f20SBram Moolenaar 			&& (aep->ae_u.term.stop == NULL)
2100f9cc9f20SBram Moolenaar 					     == (taep->ae_u.term.stop == NULL)
2101f9cc9f20SBram Moolenaar 			&& (aep->ae_u.term.stop == NULL
2102f9cc9f20SBram Moolenaar 			    || STRCMP(aep->ae_u.term.stop,
2103f9cc9f20SBram Moolenaar 						  taep->ae_u.term.stop) == 0))
2104f9cc9f20SBram Moolenaar 		    || (table == &cterm_attr_table
2105f9cc9f20SBram Moolenaar 			    && aep->ae_u.cterm.fg_color
2106f9cc9f20SBram Moolenaar 						  == taep->ae_u.cterm.fg_color
2107f9cc9f20SBram Moolenaar 			    && aep->ae_u.cterm.bg_color
2108f9cc9f20SBram Moolenaar 						  == taep->ae_u.cterm.bg_color
2109f9cc9f20SBram Moolenaar #ifdef FEAT_TERMGUICOLORS
2110f9cc9f20SBram Moolenaar 			    && aep->ae_u.cterm.fg_rgb
2111f9cc9f20SBram Moolenaar 						    == taep->ae_u.cterm.fg_rgb
2112f9cc9f20SBram Moolenaar 			    && aep->ae_u.cterm.bg_rgb
2113f9cc9f20SBram Moolenaar 						    == taep->ae_u.cterm.bg_rgb
2114f9cc9f20SBram Moolenaar #endif
2115f9cc9f20SBram Moolenaar 		       )))
2116f9cc9f20SBram Moolenaar 
2117f9cc9f20SBram Moolenaar 	return i + ATTR_OFF;
2118f9cc9f20SBram Moolenaar     }
2119f9cc9f20SBram Moolenaar 
2120f9cc9f20SBram Moolenaar     if (table->ga_len + ATTR_OFF > MAX_TYPENR)
2121f9cc9f20SBram Moolenaar     {
2122f9cc9f20SBram Moolenaar 	/*
2123f9cc9f20SBram Moolenaar 	 * Running out of attribute entries!  remove all attributes, and
2124f9cc9f20SBram Moolenaar 	 * compute new ones for all groups.
2125f9cc9f20SBram Moolenaar 	 * When called recursively, we are really out of numbers.
2126f9cc9f20SBram Moolenaar 	 */
2127f9cc9f20SBram Moolenaar 	if (recursive)
2128f9cc9f20SBram Moolenaar 	{
2129f9cc9f20SBram Moolenaar 	    emsg(_("E424: Too many different highlighting attributes in use"));
2130f9cc9f20SBram Moolenaar 	    return 0;
2131f9cc9f20SBram Moolenaar 	}
2132f9cc9f20SBram Moolenaar 	recursive = TRUE;
2133f9cc9f20SBram Moolenaar 
2134f9cc9f20SBram Moolenaar 	clear_hl_tables();
2135f9cc9f20SBram Moolenaar 
2136f9cc9f20SBram Moolenaar 	must_redraw = CLEAR;
2137f9cc9f20SBram Moolenaar 
2138f9cc9f20SBram Moolenaar 	for (i = 0; i < highlight_ga.ga_len; ++i)
2139f9cc9f20SBram Moolenaar 	    set_hl_attr(i);
2140f9cc9f20SBram Moolenaar 
2141f9cc9f20SBram Moolenaar 	recursive = FALSE;
2142f9cc9f20SBram Moolenaar     }
2143f9cc9f20SBram Moolenaar 
2144f9cc9f20SBram Moolenaar     /*
2145f9cc9f20SBram Moolenaar      * This is a new combination of colors and font, add an entry.
2146f9cc9f20SBram Moolenaar      */
2147f9cc9f20SBram Moolenaar     if (ga_grow(table, 1) == FAIL)
2148f9cc9f20SBram Moolenaar 	return 0;
2149f9cc9f20SBram Moolenaar 
2150f9cc9f20SBram Moolenaar     taep = &(((attrentry_T *)table->ga_data)[table->ga_len]);
2151f9cc9f20SBram Moolenaar     vim_memset(taep, 0, sizeof(attrentry_T));
2152f9cc9f20SBram Moolenaar     taep->ae_attr = aep->ae_attr;
2153f9cc9f20SBram Moolenaar #ifdef FEAT_GUI
2154f9cc9f20SBram Moolenaar     if (table == &gui_attr_table)
2155f9cc9f20SBram Moolenaar     {
2156f9cc9f20SBram Moolenaar 	taep->ae_u.gui.fg_color = aep->ae_u.gui.fg_color;
2157f9cc9f20SBram Moolenaar 	taep->ae_u.gui.bg_color = aep->ae_u.gui.bg_color;
2158f9cc9f20SBram Moolenaar 	taep->ae_u.gui.sp_color = aep->ae_u.gui.sp_color;
2159f9cc9f20SBram Moolenaar 	taep->ae_u.gui.font = aep->ae_u.gui.font;
2160f9cc9f20SBram Moolenaar # ifdef FEAT_XFONTSET
2161f9cc9f20SBram Moolenaar 	taep->ae_u.gui.fontset = aep->ae_u.gui.fontset;
2162f9cc9f20SBram Moolenaar # endif
2163f9cc9f20SBram Moolenaar     }
2164f9cc9f20SBram Moolenaar #endif
2165f9cc9f20SBram Moolenaar     if (table == &term_attr_table)
2166f9cc9f20SBram Moolenaar     {
2167f9cc9f20SBram Moolenaar 	if (aep->ae_u.term.start == NULL)
2168f9cc9f20SBram Moolenaar 	    taep->ae_u.term.start = NULL;
2169f9cc9f20SBram Moolenaar 	else
2170f9cc9f20SBram Moolenaar 	    taep->ae_u.term.start = vim_strsave(aep->ae_u.term.start);
2171f9cc9f20SBram Moolenaar 	if (aep->ae_u.term.stop == NULL)
2172f9cc9f20SBram Moolenaar 	    taep->ae_u.term.stop = NULL;
2173f9cc9f20SBram Moolenaar 	else
2174f9cc9f20SBram Moolenaar 	    taep->ae_u.term.stop = vim_strsave(aep->ae_u.term.stop);
2175f9cc9f20SBram Moolenaar     }
2176f9cc9f20SBram Moolenaar     else if (table == &cterm_attr_table)
2177f9cc9f20SBram Moolenaar     {
2178f9cc9f20SBram Moolenaar 	taep->ae_u.cterm.fg_color = aep->ae_u.cterm.fg_color;
2179f9cc9f20SBram Moolenaar 	taep->ae_u.cterm.bg_color = aep->ae_u.cterm.bg_color;
2180f9cc9f20SBram Moolenaar #ifdef FEAT_TERMGUICOLORS
2181f9cc9f20SBram Moolenaar 	taep->ae_u.cterm.fg_rgb = aep->ae_u.cterm.fg_rgb;
2182f9cc9f20SBram Moolenaar 	taep->ae_u.cterm.bg_rgb = aep->ae_u.cterm.bg_rgb;
2183f9cc9f20SBram Moolenaar #endif
2184f9cc9f20SBram Moolenaar     }
2185f9cc9f20SBram Moolenaar     ++table->ga_len;
2186f9cc9f20SBram Moolenaar     return (table->ga_len - 1 + ATTR_OFF);
2187f9cc9f20SBram Moolenaar }
2188f9cc9f20SBram Moolenaar 
2189f9cc9f20SBram Moolenaar #if defined(FEAT_TERMINAL) || defined(PROTO)
2190f9cc9f20SBram Moolenaar /*
2191f9cc9f20SBram Moolenaar  * Get an attribute index for a cterm entry.
2192f9cc9f20SBram Moolenaar  * Uses an existing entry when possible or adds one when needed.
2193f9cc9f20SBram Moolenaar  */
2194f9cc9f20SBram Moolenaar     int
2195f9cc9f20SBram Moolenaar get_cterm_attr_idx(int attr, int fg, int bg)
2196f9cc9f20SBram Moolenaar {
2197f9cc9f20SBram Moolenaar     attrentry_T		at_en;
2198f9cc9f20SBram Moolenaar 
2199f9cc9f20SBram Moolenaar     vim_memset(&at_en, 0, sizeof(attrentry_T));
2200f9cc9f20SBram Moolenaar #ifdef FEAT_TERMGUICOLORS
2201f9cc9f20SBram Moolenaar     at_en.ae_u.cterm.fg_rgb = INVALCOLOR;
2202f9cc9f20SBram Moolenaar     at_en.ae_u.cterm.bg_rgb = INVALCOLOR;
2203f9cc9f20SBram Moolenaar #endif
2204f9cc9f20SBram Moolenaar     at_en.ae_attr = attr;
2205f9cc9f20SBram Moolenaar     at_en.ae_u.cterm.fg_color = fg;
2206f9cc9f20SBram Moolenaar     at_en.ae_u.cterm.bg_color = bg;
2207f9cc9f20SBram Moolenaar     return get_attr_entry(&cterm_attr_table, &at_en);
2208f9cc9f20SBram Moolenaar }
2209f9cc9f20SBram Moolenaar #endif
2210f9cc9f20SBram Moolenaar 
2211f9cc9f20SBram Moolenaar #if (defined(FEAT_TERMINAL) && defined(FEAT_TERMGUICOLORS)) || defined(PROTO)
2212f9cc9f20SBram Moolenaar /*
2213f9cc9f20SBram Moolenaar  * Get an attribute index for a 'termguicolors' entry.
2214f9cc9f20SBram Moolenaar  * Uses an existing entry when possible or adds one when needed.
2215f9cc9f20SBram Moolenaar  */
2216f9cc9f20SBram Moolenaar     int
2217f9cc9f20SBram Moolenaar get_tgc_attr_idx(int attr, guicolor_T fg, guicolor_T bg)
2218f9cc9f20SBram Moolenaar {
2219f9cc9f20SBram Moolenaar     attrentry_T		at_en;
2220f9cc9f20SBram Moolenaar 
2221f9cc9f20SBram Moolenaar     vim_memset(&at_en, 0, sizeof(attrentry_T));
2222f9cc9f20SBram Moolenaar     at_en.ae_attr = attr;
2223f9cc9f20SBram Moolenaar     if (fg == INVALCOLOR && bg == INVALCOLOR)
2224f9cc9f20SBram Moolenaar     {
2225f9cc9f20SBram Moolenaar 	// If both GUI colors are not set fall back to the cterm colors.  Helps
2226f9cc9f20SBram Moolenaar 	// if the GUI only has an attribute, such as undercurl.
2227f9cc9f20SBram Moolenaar 	at_en.ae_u.cterm.fg_rgb = CTERMCOLOR;
2228f9cc9f20SBram Moolenaar 	at_en.ae_u.cterm.bg_rgb = CTERMCOLOR;
2229f9cc9f20SBram Moolenaar     }
2230f9cc9f20SBram Moolenaar     else
2231f9cc9f20SBram Moolenaar     {
2232f9cc9f20SBram Moolenaar 	at_en.ae_u.cterm.fg_rgb = fg;
2233f9cc9f20SBram Moolenaar 	at_en.ae_u.cterm.bg_rgb = bg;
2234f9cc9f20SBram Moolenaar     }
2235f9cc9f20SBram Moolenaar     return get_attr_entry(&cterm_attr_table, &at_en);
2236f9cc9f20SBram Moolenaar }
2237f9cc9f20SBram Moolenaar #endif
2238f9cc9f20SBram Moolenaar 
2239f9cc9f20SBram Moolenaar #if (defined(FEAT_TERMINAL) && defined(FEAT_GUI)) || defined(PROTO)
2240f9cc9f20SBram Moolenaar /*
2241f9cc9f20SBram Moolenaar  * Get an attribute index for a cterm entry.
2242f9cc9f20SBram Moolenaar  * Uses an existing entry when possible or adds one when needed.
2243f9cc9f20SBram Moolenaar  */
2244f9cc9f20SBram Moolenaar     int
2245f9cc9f20SBram Moolenaar get_gui_attr_idx(int attr, guicolor_T fg, guicolor_T bg)
2246f9cc9f20SBram Moolenaar {
2247f9cc9f20SBram Moolenaar     attrentry_T		at_en;
2248f9cc9f20SBram Moolenaar 
2249f9cc9f20SBram Moolenaar     vim_memset(&at_en, 0, sizeof(attrentry_T));
2250f9cc9f20SBram Moolenaar     at_en.ae_attr = attr;
2251f9cc9f20SBram Moolenaar     at_en.ae_u.gui.fg_color = fg;
2252f9cc9f20SBram Moolenaar     at_en.ae_u.gui.bg_color = bg;
2253f9cc9f20SBram Moolenaar     return get_attr_entry(&gui_attr_table, &at_en);
2254f9cc9f20SBram Moolenaar }
2255f9cc9f20SBram Moolenaar #endif
2256f9cc9f20SBram Moolenaar 
2257f9cc9f20SBram Moolenaar /*
2258f9cc9f20SBram Moolenaar  * Clear all highlight tables.
2259f9cc9f20SBram Moolenaar  */
2260f9cc9f20SBram Moolenaar     void
2261f9cc9f20SBram Moolenaar clear_hl_tables(void)
2262f9cc9f20SBram Moolenaar {
2263f9cc9f20SBram Moolenaar     int		i;
2264f9cc9f20SBram Moolenaar     attrentry_T	*taep;
2265f9cc9f20SBram Moolenaar 
2266f9cc9f20SBram Moolenaar #ifdef FEAT_GUI
2267f9cc9f20SBram Moolenaar     ga_clear(&gui_attr_table);
2268f9cc9f20SBram Moolenaar #endif
2269f9cc9f20SBram Moolenaar     for (i = 0; i < term_attr_table.ga_len; ++i)
2270f9cc9f20SBram Moolenaar     {
2271f9cc9f20SBram Moolenaar 	taep = &(((attrentry_T *)term_attr_table.ga_data)[i]);
2272f9cc9f20SBram Moolenaar 	vim_free(taep->ae_u.term.start);
2273f9cc9f20SBram Moolenaar 	vim_free(taep->ae_u.term.stop);
2274f9cc9f20SBram Moolenaar     }
2275f9cc9f20SBram Moolenaar     ga_clear(&term_attr_table);
2276f9cc9f20SBram Moolenaar     ga_clear(&cterm_attr_table);
2277f9cc9f20SBram Moolenaar }
2278f9cc9f20SBram Moolenaar 
2279f9cc9f20SBram Moolenaar /*
2280f9cc9f20SBram Moolenaar  * Combine special attributes (e.g., for spelling) with other attributes
2281f9cc9f20SBram Moolenaar  * (e.g., for syntax highlighting).
2282f9cc9f20SBram Moolenaar  * "prim_attr" overrules "char_attr".
2283f9cc9f20SBram Moolenaar  * This creates a new group when required.
2284f9cc9f20SBram Moolenaar  * Since we expect there to be few spelling mistakes we don't cache the
2285f9cc9f20SBram Moolenaar  * result.
2286f9cc9f20SBram Moolenaar  * Return the resulting attributes.
2287f9cc9f20SBram Moolenaar  */
2288f9cc9f20SBram Moolenaar     int
2289f9cc9f20SBram Moolenaar hl_combine_attr(int char_attr, int prim_attr)
2290f9cc9f20SBram Moolenaar {
2291f9cc9f20SBram Moolenaar     attrentry_T *char_aep = NULL;
2292f9cc9f20SBram Moolenaar     attrentry_T *spell_aep;
2293f9cc9f20SBram Moolenaar     attrentry_T new_en;
2294f9cc9f20SBram Moolenaar 
2295f9cc9f20SBram Moolenaar     if (char_attr == 0)
2296f9cc9f20SBram Moolenaar 	return prim_attr;
2297f9cc9f20SBram Moolenaar     if (char_attr <= HL_ALL && prim_attr <= HL_ALL)
2298f9cc9f20SBram Moolenaar 	return ATTR_COMBINE(char_attr, prim_attr);
2299f9cc9f20SBram Moolenaar #ifdef FEAT_GUI
2300f9cc9f20SBram Moolenaar     if (gui.in_use)
2301f9cc9f20SBram Moolenaar     {
2302f9cc9f20SBram Moolenaar 	if (char_attr > HL_ALL)
2303f9cc9f20SBram Moolenaar 	    char_aep = syn_gui_attr2entry(char_attr);
2304f9cc9f20SBram Moolenaar 	if (char_aep != NULL)
2305f9cc9f20SBram Moolenaar 	    new_en = *char_aep;
2306f9cc9f20SBram Moolenaar 	else
2307f9cc9f20SBram Moolenaar 	{
2308f9cc9f20SBram Moolenaar 	    vim_memset(&new_en, 0, sizeof(new_en));
2309f9cc9f20SBram Moolenaar 	    new_en.ae_u.gui.fg_color = INVALCOLOR;
2310f9cc9f20SBram Moolenaar 	    new_en.ae_u.gui.bg_color = INVALCOLOR;
2311f9cc9f20SBram Moolenaar 	    new_en.ae_u.gui.sp_color = INVALCOLOR;
2312f9cc9f20SBram Moolenaar 	    if (char_attr <= HL_ALL)
2313f9cc9f20SBram Moolenaar 		new_en.ae_attr = char_attr;
2314f9cc9f20SBram Moolenaar 	}
2315f9cc9f20SBram Moolenaar 
2316f9cc9f20SBram Moolenaar 	if (prim_attr <= HL_ALL)
2317f9cc9f20SBram Moolenaar 	    new_en.ae_attr = ATTR_COMBINE(new_en.ae_attr, prim_attr);
2318f9cc9f20SBram Moolenaar 	else
2319f9cc9f20SBram Moolenaar 	{
2320f9cc9f20SBram Moolenaar 	    spell_aep = syn_gui_attr2entry(prim_attr);
2321f9cc9f20SBram Moolenaar 	    if (spell_aep != NULL)
2322f9cc9f20SBram Moolenaar 	    {
2323f9cc9f20SBram Moolenaar 		new_en.ae_attr = ATTR_COMBINE(new_en.ae_attr,
2324f9cc9f20SBram Moolenaar 							   spell_aep->ae_attr);
2325f9cc9f20SBram Moolenaar 		if (spell_aep->ae_u.gui.fg_color != INVALCOLOR)
2326f9cc9f20SBram Moolenaar 		    new_en.ae_u.gui.fg_color = spell_aep->ae_u.gui.fg_color;
2327f9cc9f20SBram Moolenaar 		if (spell_aep->ae_u.gui.bg_color != INVALCOLOR)
2328f9cc9f20SBram Moolenaar 		    new_en.ae_u.gui.bg_color = spell_aep->ae_u.gui.bg_color;
2329f9cc9f20SBram Moolenaar 		if (spell_aep->ae_u.gui.sp_color != INVALCOLOR)
2330f9cc9f20SBram Moolenaar 		    new_en.ae_u.gui.sp_color = spell_aep->ae_u.gui.sp_color;
2331f9cc9f20SBram Moolenaar 		if (spell_aep->ae_u.gui.font != NOFONT)
2332f9cc9f20SBram Moolenaar 		    new_en.ae_u.gui.font = spell_aep->ae_u.gui.font;
2333f9cc9f20SBram Moolenaar # ifdef FEAT_XFONTSET
2334f9cc9f20SBram Moolenaar 		if (spell_aep->ae_u.gui.fontset != NOFONTSET)
2335f9cc9f20SBram Moolenaar 		    new_en.ae_u.gui.fontset = spell_aep->ae_u.gui.fontset;
2336f9cc9f20SBram Moolenaar # endif
2337f9cc9f20SBram Moolenaar 	    }
2338f9cc9f20SBram Moolenaar 	}
2339f9cc9f20SBram Moolenaar 	return get_attr_entry(&gui_attr_table, &new_en);
2340f9cc9f20SBram Moolenaar     }
2341f9cc9f20SBram Moolenaar #endif
2342f9cc9f20SBram Moolenaar 
2343f9cc9f20SBram Moolenaar     if (IS_CTERM)
2344f9cc9f20SBram Moolenaar     {
2345f9cc9f20SBram Moolenaar 	if (char_attr > HL_ALL)
2346f9cc9f20SBram Moolenaar 	    char_aep = syn_cterm_attr2entry(char_attr);
2347f9cc9f20SBram Moolenaar 	if (char_aep != NULL)
2348f9cc9f20SBram Moolenaar 	    new_en = *char_aep;
2349f9cc9f20SBram Moolenaar 	else
2350f9cc9f20SBram Moolenaar 	{
2351f9cc9f20SBram Moolenaar 	    vim_memset(&new_en, 0, sizeof(new_en));
2352f9cc9f20SBram Moolenaar #ifdef FEAT_TERMGUICOLORS
2353f9cc9f20SBram Moolenaar 	    new_en.ae_u.cterm.bg_rgb = INVALCOLOR;
2354f9cc9f20SBram Moolenaar 	    new_en.ae_u.cterm.fg_rgb = INVALCOLOR;
2355f9cc9f20SBram Moolenaar #endif
2356f9cc9f20SBram Moolenaar 	    if (char_attr <= HL_ALL)
2357f9cc9f20SBram Moolenaar 		new_en.ae_attr = char_attr;
2358f9cc9f20SBram Moolenaar 	}
2359f9cc9f20SBram Moolenaar 
2360f9cc9f20SBram Moolenaar 	if (prim_attr <= HL_ALL)
2361f9cc9f20SBram Moolenaar 		new_en.ae_attr = ATTR_COMBINE(new_en.ae_attr, prim_attr);
2362f9cc9f20SBram Moolenaar 	else
2363f9cc9f20SBram Moolenaar 	{
2364f9cc9f20SBram Moolenaar 	    spell_aep = syn_cterm_attr2entry(prim_attr);
2365f9cc9f20SBram Moolenaar 	    if (spell_aep != NULL)
2366f9cc9f20SBram Moolenaar 	    {
2367f9cc9f20SBram Moolenaar 		new_en.ae_attr = ATTR_COMBINE(new_en.ae_attr,
2368f9cc9f20SBram Moolenaar 							   spell_aep->ae_attr);
2369f9cc9f20SBram Moolenaar 		if (spell_aep->ae_u.cterm.fg_color > 0)
2370f9cc9f20SBram Moolenaar 		    new_en.ae_u.cterm.fg_color = spell_aep->ae_u.cterm.fg_color;
2371f9cc9f20SBram Moolenaar 		if (spell_aep->ae_u.cterm.bg_color > 0)
2372f9cc9f20SBram Moolenaar 		    new_en.ae_u.cterm.bg_color = spell_aep->ae_u.cterm.bg_color;
2373f9cc9f20SBram Moolenaar #ifdef FEAT_TERMGUICOLORS
2374f9cc9f20SBram Moolenaar 		// If both fg and bg are not set fall back to cterm colors.
2375f9cc9f20SBram Moolenaar 		// Helps for SpellBad which uses undercurl in the GUI.
2376f9cc9f20SBram Moolenaar 		if (COLOR_INVALID(spell_aep->ae_u.cterm.fg_rgb)
2377f9cc9f20SBram Moolenaar 			&& COLOR_INVALID(spell_aep->ae_u.cterm.bg_rgb))
2378f9cc9f20SBram Moolenaar 		{
2379f9cc9f20SBram Moolenaar 		    if (spell_aep->ae_u.cterm.fg_color > 0)
2380f9cc9f20SBram Moolenaar 			new_en.ae_u.cterm.fg_rgb = CTERMCOLOR;
2381f9cc9f20SBram Moolenaar 		    if (spell_aep->ae_u.cterm.bg_color > 0)
2382f9cc9f20SBram Moolenaar 			new_en.ae_u.cterm.bg_rgb = CTERMCOLOR;
2383f9cc9f20SBram Moolenaar 		}
2384f9cc9f20SBram Moolenaar 		else
2385f9cc9f20SBram Moolenaar 		{
2386f9cc9f20SBram Moolenaar 		    if (spell_aep->ae_u.cterm.fg_rgb != INVALCOLOR)
2387f9cc9f20SBram Moolenaar 			new_en.ae_u.cterm.fg_rgb = spell_aep->ae_u.cterm.fg_rgb;
2388f9cc9f20SBram Moolenaar 		    if (spell_aep->ae_u.cterm.bg_rgb != INVALCOLOR)
2389f9cc9f20SBram Moolenaar 			new_en.ae_u.cterm.bg_rgb = spell_aep->ae_u.cterm.bg_rgb;
2390f9cc9f20SBram Moolenaar 		}
2391f9cc9f20SBram Moolenaar #endif
2392f9cc9f20SBram Moolenaar 	    }
2393f9cc9f20SBram Moolenaar 	}
2394f9cc9f20SBram Moolenaar 	return get_attr_entry(&cterm_attr_table, &new_en);
2395f9cc9f20SBram Moolenaar     }
2396f9cc9f20SBram Moolenaar 
2397f9cc9f20SBram Moolenaar     if (char_attr > HL_ALL)
2398f9cc9f20SBram Moolenaar 	char_aep = syn_term_attr2entry(char_attr);
2399f9cc9f20SBram Moolenaar     if (char_aep != NULL)
2400f9cc9f20SBram Moolenaar 	new_en = *char_aep;
2401f9cc9f20SBram Moolenaar     else
2402f9cc9f20SBram Moolenaar     {
2403f9cc9f20SBram Moolenaar 	vim_memset(&new_en, 0, sizeof(new_en));
2404f9cc9f20SBram Moolenaar 	if (char_attr <= HL_ALL)
2405f9cc9f20SBram Moolenaar 	    new_en.ae_attr = char_attr;
2406f9cc9f20SBram Moolenaar     }
2407f9cc9f20SBram Moolenaar 
2408f9cc9f20SBram Moolenaar     if (prim_attr <= HL_ALL)
2409f9cc9f20SBram Moolenaar 	new_en.ae_attr = ATTR_COMBINE(new_en.ae_attr, prim_attr);
2410f9cc9f20SBram Moolenaar     else
2411f9cc9f20SBram Moolenaar     {
2412f9cc9f20SBram Moolenaar 	spell_aep = syn_term_attr2entry(prim_attr);
2413f9cc9f20SBram Moolenaar 	if (spell_aep != NULL)
2414f9cc9f20SBram Moolenaar 	{
2415f9cc9f20SBram Moolenaar 	    new_en.ae_attr = ATTR_COMBINE(new_en.ae_attr, spell_aep->ae_attr);
2416f9cc9f20SBram Moolenaar 	    if (spell_aep->ae_u.term.start != NULL)
2417f9cc9f20SBram Moolenaar 	    {
2418f9cc9f20SBram Moolenaar 		new_en.ae_u.term.start = spell_aep->ae_u.term.start;
2419f9cc9f20SBram Moolenaar 		new_en.ae_u.term.stop = spell_aep->ae_u.term.stop;
2420f9cc9f20SBram Moolenaar 	    }
2421f9cc9f20SBram Moolenaar 	}
2422f9cc9f20SBram Moolenaar     }
2423f9cc9f20SBram Moolenaar     return get_attr_entry(&term_attr_table, &new_en);
2424f9cc9f20SBram Moolenaar }
2425f9cc9f20SBram Moolenaar 
2426f9cc9f20SBram Moolenaar #ifdef FEAT_GUI
2427f9cc9f20SBram Moolenaar     attrentry_T *
2428f9cc9f20SBram Moolenaar syn_gui_attr2entry(int attr)
2429f9cc9f20SBram Moolenaar {
2430f9cc9f20SBram Moolenaar     attr -= ATTR_OFF;
2431f9cc9f20SBram Moolenaar     if (attr >= gui_attr_table.ga_len)	    // did ":syntax clear"
2432f9cc9f20SBram Moolenaar 	return NULL;
2433f9cc9f20SBram Moolenaar     return &(GUI_ATTR_ENTRY(attr));
2434f9cc9f20SBram Moolenaar }
2435f9cc9f20SBram Moolenaar #endif
2436f9cc9f20SBram Moolenaar 
2437f9cc9f20SBram Moolenaar /*
2438f9cc9f20SBram Moolenaar  * Get the highlight attributes (HL_BOLD etc.) from an attribute nr.
2439f9cc9f20SBram Moolenaar  * Only to be used when "attr" > HL_ALL.
2440f9cc9f20SBram Moolenaar  */
2441f9cc9f20SBram Moolenaar     int
2442f9cc9f20SBram Moolenaar syn_attr2attr(int attr)
2443f9cc9f20SBram Moolenaar {
2444f9cc9f20SBram Moolenaar     attrentry_T	*aep;
2445f9cc9f20SBram Moolenaar 
2446f9cc9f20SBram Moolenaar #ifdef FEAT_GUI
2447f9cc9f20SBram Moolenaar     if (gui.in_use)
2448f9cc9f20SBram Moolenaar 	aep = syn_gui_attr2entry(attr);
2449f9cc9f20SBram Moolenaar     else
2450f9cc9f20SBram Moolenaar #endif
2451f9cc9f20SBram Moolenaar 	if (IS_CTERM)
2452f9cc9f20SBram Moolenaar 	    aep = syn_cterm_attr2entry(attr);
2453f9cc9f20SBram Moolenaar 	else
2454f9cc9f20SBram Moolenaar 	    aep = syn_term_attr2entry(attr);
2455f9cc9f20SBram Moolenaar 
2456f9cc9f20SBram Moolenaar     if (aep == NULL)	    // highlighting not set
2457f9cc9f20SBram Moolenaar 	return 0;
2458f9cc9f20SBram Moolenaar     return aep->ae_attr;
2459f9cc9f20SBram Moolenaar }
2460f9cc9f20SBram Moolenaar 
2461f9cc9f20SBram Moolenaar 
2462f9cc9f20SBram Moolenaar     attrentry_T *
2463f9cc9f20SBram Moolenaar syn_term_attr2entry(int attr)
2464f9cc9f20SBram Moolenaar {
2465f9cc9f20SBram Moolenaar     attr -= ATTR_OFF;
2466f9cc9f20SBram Moolenaar     if (attr >= term_attr_table.ga_len)	    // did ":syntax clear"
2467f9cc9f20SBram Moolenaar 	return NULL;
2468f9cc9f20SBram Moolenaar     return &(TERM_ATTR_ENTRY(attr));
2469f9cc9f20SBram Moolenaar }
2470f9cc9f20SBram Moolenaar 
2471f9cc9f20SBram Moolenaar     attrentry_T *
2472f9cc9f20SBram Moolenaar syn_cterm_attr2entry(int attr)
2473f9cc9f20SBram Moolenaar {
2474f9cc9f20SBram Moolenaar     attr -= ATTR_OFF;
2475f9cc9f20SBram Moolenaar     if (attr >= cterm_attr_table.ga_len)	// did ":syntax clear"
2476f9cc9f20SBram Moolenaar 	return NULL;
2477f9cc9f20SBram Moolenaar     return &(CTERM_ATTR_ENTRY(attr));
2478f9cc9f20SBram Moolenaar }
2479f9cc9f20SBram Moolenaar 
2480f9cc9f20SBram Moolenaar #define LIST_ATTR   1
2481f9cc9f20SBram Moolenaar #define LIST_STRING 2
2482f9cc9f20SBram Moolenaar #define LIST_INT    3
2483f9cc9f20SBram Moolenaar 
2484f9cc9f20SBram Moolenaar     static void
2485f9cc9f20SBram Moolenaar highlight_list_one(int id)
2486f9cc9f20SBram Moolenaar {
2487f9cc9f20SBram Moolenaar     hl_group_T	    *sgp;
2488f9cc9f20SBram Moolenaar     int		    didh = FALSE;
2489f9cc9f20SBram Moolenaar 
2490f9cc9f20SBram Moolenaar     sgp = &HL_TABLE()[id - 1];	    // index is ID minus one
2491f9cc9f20SBram Moolenaar 
2492f9cc9f20SBram Moolenaar     if (message_filtered(sgp->sg_name))
2493f9cc9f20SBram Moolenaar 	return;
2494f9cc9f20SBram Moolenaar 
2495f9cc9f20SBram Moolenaar     didh = highlight_list_arg(id, didh, LIST_ATTR,
2496f9cc9f20SBram Moolenaar 				    sgp->sg_term, NULL, "term");
2497f9cc9f20SBram Moolenaar     didh = highlight_list_arg(id, didh, LIST_STRING,
2498f9cc9f20SBram Moolenaar 				    0, sgp->sg_start, "start");
2499f9cc9f20SBram Moolenaar     didh = highlight_list_arg(id, didh, LIST_STRING,
2500f9cc9f20SBram Moolenaar 				    0, sgp->sg_stop, "stop");
2501f9cc9f20SBram Moolenaar 
2502f9cc9f20SBram Moolenaar     didh = highlight_list_arg(id, didh, LIST_ATTR,
2503f9cc9f20SBram Moolenaar 				    sgp->sg_cterm, NULL, "cterm");
2504f9cc9f20SBram Moolenaar     didh = highlight_list_arg(id, didh, LIST_INT,
2505f9cc9f20SBram Moolenaar 				    sgp->sg_cterm_fg, NULL, "ctermfg");
2506f9cc9f20SBram Moolenaar     didh = highlight_list_arg(id, didh, LIST_INT,
2507f9cc9f20SBram Moolenaar 				    sgp->sg_cterm_bg, NULL, "ctermbg");
2508f9cc9f20SBram Moolenaar 
2509f9cc9f20SBram Moolenaar #if defined(FEAT_GUI) || defined(FEAT_EVAL)
2510f9cc9f20SBram Moolenaar     didh = highlight_list_arg(id, didh, LIST_ATTR,
2511f9cc9f20SBram Moolenaar 				    sgp->sg_gui, NULL, "gui");
2512f9cc9f20SBram Moolenaar     didh = highlight_list_arg(id, didh, LIST_STRING,
2513f9cc9f20SBram Moolenaar 				    0, sgp->sg_gui_fg_name, "guifg");
2514f9cc9f20SBram Moolenaar     didh = highlight_list_arg(id, didh, LIST_STRING,
2515f9cc9f20SBram Moolenaar 				    0, sgp->sg_gui_bg_name, "guibg");
2516f9cc9f20SBram Moolenaar     didh = highlight_list_arg(id, didh, LIST_STRING,
2517f9cc9f20SBram Moolenaar 				    0, sgp->sg_gui_sp_name, "guisp");
2518f9cc9f20SBram Moolenaar #endif
2519f9cc9f20SBram Moolenaar #ifdef FEAT_GUI
2520f9cc9f20SBram Moolenaar     didh = highlight_list_arg(id, didh, LIST_STRING,
2521f9cc9f20SBram Moolenaar 				    0, sgp->sg_font_name, "font");
2522f9cc9f20SBram Moolenaar #endif
2523f9cc9f20SBram Moolenaar 
2524f9cc9f20SBram Moolenaar     if (sgp->sg_link && !got_int)
2525f9cc9f20SBram Moolenaar     {
2526f9cc9f20SBram Moolenaar 	(void)syn_list_header(didh, 9999, id);
2527f9cc9f20SBram Moolenaar 	didh = TRUE;
2528f9cc9f20SBram Moolenaar 	msg_puts_attr("links to", HL_ATTR(HLF_D));
2529f9cc9f20SBram Moolenaar 	msg_putchar(' ');
2530f9cc9f20SBram Moolenaar 	msg_outtrans(HL_TABLE()[HL_TABLE()[id - 1].sg_link - 1].sg_name);
2531f9cc9f20SBram Moolenaar     }
2532f9cc9f20SBram Moolenaar 
2533f9cc9f20SBram Moolenaar     if (!didh)
2534f9cc9f20SBram Moolenaar 	highlight_list_arg(id, didh, LIST_STRING, 0, (char_u *)"cleared", "");
2535f9cc9f20SBram Moolenaar #ifdef FEAT_EVAL
2536f9cc9f20SBram Moolenaar     if (p_verbose > 0)
2537f9cc9f20SBram Moolenaar 	last_set_msg(sgp->sg_script_ctx);
2538f9cc9f20SBram Moolenaar #endif
2539f9cc9f20SBram Moolenaar }
2540f9cc9f20SBram Moolenaar 
2541f9cc9f20SBram Moolenaar     static int
2542f9cc9f20SBram Moolenaar highlight_list_arg(
2543f9cc9f20SBram Moolenaar     int		id,
2544f9cc9f20SBram Moolenaar     int		didh,
2545f9cc9f20SBram Moolenaar     int		type,
2546f9cc9f20SBram Moolenaar     int		iarg,
2547f9cc9f20SBram Moolenaar     char_u	*sarg,
2548f9cc9f20SBram Moolenaar     char	*name)
2549f9cc9f20SBram Moolenaar {
2550f9cc9f20SBram Moolenaar     char_u	buf[100];
2551f9cc9f20SBram Moolenaar     char_u	*ts;
2552f9cc9f20SBram Moolenaar     int		i;
2553f9cc9f20SBram Moolenaar 
2554f9cc9f20SBram Moolenaar     if (got_int)
2555f9cc9f20SBram Moolenaar 	return FALSE;
2556f9cc9f20SBram Moolenaar     if (type == LIST_STRING ? (sarg != NULL) : (iarg != 0))
2557f9cc9f20SBram Moolenaar     {
2558f9cc9f20SBram Moolenaar 	ts = buf;
2559f9cc9f20SBram Moolenaar 	if (type == LIST_INT)
2560f9cc9f20SBram Moolenaar 	    sprintf((char *)buf, "%d", iarg - 1);
2561f9cc9f20SBram Moolenaar 	else if (type == LIST_STRING)
2562f9cc9f20SBram Moolenaar 	    ts = sarg;
2563f9cc9f20SBram Moolenaar 	else // type == LIST_ATTR
2564f9cc9f20SBram Moolenaar 	{
2565f9cc9f20SBram Moolenaar 	    buf[0] = NUL;
2566f9cc9f20SBram Moolenaar 	    for (i = 0; hl_attr_table[i] != 0; ++i)
2567f9cc9f20SBram Moolenaar 	    {
2568f9cc9f20SBram Moolenaar 		if (iarg & hl_attr_table[i])
2569f9cc9f20SBram Moolenaar 		{
2570f9cc9f20SBram Moolenaar 		    if (buf[0] != NUL)
2571f9cc9f20SBram Moolenaar 			vim_strcat(buf, (char_u *)",", 100);
2572f9cc9f20SBram Moolenaar 		    vim_strcat(buf, (char_u *)hl_name_table[i], 100);
2573f9cc9f20SBram Moolenaar 		    iarg &= ~hl_attr_table[i];	    // don't want "inverse"
2574f9cc9f20SBram Moolenaar 		}
2575f9cc9f20SBram Moolenaar 	    }
2576f9cc9f20SBram Moolenaar 	}
2577f9cc9f20SBram Moolenaar 
2578f9cc9f20SBram Moolenaar 	(void)syn_list_header(didh,
2579f9cc9f20SBram Moolenaar 			       (int)(vim_strsize(ts) + STRLEN(name) + 1), id);
2580f9cc9f20SBram Moolenaar 	didh = TRUE;
2581f9cc9f20SBram Moolenaar 	if (!got_int)
2582f9cc9f20SBram Moolenaar 	{
2583f9cc9f20SBram Moolenaar 	    if (*name != NUL)
2584f9cc9f20SBram Moolenaar 	    {
2585f9cc9f20SBram Moolenaar 		msg_puts_attr(name, HL_ATTR(HLF_D));
2586f9cc9f20SBram Moolenaar 		msg_puts_attr("=", HL_ATTR(HLF_D));
2587f9cc9f20SBram Moolenaar 	    }
2588f9cc9f20SBram Moolenaar 	    msg_outtrans(ts);
2589f9cc9f20SBram Moolenaar 	}
2590f9cc9f20SBram Moolenaar     }
2591f9cc9f20SBram Moolenaar     return didh;
2592f9cc9f20SBram Moolenaar }
2593f9cc9f20SBram Moolenaar 
2594f9cc9f20SBram Moolenaar #if (((defined(FEAT_EVAL) || defined(FEAT_PRINTER))) && defined(FEAT_SYN_HL)) || defined(PROTO)
2595f9cc9f20SBram Moolenaar /*
2596f9cc9f20SBram Moolenaar  * Return "1" if highlight group "id" has attribute "flag".
2597f9cc9f20SBram Moolenaar  * Return NULL otherwise.
2598f9cc9f20SBram Moolenaar  */
2599f9cc9f20SBram Moolenaar     char_u *
2600f9cc9f20SBram Moolenaar highlight_has_attr(
2601f9cc9f20SBram Moolenaar     int		id,
2602f9cc9f20SBram Moolenaar     int		flag,
2603f9cc9f20SBram Moolenaar     int		modec)	// 'g' for GUI, 'c' for cterm, 't' for term
2604f9cc9f20SBram Moolenaar {
2605f9cc9f20SBram Moolenaar     int		attr;
2606f9cc9f20SBram Moolenaar 
2607f9cc9f20SBram Moolenaar     if (id <= 0 || id > highlight_ga.ga_len)
2608f9cc9f20SBram Moolenaar 	return NULL;
2609f9cc9f20SBram Moolenaar 
2610f9cc9f20SBram Moolenaar #if defined(FEAT_GUI) || defined(FEAT_EVAL)
2611f9cc9f20SBram Moolenaar     if (modec == 'g')
2612f9cc9f20SBram Moolenaar 	attr = HL_TABLE()[id - 1].sg_gui;
2613f9cc9f20SBram Moolenaar     else
2614f9cc9f20SBram Moolenaar #endif
2615f9cc9f20SBram Moolenaar 	 if (modec == 'c')
2616f9cc9f20SBram Moolenaar 	attr = HL_TABLE()[id - 1].sg_cterm;
2617f9cc9f20SBram Moolenaar     else
2618f9cc9f20SBram Moolenaar 	attr = HL_TABLE()[id - 1].sg_term;
2619f9cc9f20SBram Moolenaar 
2620f9cc9f20SBram Moolenaar     if (attr & flag)
2621f9cc9f20SBram Moolenaar 	return (char_u *)"1";
2622f9cc9f20SBram Moolenaar     return NULL;
2623f9cc9f20SBram Moolenaar }
2624f9cc9f20SBram Moolenaar #endif
2625f9cc9f20SBram Moolenaar 
2626f9cc9f20SBram Moolenaar #if (defined(FEAT_SYN_HL) && defined(FEAT_EVAL)) || defined(PROTO)
2627f9cc9f20SBram Moolenaar /*
2628f9cc9f20SBram Moolenaar  * Return color name of highlight group "id".
2629f9cc9f20SBram Moolenaar  */
2630f9cc9f20SBram Moolenaar     char_u *
2631f9cc9f20SBram Moolenaar highlight_color(
2632f9cc9f20SBram Moolenaar     int		id,
2633f9cc9f20SBram Moolenaar     char_u	*what,	// "font", "fg", "bg", "sp", "fg#", "bg#" or "sp#"
2634f9cc9f20SBram Moolenaar     int		modec)	// 'g' for GUI, 'c' for cterm, 't' for term
2635f9cc9f20SBram Moolenaar {
2636f9cc9f20SBram Moolenaar     static char_u	name[20];
2637f9cc9f20SBram Moolenaar     int			n;
2638f9cc9f20SBram Moolenaar     int			fg = FALSE;
2639f9cc9f20SBram Moolenaar     int			sp = FALSE;
2640f9cc9f20SBram Moolenaar     int			font = FALSE;
2641f9cc9f20SBram Moolenaar 
2642f9cc9f20SBram Moolenaar     if (id <= 0 || id > highlight_ga.ga_len)
2643f9cc9f20SBram Moolenaar 	return NULL;
2644f9cc9f20SBram Moolenaar 
2645f9cc9f20SBram Moolenaar     if (TOLOWER_ASC(what[0]) == 'f' && TOLOWER_ASC(what[1]) == 'g')
2646f9cc9f20SBram Moolenaar 	fg = TRUE;
2647f9cc9f20SBram Moolenaar     else if (TOLOWER_ASC(what[0]) == 'f' && TOLOWER_ASC(what[1]) == 'o'
2648f9cc9f20SBram Moolenaar 	     && TOLOWER_ASC(what[2]) == 'n' && TOLOWER_ASC(what[3]) == 't')
2649f9cc9f20SBram Moolenaar 	font = TRUE;
2650f9cc9f20SBram Moolenaar     else if (TOLOWER_ASC(what[0]) == 's' && TOLOWER_ASC(what[1]) == 'p')
2651f9cc9f20SBram Moolenaar 	sp = TRUE;
2652f9cc9f20SBram Moolenaar     else if (!(TOLOWER_ASC(what[0]) == 'b' && TOLOWER_ASC(what[1]) == 'g'))
2653f9cc9f20SBram Moolenaar 	return NULL;
2654f9cc9f20SBram Moolenaar     if (modec == 'g')
2655f9cc9f20SBram Moolenaar     {
2656f9cc9f20SBram Moolenaar # if defined(FEAT_GUI) || defined(FEAT_TERMGUICOLORS)
2657f9cc9f20SBram Moolenaar #  ifdef FEAT_GUI
2658f9cc9f20SBram Moolenaar 	// return font name
2659f9cc9f20SBram Moolenaar 	if (font)
2660f9cc9f20SBram Moolenaar 	    return HL_TABLE()[id - 1].sg_font_name;
2661f9cc9f20SBram Moolenaar #  endif
2662f9cc9f20SBram Moolenaar 
2663f9cc9f20SBram Moolenaar 	// return #RRGGBB form (only possible when GUI is running)
2664f9cc9f20SBram Moolenaar 	if ((USE_24BIT) && what[2] == '#')
2665f9cc9f20SBram Moolenaar 	{
2666f9cc9f20SBram Moolenaar 	    guicolor_T		color;
2667f9cc9f20SBram Moolenaar 	    long_u		rgb;
2668f9cc9f20SBram Moolenaar 	    static char_u	buf[10];
2669f9cc9f20SBram Moolenaar 
2670f9cc9f20SBram Moolenaar 	    if (fg)
2671f9cc9f20SBram Moolenaar 		color = HL_TABLE()[id - 1].sg_gui_fg;
2672f9cc9f20SBram Moolenaar 	    else if (sp)
2673f9cc9f20SBram Moolenaar #  ifdef FEAT_GUI
2674f9cc9f20SBram Moolenaar 		color = HL_TABLE()[id - 1].sg_gui_sp;
2675f9cc9f20SBram Moolenaar #  else
2676f9cc9f20SBram Moolenaar 		color = INVALCOLOR;
2677f9cc9f20SBram Moolenaar #  endif
2678f9cc9f20SBram Moolenaar 	    else
2679f9cc9f20SBram Moolenaar 		color = HL_TABLE()[id - 1].sg_gui_bg;
2680f9cc9f20SBram Moolenaar 	    if (color == INVALCOLOR)
2681f9cc9f20SBram Moolenaar 		return NULL;
2682f9cc9f20SBram Moolenaar 	    rgb = (long_u)GUI_MCH_GET_RGB(color);
2683f9cc9f20SBram Moolenaar 	    sprintf((char *)buf, "#%02x%02x%02x",
2684f9cc9f20SBram Moolenaar 				      (unsigned)(rgb >> 16),
2685f9cc9f20SBram Moolenaar 				      (unsigned)(rgb >> 8) & 255,
2686f9cc9f20SBram Moolenaar 				      (unsigned)rgb & 255);
2687f9cc9f20SBram Moolenaar 	    return buf;
2688f9cc9f20SBram Moolenaar 	}
2689f9cc9f20SBram Moolenaar # endif
2690f9cc9f20SBram Moolenaar 	if (fg)
2691f9cc9f20SBram Moolenaar 	    return (HL_TABLE()[id - 1].sg_gui_fg_name);
2692f9cc9f20SBram Moolenaar 	if (sp)
2693f9cc9f20SBram Moolenaar 	    return (HL_TABLE()[id - 1].sg_gui_sp_name);
2694f9cc9f20SBram Moolenaar 	return (HL_TABLE()[id - 1].sg_gui_bg_name);
2695f9cc9f20SBram Moolenaar     }
2696f9cc9f20SBram Moolenaar     if (font || sp)
2697f9cc9f20SBram Moolenaar 	return NULL;
2698f9cc9f20SBram Moolenaar     if (modec == 'c')
2699f9cc9f20SBram Moolenaar     {
2700f9cc9f20SBram Moolenaar 	if (fg)
2701f9cc9f20SBram Moolenaar 	    n = HL_TABLE()[id - 1].sg_cterm_fg - 1;
2702f9cc9f20SBram Moolenaar 	else
2703f9cc9f20SBram Moolenaar 	    n = HL_TABLE()[id - 1].sg_cterm_bg - 1;
2704f9cc9f20SBram Moolenaar 	if (n < 0)
2705f9cc9f20SBram Moolenaar 	    return NULL;
2706f9cc9f20SBram Moolenaar 	sprintf((char *)name, "%d", n);
2707f9cc9f20SBram Moolenaar 	return name;
2708f9cc9f20SBram Moolenaar     }
2709f9cc9f20SBram Moolenaar     // term doesn't have color
2710f9cc9f20SBram Moolenaar     return NULL;
2711f9cc9f20SBram Moolenaar }
2712f9cc9f20SBram Moolenaar #endif
2713f9cc9f20SBram Moolenaar 
2714f9cc9f20SBram Moolenaar #if (defined(FEAT_SYN_HL) \
2715f9cc9f20SBram Moolenaar 	    && (defined(FEAT_GUI) || defined(FEAT_TERMGUICOLORS)) \
2716f9cc9f20SBram Moolenaar 	&& defined(FEAT_PRINTER)) || defined(PROTO)
2717f9cc9f20SBram Moolenaar /*
2718f9cc9f20SBram Moolenaar  * Return color name of highlight group "id" as RGB value.
2719f9cc9f20SBram Moolenaar  */
2720f9cc9f20SBram Moolenaar     long_u
2721f9cc9f20SBram Moolenaar highlight_gui_color_rgb(
2722f9cc9f20SBram Moolenaar     int		id,
2723f9cc9f20SBram Moolenaar     int		fg)	// TRUE = fg, FALSE = bg
2724f9cc9f20SBram Moolenaar {
2725f9cc9f20SBram Moolenaar     guicolor_T	color;
2726f9cc9f20SBram Moolenaar 
2727f9cc9f20SBram Moolenaar     if (id <= 0 || id > highlight_ga.ga_len)
2728f9cc9f20SBram Moolenaar 	return 0L;
2729f9cc9f20SBram Moolenaar 
2730f9cc9f20SBram Moolenaar     if (fg)
2731f9cc9f20SBram Moolenaar 	color = HL_TABLE()[id - 1].sg_gui_fg;
2732f9cc9f20SBram Moolenaar     else
2733f9cc9f20SBram Moolenaar 	color = HL_TABLE()[id - 1].sg_gui_bg;
2734f9cc9f20SBram Moolenaar 
2735f9cc9f20SBram Moolenaar     if (color == INVALCOLOR)
2736f9cc9f20SBram Moolenaar 	return 0L;
2737f9cc9f20SBram Moolenaar 
2738f9cc9f20SBram Moolenaar     return GUI_MCH_GET_RGB(color);
2739f9cc9f20SBram Moolenaar }
2740f9cc9f20SBram Moolenaar #endif
2741f9cc9f20SBram Moolenaar 
2742f9cc9f20SBram Moolenaar /*
2743f9cc9f20SBram Moolenaar  * Output the syntax list header.
2744f9cc9f20SBram Moolenaar  * Return TRUE when started a new line.
2745f9cc9f20SBram Moolenaar  */
2746f9cc9f20SBram Moolenaar     int
2747f9cc9f20SBram Moolenaar syn_list_header(
2748f9cc9f20SBram Moolenaar     int	    did_header,		// did header already
2749f9cc9f20SBram Moolenaar     int	    outlen,		// length of string that comes
2750f9cc9f20SBram Moolenaar     int	    id)			// highlight group id
2751f9cc9f20SBram Moolenaar {
2752f9cc9f20SBram Moolenaar     int	    endcol = 19;
2753f9cc9f20SBram Moolenaar     int	    newline = TRUE;
2754f9cc9f20SBram Moolenaar     int	    name_col = 0;
2755f9cc9f20SBram Moolenaar 
2756f9cc9f20SBram Moolenaar     if (!did_header)
2757f9cc9f20SBram Moolenaar     {
2758f9cc9f20SBram Moolenaar 	msg_putchar('\n');
2759f9cc9f20SBram Moolenaar 	if (got_int)
2760f9cc9f20SBram Moolenaar 	    return TRUE;
2761f9cc9f20SBram Moolenaar 	msg_outtrans(HL_TABLE()[id - 1].sg_name);
2762f9cc9f20SBram Moolenaar 	name_col = msg_col;
2763f9cc9f20SBram Moolenaar 	endcol = 15;
2764f9cc9f20SBram Moolenaar     }
2765f9cc9f20SBram Moolenaar     else if (msg_col + outlen + 1 >= Columns)
2766f9cc9f20SBram Moolenaar     {
2767f9cc9f20SBram Moolenaar 	msg_putchar('\n');
2768f9cc9f20SBram Moolenaar 	if (got_int)
2769f9cc9f20SBram Moolenaar 	    return TRUE;
2770f9cc9f20SBram Moolenaar     }
2771f9cc9f20SBram Moolenaar     else
2772f9cc9f20SBram Moolenaar     {
2773f9cc9f20SBram Moolenaar 	if (msg_col >= endcol)	// wrap around is like starting a new line
2774f9cc9f20SBram Moolenaar 	    newline = FALSE;
2775f9cc9f20SBram Moolenaar     }
2776f9cc9f20SBram Moolenaar 
2777f9cc9f20SBram Moolenaar     if (msg_col >= endcol)	// output at least one space
2778f9cc9f20SBram Moolenaar 	endcol = msg_col + 1;
2779f9cc9f20SBram Moolenaar     if (Columns <= endcol)	// avoid hang for tiny window
2780f9cc9f20SBram Moolenaar 	endcol = Columns - 1;
2781f9cc9f20SBram Moolenaar 
2782f9cc9f20SBram Moolenaar     msg_advance(endcol);
2783f9cc9f20SBram Moolenaar 
2784f9cc9f20SBram Moolenaar     // Show "xxx" with the attributes.
2785f9cc9f20SBram Moolenaar     if (!did_header)
2786f9cc9f20SBram Moolenaar     {
2787f9cc9f20SBram Moolenaar 	if (endcol == Columns - 1 && endcol <= name_col)
2788f9cc9f20SBram Moolenaar 	    msg_putchar(' ');
2789f9cc9f20SBram Moolenaar 	msg_puts_attr("xxx", syn_id2attr(id));
2790f9cc9f20SBram Moolenaar 	msg_putchar(' ');
2791f9cc9f20SBram Moolenaar     }
2792f9cc9f20SBram Moolenaar 
2793f9cc9f20SBram Moolenaar     return newline;
2794f9cc9f20SBram Moolenaar }
2795f9cc9f20SBram Moolenaar 
2796f9cc9f20SBram Moolenaar /*
2797f9cc9f20SBram Moolenaar  * Set the attribute numbers for a highlight group.
2798f9cc9f20SBram Moolenaar  * Called after one of the attributes has changed.
2799f9cc9f20SBram Moolenaar  */
2800f9cc9f20SBram Moolenaar     static void
2801f9cc9f20SBram Moolenaar set_hl_attr(
2802f9cc9f20SBram Moolenaar     int		idx)	    // index in array
2803f9cc9f20SBram Moolenaar {
2804f9cc9f20SBram Moolenaar     attrentry_T	    at_en;
2805f9cc9f20SBram Moolenaar     hl_group_T	    *sgp = HL_TABLE() + idx;
2806f9cc9f20SBram Moolenaar 
2807f9cc9f20SBram Moolenaar     // The "Normal" group doesn't need an attribute number
2808f9cc9f20SBram Moolenaar     if (sgp->sg_name_u != NULL && STRCMP(sgp->sg_name_u, "NORMAL") == 0)
2809f9cc9f20SBram Moolenaar 	return;
2810f9cc9f20SBram Moolenaar 
2811f9cc9f20SBram Moolenaar #ifdef FEAT_GUI
2812f9cc9f20SBram Moolenaar     /*
2813f9cc9f20SBram Moolenaar      * For the GUI mode: If there are other than "normal" highlighting
2814f9cc9f20SBram Moolenaar      * attributes, need to allocate an attr number.
2815f9cc9f20SBram Moolenaar      */
2816f9cc9f20SBram Moolenaar     if (sgp->sg_gui_fg == INVALCOLOR
2817f9cc9f20SBram Moolenaar 	    && sgp->sg_gui_bg == INVALCOLOR
2818f9cc9f20SBram Moolenaar 	    && sgp->sg_gui_sp == INVALCOLOR
2819f9cc9f20SBram Moolenaar 	    && sgp->sg_font == NOFONT
2820f9cc9f20SBram Moolenaar # ifdef FEAT_XFONTSET
2821f9cc9f20SBram Moolenaar 	    && sgp->sg_fontset == NOFONTSET
2822f9cc9f20SBram Moolenaar # endif
2823f9cc9f20SBram Moolenaar 	    )
2824f9cc9f20SBram Moolenaar     {
2825f9cc9f20SBram Moolenaar 	sgp->sg_gui_attr = sgp->sg_gui;
2826f9cc9f20SBram Moolenaar     }
2827f9cc9f20SBram Moolenaar     else
2828f9cc9f20SBram Moolenaar     {
2829f9cc9f20SBram Moolenaar 	at_en.ae_attr = sgp->sg_gui;
2830f9cc9f20SBram Moolenaar 	at_en.ae_u.gui.fg_color = sgp->sg_gui_fg;
2831f9cc9f20SBram Moolenaar 	at_en.ae_u.gui.bg_color = sgp->sg_gui_bg;
2832f9cc9f20SBram Moolenaar 	at_en.ae_u.gui.sp_color = sgp->sg_gui_sp;
2833f9cc9f20SBram Moolenaar 	at_en.ae_u.gui.font = sgp->sg_font;
2834f9cc9f20SBram Moolenaar # ifdef FEAT_XFONTSET
2835f9cc9f20SBram Moolenaar 	at_en.ae_u.gui.fontset = sgp->sg_fontset;
2836f9cc9f20SBram Moolenaar # endif
2837f9cc9f20SBram Moolenaar 	sgp->sg_gui_attr = get_attr_entry(&gui_attr_table, &at_en);
2838f9cc9f20SBram Moolenaar     }
2839f9cc9f20SBram Moolenaar #endif
2840f9cc9f20SBram Moolenaar     /*
2841f9cc9f20SBram Moolenaar      * For the term mode: If there are other than "normal" highlighting
2842f9cc9f20SBram Moolenaar      * attributes, need to allocate an attr number.
2843f9cc9f20SBram Moolenaar      */
2844f9cc9f20SBram Moolenaar     if (sgp->sg_start == NULL && sgp->sg_stop == NULL)
2845f9cc9f20SBram Moolenaar 	sgp->sg_term_attr = sgp->sg_term;
2846f9cc9f20SBram Moolenaar     else
2847f9cc9f20SBram Moolenaar     {
2848f9cc9f20SBram Moolenaar 	at_en.ae_attr = sgp->sg_term;
2849f9cc9f20SBram Moolenaar 	at_en.ae_u.term.start = sgp->sg_start;
2850f9cc9f20SBram Moolenaar 	at_en.ae_u.term.stop = sgp->sg_stop;
2851f9cc9f20SBram Moolenaar 	sgp->sg_term_attr = get_attr_entry(&term_attr_table, &at_en);
2852f9cc9f20SBram Moolenaar     }
2853f9cc9f20SBram Moolenaar 
2854f9cc9f20SBram Moolenaar     /*
2855f9cc9f20SBram Moolenaar      * For the color term mode: If there are other than "normal"
2856f9cc9f20SBram Moolenaar      * highlighting attributes, need to allocate an attr number.
2857f9cc9f20SBram Moolenaar      */
2858f9cc9f20SBram Moolenaar     if (sgp->sg_cterm_fg == 0 && sgp->sg_cterm_bg == 0
2859f9cc9f20SBram Moolenaar # ifdef FEAT_TERMGUICOLORS
2860f9cc9f20SBram Moolenaar 	    && sgp->sg_gui_fg == INVALCOLOR
2861f9cc9f20SBram Moolenaar 	    && sgp->sg_gui_bg == INVALCOLOR
2862f9cc9f20SBram Moolenaar # endif
2863f9cc9f20SBram Moolenaar 	    )
2864f9cc9f20SBram Moolenaar 	sgp->sg_cterm_attr = sgp->sg_cterm;
2865f9cc9f20SBram Moolenaar     else
2866f9cc9f20SBram Moolenaar     {
2867f9cc9f20SBram Moolenaar 	at_en.ae_attr = sgp->sg_cterm;
2868f9cc9f20SBram Moolenaar 	at_en.ae_u.cterm.fg_color = sgp->sg_cterm_fg;
2869f9cc9f20SBram Moolenaar 	at_en.ae_u.cterm.bg_color = sgp->sg_cterm_bg;
2870f9cc9f20SBram Moolenaar # ifdef FEAT_TERMGUICOLORS
2871f9cc9f20SBram Moolenaar #  ifdef MSWIN
2872f9cc9f20SBram Moolenaar #   ifdef VIMDLL
2873f9cc9f20SBram Moolenaar 	// Only when not using the GUI.
2874f9cc9f20SBram Moolenaar 	if (!gui.in_use && !gui.starting)
2875f9cc9f20SBram Moolenaar #   endif
2876f9cc9f20SBram Moolenaar 	{
2877f9cc9f20SBram Moolenaar 	    int id;
2878f9cc9f20SBram Moolenaar 	    guicolor_T fg, bg;
2879f9cc9f20SBram Moolenaar 
2880f9cc9f20SBram Moolenaar 	    id = syn_name2id((char_u *)"Normal");
2881f9cc9f20SBram Moolenaar 	    if (id > 0)
2882f9cc9f20SBram Moolenaar 	    {
2883f9cc9f20SBram Moolenaar 		syn_id2colors(id, &fg, &bg);
2884f9cc9f20SBram Moolenaar 		if (sgp->sg_gui_fg == INVALCOLOR)
2885f9cc9f20SBram Moolenaar 		    sgp->sg_gui_fg = fg;
2886f9cc9f20SBram Moolenaar 		if (sgp->sg_gui_bg == INVALCOLOR)
2887f9cc9f20SBram Moolenaar 		    sgp->sg_gui_bg = bg;
2888f9cc9f20SBram Moolenaar 	    }
2889f9cc9f20SBram Moolenaar 
2890f9cc9f20SBram Moolenaar 	}
2891f9cc9f20SBram Moolenaar #  endif
2892f9cc9f20SBram Moolenaar 	at_en.ae_u.cterm.fg_rgb = GUI_MCH_GET_RGB2(sgp->sg_gui_fg);
2893f9cc9f20SBram Moolenaar 	at_en.ae_u.cterm.bg_rgb = GUI_MCH_GET_RGB2(sgp->sg_gui_bg);
2894f9cc9f20SBram Moolenaar 	if (at_en.ae_u.cterm.fg_rgb == INVALCOLOR
2895f9cc9f20SBram Moolenaar 		&& at_en.ae_u.cterm.bg_rgb == INVALCOLOR)
2896f9cc9f20SBram Moolenaar 	{
2897f9cc9f20SBram Moolenaar 	    // If both fg and bg are invalid fall back to the cterm colors.
2898f9cc9f20SBram Moolenaar 	    // Helps when the GUI only uses an attribute, e.g. undercurl.
2899f9cc9f20SBram Moolenaar 	    at_en.ae_u.cterm.fg_rgb = CTERMCOLOR;
2900f9cc9f20SBram Moolenaar 	    at_en.ae_u.cterm.bg_rgb = CTERMCOLOR;
2901f9cc9f20SBram Moolenaar 	}
2902f9cc9f20SBram Moolenaar # endif
2903f9cc9f20SBram Moolenaar 	sgp->sg_cterm_attr = get_attr_entry(&cterm_attr_table, &at_en);
2904f9cc9f20SBram Moolenaar     }
2905f9cc9f20SBram Moolenaar }
2906f9cc9f20SBram Moolenaar 
2907f9cc9f20SBram Moolenaar /*
2908f9cc9f20SBram Moolenaar  * Lookup a highlight group name and return its ID.
2909f9cc9f20SBram Moolenaar  * If it is not found, 0 is returned.
2910f9cc9f20SBram Moolenaar  */
2911f9cc9f20SBram Moolenaar     int
2912f9cc9f20SBram Moolenaar syn_name2id(char_u *name)
2913f9cc9f20SBram Moolenaar {
2914f9cc9f20SBram Moolenaar     int		i;
2915f9cc9f20SBram Moolenaar     char_u	name_u[200];
2916f9cc9f20SBram Moolenaar 
2917f9cc9f20SBram Moolenaar     // Avoid using stricmp() too much, it's slow on some systems
2918f9cc9f20SBram Moolenaar     // Avoid alloc()/free(), these are slow too.  ID names over 200 chars
2919f9cc9f20SBram Moolenaar     // don't deserve to be found!
2920f9cc9f20SBram Moolenaar     vim_strncpy(name_u, name, 199);
2921f9cc9f20SBram Moolenaar     vim_strup(name_u);
2922f9cc9f20SBram Moolenaar     for (i = highlight_ga.ga_len; --i >= 0; )
2923f9cc9f20SBram Moolenaar 	if (HL_TABLE()[i].sg_name_u != NULL
2924f9cc9f20SBram Moolenaar 		&& STRCMP(name_u, HL_TABLE()[i].sg_name_u) == 0)
2925f9cc9f20SBram Moolenaar 	    break;
2926f9cc9f20SBram Moolenaar     return i + 1;
2927f9cc9f20SBram Moolenaar }
2928f9cc9f20SBram Moolenaar 
2929f9cc9f20SBram Moolenaar /*
2930f9cc9f20SBram Moolenaar  * Lookup a highlight group name and return its attributes.
2931f9cc9f20SBram Moolenaar  * Return zero if not found.
2932f9cc9f20SBram Moolenaar  */
2933f9cc9f20SBram Moolenaar     int
2934f9cc9f20SBram Moolenaar syn_name2attr(char_u *name)
2935f9cc9f20SBram Moolenaar {
2936f9cc9f20SBram Moolenaar     int id = syn_name2id(name);
2937f9cc9f20SBram Moolenaar 
2938f9cc9f20SBram Moolenaar     if (id != 0)
2939f9cc9f20SBram Moolenaar 	return syn_id2attr(id);
2940f9cc9f20SBram Moolenaar     return 0;
2941f9cc9f20SBram Moolenaar }
2942f9cc9f20SBram Moolenaar 
2943f9cc9f20SBram Moolenaar #if defined(FEAT_EVAL) || defined(PROTO)
2944f9cc9f20SBram Moolenaar /*
2945f9cc9f20SBram Moolenaar  * Return TRUE if highlight group "name" exists.
2946f9cc9f20SBram Moolenaar  */
2947f9cc9f20SBram Moolenaar     int
2948f9cc9f20SBram Moolenaar highlight_exists(char_u *name)
2949f9cc9f20SBram Moolenaar {
2950f9cc9f20SBram Moolenaar     return (syn_name2id(name) > 0);
2951f9cc9f20SBram Moolenaar }
2952f9cc9f20SBram Moolenaar 
2953f9cc9f20SBram Moolenaar # if defined(FEAT_SEARCH_EXTRA) || defined(PROTO)
2954f9cc9f20SBram Moolenaar /*
2955f9cc9f20SBram Moolenaar  * Return the name of highlight group "id".
2956f9cc9f20SBram Moolenaar  * When not a valid ID return an empty string.
2957f9cc9f20SBram Moolenaar  */
2958f9cc9f20SBram Moolenaar     char_u *
2959f9cc9f20SBram Moolenaar syn_id2name(int id)
2960f9cc9f20SBram Moolenaar {
2961f9cc9f20SBram Moolenaar     if (id <= 0 || id > highlight_ga.ga_len)
2962f9cc9f20SBram Moolenaar 	return (char_u *)"";
2963f9cc9f20SBram Moolenaar     return HL_TABLE()[id - 1].sg_name;
2964f9cc9f20SBram Moolenaar }
2965f9cc9f20SBram Moolenaar # endif
2966f9cc9f20SBram Moolenaar #endif
2967f9cc9f20SBram Moolenaar 
2968f9cc9f20SBram Moolenaar /*
2969f9cc9f20SBram Moolenaar  * Like syn_name2id(), but take a pointer + length argument.
2970f9cc9f20SBram Moolenaar  */
2971f9cc9f20SBram Moolenaar     int
2972f9cc9f20SBram Moolenaar syn_namen2id(char_u *linep, int len)
2973f9cc9f20SBram Moolenaar {
2974f9cc9f20SBram Moolenaar     char_u  *name;
2975f9cc9f20SBram Moolenaar     int	    id = 0;
2976f9cc9f20SBram Moolenaar 
2977f9cc9f20SBram Moolenaar     name = vim_strnsave(linep, len);
2978f9cc9f20SBram Moolenaar     if (name != NULL)
2979f9cc9f20SBram Moolenaar     {
2980f9cc9f20SBram Moolenaar 	id = syn_name2id(name);
2981f9cc9f20SBram Moolenaar 	vim_free(name);
2982f9cc9f20SBram Moolenaar     }
2983f9cc9f20SBram Moolenaar     return id;
2984f9cc9f20SBram Moolenaar }
2985f9cc9f20SBram Moolenaar 
2986f9cc9f20SBram Moolenaar /*
2987f9cc9f20SBram Moolenaar  * Find highlight group name in the table and return its ID.
2988f9cc9f20SBram Moolenaar  * The argument is a pointer to the name and the length of the name.
2989f9cc9f20SBram Moolenaar  * If it doesn't exist yet, a new entry is created.
2990f9cc9f20SBram Moolenaar  * Return 0 for failure.
2991f9cc9f20SBram Moolenaar  */
2992f9cc9f20SBram Moolenaar     int
2993f9cc9f20SBram Moolenaar syn_check_group(char_u *pp, int len)
2994f9cc9f20SBram Moolenaar {
2995f9cc9f20SBram Moolenaar     int	    id;
2996f9cc9f20SBram Moolenaar     char_u  *name;
2997f9cc9f20SBram Moolenaar 
2998f9cc9f20SBram Moolenaar     name = vim_strnsave(pp, len);
2999f9cc9f20SBram Moolenaar     if (name == NULL)
3000f9cc9f20SBram Moolenaar 	return 0;
3001f9cc9f20SBram Moolenaar 
3002f9cc9f20SBram Moolenaar     id = syn_name2id(name);
3003f9cc9f20SBram Moolenaar     if (id == 0)			// doesn't exist yet
3004f9cc9f20SBram Moolenaar 	id = syn_add_group(name);
3005f9cc9f20SBram Moolenaar     else
3006f9cc9f20SBram Moolenaar 	vim_free(name);
3007f9cc9f20SBram Moolenaar     return id;
3008f9cc9f20SBram Moolenaar }
3009f9cc9f20SBram Moolenaar 
3010f9cc9f20SBram Moolenaar /*
3011f9cc9f20SBram Moolenaar  * Add new highlight group and return its ID.
3012f9cc9f20SBram Moolenaar  * "name" must be an allocated string, it will be consumed.
3013f9cc9f20SBram Moolenaar  * Return 0 for failure.
3014f9cc9f20SBram Moolenaar  */
3015f9cc9f20SBram Moolenaar     static int
3016f9cc9f20SBram Moolenaar syn_add_group(char_u *name)
3017f9cc9f20SBram Moolenaar {
3018f9cc9f20SBram Moolenaar     char_u	*p;
3019f9cc9f20SBram Moolenaar 
3020f9cc9f20SBram Moolenaar     // Check that the name is ASCII letters, digits and underscore.
3021f9cc9f20SBram Moolenaar     for (p = name; *p != NUL; ++p)
3022f9cc9f20SBram Moolenaar     {
3023f9cc9f20SBram Moolenaar 	if (!vim_isprintc(*p))
3024f9cc9f20SBram Moolenaar 	{
3025f9cc9f20SBram Moolenaar 	    emsg(_("E669: Unprintable character in group name"));
3026f9cc9f20SBram Moolenaar 	    vim_free(name);
3027f9cc9f20SBram Moolenaar 	    return 0;
3028f9cc9f20SBram Moolenaar 	}
3029f9cc9f20SBram Moolenaar 	else if (!ASCII_ISALNUM(*p) && *p != '_')
3030f9cc9f20SBram Moolenaar 	{
3031f9cc9f20SBram Moolenaar 	    // This is an error, but since there previously was no check only
3032f9cc9f20SBram Moolenaar 	    // give a warning.
3033f9cc9f20SBram Moolenaar 	    msg_source(HL_ATTR(HLF_W));
3034f9cc9f20SBram Moolenaar 	    msg(_("W18: Invalid character in group name"));
3035f9cc9f20SBram Moolenaar 	    break;
3036f9cc9f20SBram Moolenaar 	}
3037f9cc9f20SBram Moolenaar     }
3038f9cc9f20SBram Moolenaar 
3039f9cc9f20SBram Moolenaar     /*
3040f9cc9f20SBram Moolenaar      * First call for this growarray: init growing array.
3041f9cc9f20SBram Moolenaar      */
3042f9cc9f20SBram Moolenaar     if (highlight_ga.ga_data == NULL)
3043f9cc9f20SBram Moolenaar     {
3044f9cc9f20SBram Moolenaar 	highlight_ga.ga_itemsize = sizeof(hl_group_T);
3045f9cc9f20SBram Moolenaar 	highlight_ga.ga_growsize = 10;
3046f9cc9f20SBram Moolenaar     }
3047f9cc9f20SBram Moolenaar 
3048f9cc9f20SBram Moolenaar     if (highlight_ga.ga_len >= MAX_HL_ID)
3049f9cc9f20SBram Moolenaar     {
3050f9cc9f20SBram Moolenaar 	emsg(_("E849: Too many highlight and syntax groups"));
3051f9cc9f20SBram Moolenaar 	vim_free(name);
3052f9cc9f20SBram Moolenaar 	return 0;
3053f9cc9f20SBram Moolenaar     }
3054f9cc9f20SBram Moolenaar 
3055f9cc9f20SBram Moolenaar     /*
3056f9cc9f20SBram Moolenaar      * Make room for at least one other syntax_highlight entry.
3057f9cc9f20SBram Moolenaar      */
3058f9cc9f20SBram Moolenaar     if (ga_grow(&highlight_ga, 1) == FAIL)
3059f9cc9f20SBram Moolenaar     {
3060f9cc9f20SBram Moolenaar 	vim_free(name);
3061f9cc9f20SBram Moolenaar 	return 0;
3062f9cc9f20SBram Moolenaar     }
3063f9cc9f20SBram Moolenaar 
3064f9cc9f20SBram Moolenaar     vim_memset(&(HL_TABLE()[highlight_ga.ga_len]), 0, sizeof(hl_group_T));
3065f9cc9f20SBram Moolenaar     HL_TABLE()[highlight_ga.ga_len].sg_name = name;
3066f9cc9f20SBram Moolenaar     HL_TABLE()[highlight_ga.ga_len].sg_name_u = vim_strsave_up(name);
3067f9cc9f20SBram Moolenaar #if defined(FEAT_GUI) || defined(FEAT_TERMGUICOLORS)
3068f9cc9f20SBram Moolenaar     HL_TABLE()[highlight_ga.ga_len].sg_gui_bg = INVALCOLOR;
3069f9cc9f20SBram Moolenaar     HL_TABLE()[highlight_ga.ga_len].sg_gui_fg = INVALCOLOR;
3070f9cc9f20SBram Moolenaar # ifdef FEAT_GUI
3071f9cc9f20SBram Moolenaar     HL_TABLE()[highlight_ga.ga_len].sg_gui_sp = INVALCOLOR;
3072f9cc9f20SBram Moolenaar # endif
3073f9cc9f20SBram Moolenaar #endif
3074f9cc9f20SBram Moolenaar     ++highlight_ga.ga_len;
3075f9cc9f20SBram Moolenaar 
3076f9cc9f20SBram Moolenaar     return highlight_ga.ga_len;		    // ID is index plus one
3077f9cc9f20SBram Moolenaar }
3078f9cc9f20SBram Moolenaar 
3079f9cc9f20SBram Moolenaar /*
3080f9cc9f20SBram Moolenaar  * When, just after calling syn_add_group(), an error is discovered, this
3081f9cc9f20SBram Moolenaar  * function deletes the new name.
3082f9cc9f20SBram Moolenaar  */
3083f9cc9f20SBram Moolenaar     static void
3084f9cc9f20SBram Moolenaar syn_unadd_group(void)
3085f9cc9f20SBram Moolenaar {
3086f9cc9f20SBram Moolenaar     --highlight_ga.ga_len;
3087f9cc9f20SBram Moolenaar     vim_free(HL_TABLE()[highlight_ga.ga_len].sg_name);
3088f9cc9f20SBram Moolenaar     vim_free(HL_TABLE()[highlight_ga.ga_len].sg_name_u);
3089f9cc9f20SBram Moolenaar }
3090f9cc9f20SBram Moolenaar 
3091f9cc9f20SBram Moolenaar /*
3092f9cc9f20SBram Moolenaar  * Translate a group ID to highlight attributes.
3093f9cc9f20SBram Moolenaar  */
3094f9cc9f20SBram Moolenaar     int
3095f9cc9f20SBram Moolenaar syn_id2attr(int hl_id)
3096f9cc9f20SBram Moolenaar {
3097f9cc9f20SBram Moolenaar     int		attr;
3098f9cc9f20SBram Moolenaar     hl_group_T	*sgp;
3099f9cc9f20SBram Moolenaar 
3100f9cc9f20SBram Moolenaar     hl_id = syn_get_final_id(hl_id);
3101f9cc9f20SBram Moolenaar     sgp = &HL_TABLE()[hl_id - 1];	    // index is ID minus one
3102f9cc9f20SBram Moolenaar 
3103f9cc9f20SBram Moolenaar #ifdef FEAT_GUI
3104f9cc9f20SBram Moolenaar     /*
3105f9cc9f20SBram Moolenaar      * Only use GUI attr when the GUI is being used.
3106f9cc9f20SBram Moolenaar      */
3107f9cc9f20SBram Moolenaar     if (gui.in_use)
3108f9cc9f20SBram Moolenaar 	attr = sgp->sg_gui_attr;
3109f9cc9f20SBram Moolenaar     else
3110f9cc9f20SBram Moolenaar #endif
3111f9cc9f20SBram Moolenaar 	if (IS_CTERM)
3112f9cc9f20SBram Moolenaar 	    attr = sgp->sg_cterm_attr;
3113f9cc9f20SBram Moolenaar 	else
3114f9cc9f20SBram Moolenaar 	    attr = sgp->sg_term_attr;
3115f9cc9f20SBram Moolenaar 
3116f9cc9f20SBram Moolenaar     return attr;
3117f9cc9f20SBram Moolenaar }
3118f9cc9f20SBram Moolenaar 
3119f9cc9f20SBram Moolenaar #if defined(FEAT_GUI) || defined(FEAT_TERMGUICOLORS) || defined(PROTO)
3120f9cc9f20SBram Moolenaar /*
3121f9cc9f20SBram Moolenaar  * Get the GUI colors and attributes for a group ID.
3122f9cc9f20SBram Moolenaar  * NOTE: the colors will be INVALCOLOR when not set, the color otherwise.
3123f9cc9f20SBram Moolenaar  */
3124f9cc9f20SBram Moolenaar     int
3125f9cc9f20SBram Moolenaar syn_id2colors(int hl_id, guicolor_T *fgp, guicolor_T *bgp)
3126f9cc9f20SBram Moolenaar {
3127f9cc9f20SBram Moolenaar     hl_group_T	*sgp;
3128f9cc9f20SBram Moolenaar 
3129f9cc9f20SBram Moolenaar     hl_id = syn_get_final_id(hl_id);
3130f9cc9f20SBram Moolenaar     sgp = &HL_TABLE()[hl_id - 1];	    // index is ID minus one
3131f9cc9f20SBram Moolenaar 
3132f9cc9f20SBram Moolenaar     *fgp = sgp->sg_gui_fg;
3133f9cc9f20SBram Moolenaar     *bgp = sgp->sg_gui_bg;
3134f9cc9f20SBram Moolenaar     return sgp->sg_gui;
3135f9cc9f20SBram Moolenaar }
3136f9cc9f20SBram Moolenaar #endif
3137f9cc9f20SBram Moolenaar 
3138f9cc9f20SBram Moolenaar #if (defined(MSWIN) \
3139f9cc9f20SBram Moolenaar 	&& (!defined(FEAT_GUI_MSWIN) || defined(VIMDLL)) \
3140f9cc9f20SBram Moolenaar 	&& defined(FEAT_TERMGUICOLORS)) || defined(PROTO)
3141f9cc9f20SBram Moolenaar     void
3142f9cc9f20SBram Moolenaar syn_id2cterm_bg(int hl_id, int *fgp, int *bgp)
3143f9cc9f20SBram Moolenaar {
3144f9cc9f20SBram Moolenaar     hl_group_T	*sgp;
3145f9cc9f20SBram Moolenaar 
3146f9cc9f20SBram Moolenaar     hl_id = syn_get_final_id(hl_id);
3147f9cc9f20SBram Moolenaar     sgp = &HL_TABLE()[hl_id - 1];	    // index is ID minus one
3148f9cc9f20SBram Moolenaar     *fgp = sgp->sg_cterm_fg - 1;
3149f9cc9f20SBram Moolenaar     *bgp = sgp->sg_cterm_bg - 1;
3150f9cc9f20SBram Moolenaar }
3151f9cc9f20SBram Moolenaar #endif
3152f9cc9f20SBram Moolenaar 
3153f9cc9f20SBram Moolenaar /*
3154f9cc9f20SBram Moolenaar  * Translate a group ID to the final group ID (following links).
3155f9cc9f20SBram Moolenaar  */
3156f9cc9f20SBram Moolenaar     int
3157f9cc9f20SBram Moolenaar syn_get_final_id(int hl_id)
3158f9cc9f20SBram Moolenaar {
3159f9cc9f20SBram Moolenaar     int		count;
3160f9cc9f20SBram Moolenaar     hl_group_T	*sgp;
3161f9cc9f20SBram Moolenaar 
3162f9cc9f20SBram Moolenaar     if (hl_id > highlight_ga.ga_len || hl_id < 1)
3163f9cc9f20SBram Moolenaar 	return 0;			// Can be called from eval!!
3164f9cc9f20SBram Moolenaar 
3165f9cc9f20SBram Moolenaar     /*
3166f9cc9f20SBram Moolenaar      * Follow links until there is no more.
3167f9cc9f20SBram Moolenaar      * Look out for loops!  Break after 100 links.
3168f9cc9f20SBram Moolenaar      */
3169f9cc9f20SBram Moolenaar     for (count = 100; --count >= 0; )
3170f9cc9f20SBram Moolenaar     {
3171f9cc9f20SBram Moolenaar 	sgp = &HL_TABLE()[hl_id - 1];	    // index is ID minus one
3172f9cc9f20SBram Moolenaar 	if (sgp->sg_link == 0 || sgp->sg_link > highlight_ga.ga_len)
3173f9cc9f20SBram Moolenaar 	    break;
3174f9cc9f20SBram Moolenaar 	hl_id = sgp->sg_link;
3175f9cc9f20SBram Moolenaar     }
3176f9cc9f20SBram Moolenaar 
3177f9cc9f20SBram Moolenaar     return hl_id;
3178f9cc9f20SBram Moolenaar }
3179f9cc9f20SBram Moolenaar 
3180f9cc9f20SBram Moolenaar #if defined(FEAT_GUI) || defined(FEAT_TERMGUICOLORS) || defined(PROTO)
3181f9cc9f20SBram Moolenaar /*
3182f9cc9f20SBram Moolenaar  * Call this function just after the GUI has started.
3183f9cc9f20SBram Moolenaar  * Also called when 'termguicolors' was set, gui.in_use will be FALSE then.
3184f9cc9f20SBram Moolenaar  * It finds the font and color handles for the highlighting groups.
3185f9cc9f20SBram Moolenaar  */
3186f9cc9f20SBram Moolenaar     void
3187f9cc9f20SBram Moolenaar highlight_gui_started(void)
3188f9cc9f20SBram Moolenaar {
3189f9cc9f20SBram Moolenaar     int	    idx;
3190f9cc9f20SBram Moolenaar 
3191f9cc9f20SBram Moolenaar     // First get the colors from the "Normal" and "Menu" group, if set
3192f9cc9f20SBram Moolenaar     if (USE_24BIT)
3193f9cc9f20SBram Moolenaar 	set_normal_colors();
3194f9cc9f20SBram Moolenaar 
3195f9cc9f20SBram Moolenaar     for (idx = 0; idx < highlight_ga.ga_len; ++idx)
3196f9cc9f20SBram Moolenaar 	gui_do_one_color(idx, FALSE, FALSE);
3197f9cc9f20SBram Moolenaar 
3198f9cc9f20SBram Moolenaar     highlight_changed();
3199f9cc9f20SBram Moolenaar }
3200f9cc9f20SBram Moolenaar 
3201f9cc9f20SBram Moolenaar     static void
3202f9cc9f20SBram Moolenaar gui_do_one_color(
3203f9cc9f20SBram Moolenaar     int		idx,
3204f9cc9f20SBram Moolenaar     int		do_menu UNUSED,	   // TRUE: might set the menu font
3205f9cc9f20SBram Moolenaar     int		do_tooltip UNUSED) // TRUE: might set the tooltip font
3206f9cc9f20SBram Moolenaar {
3207f9cc9f20SBram Moolenaar     int		didit = FALSE;
3208f9cc9f20SBram Moolenaar 
3209f9cc9f20SBram Moolenaar # ifdef FEAT_GUI
3210f9cc9f20SBram Moolenaar #  ifdef FEAT_TERMGUICOLORS
3211f9cc9f20SBram Moolenaar     if (gui.in_use)
3212f9cc9f20SBram Moolenaar #  endif
3213f9cc9f20SBram Moolenaar 	if (HL_TABLE()[idx].sg_font_name != NULL)
3214f9cc9f20SBram Moolenaar 	{
3215f9cc9f20SBram Moolenaar 	    hl_do_font(idx, HL_TABLE()[idx].sg_font_name, FALSE, do_menu,
3216f9cc9f20SBram Moolenaar 							    do_tooltip, TRUE);
3217f9cc9f20SBram Moolenaar 	    didit = TRUE;
3218f9cc9f20SBram Moolenaar 	}
3219f9cc9f20SBram Moolenaar # endif
3220f9cc9f20SBram Moolenaar     if (HL_TABLE()[idx].sg_gui_fg_name != NULL)
3221f9cc9f20SBram Moolenaar     {
3222f9cc9f20SBram Moolenaar 	HL_TABLE()[idx].sg_gui_fg =
3223f9cc9f20SBram Moolenaar 			    color_name2handle(HL_TABLE()[idx].sg_gui_fg_name);
3224f9cc9f20SBram Moolenaar 	didit = TRUE;
3225f9cc9f20SBram Moolenaar     }
3226f9cc9f20SBram Moolenaar     if (HL_TABLE()[idx].sg_gui_bg_name != NULL)
3227f9cc9f20SBram Moolenaar     {
3228f9cc9f20SBram Moolenaar 	HL_TABLE()[idx].sg_gui_bg =
3229f9cc9f20SBram Moolenaar 			    color_name2handle(HL_TABLE()[idx].sg_gui_bg_name);
3230f9cc9f20SBram Moolenaar 	didit = TRUE;
3231f9cc9f20SBram Moolenaar     }
3232f9cc9f20SBram Moolenaar # ifdef FEAT_GUI
3233f9cc9f20SBram Moolenaar     if (HL_TABLE()[idx].sg_gui_sp_name != NULL)
3234f9cc9f20SBram Moolenaar     {
3235f9cc9f20SBram Moolenaar 	HL_TABLE()[idx].sg_gui_sp =
3236f9cc9f20SBram Moolenaar 			    color_name2handle(HL_TABLE()[idx].sg_gui_sp_name);
3237f9cc9f20SBram Moolenaar 	didit = TRUE;
3238f9cc9f20SBram Moolenaar     }
3239f9cc9f20SBram Moolenaar # endif
3240f9cc9f20SBram Moolenaar     if (didit)	// need to get a new attr number
3241f9cc9f20SBram Moolenaar 	set_hl_attr(idx);
3242f9cc9f20SBram Moolenaar }
3243f9cc9f20SBram Moolenaar #endif
3244f9cc9f20SBram Moolenaar 
3245f9cc9f20SBram Moolenaar #if defined(USER_HIGHLIGHT) && defined(FEAT_STL_OPT)
3246f9cc9f20SBram Moolenaar /*
3247f9cc9f20SBram Moolenaar  * Apply difference between User[1-9] and HLF_S to HLF_SNC, HLF_ST or HLF_STNC.
3248f9cc9f20SBram Moolenaar  */
3249f9cc9f20SBram Moolenaar     static void
3250f9cc9f20SBram Moolenaar combine_stl_hlt(
3251f9cc9f20SBram Moolenaar 	int id,
3252f9cc9f20SBram Moolenaar 	int id_S,
3253f9cc9f20SBram Moolenaar 	int id_alt,
3254f9cc9f20SBram Moolenaar 	int hlcnt,
3255f9cc9f20SBram Moolenaar 	int i,
3256f9cc9f20SBram Moolenaar 	int hlf,
3257f9cc9f20SBram Moolenaar 	int *table)
3258f9cc9f20SBram Moolenaar {
3259f9cc9f20SBram Moolenaar     hl_group_T *hlt = HL_TABLE();
3260f9cc9f20SBram Moolenaar 
3261f9cc9f20SBram Moolenaar     if (id_alt == 0)
3262f9cc9f20SBram Moolenaar     {
3263f9cc9f20SBram Moolenaar 	vim_memset(&hlt[hlcnt + i], 0, sizeof(hl_group_T));
3264f9cc9f20SBram Moolenaar 	hlt[hlcnt + i].sg_term = highlight_attr[hlf];
3265f9cc9f20SBram Moolenaar 	hlt[hlcnt + i].sg_cterm = highlight_attr[hlf];
3266f9cc9f20SBram Moolenaar #  if defined(FEAT_GUI) || defined(FEAT_EVAL)
3267f9cc9f20SBram Moolenaar 	hlt[hlcnt + i].sg_gui = highlight_attr[hlf];
3268f9cc9f20SBram Moolenaar #  endif
3269f9cc9f20SBram Moolenaar     }
3270f9cc9f20SBram Moolenaar     else
3271f9cc9f20SBram Moolenaar 	mch_memmove(&hlt[hlcnt + i],
3272f9cc9f20SBram Moolenaar 		    &hlt[id_alt - 1],
3273f9cc9f20SBram Moolenaar 		    sizeof(hl_group_T));
3274f9cc9f20SBram Moolenaar     hlt[hlcnt + i].sg_link = 0;
3275f9cc9f20SBram Moolenaar 
3276f9cc9f20SBram Moolenaar     hlt[hlcnt + i].sg_term ^=
3277f9cc9f20SBram Moolenaar 	hlt[id - 1].sg_term ^ hlt[id_S - 1].sg_term;
3278f9cc9f20SBram Moolenaar     if (hlt[id - 1].sg_start != hlt[id_S - 1].sg_start)
3279f9cc9f20SBram Moolenaar 	hlt[hlcnt + i].sg_start = hlt[id - 1].sg_start;
3280f9cc9f20SBram Moolenaar     if (hlt[id - 1].sg_stop != hlt[id_S - 1].sg_stop)
3281f9cc9f20SBram Moolenaar 	hlt[hlcnt + i].sg_stop = hlt[id - 1].sg_stop;
3282f9cc9f20SBram Moolenaar     hlt[hlcnt + i].sg_cterm ^=
3283f9cc9f20SBram Moolenaar 	hlt[id - 1].sg_cterm ^ hlt[id_S - 1].sg_cterm;
3284f9cc9f20SBram Moolenaar     if (hlt[id - 1].sg_cterm_fg != hlt[id_S - 1].sg_cterm_fg)
3285f9cc9f20SBram Moolenaar 	hlt[hlcnt + i].sg_cterm_fg = hlt[id - 1].sg_cterm_fg;
3286f9cc9f20SBram Moolenaar     if (hlt[id - 1].sg_cterm_bg != hlt[id_S - 1].sg_cterm_bg)
3287f9cc9f20SBram Moolenaar 	hlt[hlcnt + i].sg_cterm_bg = hlt[id - 1].sg_cterm_bg;
3288f9cc9f20SBram Moolenaar #  if defined(FEAT_GUI) || defined(FEAT_EVAL)
3289f9cc9f20SBram Moolenaar     hlt[hlcnt + i].sg_gui ^=
3290f9cc9f20SBram Moolenaar 	hlt[id - 1].sg_gui ^ hlt[id_S - 1].sg_gui;
3291f9cc9f20SBram Moolenaar #  endif
3292f9cc9f20SBram Moolenaar #  ifdef FEAT_GUI
3293f9cc9f20SBram Moolenaar     if (hlt[id - 1].sg_gui_fg != hlt[id_S - 1].sg_gui_fg)
3294f9cc9f20SBram Moolenaar 	hlt[hlcnt + i].sg_gui_fg = hlt[id - 1].sg_gui_fg;
3295f9cc9f20SBram Moolenaar     if (hlt[id - 1].sg_gui_bg != hlt[id_S - 1].sg_gui_bg)
3296f9cc9f20SBram Moolenaar 	hlt[hlcnt + i].sg_gui_bg = hlt[id - 1].sg_gui_bg;
3297f9cc9f20SBram Moolenaar     if (hlt[id - 1].sg_gui_sp != hlt[id_S - 1].sg_gui_sp)
3298f9cc9f20SBram Moolenaar 	hlt[hlcnt + i].sg_gui_sp = hlt[id - 1].sg_gui_sp;
3299f9cc9f20SBram Moolenaar     if (hlt[id - 1].sg_font != hlt[id_S - 1].sg_font)
3300f9cc9f20SBram Moolenaar 	hlt[hlcnt + i].sg_font = hlt[id - 1].sg_font;
3301f9cc9f20SBram Moolenaar #   ifdef FEAT_XFONTSET
3302f9cc9f20SBram Moolenaar     if (hlt[id - 1].sg_fontset != hlt[id_S - 1].sg_fontset)
3303f9cc9f20SBram Moolenaar 	hlt[hlcnt + i].sg_fontset = hlt[id - 1].sg_fontset;
3304f9cc9f20SBram Moolenaar #   endif
3305f9cc9f20SBram Moolenaar #  endif
3306f9cc9f20SBram Moolenaar     highlight_ga.ga_len = hlcnt + i + 1;
3307f9cc9f20SBram Moolenaar     set_hl_attr(hlcnt + i);	// At long last we can apply
3308f9cc9f20SBram Moolenaar     table[i] = syn_id2attr(hlcnt + i + 1);
3309f9cc9f20SBram Moolenaar }
3310f9cc9f20SBram Moolenaar #endif
3311f9cc9f20SBram Moolenaar 
3312f9cc9f20SBram Moolenaar /*
3313f9cc9f20SBram Moolenaar  * Translate the 'highlight' option into attributes in highlight_attr[] and
3314f9cc9f20SBram Moolenaar  * set up the user highlights User1..9.  If FEAT_STL_OPT is in use, a set of
3315f9cc9f20SBram Moolenaar  * corresponding highlights to use on top of HLF_SNC is computed.
3316f9cc9f20SBram Moolenaar  * Called only when the 'highlight' option has been changed and upon first
3317f9cc9f20SBram Moolenaar  * screen redraw after any :highlight command.
3318f9cc9f20SBram Moolenaar  * Return FAIL when an invalid flag is found in 'highlight'.  OK otherwise.
3319f9cc9f20SBram Moolenaar  */
3320f9cc9f20SBram Moolenaar     int
3321f9cc9f20SBram Moolenaar highlight_changed(void)
3322f9cc9f20SBram Moolenaar {
3323f9cc9f20SBram Moolenaar     int		hlf;
3324f9cc9f20SBram Moolenaar     int		i;
3325f9cc9f20SBram Moolenaar     char_u	*p;
3326f9cc9f20SBram Moolenaar     int		attr;
3327f9cc9f20SBram Moolenaar     char_u	*end;
3328f9cc9f20SBram Moolenaar     int		id;
3329f9cc9f20SBram Moolenaar #ifdef USER_HIGHLIGHT
3330f9cc9f20SBram Moolenaar     char_u      userhl[30];  // use 30 to avoid compiler warning
3331f9cc9f20SBram Moolenaar # ifdef FEAT_STL_OPT
3332f9cc9f20SBram Moolenaar     int		id_S = -1;
3333f9cc9f20SBram Moolenaar     int		id_SNC = 0;
3334f9cc9f20SBram Moolenaar #  ifdef FEAT_TERMINAL
3335f9cc9f20SBram Moolenaar     int		id_ST = 0;
3336f9cc9f20SBram Moolenaar     int		id_STNC = 0;
3337f9cc9f20SBram Moolenaar #  endif
3338f9cc9f20SBram Moolenaar     int		hlcnt;
3339f9cc9f20SBram Moolenaar # endif
3340f9cc9f20SBram Moolenaar #endif
3341f9cc9f20SBram Moolenaar     static int	hl_flags[HLF_COUNT] = HL_FLAGS;
3342f9cc9f20SBram Moolenaar 
3343f9cc9f20SBram Moolenaar     need_highlight_changed = FALSE;
3344f9cc9f20SBram Moolenaar 
3345f9cc9f20SBram Moolenaar     /*
3346f9cc9f20SBram Moolenaar      * Clear all attributes.
3347f9cc9f20SBram Moolenaar      */
3348f9cc9f20SBram Moolenaar     for (hlf = 0; hlf < (int)HLF_COUNT; ++hlf)
3349f9cc9f20SBram Moolenaar 	highlight_attr[hlf] = 0;
3350f9cc9f20SBram Moolenaar 
3351f9cc9f20SBram Moolenaar     /*
3352f9cc9f20SBram Moolenaar      * First set all attributes to their default value.
3353f9cc9f20SBram Moolenaar      * Then use the attributes from the 'highlight' option.
3354f9cc9f20SBram Moolenaar      */
3355f9cc9f20SBram Moolenaar     for (i = 0; i < 2; ++i)
3356f9cc9f20SBram Moolenaar     {
3357f9cc9f20SBram Moolenaar 	if (i)
3358f9cc9f20SBram Moolenaar 	    p = p_hl;
3359f9cc9f20SBram Moolenaar 	else
3360f9cc9f20SBram Moolenaar 	    p = get_highlight_default();
3361f9cc9f20SBram Moolenaar 	if (p == NULL)	    // just in case
3362f9cc9f20SBram Moolenaar 	    continue;
3363f9cc9f20SBram Moolenaar 
3364f9cc9f20SBram Moolenaar 	while (*p)
3365f9cc9f20SBram Moolenaar 	{
3366f9cc9f20SBram Moolenaar 	    for (hlf = 0; hlf < (int)HLF_COUNT; ++hlf)
3367f9cc9f20SBram Moolenaar 		if (hl_flags[hlf] == *p)
3368f9cc9f20SBram Moolenaar 		    break;
3369f9cc9f20SBram Moolenaar 	    ++p;
3370f9cc9f20SBram Moolenaar 	    if (hlf == (int)HLF_COUNT || *p == NUL)
3371f9cc9f20SBram Moolenaar 		return FAIL;
3372f9cc9f20SBram Moolenaar 
3373f9cc9f20SBram Moolenaar 	    /*
3374f9cc9f20SBram Moolenaar 	     * Allow several hl_flags to be combined, like "bu" for
3375f9cc9f20SBram Moolenaar 	     * bold-underlined.
3376f9cc9f20SBram Moolenaar 	     */
3377f9cc9f20SBram Moolenaar 	    attr = 0;
3378f9cc9f20SBram Moolenaar 	    for ( ; *p && *p != ','; ++p)	    // parse upto comma
3379f9cc9f20SBram Moolenaar 	    {
3380f9cc9f20SBram Moolenaar 		if (VIM_ISWHITE(*p))		    // ignore white space
3381f9cc9f20SBram Moolenaar 		    continue;
3382f9cc9f20SBram Moolenaar 
3383f9cc9f20SBram Moolenaar 		if (attr > HL_ALL)  // Combination with ':' is not allowed.
3384f9cc9f20SBram Moolenaar 		    return FAIL;
3385f9cc9f20SBram Moolenaar 
3386f9cc9f20SBram Moolenaar 		switch (*p)
3387f9cc9f20SBram Moolenaar 		{
3388f9cc9f20SBram Moolenaar 		    case 'b':	attr |= HL_BOLD;
3389f9cc9f20SBram Moolenaar 				break;
3390f9cc9f20SBram Moolenaar 		    case 'i':	attr |= HL_ITALIC;
3391f9cc9f20SBram Moolenaar 				break;
3392f9cc9f20SBram Moolenaar 		    case '-':
3393f9cc9f20SBram Moolenaar 		    case 'n':			    // no highlighting
3394f9cc9f20SBram Moolenaar 				break;
3395f9cc9f20SBram Moolenaar 		    case 'r':	attr |= HL_INVERSE;
3396f9cc9f20SBram Moolenaar 				break;
3397f9cc9f20SBram Moolenaar 		    case 's':	attr |= HL_STANDOUT;
3398f9cc9f20SBram Moolenaar 				break;
3399f9cc9f20SBram Moolenaar 		    case 'u':	attr |= HL_UNDERLINE;
3400f9cc9f20SBram Moolenaar 				break;
3401f9cc9f20SBram Moolenaar 		    case 'c':	attr |= HL_UNDERCURL;
3402f9cc9f20SBram Moolenaar 				break;
3403f9cc9f20SBram Moolenaar 		    case 't':	attr |= HL_STRIKETHROUGH;
3404f9cc9f20SBram Moolenaar 				break;
3405f9cc9f20SBram Moolenaar 		    case ':':	++p;		    // highlight group name
3406f9cc9f20SBram Moolenaar 				if (attr || *p == NUL)	 // no combinations
3407f9cc9f20SBram Moolenaar 				    return FAIL;
3408f9cc9f20SBram Moolenaar 				end = vim_strchr(p, ',');
3409f9cc9f20SBram Moolenaar 				if (end == NULL)
3410f9cc9f20SBram Moolenaar 				    end = p + STRLEN(p);
3411f9cc9f20SBram Moolenaar 				id = syn_check_group(p, (int)(end - p));
3412f9cc9f20SBram Moolenaar 				if (id == 0)
3413f9cc9f20SBram Moolenaar 				    return FAIL;
3414f9cc9f20SBram Moolenaar 				attr = syn_id2attr(id);
3415f9cc9f20SBram Moolenaar 				p = end - 1;
3416f9cc9f20SBram Moolenaar #if defined(FEAT_STL_OPT) && defined(USER_HIGHLIGHT)
3417f9cc9f20SBram Moolenaar 				if (hlf == (int)HLF_SNC)
3418f9cc9f20SBram Moolenaar 				    id_SNC = syn_get_final_id(id);
3419f9cc9f20SBram Moolenaar # ifdef FEAT_TERMINAL
3420f9cc9f20SBram Moolenaar 				else if (hlf == (int)HLF_ST)
3421f9cc9f20SBram Moolenaar 				    id_ST = syn_get_final_id(id);
3422f9cc9f20SBram Moolenaar 				else if (hlf == (int)HLF_STNC)
3423f9cc9f20SBram Moolenaar 				    id_STNC = syn_get_final_id(id);
3424f9cc9f20SBram Moolenaar # endif
3425f9cc9f20SBram Moolenaar 				else if (hlf == (int)HLF_S)
3426f9cc9f20SBram Moolenaar 				    id_S = syn_get_final_id(id);
3427f9cc9f20SBram Moolenaar #endif
3428f9cc9f20SBram Moolenaar 				break;
3429f9cc9f20SBram Moolenaar 		    default:	return FAIL;
3430f9cc9f20SBram Moolenaar 		}
3431f9cc9f20SBram Moolenaar 	    }
3432f9cc9f20SBram Moolenaar 	    highlight_attr[hlf] = attr;
3433f9cc9f20SBram Moolenaar 
3434f9cc9f20SBram Moolenaar 	    p = skip_to_option_part(p);	    // skip comma and spaces
3435f9cc9f20SBram Moolenaar 	}
3436f9cc9f20SBram Moolenaar     }
3437f9cc9f20SBram Moolenaar 
3438f9cc9f20SBram Moolenaar #ifdef USER_HIGHLIGHT
3439f9cc9f20SBram Moolenaar     /*
3440f9cc9f20SBram Moolenaar      * Setup the user highlights
3441f9cc9f20SBram Moolenaar      *
3442f9cc9f20SBram Moolenaar      * Temporarily utilize 28 more hl entries:
3443f9cc9f20SBram Moolenaar      * 9 for User1-User9 combined with StatusLineNC
3444f9cc9f20SBram Moolenaar      * 9 for User1-User9 combined with StatusLineTerm
3445f9cc9f20SBram Moolenaar      * 9 for User1-User9 combined with StatusLineTermNC
3446f9cc9f20SBram Moolenaar      * 1 for StatusLine default
3447f9cc9f20SBram Moolenaar      * Have to be in there simultaneously in case of table overflows in
3448f9cc9f20SBram Moolenaar      * get_attr_entry()
3449f9cc9f20SBram Moolenaar      */
3450f9cc9f20SBram Moolenaar # ifdef FEAT_STL_OPT
3451f9cc9f20SBram Moolenaar     if (ga_grow(&highlight_ga, 28) == FAIL)
3452f9cc9f20SBram Moolenaar 	return FAIL;
3453f9cc9f20SBram Moolenaar     hlcnt = highlight_ga.ga_len;
3454f9cc9f20SBram Moolenaar     if (id_S == -1)
3455f9cc9f20SBram Moolenaar     {
3456f9cc9f20SBram Moolenaar 	// Make sure id_S is always valid to simplify code below. Use the last
3457f9cc9f20SBram Moolenaar 	// entry.
3458f9cc9f20SBram Moolenaar 	vim_memset(&HL_TABLE()[hlcnt + 27], 0, sizeof(hl_group_T));
3459f9cc9f20SBram Moolenaar 	HL_TABLE()[hlcnt + 18].sg_term = highlight_attr[HLF_S];
3460f9cc9f20SBram Moolenaar 	id_S = hlcnt + 19;
3461f9cc9f20SBram Moolenaar     }
3462f9cc9f20SBram Moolenaar # endif
3463f9cc9f20SBram Moolenaar     for (i = 0; i < 9; i++)
3464f9cc9f20SBram Moolenaar     {
3465f9cc9f20SBram Moolenaar 	sprintf((char *)userhl, "User%d", i + 1);
3466f9cc9f20SBram Moolenaar 	id = syn_name2id(userhl);
3467f9cc9f20SBram Moolenaar 	if (id == 0)
3468f9cc9f20SBram Moolenaar 	{
3469f9cc9f20SBram Moolenaar 	    highlight_user[i] = 0;
3470f9cc9f20SBram Moolenaar # ifdef FEAT_STL_OPT
3471f9cc9f20SBram Moolenaar 	    highlight_stlnc[i] = 0;
3472f9cc9f20SBram Moolenaar #  ifdef FEAT_TERMINAL
3473f9cc9f20SBram Moolenaar 	    highlight_stlterm[i] = 0;
3474f9cc9f20SBram Moolenaar 	    highlight_stltermnc[i] = 0;
3475f9cc9f20SBram Moolenaar #  endif
3476f9cc9f20SBram Moolenaar # endif
3477f9cc9f20SBram Moolenaar 	}
3478f9cc9f20SBram Moolenaar 	else
3479f9cc9f20SBram Moolenaar 	{
3480f9cc9f20SBram Moolenaar 	    highlight_user[i] = syn_id2attr(id);
3481f9cc9f20SBram Moolenaar # ifdef FEAT_STL_OPT
3482f9cc9f20SBram Moolenaar 	    combine_stl_hlt(id, id_S, id_SNC, hlcnt, i,
3483f9cc9f20SBram Moolenaar 						     HLF_SNC, highlight_stlnc);
3484f9cc9f20SBram Moolenaar #  ifdef FEAT_TERMINAL
3485f9cc9f20SBram Moolenaar 	    combine_stl_hlt(id, id_S, id_ST, hlcnt + 9, i,
3486f9cc9f20SBram Moolenaar 						    HLF_ST, highlight_stlterm);
3487f9cc9f20SBram Moolenaar 	    combine_stl_hlt(id, id_S, id_STNC, hlcnt + 18, i,
3488f9cc9f20SBram Moolenaar 						HLF_STNC, highlight_stltermnc);
3489f9cc9f20SBram Moolenaar #  endif
3490f9cc9f20SBram Moolenaar # endif
3491f9cc9f20SBram Moolenaar 	}
3492f9cc9f20SBram Moolenaar     }
3493f9cc9f20SBram Moolenaar # ifdef FEAT_STL_OPT
3494f9cc9f20SBram Moolenaar     highlight_ga.ga_len = hlcnt;
3495f9cc9f20SBram Moolenaar # endif
3496f9cc9f20SBram Moolenaar 
3497f9cc9f20SBram Moolenaar #endif // USER_HIGHLIGHT
3498f9cc9f20SBram Moolenaar 
3499f9cc9f20SBram Moolenaar     return OK;
3500f9cc9f20SBram Moolenaar }
3501f9cc9f20SBram Moolenaar 
3502f9cc9f20SBram Moolenaar #if defined(FEAT_CMDL_COMPL) || defined(PROTO)
3503f9cc9f20SBram Moolenaar 
3504f9cc9f20SBram Moolenaar static void highlight_list(void);
3505f9cc9f20SBram Moolenaar static void highlight_list_two(int cnt, int attr);
3506f9cc9f20SBram Moolenaar 
3507f9cc9f20SBram Moolenaar /*
3508f9cc9f20SBram Moolenaar  * Handle command line completion for :highlight command.
3509f9cc9f20SBram Moolenaar  */
3510f9cc9f20SBram Moolenaar     void
3511f9cc9f20SBram Moolenaar set_context_in_highlight_cmd(expand_T *xp, char_u *arg)
3512f9cc9f20SBram Moolenaar {
3513f9cc9f20SBram Moolenaar     char_u	*p;
3514f9cc9f20SBram Moolenaar 
3515f9cc9f20SBram Moolenaar     // Default: expand group names
3516f9cc9f20SBram Moolenaar     xp->xp_context = EXPAND_HIGHLIGHT;
3517f9cc9f20SBram Moolenaar     xp->xp_pattern = arg;
3518f9cc9f20SBram Moolenaar     include_link = 2;
3519f9cc9f20SBram Moolenaar     include_default = 1;
3520f9cc9f20SBram Moolenaar 
3521f9cc9f20SBram Moolenaar     // (part of) subcommand already typed
3522f9cc9f20SBram Moolenaar     if (*arg != NUL)
3523f9cc9f20SBram Moolenaar     {
3524f9cc9f20SBram Moolenaar 	p = skiptowhite(arg);
3525f9cc9f20SBram Moolenaar 	if (*p != NUL)			// past "default" or group name
3526f9cc9f20SBram Moolenaar 	{
3527f9cc9f20SBram Moolenaar 	    include_default = 0;
3528f9cc9f20SBram Moolenaar 	    if (STRNCMP("default", arg, p - arg) == 0)
3529f9cc9f20SBram Moolenaar 	    {
3530f9cc9f20SBram Moolenaar 		arg = skipwhite(p);
3531f9cc9f20SBram Moolenaar 		xp->xp_pattern = arg;
3532f9cc9f20SBram Moolenaar 		p = skiptowhite(arg);
3533f9cc9f20SBram Moolenaar 	    }
3534f9cc9f20SBram Moolenaar 	    if (*p != NUL)			// past group name
3535f9cc9f20SBram Moolenaar 	    {
3536f9cc9f20SBram Moolenaar 		include_link = 0;
3537f9cc9f20SBram Moolenaar 		if (arg[1] == 'i' && arg[0] == 'N')
3538f9cc9f20SBram Moolenaar 		    highlight_list();
3539f9cc9f20SBram Moolenaar 		if (STRNCMP("link", arg, p - arg) == 0
3540f9cc9f20SBram Moolenaar 			|| STRNCMP("clear", arg, p - arg) == 0)
3541f9cc9f20SBram Moolenaar 		{
3542f9cc9f20SBram Moolenaar 		    xp->xp_pattern = skipwhite(p);
3543f9cc9f20SBram Moolenaar 		    p = skiptowhite(xp->xp_pattern);
3544f9cc9f20SBram Moolenaar 		    if (*p != NUL)		// past first group name
3545f9cc9f20SBram Moolenaar 		    {
3546f9cc9f20SBram Moolenaar 			xp->xp_pattern = skipwhite(p);
3547f9cc9f20SBram Moolenaar 			p = skiptowhite(xp->xp_pattern);
3548f9cc9f20SBram Moolenaar 		    }
3549f9cc9f20SBram Moolenaar 		}
3550f9cc9f20SBram Moolenaar 		if (*p != NUL)			// past group name(s)
3551f9cc9f20SBram Moolenaar 		    xp->xp_context = EXPAND_NOTHING;
3552f9cc9f20SBram Moolenaar 	    }
3553f9cc9f20SBram Moolenaar 	}
3554f9cc9f20SBram Moolenaar     }
3555f9cc9f20SBram Moolenaar }
3556f9cc9f20SBram Moolenaar 
3557f9cc9f20SBram Moolenaar /*
3558f9cc9f20SBram Moolenaar  * List highlighting matches in a nice way.
3559f9cc9f20SBram Moolenaar  */
3560f9cc9f20SBram Moolenaar     static void
3561f9cc9f20SBram Moolenaar highlight_list(void)
3562f9cc9f20SBram Moolenaar {
3563f9cc9f20SBram Moolenaar     int		i;
3564f9cc9f20SBram Moolenaar 
3565f9cc9f20SBram Moolenaar     for (i = 10; --i >= 0; )
3566f9cc9f20SBram Moolenaar 	highlight_list_two(i, HL_ATTR(HLF_D));
3567f9cc9f20SBram Moolenaar     for (i = 40; --i >= 0; )
3568f9cc9f20SBram Moolenaar 	highlight_list_two(99, 0);
3569f9cc9f20SBram Moolenaar }
3570f9cc9f20SBram Moolenaar 
3571f9cc9f20SBram Moolenaar     static void
3572f9cc9f20SBram Moolenaar highlight_list_two(int cnt, int attr)
3573f9cc9f20SBram Moolenaar {
3574f9cc9f20SBram Moolenaar     msg_puts_attr(&("N \bI \b!  \b"[cnt / 11]), attr);
3575f9cc9f20SBram Moolenaar     msg_clr_eos();
3576f9cc9f20SBram Moolenaar     out_flush();
3577f9cc9f20SBram Moolenaar     ui_delay(cnt == 99 ? 40L : (long)cnt * 50L, FALSE);
3578f9cc9f20SBram Moolenaar }
3579f9cc9f20SBram Moolenaar 
3580f9cc9f20SBram Moolenaar #endif // FEAT_CMDL_COMPL
3581f9cc9f20SBram Moolenaar 
3582f9cc9f20SBram Moolenaar #if defined(FEAT_CMDL_COMPL) || (defined(FEAT_SYN_HL) && defined(FEAT_EVAL)) \
3583f9cc9f20SBram Moolenaar     || defined(FEAT_SIGNS) || defined(PROTO)
3584f9cc9f20SBram Moolenaar /*
3585f9cc9f20SBram Moolenaar  * Function given to ExpandGeneric() to obtain the list of group names.
3586f9cc9f20SBram Moolenaar  */
3587f9cc9f20SBram Moolenaar     char_u *
3588f9cc9f20SBram Moolenaar get_highlight_name(expand_T *xp UNUSED, int idx)
3589f9cc9f20SBram Moolenaar {
3590f9cc9f20SBram Moolenaar     return get_highlight_name_ext(xp, idx, TRUE);
3591f9cc9f20SBram Moolenaar }
3592f9cc9f20SBram Moolenaar 
3593f9cc9f20SBram Moolenaar /*
3594f9cc9f20SBram Moolenaar  * Obtain a highlight group name.
3595f9cc9f20SBram Moolenaar  * When "skip_cleared" is TRUE don't return a cleared entry.
3596f9cc9f20SBram Moolenaar  */
3597f9cc9f20SBram Moolenaar     char_u *
3598f9cc9f20SBram Moolenaar get_highlight_name_ext(expand_T *xp UNUSED, int idx, int skip_cleared)
3599f9cc9f20SBram Moolenaar {
3600f9cc9f20SBram Moolenaar     if (idx < 0)
3601f9cc9f20SBram Moolenaar 	return NULL;
3602f9cc9f20SBram Moolenaar 
3603f9cc9f20SBram Moolenaar     // Items are never removed from the table, skip the ones that were
3604f9cc9f20SBram Moolenaar     // cleared.
3605f9cc9f20SBram Moolenaar     if (skip_cleared && idx < highlight_ga.ga_len && HL_TABLE()[idx].sg_cleared)
3606f9cc9f20SBram Moolenaar 	return (char_u *)"";
3607f9cc9f20SBram Moolenaar 
3608f9cc9f20SBram Moolenaar #ifdef FEAT_CMDL_COMPL
3609f9cc9f20SBram Moolenaar     if (idx == highlight_ga.ga_len && include_none != 0)
3610f9cc9f20SBram Moolenaar 	return (char_u *)"none";
3611f9cc9f20SBram Moolenaar     if (idx == highlight_ga.ga_len + include_none && include_default != 0)
3612f9cc9f20SBram Moolenaar 	return (char_u *)"default";
3613f9cc9f20SBram Moolenaar     if (idx == highlight_ga.ga_len + include_none + include_default
3614f9cc9f20SBram Moolenaar 							 && include_link != 0)
3615f9cc9f20SBram Moolenaar 	return (char_u *)"link";
3616f9cc9f20SBram Moolenaar     if (idx == highlight_ga.ga_len + include_none + include_default + 1
3617f9cc9f20SBram Moolenaar 							 && include_link != 0)
3618f9cc9f20SBram Moolenaar 	return (char_u *)"clear";
3619f9cc9f20SBram Moolenaar #endif
3620f9cc9f20SBram Moolenaar     if (idx >= highlight_ga.ga_len)
3621f9cc9f20SBram Moolenaar 	return NULL;
3622f9cc9f20SBram Moolenaar     return HL_TABLE()[idx].sg_name;
3623f9cc9f20SBram Moolenaar }
3624f9cc9f20SBram Moolenaar #endif
3625f9cc9f20SBram Moolenaar 
3626f9cc9f20SBram Moolenaar #if defined(FEAT_GUI) || defined(PROTO)
3627f9cc9f20SBram Moolenaar /*
3628f9cc9f20SBram Moolenaar  * Free all the highlight group fonts.
3629f9cc9f20SBram Moolenaar  * Used when quitting for systems which need it.
3630f9cc9f20SBram Moolenaar  */
3631f9cc9f20SBram Moolenaar     void
3632f9cc9f20SBram Moolenaar free_highlight_fonts(void)
3633f9cc9f20SBram Moolenaar {
3634f9cc9f20SBram Moolenaar     int	    idx;
3635f9cc9f20SBram Moolenaar 
3636f9cc9f20SBram Moolenaar     for (idx = 0; idx < highlight_ga.ga_len; ++idx)
3637f9cc9f20SBram Moolenaar     {
3638f9cc9f20SBram Moolenaar 	gui_mch_free_font(HL_TABLE()[idx].sg_font);
3639f9cc9f20SBram Moolenaar 	HL_TABLE()[idx].sg_font = NOFONT;
3640f9cc9f20SBram Moolenaar # ifdef FEAT_XFONTSET
3641f9cc9f20SBram Moolenaar 	gui_mch_free_fontset(HL_TABLE()[idx].sg_fontset);
3642f9cc9f20SBram Moolenaar 	HL_TABLE()[idx].sg_fontset = NOFONTSET;
3643f9cc9f20SBram Moolenaar # endif
3644f9cc9f20SBram Moolenaar     }
3645f9cc9f20SBram Moolenaar 
3646f9cc9f20SBram Moolenaar     gui_mch_free_font(gui.norm_font);
3647f9cc9f20SBram Moolenaar # ifdef FEAT_XFONTSET
3648f9cc9f20SBram Moolenaar     gui_mch_free_fontset(gui.fontset);
3649f9cc9f20SBram Moolenaar # endif
3650f9cc9f20SBram Moolenaar # ifndef FEAT_GUI_GTK
3651f9cc9f20SBram Moolenaar     gui_mch_free_font(gui.bold_font);
3652f9cc9f20SBram Moolenaar     gui_mch_free_font(gui.ital_font);
3653f9cc9f20SBram Moolenaar     gui_mch_free_font(gui.boldital_font);
3654f9cc9f20SBram Moolenaar # endif
3655f9cc9f20SBram Moolenaar }
3656f9cc9f20SBram Moolenaar #endif
365729b7d7a9SBram Moolenaar 
365829b7d7a9SBram Moolenaar 
365929b7d7a9SBram Moolenaar #if defined(FEAT_SEARCH_EXTRA) || defined(PROTO)
366029b7d7a9SBram Moolenaar /*
366129b7d7a9SBram Moolenaar  * Add match to the match list of window 'wp'.  The pattern 'pat' will be
366229b7d7a9SBram Moolenaar  * highlighted with the group 'grp' with priority 'prio'.
366329b7d7a9SBram Moolenaar  * Optionally, a desired ID 'id' can be specified (greater than or equal to 1).
366429b7d7a9SBram Moolenaar  * If no particular ID is desired, -1 must be specified for 'id'.
366529b7d7a9SBram Moolenaar  * Return ID of added match, -1 on failure.
366629b7d7a9SBram Moolenaar  */
366729b7d7a9SBram Moolenaar     int
366829b7d7a9SBram Moolenaar match_add(
366929b7d7a9SBram Moolenaar     win_T	*wp,
367029b7d7a9SBram Moolenaar     char_u	*grp,
367129b7d7a9SBram Moolenaar     char_u	*pat,
367229b7d7a9SBram Moolenaar     int		prio,
367329b7d7a9SBram Moolenaar     int		id,
367429b7d7a9SBram Moolenaar     list_T	*pos_list,
367529b7d7a9SBram Moolenaar     char_u      *conceal_char UNUSED) /* pointer to conceal replacement char */
367629b7d7a9SBram Moolenaar {
367729b7d7a9SBram Moolenaar     matchitem_T	*cur;
367829b7d7a9SBram Moolenaar     matchitem_T	*prev;
367929b7d7a9SBram Moolenaar     matchitem_T	*m;
368029b7d7a9SBram Moolenaar     int		hlg_id;
368129b7d7a9SBram Moolenaar     regprog_T	*regprog = NULL;
368229b7d7a9SBram Moolenaar     int		rtype = SOME_VALID;
368329b7d7a9SBram Moolenaar 
368429b7d7a9SBram Moolenaar     if (*grp == NUL || (pat != NULL && *pat == NUL))
368529b7d7a9SBram Moolenaar 	return -1;
368629b7d7a9SBram Moolenaar     if (id < -1 || id == 0)
368729b7d7a9SBram Moolenaar     {
368829b7d7a9SBram Moolenaar 	semsg(_("E799: Invalid ID: %d (must be greater than or equal to 1)"), id);
368929b7d7a9SBram Moolenaar 	return -1;
369029b7d7a9SBram Moolenaar     }
369129b7d7a9SBram Moolenaar     if (id != -1)
369229b7d7a9SBram Moolenaar     {
369329b7d7a9SBram Moolenaar 	cur = wp->w_match_head;
369429b7d7a9SBram Moolenaar 	while (cur != NULL)
369529b7d7a9SBram Moolenaar 	{
369629b7d7a9SBram Moolenaar 	    if (cur->id == id)
369729b7d7a9SBram Moolenaar 	    {
369829b7d7a9SBram Moolenaar 		semsg(_("E801: ID already taken: %d"), id);
369929b7d7a9SBram Moolenaar 		return -1;
370029b7d7a9SBram Moolenaar 	    }
370129b7d7a9SBram Moolenaar 	    cur = cur->next;
370229b7d7a9SBram Moolenaar 	}
370329b7d7a9SBram Moolenaar     }
370429b7d7a9SBram Moolenaar     if ((hlg_id = syn_namen2id(grp, (int)STRLEN(grp))) == 0)
370529b7d7a9SBram Moolenaar     {
370629b7d7a9SBram Moolenaar 	semsg(_(e_nogroup), grp);
370729b7d7a9SBram Moolenaar 	return -1;
370829b7d7a9SBram Moolenaar     }
370929b7d7a9SBram Moolenaar     if (pat != NULL && (regprog = vim_regcomp(pat, RE_MAGIC)) == NULL)
371029b7d7a9SBram Moolenaar     {
371129b7d7a9SBram Moolenaar 	semsg(_(e_invarg2), pat);
371229b7d7a9SBram Moolenaar 	return -1;
371329b7d7a9SBram Moolenaar     }
371429b7d7a9SBram Moolenaar 
371529b7d7a9SBram Moolenaar     /* Find available match ID. */
371629b7d7a9SBram Moolenaar     while (id == -1)
371729b7d7a9SBram Moolenaar     {
371829b7d7a9SBram Moolenaar 	cur = wp->w_match_head;
371929b7d7a9SBram Moolenaar 	while (cur != NULL && cur->id != wp->w_next_match_id)
372029b7d7a9SBram Moolenaar 	    cur = cur->next;
372129b7d7a9SBram Moolenaar 	if (cur == NULL)
372229b7d7a9SBram Moolenaar 	    id = wp->w_next_match_id;
372329b7d7a9SBram Moolenaar 	wp->w_next_match_id++;
372429b7d7a9SBram Moolenaar     }
372529b7d7a9SBram Moolenaar 
372629b7d7a9SBram Moolenaar     /* Build new match. */
372729b7d7a9SBram Moolenaar     m = ALLOC_CLEAR_ONE(matchitem_T);
372829b7d7a9SBram Moolenaar     m->id = id;
372929b7d7a9SBram Moolenaar     m->priority = prio;
373029b7d7a9SBram Moolenaar     m->pattern = pat == NULL ? NULL : vim_strsave(pat);
373129b7d7a9SBram Moolenaar     m->hlg_id = hlg_id;
373229b7d7a9SBram Moolenaar     m->match.regprog = regprog;
373329b7d7a9SBram Moolenaar     m->match.rmm_ic = FALSE;
373429b7d7a9SBram Moolenaar     m->match.rmm_maxcol = 0;
373529b7d7a9SBram Moolenaar # if defined(FEAT_CONCEAL)
373629b7d7a9SBram Moolenaar     m->conceal_char = 0;
373729b7d7a9SBram Moolenaar     if (conceal_char != NULL)
373829b7d7a9SBram Moolenaar 	m->conceal_char = (*mb_ptr2char)(conceal_char);
373929b7d7a9SBram Moolenaar # endif
374029b7d7a9SBram Moolenaar 
374129b7d7a9SBram Moolenaar     /* Set up position matches */
374229b7d7a9SBram Moolenaar     if (pos_list != NULL)
374329b7d7a9SBram Moolenaar     {
374429b7d7a9SBram Moolenaar 	linenr_T	toplnum = 0;
374529b7d7a9SBram Moolenaar 	linenr_T	botlnum = 0;
374629b7d7a9SBram Moolenaar 	listitem_T	*li;
374729b7d7a9SBram Moolenaar 	int		i;
374829b7d7a9SBram Moolenaar 
374929b7d7a9SBram Moolenaar 	for (i = 0, li = pos_list->lv_first; li != NULL && i < MAXPOSMATCH;
375029b7d7a9SBram Moolenaar 							i++, li = li->li_next)
375129b7d7a9SBram Moolenaar 	{
375229b7d7a9SBram Moolenaar 	    linenr_T	lnum = 0;
375329b7d7a9SBram Moolenaar 	    colnr_T	col = 0;
375429b7d7a9SBram Moolenaar 	    int		len = 1;
375529b7d7a9SBram Moolenaar 	    list_T	*subl;
375629b7d7a9SBram Moolenaar 	    listitem_T	*subli;
375729b7d7a9SBram Moolenaar 	    int		error = FALSE;
375829b7d7a9SBram Moolenaar 
375929b7d7a9SBram Moolenaar 	    if (li->li_tv.v_type == VAR_LIST)
376029b7d7a9SBram Moolenaar 	    {
376129b7d7a9SBram Moolenaar 		subl = li->li_tv.vval.v_list;
376229b7d7a9SBram Moolenaar 		if (subl == NULL)
376329b7d7a9SBram Moolenaar 		    goto fail;
376429b7d7a9SBram Moolenaar 		subli = subl->lv_first;
376529b7d7a9SBram Moolenaar 		if (subli == NULL)
376629b7d7a9SBram Moolenaar 		    goto fail;
376729b7d7a9SBram Moolenaar 		lnum = tv_get_number_chk(&subli->li_tv, &error);
376829b7d7a9SBram Moolenaar 		if (error == TRUE)
376929b7d7a9SBram Moolenaar 		    goto fail;
377029b7d7a9SBram Moolenaar 		if (lnum == 0)
377129b7d7a9SBram Moolenaar 		{
377229b7d7a9SBram Moolenaar 		    --i;
377329b7d7a9SBram Moolenaar 		    continue;
377429b7d7a9SBram Moolenaar 		}
377529b7d7a9SBram Moolenaar 		m->pos.pos[i].lnum = lnum;
377629b7d7a9SBram Moolenaar 		subli = subli->li_next;
377729b7d7a9SBram Moolenaar 		if (subli != NULL)
377829b7d7a9SBram Moolenaar 		{
377929b7d7a9SBram Moolenaar 		    col = tv_get_number_chk(&subli->li_tv, &error);
378029b7d7a9SBram Moolenaar 		    if (error == TRUE)
378129b7d7a9SBram Moolenaar 			goto fail;
378229b7d7a9SBram Moolenaar 		    subli = subli->li_next;
378329b7d7a9SBram Moolenaar 		    if (subli != NULL)
378429b7d7a9SBram Moolenaar 		    {
378529b7d7a9SBram Moolenaar 			len = tv_get_number_chk(&subli->li_tv, &error);
378629b7d7a9SBram Moolenaar 			if (error == TRUE)
378729b7d7a9SBram Moolenaar 			    goto fail;
378829b7d7a9SBram Moolenaar 		    }
378929b7d7a9SBram Moolenaar 		}
379029b7d7a9SBram Moolenaar 		m->pos.pos[i].col = col;
379129b7d7a9SBram Moolenaar 		m->pos.pos[i].len = len;
379229b7d7a9SBram Moolenaar 	    }
379329b7d7a9SBram Moolenaar 	    else if (li->li_tv.v_type == VAR_NUMBER)
379429b7d7a9SBram Moolenaar 	    {
379529b7d7a9SBram Moolenaar 		if (li->li_tv.vval.v_number == 0)
379629b7d7a9SBram Moolenaar 		{
379729b7d7a9SBram Moolenaar 		    --i;
379829b7d7a9SBram Moolenaar 		    continue;
379929b7d7a9SBram Moolenaar 		}
380029b7d7a9SBram Moolenaar 		m->pos.pos[i].lnum = li->li_tv.vval.v_number;
380129b7d7a9SBram Moolenaar 		m->pos.pos[i].col = 0;
380229b7d7a9SBram Moolenaar 		m->pos.pos[i].len = 0;
380329b7d7a9SBram Moolenaar 	    }
380429b7d7a9SBram Moolenaar 	    else
380529b7d7a9SBram Moolenaar 	    {
380629b7d7a9SBram Moolenaar 		emsg(_("List or number required"));
380729b7d7a9SBram Moolenaar 		goto fail;
380829b7d7a9SBram Moolenaar 	    }
380929b7d7a9SBram Moolenaar 	    if (toplnum == 0 || lnum < toplnum)
381029b7d7a9SBram Moolenaar 		toplnum = lnum;
381129b7d7a9SBram Moolenaar 	    if (botlnum == 0 || lnum >= botlnum)
381229b7d7a9SBram Moolenaar 		botlnum = lnum + 1;
381329b7d7a9SBram Moolenaar 	}
381429b7d7a9SBram Moolenaar 
381529b7d7a9SBram Moolenaar 	/* Calculate top and bottom lines for redrawing area */
381629b7d7a9SBram Moolenaar 	if (toplnum != 0)
381729b7d7a9SBram Moolenaar 	{
381829b7d7a9SBram Moolenaar 	    if (wp->w_buffer->b_mod_set)
381929b7d7a9SBram Moolenaar 	    {
382029b7d7a9SBram Moolenaar 		if (wp->w_buffer->b_mod_top > toplnum)
382129b7d7a9SBram Moolenaar 		    wp->w_buffer->b_mod_top = toplnum;
382229b7d7a9SBram Moolenaar 		if (wp->w_buffer->b_mod_bot < botlnum)
382329b7d7a9SBram Moolenaar 		    wp->w_buffer->b_mod_bot = botlnum;
382429b7d7a9SBram Moolenaar 	    }
382529b7d7a9SBram Moolenaar 	    else
382629b7d7a9SBram Moolenaar 	    {
382729b7d7a9SBram Moolenaar 		wp->w_buffer->b_mod_set = TRUE;
382829b7d7a9SBram Moolenaar 		wp->w_buffer->b_mod_top = toplnum;
382929b7d7a9SBram Moolenaar 		wp->w_buffer->b_mod_bot = botlnum;
383029b7d7a9SBram Moolenaar 		wp->w_buffer->b_mod_xlines = 0;
383129b7d7a9SBram Moolenaar 	    }
383229b7d7a9SBram Moolenaar 	    m->pos.toplnum = toplnum;
383329b7d7a9SBram Moolenaar 	    m->pos.botlnum = botlnum;
383429b7d7a9SBram Moolenaar 	    rtype = VALID;
383529b7d7a9SBram Moolenaar 	}
383629b7d7a9SBram Moolenaar     }
383729b7d7a9SBram Moolenaar 
383829b7d7a9SBram Moolenaar     /* Insert new match.  The match list is in ascending order with regard to
383929b7d7a9SBram Moolenaar      * the match priorities. */
384029b7d7a9SBram Moolenaar     cur = wp->w_match_head;
384129b7d7a9SBram Moolenaar     prev = cur;
384229b7d7a9SBram Moolenaar     while (cur != NULL && prio >= cur->priority)
384329b7d7a9SBram Moolenaar     {
384429b7d7a9SBram Moolenaar 	prev = cur;
384529b7d7a9SBram Moolenaar 	cur = cur->next;
384629b7d7a9SBram Moolenaar     }
384729b7d7a9SBram Moolenaar     if (cur == prev)
384829b7d7a9SBram Moolenaar 	wp->w_match_head = m;
384929b7d7a9SBram Moolenaar     else
385029b7d7a9SBram Moolenaar 	prev->next = m;
385129b7d7a9SBram Moolenaar     m->next = cur;
385229b7d7a9SBram Moolenaar 
3853*4ef18dccSBram Moolenaar     redraw_win_later(wp, rtype);
385429b7d7a9SBram Moolenaar     return id;
385529b7d7a9SBram Moolenaar 
385629b7d7a9SBram Moolenaar fail:
385729b7d7a9SBram Moolenaar     vim_free(m);
385829b7d7a9SBram Moolenaar     return -1;
385929b7d7a9SBram Moolenaar }
386029b7d7a9SBram Moolenaar 
386129b7d7a9SBram Moolenaar /*
386229b7d7a9SBram Moolenaar  * Delete match with ID 'id' in the match list of window 'wp'.
386329b7d7a9SBram Moolenaar  * Print error messages if 'perr' is TRUE.
386429b7d7a9SBram Moolenaar  */
386529b7d7a9SBram Moolenaar     int
386629b7d7a9SBram Moolenaar match_delete(win_T *wp, int id, int perr)
386729b7d7a9SBram Moolenaar {
386829b7d7a9SBram Moolenaar     matchitem_T	*cur = wp->w_match_head;
386929b7d7a9SBram Moolenaar     matchitem_T	*prev = cur;
387029b7d7a9SBram Moolenaar     int		rtype = SOME_VALID;
387129b7d7a9SBram Moolenaar 
387229b7d7a9SBram Moolenaar     if (id < 1)
387329b7d7a9SBram Moolenaar     {
387429b7d7a9SBram Moolenaar 	if (perr == TRUE)
387529b7d7a9SBram Moolenaar 	    semsg(_("E802: Invalid ID: %d (must be greater than or equal to 1)"),
387629b7d7a9SBram Moolenaar 									  id);
387729b7d7a9SBram Moolenaar 	return -1;
387829b7d7a9SBram Moolenaar     }
387929b7d7a9SBram Moolenaar     while (cur != NULL && cur->id != id)
388029b7d7a9SBram Moolenaar     {
388129b7d7a9SBram Moolenaar 	prev = cur;
388229b7d7a9SBram Moolenaar 	cur = cur->next;
388329b7d7a9SBram Moolenaar     }
388429b7d7a9SBram Moolenaar     if (cur == NULL)
388529b7d7a9SBram Moolenaar     {
388629b7d7a9SBram Moolenaar 	if (perr == TRUE)
388729b7d7a9SBram Moolenaar 	    semsg(_("E803: ID not found: %d"), id);
388829b7d7a9SBram Moolenaar 	return -1;
388929b7d7a9SBram Moolenaar     }
389029b7d7a9SBram Moolenaar     if (cur == prev)
389129b7d7a9SBram Moolenaar 	wp->w_match_head = cur->next;
389229b7d7a9SBram Moolenaar     else
389329b7d7a9SBram Moolenaar 	prev->next = cur->next;
389429b7d7a9SBram Moolenaar     vim_regfree(cur->match.regprog);
389529b7d7a9SBram Moolenaar     vim_free(cur->pattern);
389629b7d7a9SBram Moolenaar     if (cur->pos.toplnum != 0)
389729b7d7a9SBram Moolenaar     {
389829b7d7a9SBram Moolenaar 	if (wp->w_buffer->b_mod_set)
389929b7d7a9SBram Moolenaar 	{
390029b7d7a9SBram Moolenaar 	    if (wp->w_buffer->b_mod_top > cur->pos.toplnum)
390129b7d7a9SBram Moolenaar 		wp->w_buffer->b_mod_top = cur->pos.toplnum;
390229b7d7a9SBram Moolenaar 	    if (wp->w_buffer->b_mod_bot < cur->pos.botlnum)
390329b7d7a9SBram Moolenaar 		wp->w_buffer->b_mod_bot = cur->pos.botlnum;
390429b7d7a9SBram Moolenaar 	}
390529b7d7a9SBram Moolenaar 	else
390629b7d7a9SBram Moolenaar 	{
390729b7d7a9SBram Moolenaar 	    wp->w_buffer->b_mod_set = TRUE;
390829b7d7a9SBram Moolenaar 	    wp->w_buffer->b_mod_top = cur->pos.toplnum;
390929b7d7a9SBram Moolenaar 	    wp->w_buffer->b_mod_bot = cur->pos.botlnum;
391029b7d7a9SBram Moolenaar 	    wp->w_buffer->b_mod_xlines = 0;
391129b7d7a9SBram Moolenaar 	}
391229b7d7a9SBram Moolenaar 	rtype = VALID;
391329b7d7a9SBram Moolenaar     }
391429b7d7a9SBram Moolenaar     vim_free(cur);
391506029a85SBram Moolenaar     redraw_win_later(wp, rtype);
391629b7d7a9SBram Moolenaar     return 0;
391729b7d7a9SBram Moolenaar }
391829b7d7a9SBram Moolenaar 
391929b7d7a9SBram Moolenaar /*
392029b7d7a9SBram Moolenaar  * Delete all matches in the match list of window 'wp'.
392129b7d7a9SBram Moolenaar  */
392229b7d7a9SBram Moolenaar     void
392329b7d7a9SBram Moolenaar clear_matches(win_T *wp)
392429b7d7a9SBram Moolenaar {
392529b7d7a9SBram Moolenaar     matchitem_T *m;
392629b7d7a9SBram Moolenaar 
392729b7d7a9SBram Moolenaar     while (wp->w_match_head != NULL)
392829b7d7a9SBram Moolenaar     {
392929b7d7a9SBram Moolenaar 	m = wp->w_match_head->next;
393029b7d7a9SBram Moolenaar 	vim_regfree(wp->w_match_head->match.regprog);
393129b7d7a9SBram Moolenaar 	vim_free(wp->w_match_head->pattern);
393229b7d7a9SBram Moolenaar 	vim_free(wp->w_match_head);
393329b7d7a9SBram Moolenaar 	wp->w_match_head = m;
393429b7d7a9SBram Moolenaar     }
3935*4ef18dccSBram Moolenaar     redraw_win_later(wp, SOME_VALID);
393629b7d7a9SBram Moolenaar }
393729b7d7a9SBram Moolenaar 
393829b7d7a9SBram Moolenaar /*
393929b7d7a9SBram Moolenaar  * Get match from ID 'id' in window 'wp'.
394029b7d7a9SBram Moolenaar  * Return NULL if match not found.
394129b7d7a9SBram Moolenaar  */
394229b7d7a9SBram Moolenaar     matchitem_T *
394329b7d7a9SBram Moolenaar get_match(win_T *wp, int id)
394429b7d7a9SBram Moolenaar {
394529b7d7a9SBram Moolenaar     matchitem_T *cur = wp->w_match_head;
394629b7d7a9SBram Moolenaar 
394729b7d7a9SBram Moolenaar     while (cur != NULL && cur->id != id)
394829b7d7a9SBram Moolenaar 	cur = cur->next;
394929b7d7a9SBram Moolenaar     return cur;
395029b7d7a9SBram Moolenaar }
3951c61a48d2SBram Moolenaar #endif
395229b7d7a9SBram Moolenaar 
3953c61a48d2SBram Moolenaar #if defined(FEAT_EVAL) || defined(PROTO)
3954c61a48d2SBram Moolenaar # ifdef FEAT_SEARCH_EXTRA
395529b7d7a9SBram Moolenaar     static int
395629b7d7a9SBram Moolenaar matchadd_dict_arg(typval_T *tv, char_u **conceal_char, win_T **win)
395729b7d7a9SBram Moolenaar {
395829b7d7a9SBram Moolenaar     dictitem_T *di;
395929b7d7a9SBram Moolenaar 
396029b7d7a9SBram Moolenaar     if (tv->v_type != VAR_DICT)
396129b7d7a9SBram Moolenaar     {
396229b7d7a9SBram Moolenaar 	emsg(_(e_dictreq));
396329b7d7a9SBram Moolenaar 	return FAIL;
396429b7d7a9SBram Moolenaar     }
396529b7d7a9SBram Moolenaar 
396629b7d7a9SBram Moolenaar     if (dict_find(tv->vval.v_dict, (char_u *)"conceal", -1) != NULL)
396729b7d7a9SBram Moolenaar 	*conceal_char = dict_get_string(tv->vval.v_dict,
396829b7d7a9SBram Moolenaar 						   (char_u *)"conceal", FALSE);
396929b7d7a9SBram Moolenaar 
397029b7d7a9SBram Moolenaar     if ((di = dict_find(tv->vval.v_dict, (char_u *)"window", -1)) != NULL)
397129b7d7a9SBram Moolenaar     {
397229b7d7a9SBram Moolenaar 	*win = find_win_by_nr_or_id(&di->di_tv);
397329b7d7a9SBram Moolenaar 	if (*win == NULL)
397429b7d7a9SBram Moolenaar 	{
397529b7d7a9SBram Moolenaar 	    emsg(_(e_invalwindow));
397629b7d7a9SBram Moolenaar 	    return FAIL;
397729b7d7a9SBram Moolenaar 	}
397829b7d7a9SBram Moolenaar     }
397929b7d7a9SBram Moolenaar 
398029b7d7a9SBram Moolenaar     return OK;
398129b7d7a9SBram Moolenaar }
398229b7d7a9SBram Moolenaar #endif
398329b7d7a9SBram Moolenaar 
398429b7d7a9SBram Moolenaar /*
398529b7d7a9SBram Moolenaar  * "getmatches()" function
398629b7d7a9SBram Moolenaar  */
398729b7d7a9SBram Moolenaar     void
398829b7d7a9SBram Moolenaar f_getmatches(typval_T *argvars UNUSED, typval_T *rettv UNUSED)
398929b7d7a9SBram Moolenaar {
399029b7d7a9SBram Moolenaar # ifdef FEAT_SEARCH_EXTRA
399129b7d7a9SBram Moolenaar     dict_T	*dict;
399229b7d7a9SBram Moolenaar     matchitem_T	*cur;
399329b7d7a9SBram Moolenaar     int		i;
399429b7d7a9SBram Moolenaar     win_T	*win = get_optional_window(argvars, 0);
399529b7d7a9SBram Moolenaar 
399629b7d7a9SBram Moolenaar     if (rettv_list_alloc(rettv) == FAIL || win == NULL)
399729b7d7a9SBram Moolenaar 	return;
399829b7d7a9SBram Moolenaar 
399929b7d7a9SBram Moolenaar     cur = win->w_match_head;
400029b7d7a9SBram Moolenaar     while (cur != NULL)
400129b7d7a9SBram Moolenaar     {
400229b7d7a9SBram Moolenaar 	dict = dict_alloc();
400329b7d7a9SBram Moolenaar 	if (dict == NULL)
400429b7d7a9SBram Moolenaar 	    return;
400529b7d7a9SBram Moolenaar 	if (cur->match.regprog == NULL)
400629b7d7a9SBram Moolenaar 	{
400729b7d7a9SBram Moolenaar 	    /* match added with matchaddpos() */
400829b7d7a9SBram Moolenaar 	    for (i = 0; i < MAXPOSMATCH; ++i)
400929b7d7a9SBram Moolenaar 	    {
401029b7d7a9SBram Moolenaar 		llpos_T	*llpos;
401129b7d7a9SBram Moolenaar 		char	buf[30];  // use 30 to avoid compiler warning
401229b7d7a9SBram Moolenaar 		list_T	*l;
401329b7d7a9SBram Moolenaar 
401429b7d7a9SBram Moolenaar 		llpos = &cur->pos.pos[i];
401529b7d7a9SBram Moolenaar 		if (llpos->lnum == 0)
401629b7d7a9SBram Moolenaar 		    break;
401729b7d7a9SBram Moolenaar 		l = list_alloc();
401829b7d7a9SBram Moolenaar 		if (l == NULL)
401929b7d7a9SBram Moolenaar 		    break;
402029b7d7a9SBram Moolenaar 		list_append_number(l, (varnumber_T)llpos->lnum);
402129b7d7a9SBram Moolenaar 		if (llpos->col > 0)
402229b7d7a9SBram Moolenaar 		{
402329b7d7a9SBram Moolenaar 		    list_append_number(l, (varnumber_T)llpos->col);
402429b7d7a9SBram Moolenaar 		    list_append_number(l, (varnumber_T)llpos->len);
402529b7d7a9SBram Moolenaar 		}
402629b7d7a9SBram Moolenaar 		sprintf(buf, "pos%d", i + 1);
402729b7d7a9SBram Moolenaar 		dict_add_list(dict, buf, l);
402829b7d7a9SBram Moolenaar 	    }
402929b7d7a9SBram Moolenaar 	}
403029b7d7a9SBram Moolenaar 	else
403129b7d7a9SBram Moolenaar 	{
403229b7d7a9SBram Moolenaar 	    dict_add_string(dict, "pattern", cur->pattern);
403329b7d7a9SBram Moolenaar 	}
403429b7d7a9SBram Moolenaar 	dict_add_string(dict, "group", syn_id2name(cur->hlg_id));
403529b7d7a9SBram Moolenaar 	dict_add_number(dict, "priority", (long)cur->priority);
403629b7d7a9SBram Moolenaar 	dict_add_number(dict, "id", (long)cur->id);
403729b7d7a9SBram Moolenaar #  if defined(FEAT_CONCEAL)
403829b7d7a9SBram Moolenaar 	if (cur->conceal_char)
403929b7d7a9SBram Moolenaar 	{
404029b7d7a9SBram Moolenaar 	    char_u buf[MB_MAXBYTES + 1];
404129b7d7a9SBram Moolenaar 
404229b7d7a9SBram Moolenaar 	    buf[(*mb_char2bytes)((int)cur->conceal_char, buf)] = NUL;
404329b7d7a9SBram Moolenaar 	    dict_add_string(dict, "conceal", (char_u *)&buf);
404429b7d7a9SBram Moolenaar 	}
404529b7d7a9SBram Moolenaar #  endif
404629b7d7a9SBram Moolenaar 	list_append_dict(rettv->vval.v_list, dict);
404729b7d7a9SBram Moolenaar 	cur = cur->next;
404829b7d7a9SBram Moolenaar     }
404929b7d7a9SBram Moolenaar # endif
405029b7d7a9SBram Moolenaar }
405129b7d7a9SBram Moolenaar 
405229b7d7a9SBram Moolenaar /*
405329b7d7a9SBram Moolenaar  * "matchadd()" function
405429b7d7a9SBram Moolenaar  */
405529b7d7a9SBram Moolenaar     void
405629b7d7a9SBram Moolenaar f_matchadd(typval_T *argvars UNUSED, typval_T *rettv UNUSED)
405729b7d7a9SBram Moolenaar {
405829b7d7a9SBram Moolenaar # ifdef FEAT_SEARCH_EXTRA
405929b7d7a9SBram Moolenaar     char_u	buf[NUMBUFLEN];
406029b7d7a9SBram Moolenaar     char_u	*grp = tv_get_string_buf_chk(&argvars[0], buf);	/* group */
406129b7d7a9SBram Moolenaar     char_u	*pat = tv_get_string_buf_chk(&argvars[1], buf);	/* pattern */
406229b7d7a9SBram Moolenaar     int		prio = 10;	/* default priority */
406329b7d7a9SBram Moolenaar     int		id = -1;
406429b7d7a9SBram Moolenaar     int		error = FALSE;
406529b7d7a9SBram Moolenaar     char_u	*conceal_char = NULL;
406629b7d7a9SBram Moolenaar     win_T	*win = curwin;
406729b7d7a9SBram Moolenaar 
406829b7d7a9SBram Moolenaar     rettv->vval.v_number = -1;
406929b7d7a9SBram Moolenaar 
407029b7d7a9SBram Moolenaar     if (grp == NULL || pat == NULL)
407129b7d7a9SBram Moolenaar 	return;
407229b7d7a9SBram Moolenaar     if (argvars[2].v_type != VAR_UNKNOWN)
407329b7d7a9SBram Moolenaar     {
407429b7d7a9SBram Moolenaar 	prio = (int)tv_get_number_chk(&argvars[2], &error);
407529b7d7a9SBram Moolenaar 	if (argvars[3].v_type != VAR_UNKNOWN)
407629b7d7a9SBram Moolenaar 	{
407729b7d7a9SBram Moolenaar 	    id = (int)tv_get_number_chk(&argvars[3], &error);
407829b7d7a9SBram Moolenaar 	    if (argvars[4].v_type != VAR_UNKNOWN
407929b7d7a9SBram Moolenaar 		&& matchadd_dict_arg(&argvars[4], &conceal_char, &win) == FAIL)
408029b7d7a9SBram Moolenaar 		return;
408129b7d7a9SBram Moolenaar 	}
408229b7d7a9SBram Moolenaar     }
408329b7d7a9SBram Moolenaar     if (error == TRUE)
408429b7d7a9SBram Moolenaar 	return;
408529b7d7a9SBram Moolenaar     if (id >= 1 && id <= 3)
408629b7d7a9SBram Moolenaar     {
408729b7d7a9SBram Moolenaar 	semsg(_("E798: ID is reserved for \":match\": %d"), id);
408829b7d7a9SBram Moolenaar 	return;
408929b7d7a9SBram Moolenaar     }
409029b7d7a9SBram Moolenaar 
409129b7d7a9SBram Moolenaar     rettv->vval.v_number = match_add(win, grp, pat, prio, id, NULL,
409229b7d7a9SBram Moolenaar 								conceal_char);
409329b7d7a9SBram Moolenaar # endif
409429b7d7a9SBram Moolenaar }
409529b7d7a9SBram Moolenaar 
409629b7d7a9SBram Moolenaar /*
409729b7d7a9SBram Moolenaar  * "matchaddpos()" function
409829b7d7a9SBram Moolenaar  */
409929b7d7a9SBram Moolenaar     void
410029b7d7a9SBram Moolenaar f_matchaddpos(typval_T *argvars UNUSED, typval_T *rettv UNUSED)
410129b7d7a9SBram Moolenaar {
410229b7d7a9SBram Moolenaar # ifdef FEAT_SEARCH_EXTRA
410329b7d7a9SBram Moolenaar     char_u	buf[NUMBUFLEN];
410429b7d7a9SBram Moolenaar     char_u	*group;
410529b7d7a9SBram Moolenaar     int		prio = 10;
410629b7d7a9SBram Moolenaar     int		id = -1;
410729b7d7a9SBram Moolenaar     int		error = FALSE;
410829b7d7a9SBram Moolenaar     list_T	*l;
410929b7d7a9SBram Moolenaar     char_u	*conceal_char = NULL;
411029b7d7a9SBram Moolenaar     win_T	*win = curwin;
411129b7d7a9SBram Moolenaar 
411229b7d7a9SBram Moolenaar     rettv->vval.v_number = -1;
411329b7d7a9SBram Moolenaar 
411429b7d7a9SBram Moolenaar     group = tv_get_string_buf_chk(&argvars[0], buf);
411529b7d7a9SBram Moolenaar     if (group == NULL)
411629b7d7a9SBram Moolenaar 	return;
411729b7d7a9SBram Moolenaar 
411829b7d7a9SBram Moolenaar     if (argvars[1].v_type != VAR_LIST)
411929b7d7a9SBram Moolenaar     {
412029b7d7a9SBram Moolenaar 	semsg(_(e_listarg), "matchaddpos()");
412129b7d7a9SBram Moolenaar 	return;
412229b7d7a9SBram Moolenaar     }
412329b7d7a9SBram Moolenaar     l = argvars[1].vval.v_list;
412429b7d7a9SBram Moolenaar     if (l == NULL)
412529b7d7a9SBram Moolenaar 	return;
412629b7d7a9SBram Moolenaar 
412729b7d7a9SBram Moolenaar     if (argvars[2].v_type != VAR_UNKNOWN)
412829b7d7a9SBram Moolenaar     {
412929b7d7a9SBram Moolenaar 	prio = (int)tv_get_number_chk(&argvars[2], &error);
413029b7d7a9SBram Moolenaar 	if (argvars[3].v_type != VAR_UNKNOWN)
413129b7d7a9SBram Moolenaar 	{
413229b7d7a9SBram Moolenaar 	    id = (int)tv_get_number_chk(&argvars[3], &error);
413329b7d7a9SBram Moolenaar 
413429b7d7a9SBram Moolenaar 	    if (argvars[4].v_type != VAR_UNKNOWN
413529b7d7a9SBram Moolenaar 		&& matchadd_dict_arg(&argvars[4], &conceal_char, &win) == FAIL)
413629b7d7a9SBram Moolenaar 		return;
413729b7d7a9SBram Moolenaar 	}
413829b7d7a9SBram Moolenaar     }
413929b7d7a9SBram Moolenaar     if (error == TRUE)
414029b7d7a9SBram Moolenaar 	return;
414129b7d7a9SBram Moolenaar 
414229b7d7a9SBram Moolenaar     /* id == 3 is ok because matchaddpos() is supposed to substitute :3match */
414329b7d7a9SBram Moolenaar     if (id == 1 || id == 2)
414429b7d7a9SBram Moolenaar     {
414529b7d7a9SBram Moolenaar 	semsg(_("E798: ID is reserved for \":match\": %d"), id);
414629b7d7a9SBram Moolenaar 	return;
414729b7d7a9SBram Moolenaar     }
414829b7d7a9SBram Moolenaar 
414929b7d7a9SBram Moolenaar     rettv->vval.v_number = match_add(win, group, NULL, prio, id, l,
415029b7d7a9SBram Moolenaar 								conceal_char);
415129b7d7a9SBram Moolenaar # endif
415229b7d7a9SBram Moolenaar }
415329b7d7a9SBram Moolenaar 
415429b7d7a9SBram Moolenaar /*
415529b7d7a9SBram Moolenaar  * "matcharg()" function
415629b7d7a9SBram Moolenaar  */
415729b7d7a9SBram Moolenaar     void
415829b7d7a9SBram Moolenaar f_matcharg(typval_T *argvars UNUSED, typval_T *rettv)
415929b7d7a9SBram Moolenaar {
416029b7d7a9SBram Moolenaar     if (rettv_list_alloc(rettv) == OK)
416129b7d7a9SBram Moolenaar     {
416229b7d7a9SBram Moolenaar # ifdef FEAT_SEARCH_EXTRA
416329b7d7a9SBram Moolenaar 	int	    id = (int)tv_get_number(&argvars[0]);
416429b7d7a9SBram Moolenaar 	matchitem_T *m;
416529b7d7a9SBram Moolenaar 
416629b7d7a9SBram Moolenaar 	if (id >= 1 && id <= 3)
416729b7d7a9SBram Moolenaar 	{
416829b7d7a9SBram Moolenaar 	    if ((m = (matchitem_T *)get_match(curwin, id)) != NULL)
416929b7d7a9SBram Moolenaar 	    {
417029b7d7a9SBram Moolenaar 		list_append_string(rettv->vval.v_list,
417129b7d7a9SBram Moolenaar 						syn_id2name(m->hlg_id), -1);
417229b7d7a9SBram Moolenaar 		list_append_string(rettv->vval.v_list, m->pattern, -1);
417329b7d7a9SBram Moolenaar 	    }
417429b7d7a9SBram Moolenaar 	    else
417529b7d7a9SBram Moolenaar 	    {
417629b7d7a9SBram Moolenaar 		list_append_string(rettv->vval.v_list, NULL, -1);
417729b7d7a9SBram Moolenaar 		list_append_string(rettv->vval.v_list, NULL, -1);
417829b7d7a9SBram Moolenaar 	    }
417929b7d7a9SBram Moolenaar 	}
418029b7d7a9SBram Moolenaar # endif
418129b7d7a9SBram Moolenaar     }
418229b7d7a9SBram Moolenaar }
418329b7d7a9SBram Moolenaar 
418429b7d7a9SBram Moolenaar /*
418529b7d7a9SBram Moolenaar  * "matchdelete()" function
418629b7d7a9SBram Moolenaar  */
418729b7d7a9SBram Moolenaar     void
418829b7d7a9SBram Moolenaar f_matchdelete(typval_T *argvars UNUSED, typval_T *rettv UNUSED)
418929b7d7a9SBram Moolenaar {
419029b7d7a9SBram Moolenaar # ifdef FEAT_SEARCH_EXTRA
419129b7d7a9SBram Moolenaar     win_T   *win = get_optional_window(argvars, 1);
419229b7d7a9SBram Moolenaar 
419329b7d7a9SBram Moolenaar     if (win == NULL)
419429b7d7a9SBram Moolenaar 	rettv->vval.v_number = -1;
419529b7d7a9SBram Moolenaar     else
419629b7d7a9SBram Moolenaar 	rettv->vval.v_number = match_delete(win,
419729b7d7a9SBram Moolenaar 				       (int)tv_get_number(&argvars[0]), TRUE);
419829b7d7a9SBram Moolenaar # endif
419929b7d7a9SBram Moolenaar }
4200c61a48d2SBram Moolenaar #endif
4201