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