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