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