-
-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathhighlight.c
4581 lines (4183 loc) · 123 KB
/
highlight.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
/* vi:set ts=8 sts=4 sw=4 noet:
*
* VIM - Vi IMproved by Bram Moolenaar
*
* Do ":help uganda" in Vim to read copying and usage conditions.
* Do ":help credits" in Vim to see a list of people who contributed.
* See README.txt for an overview of the Vim source code.
*/
/*
* Highlighting stuff.
*/
#include "vim.h"
#define SG_TERM 1 // term has been set
#define SG_CTERM 2 // cterm has been set
#define SG_GUI 4 // gui has been set
#define SG_LINK 8 // link has been set
#define MAX_SYN_NAME 200
/*
* The "term", "cterm" and "gui" arguments can be any combination of the
* following names, separated by commas (but no spaces!).
*/
static char *(hl_name_table[]) =
{"bold", "standout", "underline",
"undercurl", "underdouble", "underdotted", "underdashed",
"italic", "reverse", "inverse", "nocombine", "strikethrough", "NONE"};
static int hl_attr_table[] =
{HL_BOLD, HL_STANDOUT, HL_UNDERLINE,
HL_UNDERCURL, HL_UNDERDOUBLE, HL_UNDERDOTTED, HL_UNDERDASHED,
HL_ITALIC, HL_INVERSE, HL_INVERSE, HL_NOCOMBINE, HL_STRIKETHROUGH, 0};
// length of all attribute names, plus commas, together (and a bit more)
#define MAX_ATTR_LEN 120
#define ATTR_COMBINE(attr_a, attr_b) ((((attr_b) & HL_NOCOMBINE) ? (attr_b) : (attr_a)) | (attr_b))
/*
* Structure that stores information about a highlight group.
* The ID of a highlight group is also called group ID. It is the index in
* the highlight_ga array PLUS ONE.
*/
typedef struct
{
char_u *sg_name; // highlight group name
char_u *sg_name_u; // uppercase of sg_name
int sg_cleared; // "hi clear" was used
// for normal terminals
int sg_term; // "term=" highlighting attributes
char_u *sg_start; // terminal string for start highl
char_u *sg_stop; // terminal string for stop highl
int sg_term_attr; // Screen attr for term mode
// for color terminals
int sg_cterm; // "cterm=" highlighting attr
int sg_cterm_bold; // bold attr was set for light color
int sg_cterm_fg; // terminal fg color number + 1
int sg_cterm_bg; // terminal bg color number + 1
int sg_cterm_ul; // terminal ul color number + 1
int sg_cterm_attr; // Screen attr for color term mode
// for when using the GUI
#if defined(FEAT_GUI) || defined(FEAT_TERMGUICOLORS)
guicolor_T sg_gui_fg; // GUI foreground color handle
guicolor_T sg_gui_bg; // GUI background color handle
guicolor_T sg_gui_sp; // GUI special color handle
#endif
#ifdef FEAT_GUI
GuiFont sg_font; // GUI font handle
#ifdef FEAT_XFONTSET
GuiFontset sg_fontset; // GUI fontset handle
#endif
char_u *sg_font_name; // GUI font or fontset name
int sg_gui_attr; // Screen attr for GUI mode
#endif
#if defined(FEAT_GUI) || defined(FEAT_EVAL)
// Store the sp color name for the GUI or synIDattr()
int sg_gui; // "gui=" highlighting attributes
char_u *sg_gui_fg_name;// GUI foreground color name
char_u *sg_gui_bg_name;// GUI background color name
char_u *sg_gui_sp_name;// GUI special color name
#endif
int sg_link; // link to this highlight group ID
int sg_deflink; // default link; restored in highlight_clear()
int sg_set; // combination of SG_* flags
#ifdef FEAT_EVAL
sctx_T sg_deflink_sctx; // script where the default link was set
sctx_T sg_script_ctx; // script in which the group was last set
#endif
} hl_group_T;
// highlight groups for 'highlight' option
static garray_T highlight_ga;
#define HL_TABLE() ((hl_group_T *)((highlight_ga.ga_data)))
/*
* An attribute number is the index in attr_table plus ATTR_OFF.
*/
#define ATTR_OFF (HL_ALL + 1)
static void syn_unadd_group(void);
static void set_hl_attr(int idx);
static void highlight_list_one(int id);
static int highlight_list_arg(int id, int didh, int type, int iarg, char_u *sarg, char *name);
static int syn_add_group(char_u *name);
static int hl_has_settings(int idx, int check_link);
static void highlight_clear(int idx);
#if defined(FEAT_GUI) || defined(FEAT_TERMGUICOLORS)
static void gui_do_one_color(int idx, int do_menu, int do_tooltip);
#endif
#ifdef FEAT_GUI
static int set_group_colors(char_u *name, guicolor_T *fgp, guicolor_T *bgp, int do_menu, int use_norm, int do_tooltip);
static void hl_do_font(int idx, char_u *arg, int do_normal, int do_menu, int do_tooltip, int free_font);
#endif
/*
* The default highlight groups. These are compiled-in for fast startup and
* they still work when the runtime files can't be found.
* When making changes here, also change runtime/colors/default.vim!
* The #ifdefs are needed to reduce the amount of static data. Helps to make
* the 16 bit DOS (museum) version compile.
*/
#if defined(FEAT_GUI) || defined(FEAT_EVAL)
# define CENT(a, b) b
#else
# define CENT(a, b) a
#endif
static char *(highlight_init_both[]) = {
CENT("ErrorMsg term=standout ctermbg=DarkRed ctermfg=White",
"ErrorMsg term=standout ctermbg=DarkRed ctermfg=White guibg=Red guifg=White"),
CENT("IncSearch term=reverse cterm=reverse",
"IncSearch term=reverse cterm=reverse gui=reverse"),
CENT("ModeMsg term=bold cterm=bold",
"ModeMsg term=bold cterm=bold gui=bold"),
CENT("NonText term=bold ctermfg=Blue",
"NonText term=bold ctermfg=Blue gui=bold guifg=Blue"),
CENT("StatusLine term=reverse,bold cterm=reverse,bold",
"StatusLine term=reverse,bold cterm=reverse,bold gui=reverse,bold"),
CENT("StatusLineNC term=reverse cterm=reverse",
"StatusLineNC term=reverse cterm=reverse gui=reverse"),
"default link EndOfBuffer NonText",
CENT("VertSplit term=reverse cterm=reverse",
"VertSplit term=reverse cterm=reverse gui=reverse"),
#ifdef FEAT_CLIPBOARD
CENT("VisualNOS term=underline,bold cterm=underline,bold",
"VisualNOS term=underline,bold cterm=underline,bold gui=underline,bold"),
#endif
#ifdef FEAT_DIFF
CENT("DiffText term=reverse cterm=bold ctermbg=Red",
"DiffText term=reverse cterm=bold ctermbg=Red gui=bold guibg=Red"),
#endif
CENT("PmenuSbar ctermbg=Grey",
"PmenuSbar ctermbg=Grey guibg=Grey"),
CENT("TabLineSel term=bold cterm=bold",
"TabLineSel term=bold cterm=bold gui=bold"),
CENT("TabLineFill term=reverse cterm=reverse",
"TabLineFill term=reverse cterm=reverse gui=reverse"),
#ifdef FEAT_GUI
"Cursor guibg=fg guifg=bg",
"lCursor guibg=fg guifg=bg", // should be different, but what?
#endif
"default link QuickFixLine Search",
"default link CursorLineSign SignColumn",
"default link CursorLineFold FoldColumn",
"default link CurSearch Search",
"default link PmenuKind Pmenu",
"default link PmenuKindSel PmenuSel",
"default link PmenuExtra Pmenu",
"default link PmenuExtraSel PmenuSel",
CENT("Normal cterm=NONE", "Normal gui=NONE"),
NULL
};
// Default colors only used with a light background.
static char *(highlight_init_light[]) = {
CENT("Directory term=bold ctermfg=DarkBlue",
"Directory term=bold ctermfg=DarkBlue guifg=Blue"),
CENT("LineNr term=underline ctermfg=Brown",
"LineNr term=underline ctermfg=Brown guifg=Brown"),
CENT("CursorLineNr term=bold cterm=underline ctermfg=Brown",
"CursorLineNr term=bold cterm=underline ctermfg=Brown gui=bold guifg=Brown"),
CENT("MoreMsg term=bold ctermfg=DarkGreen",
"MoreMsg term=bold ctermfg=DarkGreen gui=bold guifg=SeaGreen"),
CENT("Question term=standout ctermfg=DarkGreen",
"Question term=standout ctermfg=DarkGreen gui=bold guifg=SeaGreen"),
CENT("Search term=reverse ctermbg=Yellow ctermfg=NONE",
"Search term=reverse ctermbg=Yellow ctermfg=NONE guibg=Yellow guifg=NONE"),
#ifdef FEAT_SPELL
CENT("SpellBad term=reverse ctermbg=LightRed",
"SpellBad term=reverse ctermbg=LightRed guisp=Red gui=undercurl"),
CENT("SpellCap term=reverse ctermbg=LightBlue",
"SpellCap term=reverse ctermbg=LightBlue guisp=Blue gui=undercurl"),
CENT("SpellRare term=reverse ctermbg=LightMagenta",
"SpellRare term=reverse ctermbg=LightMagenta guisp=Magenta gui=undercurl"),
CENT("SpellLocal term=underline ctermbg=Cyan",
"SpellLocal term=underline ctermbg=Cyan guisp=DarkCyan gui=undercurl"),
#endif
CENT("PmenuThumb ctermbg=Black",
"PmenuThumb ctermbg=Black guibg=Black"),
CENT("Pmenu ctermbg=LightMagenta ctermfg=Black",
"Pmenu ctermbg=LightMagenta ctermfg=Black guibg=LightMagenta"),
CENT("PmenuSel ctermbg=LightGrey ctermfg=Black",
"PmenuSel ctermbg=LightGrey ctermfg=Black guibg=Grey"),
CENT("SpecialKey term=bold ctermfg=DarkBlue",
"SpecialKey term=bold ctermfg=DarkBlue guifg=Blue"),
CENT("Title term=bold ctermfg=DarkMagenta",
"Title term=bold ctermfg=DarkMagenta gui=bold guifg=Magenta"),
CENT("WarningMsg term=standout ctermfg=DarkRed",
"WarningMsg term=standout ctermfg=DarkRed guifg=Red"),
CENT("WildMenu term=standout ctermbg=Yellow ctermfg=Black",
"WildMenu term=standout ctermbg=Yellow ctermfg=Black guibg=Yellow guifg=Black"),
#ifdef FEAT_FOLDING
CENT("Folded term=standout ctermbg=Grey ctermfg=DarkBlue",
"Folded term=standout ctermbg=Grey ctermfg=DarkBlue guibg=LightGrey guifg=DarkBlue"),
CENT("FoldColumn term=standout ctermbg=Grey ctermfg=DarkBlue",
"FoldColumn term=standout ctermbg=Grey ctermfg=DarkBlue guibg=Grey guifg=DarkBlue"),
#endif
#ifdef FEAT_SIGNS
CENT("SignColumn term=standout ctermbg=Grey ctermfg=DarkBlue",
"SignColumn term=standout ctermbg=Grey ctermfg=DarkBlue guibg=Grey guifg=DarkBlue"),
#endif
CENT("Visual term=reverse",
"Visual term=reverse guibg=LightGrey"),
#ifdef FEAT_DIFF
CENT("DiffAdd term=bold ctermbg=LightBlue",
"DiffAdd term=bold ctermbg=LightBlue guibg=LightBlue"),
CENT("DiffChange term=bold ctermbg=LightMagenta",
"DiffChange term=bold ctermbg=LightMagenta guibg=LightMagenta"),
CENT("DiffDelete term=bold ctermfg=Blue ctermbg=LightCyan",
"DiffDelete term=bold ctermfg=Blue ctermbg=LightCyan gui=bold guifg=Blue guibg=LightCyan"),
#endif
CENT("TabLine term=underline cterm=underline ctermfg=black ctermbg=LightGrey",
"TabLine term=underline cterm=underline ctermfg=black ctermbg=LightGrey gui=underline guibg=LightGrey"),
#ifdef FEAT_SYN_HL
CENT("CursorColumn term=reverse ctermbg=LightGrey",
"CursorColumn term=reverse ctermbg=LightGrey guibg=Grey90"),
CENT("CursorLine term=underline cterm=underline",
"CursorLine term=underline cterm=underline guibg=Grey90"),
CENT("ColorColumn term=reverse ctermbg=LightRed",
"ColorColumn term=reverse ctermbg=LightRed guibg=LightRed"),
#endif
#ifdef FEAT_CONCEAL
CENT("Conceal ctermbg=DarkGrey ctermfg=LightGrey",
"Conceal ctermbg=DarkGrey ctermfg=LightGrey guibg=DarkGrey guifg=LightGrey"),
#endif
CENT("MatchParen term=reverse ctermbg=Cyan",
"MatchParen term=reverse ctermbg=Cyan guibg=Cyan"),
#ifdef FEAT_TERMINAL
CENT("StatusLineTerm term=reverse,bold cterm=bold ctermfg=White ctermbg=DarkGreen",
"StatusLineTerm term=reverse,bold cterm=bold ctermfg=White ctermbg=DarkGreen gui=bold guifg=bg guibg=DarkGreen"),
CENT("StatusLineTermNC term=reverse ctermfg=White ctermbg=DarkGreen",
"StatusLineTermNC term=reverse ctermfg=White ctermbg=DarkGreen guifg=bg guibg=DarkGreen"),
#endif
#ifdef FEAT_MENU
CENT("ToolbarLine term=underline ctermbg=LightGrey",
"ToolbarLine term=underline ctermbg=LightGrey guibg=LightGrey"),
CENT("ToolbarButton cterm=bold ctermfg=White ctermbg=DarkGrey",
"ToolbarButton cterm=bold ctermfg=White ctermbg=DarkGrey gui=bold guifg=White guibg=Grey40"),
#endif
NULL
};
// Default colors only used with a dark background.
static char *(highlight_init_dark[]) = {
CENT("Directory term=bold ctermfg=LightCyan",
"Directory term=bold ctermfg=LightCyan guifg=Cyan"),
CENT("LineNr term=underline ctermfg=Yellow",
"LineNr term=underline ctermfg=Yellow guifg=Yellow"),
CENT("CursorLineNr term=bold cterm=underline ctermfg=Yellow",
"CursorLineNr term=bold cterm=underline ctermfg=Yellow gui=bold guifg=Yellow"),
CENT("MoreMsg term=bold ctermfg=LightGreen",
"MoreMsg term=bold ctermfg=LightGreen gui=bold guifg=SeaGreen"),
CENT("Question term=standout ctermfg=LightGreen",
"Question term=standout ctermfg=LightGreen gui=bold guifg=Green"),
CENT("Search term=reverse ctermbg=Yellow ctermfg=Black",
"Search term=reverse ctermbg=Yellow ctermfg=Black guibg=Yellow guifg=Black"),
CENT("SpecialKey term=bold ctermfg=LightBlue",
"SpecialKey term=bold ctermfg=LightBlue guifg=Cyan"),
#ifdef FEAT_SPELL
CENT("SpellBad term=reverse ctermbg=Red",
"SpellBad term=reverse ctermbg=Red guisp=Red gui=undercurl"),
CENT("SpellCap term=reverse ctermbg=Blue",
"SpellCap term=reverse ctermbg=Blue guisp=Blue gui=undercurl"),
CENT("SpellRare term=reverse ctermbg=Magenta",
"SpellRare term=reverse ctermbg=Magenta guisp=Magenta gui=undercurl"),
CENT("SpellLocal term=underline ctermbg=Cyan",
"SpellLocal term=underline ctermbg=Cyan guisp=Cyan gui=undercurl"),
#endif
CENT("PmenuThumb ctermbg=White",
"PmenuThumb ctermbg=White guibg=White"),
CENT("Pmenu ctermbg=Magenta ctermfg=Black",
"Pmenu ctermbg=Magenta ctermfg=Black guibg=Magenta"),
CENT("PmenuSel ctermbg=Black ctermfg=DarkGrey",
"PmenuSel ctermbg=Black ctermfg=DarkGrey guibg=DarkGrey"),
CENT("Title term=bold ctermfg=LightMagenta",
"Title term=bold ctermfg=LightMagenta gui=bold guifg=Magenta"),
CENT("WarningMsg term=standout ctermfg=LightRed",
"WarningMsg term=standout ctermfg=LightRed guifg=Red"),
CENT("WildMenu term=standout ctermbg=Yellow ctermfg=Black",
"WildMenu term=standout ctermbg=Yellow ctermfg=Black guibg=Yellow guifg=Black"),
#ifdef FEAT_FOLDING
CENT("Folded term=standout ctermbg=DarkGrey ctermfg=Cyan",
"Folded term=standout ctermbg=DarkGrey ctermfg=Cyan guibg=DarkGrey guifg=Cyan"),
CENT("FoldColumn term=standout ctermbg=DarkGrey ctermfg=Cyan",
"FoldColumn term=standout ctermbg=DarkGrey ctermfg=Cyan guibg=Grey guifg=Cyan"),
#endif
#ifdef FEAT_SIGNS
CENT("SignColumn term=standout ctermbg=DarkGrey ctermfg=Cyan",
"SignColumn term=standout ctermbg=DarkGrey ctermfg=Cyan guibg=Grey guifg=Cyan"),
#endif
CENT("Visual term=reverse",
"Visual term=reverse guibg=DarkGrey"),
#ifdef FEAT_DIFF
CENT("DiffAdd term=bold ctermbg=DarkBlue",
"DiffAdd term=bold ctermbg=DarkBlue guibg=DarkBlue"),
CENT("DiffChange term=bold ctermbg=DarkMagenta",
"DiffChange term=bold ctermbg=DarkMagenta guibg=DarkMagenta"),
CENT("DiffDelete term=bold ctermfg=Blue ctermbg=DarkCyan",
"DiffDelete term=bold ctermfg=Blue ctermbg=DarkCyan gui=bold guifg=Blue guibg=DarkCyan"),
#endif
CENT("TabLine term=underline cterm=underline ctermfg=white ctermbg=DarkGrey",
"TabLine term=underline cterm=underline ctermfg=white ctermbg=DarkGrey gui=underline guibg=DarkGrey"),
#ifdef FEAT_SYN_HL
CENT("CursorColumn term=reverse ctermbg=DarkGrey",
"CursorColumn term=reverse ctermbg=DarkGrey guibg=Grey40"),
CENT("CursorLine term=underline cterm=underline",
"CursorLine term=underline cterm=underline guibg=Grey40"),
CENT("ColorColumn term=reverse ctermbg=DarkRed",
"ColorColumn term=reverse ctermbg=DarkRed guibg=DarkRed"),
#endif
CENT("MatchParen term=reverse ctermbg=DarkCyan",
"MatchParen term=reverse ctermbg=DarkCyan guibg=DarkCyan"),
#ifdef FEAT_CONCEAL
CENT("Conceal ctermbg=DarkGrey ctermfg=LightGrey",
"Conceal ctermbg=DarkGrey ctermfg=LightGrey guibg=DarkGrey guifg=LightGrey"),
#endif
#ifdef FEAT_TERMINAL
CENT("StatusLineTerm term=reverse,bold cterm=bold ctermfg=Black ctermbg=LightGreen",
"StatusLineTerm term=reverse,bold cterm=bold ctermfg=Black ctermbg=LightGreen gui=bold guifg=bg guibg=LightGreen"),
CENT("StatusLineTermNC term=reverse ctermfg=Black ctermbg=LightGreen",
"StatusLineTermNC term=reverse ctermfg=Black ctermbg=LightGreen guifg=bg guibg=LightGreen"),
#endif
#ifdef FEAT_MENU
CENT("ToolbarLine term=underline ctermbg=DarkGrey",
"ToolbarLine term=underline ctermbg=DarkGrey guibg=Grey50"),
CENT("ToolbarButton cterm=bold ctermfg=Black ctermbg=LightGrey",
"ToolbarButton cterm=bold ctermfg=Black ctermbg=LightGrey gui=bold guifg=Black guibg=LightGrey"),
#endif
NULL
};
#if defined(FEAT_SYN_HL) || defined(PROTO)
/*
* Returns the number of highlight groups.
*/
int
highlight_num_groups(void)
{
return highlight_ga.ga_len;
}
/*
* Returns the name of a highlight group.
*/
char_u *
highlight_group_name(int id)
{
return HL_TABLE()[id].sg_name;
}
/*
* Returns the ID of the link to a highlight group.
*/
int
highlight_link_id(int id)
{
return HL_TABLE()[id].sg_link;
}
#endif
void
init_highlight(
int both, // include groups where 'bg' doesn't matter
int reset) // clear group first
{
int i;
char **pp;
static int had_both = FALSE;
#ifdef FEAT_EVAL
char_u *p;
// Try finding the color scheme file. Used when a color file was loaded
// and 'background' or 't_Co' is changed.
p = get_var_value((char_u *)"g:colors_name");
if (p != NULL)
{
// The value of g:colors_name could be freed when sourcing the script,
// making "p" invalid, so copy it.
char_u *copy_p = vim_strsave(p);
int r;
if (copy_p != NULL)
{
r = load_colors(copy_p);
vim_free(copy_p);
if (r == OK)
return;
}
}
#endif
// Didn't use a color file, use the compiled-in colors.
if (both)
{
had_both = TRUE;
pp = highlight_init_both;
for (i = 0; pp[i] != NULL; ++i)
do_highlight((char_u *)pp[i], reset, TRUE);
}
else if (!had_both)
// Don't do anything before the call with both == TRUE from main().
// Not everything has been setup then, and that call will overrule
// everything anyway.
return;
if (*p_bg == 'l')
pp = highlight_init_light;
else
pp = highlight_init_dark;
for (i = 0; pp[i] != NULL; ++i)
do_highlight((char_u *)pp[i], reset, TRUE);
// Reverse looks ugly, but grey may not work for 8 colors. Thus let it
// depend on the number of colors available.
// With 8 colors brown is equal to yellow, need to use black for Search fg
// to avoid Statement highlighted text disappears.
// Clear the attributes, needed when changing the t_Co value.
if (t_colors > 8)
do_highlight((char_u *)(*p_bg == 'l'
? "Visual cterm=NONE ctermbg=LightGrey"
: "Visual cterm=NONE ctermbg=DarkGrey"), FALSE, TRUE);
else
{
do_highlight((char_u *)"Visual cterm=reverse ctermbg=NONE",
FALSE, TRUE);
if (*p_bg == 'l')
do_highlight((char_u *)"Search ctermfg=black", FALSE, TRUE);
}
#ifdef FEAT_SYN_HL
// If syntax highlighting is enabled load the highlighting for it.
if (get_var_value((char_u *)"g:syntax_on") != NULL)
{
static int recursive = 0;
if (recursive >= 5)
emsg(_(e_recursive_loop_loading_syncolor_vim));
else
{
++recursive;
(void)source_runtime((char_u *)"syntax/syncolor.vim", DIP_ALL);
--recursive;
}
}
#endif
}
#if defined(FEAT_EVAL) && (defined(FEAT_GUI) || defined(FEAT_TERMGUICOLORS))
/*
* Load a default color list. Intended to support legacy color names but allows
* the user to override the color values. Only loaded once.
*/
static void
load_default_colors_lists(void)
{
// Lacking a default color list isn't the end of the world but it is likely
// an inconvenience so users should know when it is missing.
if (source_runtime((char_u *)"colors/lists/default.vim", DIP_ALL) != OK)
msg("failed to load colors/lists/default.vim");
}
#endif
/*
* Load color file "name".
* Return OK for success, FAIL for failure.
*/
int
load_colors(char_u *name)
{
char_u *buf;
int retval = FAIL;
static int recursive = FALSE;
// When being called recursively, this is probably because setting
// 'background' caused the highlighting to be reloaded. This means it is
// working, thus we should return OK.
if (recursive)
return OK;
recursive = TRUE;
buf = alloc(STRLEN(name) + 12);
if (buf != NULL)
{
#if defined(FEAT_EVAL) && (defined(FEAT_GUI) || defined(FEAT_TERMGUICOLORS))
load_default_colors_lists();
#endif
apply_autocmds(EVENT_COLORSCHEMEPRE, name,
curbuf->b_fname, FALSE, curbuf);
sprintf((char *)buf, "colors/%s.vim", name);
retval = source_runtime(buf, DIP_START + DIP_OPT);
vim_free(buf);
if (retval == OK)
apply_autocmds(EVENT_COLORSCHEME, name, curbuf->b_fname,
FALSE, curbuf);
}
recursive = FALSE;
return retval;
}
static char *(color_names[28]) = {
"Black", "DarkBlue", "DarkGreen", "DarkCyan",
"DarkRed", "DarkMagenta", "Brown", "DarkYellow",
"Gray", "Grey", "LightGray", "LightGrey",
"DarkGray", "DarkGrey",
"Blue", "LightBlue", "Green", "LightGreen",
"Cyan", "LightCyan", "Red", "LightRed", "Magenta",
"LightMagenta", "Yellow", "LightYellow", "White", "NONE"};
// indices:
// 0, 1, 2, 3,
// 4, 5, 6, 7,
// 8, 9, 10, 11,
// 12, 13,
// 14, 15, 16, 17,
// 18, 19, 20, 21, 22,
// 23, 24, 25, 26, 27
static int color_numbers_16[28] = {0, 1, 2, 3,
4, 5, 6, 6,
7, 7, 7, 7,
8, 8,
9, 9, 10, 10,
11, 11, 12, 12, 13,
13, 14, 14, 15, -1};
// for xterm with 88 colors...
static int color_numbers_88[28] = {0, 4, 2, 6,
1, 5, 32, 72,
84, 84, 7, 7,
82, 82,
12, 43, 10, 61,
14, 63, 9, 74, 13,
75, 11, 78, 15, -1};
// for xterm with 256 colors...
static int color_numbers_256[28] = {0, 4, 2, 6,
1, 5, 130, 3,
248, 248, 7, 7,
242, 242,
12, 81, 10, 121,
14, 159, 9, 224, 13,
225, 11, 229, 15, -1};
// for terminals with less than 16 colors...
static int color_numbers_8[28] = {0, 4, 2, 6,
1, 5, 3, 3,
7, 7, 7, 7,
0+8, 0+8,
4+8, 4+8, 2+8, 2+8,
6+8, 6+8, 1+8, 1+8, 5+8,
5+8, 3+8, 3+8, 7+8, -1};
/*
* Lookup the "cterm" value to be used for color with index "idx" in
* color_names[].
* "boldp" will be set to TRUE or FALSE for a foreground color when using 8
* colors, otherwise it will be unchanged.
*/
static int
lookup_color(int idx, int foreground, int *boldp)
{
int color = color_numbers_16[idx];
char_u *p;
// Use the _16 table to check if it's a valid color name.
if (color < 0)
return -1;
if (t_colors == 8)
{
// t_Co is 8: use the 8 colors table
#if defined(__QNXNTO__)
// On qnx, the 8 & 16 color arrays are the same
if (STRNCMP(T_NAME, "qansi", 5) == 0)
color = color_numbers_16[idx];
else
#endif
color = color_numbers_8[idx];
if (foreground)
{
// set/reset bold attribute to get light foreground
// colors (on some terminals, e.g. "linux")
if (color & 8)
*boldp = TRUE;
else
*boldp = FALSE;
}
color &= 7; // truncate to 8 colors
}
else if (t_colors == 16 || t_colors == 88
|| t_colors >= 256)
{
// Guess: if the termcap entry ends in 'm', it is
// probably an xterm-like terminal. Use the changed
// order for colors.
if (*T_CAF != NUL)
p = T_CAF;
else
p = T_CSF;
if (*p != NUL && (t_colors > 256
|| *(p + STRLEN(p) - 1) == 'm'))
{
if (t_colors == 88)
color = color_numbers_88[idx];
else if (t_colors >= 256)
color = color_numbers_256[idx];
else
color = color_numbers_8[idx];
}
#ifdef FEAT_TERMRESPONSE
if (t_colors >= 256 && color == 15 && is_mac_terminal)
// Terminal.app has a bug: 15 is light grey. Use white
// from the color cube instead.
color = 231;
#endif
}
return color;
}
/*
* Link highlight group 'from_hg' to 'to_hg'.
* 'dodefault' is set to TRUE for ":highlight default link".
* 'forceit' is set to TRUE for ":highlight! link"
* 'init' is set to TRUE when initializing all the highlight groups.
*/
static void
highlight_group_link(
char_u *from_hg,
int from_len,
char_u *to_hg,
int to_len,
int dodefault,
int forceit,
int init)
{
int from_id;
int to_id;
hl_group_T *hlgroup = NULL;
from_id = syn_check_group(from_hg, from_len);
if (STRNCMP(to_hg, "NONE", 4) == 0)
to_id = 0;
else
to_id = syn_check_group(to_hg, to_len);
if (from_id > 0)
{
hlgroup = &HL_TABLE()[from_id - 1];
if (dodefault && (forceit || hlgroup->sg_deflink == 0))
{
hlgroup->sg_deflink = to_id;
#ifdef FEAT_EVAL
hlgroup->sg_deflink_sctx = current_sctx;
hlgroup->sg_deflink_sctx.sc_lnum += SOURCING_LNUM;
#endif
}
}
if (from_id > 0 && (!init || hlgroup->sg_set == 0))
{
// Don't allow a link when there already is some highlighting
// for the group, unless '!' is used
if (to_id > 0 && !forceit && !init
&& hl_has_settings(from_id - 1, dodefault))
{
if (SOURCING_NAME == NULL && !dodefault)
emsg(_(e_group_has_settings_highlight_link_ignored));
}
else if (hlgroup->sg_link != to_id
#ifdef FEAT_EVAL
|| hlgroup->sg_script_ctx.sc_sid != current_sctx.sc_sid
#endif
|| hlgroup->sg_cleared)
{
if (!init)
hlgroup->sg_set |= SG_LINK;
hlgroup->sg_link = to_id;
#ifdef FEAT_EVAL
hlgroup->sg_script_ctx = current_sctx;
hlgroup->sg_script_ctx.sc_lnum += SOURCING_LNUM;
#endif
hlgroup->sg_cleared = FALSE;
redraw_all_later(UPD_SOME_VALID);
// Only call highlight_changed() once after multiple changes.
need_highlight_changed = TRUE;
}
}
}
/*
* Reset all highlighting to the defaults. Removes all highlighting for the
* groups added by the user.
*/
static void
highlight_reset_all(void)
{
int idx;
#ifdef FEAT_GUI
// First, we do not destroy the old values, but allocate the new
// ones and update the display. THEN we destroy the old values.
// If we destroy the old values first, then the old values
// (such as GuiFont's or GuiFontset's) will still be displayed but
// invalid because they were free'd.
if (gui.in_use)
{
# ifdef FEAT_BEVAL_TIP
gui_init_tooltip_font();
# endif
# if defined(FEAT_MENU) && defined(FEAT_GUI_MOTIF)
gui_init_menu_font();
# endif
}
# if defined(FEAT_GUI_MSWIN) || defined(FEAT_GUI_X11)
gui_mch_def_colors();
# endif
# ifdef FEAT_GUI_X11
# ifdef FEAT_MENU
// This only needs to be done when there is no Menu highlight
// group defined by default, which IS currently the case.
gui_mch_new_menu_colors();
# endif
if (gui.in_use)
{
gui_new_scrollbar_colors();
# ifdef FEAT_BEVAL_GUI
gui_mch_new_tooltip_colors();
# endif
# ifdef FEAT_MENU
gui_mch_new_menu_font();
# endif
}
# endif
// Ok, we're done allocating the new default graphics items.
// The screen should already be refreshed at this point.
// It is now Ok to clear out the old data.
#endif
#ifdef FEAT_EVAL
do_unlet((char_u *)"g:colors_name", TRUE);
#endif
restore_cterm_colors();
// Clear all default highlight groups and load the defaults.
for (idx = 0; idx < highlight_ga.ga_len; ++idx)
highlight_clear(idx);
init_highlight(TRUE, TRUE);
#if defined(FEAT_GUI) || defined(FEAT_TERMGUICOLORS)
if (USE_24BIT)
highlight_gui_started();
else
#endif
highlight_changed();
redraw_later_clear();
}
/*
* Set the 'term' or 'cterm' or 'gui' attributes for the highlight group at
* index 'idx'.
* 'key' is one of 'TERM' or 'CTERM' or 'GUI'
* 'arg' is the list of attribute names separated by comma.
* 'init' is set to TRUE when initializing all the highlight groups.
* Returns TRUE if the attributes are set.
*/
static int
highlight_set_termgui_attr(int idx, char_u *key, char_u *arg, int init)
{
int attr;
int off;
long i;
int len;
attr = 0;
off = 0;
while (arg[off] != NUL)
{
for (i = ARRAY_LENGTH(hl_attr_table); --i >= 0; )
{
len = (int)STRLEN(hl_name_table[i]);
if (STRNICMP(arg + off, hl_name_table[i], len) == 0)
{
attr |= hl_attr_table[i];
off += len;
break;
}
}
if (i < 0)
{
semsg(_(e_illegal_value_str), arg);
return FALSE;
}
if (arg[off] == ',') // another one follows
++off;
}
if (*key == 'T')
{
if (!init || !(HL_TABLE()[idx].sg_set & SG_TERM))
{
if (!init)
HL_TABLE()[idx].sg_set |= SG_TERM;
HL_TABLE()[idx].sg_term = attr;
}
}
else if (*key == 'C')
{
if (!init || !(HL_TABLE()[idx].sg_set & SG_CTERM))
{
if (!init)
HL_TABLE()[idx].sg_set |= SG_CTERM;
HL_TABLE()[idx].sg_cterm = attr;
HL_TABLE()[idx].sg_cterm_bold = FALSE;
}
}
#if defined(FEAT_GUI) || defined(FEAT_EVAL)
else
{
if (!init || !(HL_TABLE()[idx].sg_set & SG_GUI))
{
if (!init)
HL_TABLE()[idx].sg_set |= SG_GUI;
HL_TABLE()[idx].sg_gui = attr;
}
}
#endif
return TRUE;
}
#ifdef FEAT_GUI
/*
* Set the font for the highlight group at 'idx'.
* 'arg' is the font name.
* Returns TRUE if the font is changed.
*/
static int
highlight_set_font(
int idx,
char_u *arg,
int is_normal_group,
int is_menu_group,
int is_tooltip_group)
{
int did_change = FALSE;
// in non-GUI fonts are simply ignored
if (HL_TABLE()[idx].sg_font_name != NULL
&& STRCMP(HL_TABLE()[idx].sg_font_name, arg) == 0)
{
// Font name didn't change, ignore.
}
else if (!gui.shell_created)
{
// GUI not started yet, always accept the name.
vim_free(HL_TABLE()[idx].sg_font_name);
HL_TABLE()[idx].sg_font_name = vim_strsave(arg);
did_change = TRUE;
}
else
{
GuiFont temp_sg_font = HL_TABLE()[idx].sg_font;
# ifdef FEAT_XFONTSET
GuiFontset temp_sg_fontset = HL_TABLE()[idx].sg_fontset;
# endif
// First, save the current font/fontset.
// Then try to allocate the font/fontset.
// If the allocation fails, HL_TABLE()[idx].sg_font OR
// sg_fontset will be set to NOFONT or NOFONTSET respectively.
HL_TABLE()[idx].sg_font = NOFONT;
# ifdef FEAT_XFONTSET
HL_TABLE()[idx].sg_fontset = NOFONTSET;
# endif
hl_do_font(idx, arg, is_normal_group, is_menu_group,
is_tooltip_group, FALSE);
# ifdef FEAT_XFONTSET
if (HL_TABLE()[idx].sg_fontset != NOFONTSET)
{
// New fontset was accepted. Free the old one, if there
// was one.
gui_mch_free_fontset(temp_sg_fontset);
vim_free(HL_TABLE()[idx].sg_font_name);
HL_TABLE()[idx].sg_font_name = vim_strsave(arg);
did_change = TRUE;
}
else
HL_TABLE()[idx].sg_fontset = temp_sg_fontset;
# endif
if (HL_TABLE()[idx].sg_font != NOFONT)
{
// New font was accepted. Free the old one, if there was
// one.
gui_mch_free_font(temp_sg_font);
vim_free(HL_TABLE()[idx].sg_font_name);
HL_TABLE()[idx].sg_font_name = vim_strsave(arg);
did_change = TRUE;
}
else
HL_TABLE()[idx].sg_font = temp_sg_font;
}
return did_change;
}
#endif
/*
* Set the cterm foreground color for the Normal highlight group to "color" and
* the bold attribute to "bold".
*/
static void
hl_set_ctermfg_normal_group(int color, int bold)
{
cterm_normal_fg_color = color + 1;
cterm_normal_fg_bold = bold;
#ifdef FEAT_GUI
// Don't do this if the GUI is used.
if (!gui.in_use && !gui.starting)
#endif
{
set_must_redraw(UPD_CLEAR);
if (termcap_active && color >= 0)
term_fg_color(color);
}
}
/*
* Set the cterm foreground color for the highlight group at 'idx' to 'color'.
*/
static void
highlight_set_ctermfg(int idx, int color, int is_normal_group)
{
HL_TABLE()[idx].sg_cterm_fg = color + 1;
if (is_normal_group)
hl_set_ctermfg_normal_group(color,
(HL_TABLE()[idx].sg_cterm & HL_BOLD));
}
/*
* Set the cterm background color for the Normal highlight group to "color".
*/
static void
hl_set_ctermbg_normal_group(int color)
{
cterm_normal_bg_color = color + 1;
#ifdef FEAT_GUI
// Don't mess with 'background' if the GUI is used.
if (!gui.in_use && !gui.starting)
#endif
{
set_must_redraw(UPD_CLEAR);
if (color >= 0)
{
int dark = -1;
if (termcap_active)
term_bg_color(color);
if (t_colors < 16)
dark = (color == 0 || color == 4);
// Limit the heuristic to the standard 16 colors
else if (color < 16)
dark = (color < 7 || color == 8);
// Set the 'background' option if the value is
// wrong.
if (dark != -1
&& dark != (*p_bg == 'd')
&& !option_was_set((char_u *)"bg"))
{
set_option_value_give_err((char_u *)"bg",
0L, (char_u *)(dark ? "dark" : "light"), 0);
reset_option_was_set((char_u *)"bg");
}
}
}
}
/*
* Set the cterm background color for the highlight group at 'idx' to 'color'.
*/
static void