2 * highlighting.c - this file is part of Geany, a fast and lightweight IDE
4 * Copyright 2005-2011 Enrico Tröger <enrico(dot)troeger(at)uvena(dot)de>
5 * Copyright 2006-2011 Nick Treleaven <nick(dot)treleaven(at)btinternet(dot)com>
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
23 * @file highlighting.h
24 * Syntax highlighting for the different filetypes, using the Scintilla lexers.
34 #include "highlighting.h"
37 #include "filetypes.h"
43 #include "sciwrappers.h"
45 #include "highlightingmappings.h"
48 #define GEANY_COLORSCHEMES_SUBDIR "colorschemes"
50 /* Whitespace has to be set after setting wordchars. */
51 #define GEANY_WHITESPACE_CHARS " \t" "!\"#$%&'()*+,-./:;<=>?@[\\]^`{|}~"
54 static gchar
*whitespace_chars
;
59 gsize count
; /* number of styles */
60 GeanyLexerStyle
*styling
; /* array of styles, NULL if not used or uninitialised */
62 gchar
*wordchars
; /* NULL used for style sets with no styles */
63 gchar
**property_keys
;
64 gchar
**property_values
;
67 /* each filetype has a styleset but GEANY_FILETYPES_NONE uses common_style_set for styling */
68 static StyleSet
*style_sets
= NULL
;
71 enum /* Geany common styling */
77 GCS_MARGIN_LINENUMBER
,
79 GCS_FOLD_SYMBOL_HIGHLIGHT
,
84 GCS_LINE_WRAP_VISUALS
,
90 GCS_MARKER_TRANSLUCENCY
,
98 GeanyLexerStyle styling
[GCS_MAX
];
100 /* icon style, 1-4 */
102 /* vertical line style, 0-2 */
104 /* horizontal line when folded, 0-2 */
111 /* For filetypes.common [named_styles] section.
113 * e.g. "comment" => &GeanyLexerStyle{0x0000d0, 0xffffff, FALSE, FALSE} */
114 static GHashTable
*named_style_hash
= NULL
;
116 /* 0xBBGGRR format, set by "default" named style. */
117 static GeanyLexerStyle gsd_default
= {0x000000, 0xffffff, FALSE
, FALSE
};
120 /* Note: use sciwrappers.h instead where possible.
121 * Do not use SSM in files unrelated to scintilla. */
122 #define SSM(s, m, w, l) scintilla_send_message(s, m, w, l)
124 /* filetypes should use the filetypes.foo [lexer_properties] group instead of hardcoding */
125 static void sci_set_property(ScintillaObject
*sci
, const gchar
*name
, const gchar
*value
)
127 SSM(sci
, SCI_SETPROPERTY
, (uptr_t
) name
, (sptr_t
) value
);
131 static void new_styleset(guint file_type_id
, gsize styling_count
)
133 StyleSet
*set
= &style_sets
[file_type_id
];
135 set
->count
= styling_count
;
136 set
->styling
= g_new0(GeanyLexerStyle
, styling_count
);
140 static void free_styleset(guint file_type_id
)
143 style_ptr
= &style_sets
[file_type_id
];
145 style_ptr
->count
= 0;
146 g_free(style_ptr
->styling
);
147 style_ptr
->styling
= NULL
;
148 g_strfreev(style_ptr
->keywords
);
149 style_ptr
->keywords
= NULL
;
150 g_free(style_ptr
->wordchars
);
151 style_ptr
->wordchars
= NULL
;
152 g_strfreev(style_ptr
->property_keys
);
153 style_ptr
->property_keys
= NULL
;
154 g_strfreev(style_ptr
->property_values
);
155 style_ptr
->property_values
= NULL
;
159 static void get_keyfile_keywords(GKeyFile
*config
, GKeyFile
*configh
,
160 const gchar
*key
, guint ft_id
, guint pos
)
162 style_sets
[ft_id
].keywords
[pos
] =
163 utils_get_setting(string
, configh
, config
, "keywords", key
, "");
167 static void get_keyfile_wordchars(GKeyFile
*config
, GKeyFile
*configh
, gchar
**wordchars
)
169 *wordchars
= utils_get_setting(string
, configh
, config
,
170 "settings", "wordchars", GEANY_WORDCHARS
);
174 static gboolean
read_named_style(const gchar
*named_style
, GeanyLexerStyle
*style
)
177 gchar
*comma
, *name
= NULL
;
178 const gchar
*bold
= NULL
;
179 const gchar
*italic
= NULL
;
181 g_return_val_if_fail(named_style
, FALSE
);
182 name
= utils_strdupa(named_style
); /* named_style must not be written to, may be a static string */
184 comma
= strstr(name
, ",");
187 bold
= strstr(comma
, ",bold");
188 italic
= strstr(comma
, ",italic");
189 *comma
= '\0'; /* terminate name to make lookup work */
191 cs
= g_hash_table_lookup(named_style_hash
, name
);
197 style
->bold
= !style
->bold
;
199 style
->italic
= !style
->italic
;
203 *style
= gsd_default
;
209 /* Parses a color in `str` which can be an HTML color (ex. #0099cc),
210 * an abbreviated HTML color (ex. #09c) or a hex string color
211 * (ex. 0x0099cc). The result of the conversion is stored into the
212 * location pointed to by `clr`. */
213 static void parse_color(const gchar
*str
, gint
*clr
)
216 gchar hex_clr
[9] = { 0 };
219 g_return_if_fail(clr
!= NULL
);
221 if (G_UNLIKELY(! NZV(str
)))
226 else if (str
[0] == '0' && (str
[1] == 'x' || str
[1] == 'X'))
231 if (strlen(start
) == 3)
233 snprintf(hex_clr
, 9, "0x%c%c%c%c%c%c", start
[0], start
[0],
234 start
[1], start
[1], start
[2], start
[2]);
237 snprintf(hex_clr
, 9, "0x%s", start
);
239 c
= utils_strtod(hex_clr
, NULL
, FALSE
);
246 geany_debug("Bad color '%s'", str
);
250 static void parse_keyfile_style(gchar
**list
,
251 const GeanyLexerStyle
*default_style
, GeanyLexerStyle
*style
)
256 g_return_if_fail(default_style
);
257 g_return_if_fail(style
);
259 *style
= *default_style
;
264 len
= g_strv_length(list
);
267 if (len
== 1 && isalpha(str
[0]))
269 if (!read_named_style(str
, style
))
271 "No named style '%s'! Check filetype styles or %s color scheme.",
272 str
, NVL(editor_prefs
.color_scheme
, "filetypes.common"));
279 style
->italic
= utils_atob(list
[3]);
281 style
->bold
= utils_atob(list
[2]);
283 parse_color(list
[1], &style
->background
);
285 parse_color(list
[0], &style
->foreground
);
291 static void get_keyfile_style(GKeyFile
*config
, GKeyFile
*configh
,
292 const gchar
*key_name
, GeanyLexerStyle
*style
)
297 g_return_if_fail(config
);
298 g_return_if_fail(configh
);
299 g_return_if_fail(key_name
);
300 g_return_if_fail(style
);
302 list
= g_key_file_get_string_list(configh
, "styling", key_name
, &len
, NULL
);
304 list
= g_key_file_get_string_list(config
, "styling", key_name
, &len
, NULL
);
306 parse_keyfile_style(list
, &gsd_default
, style
);
311 /* Convert 0xRRGGBB to 0xBBGGRR, which scintilla expects. */
312 static gint
rotate_rgb(gint color
)
314 return ((color
& 0xFF0000) >> 16) +
316 ((color
& 0x0000FF) << 16);
320 static void convert_int(const gchar
*int_str
, gint
*val
)
323 gint v
= strtol(int_str
, &end
, 10);
330 /* Get first and second integer numbers, store in foreground and background fields of @a style. */
331 static void get_keyfile_int(GKeyFile
*config
, GKeyFile
*configh
, const gchar
*section
,
332 const gchar
*key
, gint fdefault_val
, gint sdefault_val
,
333 GeanyLexerStyle
*style
)
337 GeanyLexerStyle def
= {fdefault_val
, sdefault_val
, FALSE
, FALSE
};
339 g_return_if_fail(config
);
340 g_return_if_fail(configh
);
341 g_return_if_fail(section
);
342 g_return_if_fail(key
);
344 list
= g_key_file_get_string_list(configh
, section
, key
, &len
, NULL
);
346 list
= g_key_file_get_string_list(config
, section
, key
, &len
, NULL
);
354 convert_int(list
[0], &style
->foreground
);
357 convert_int(list
[1], &style
->background
);
364 /* first or second can be NULL. */
365 static void get_keyfile_ints(GKeyFile
*config
, GKeyFile
*configh
, const gchar
*section
,
367 gint fdefault_val
, gint sdefault_val
,
368 gint
*first
, gint
*second
)
370 GeanyLexerStyle tmp_style
;
372 get_keyfile_int(config
, configh
, section
, key
, fdefault_val
, sdefault_val
, &tmp_style
);
374 *first
= tmp_style
.foreground
;
376 *second
= tmp_style
.background
;
380 static guint
invert(guint icolour
)
382 if (interface_prefs
.highlighting_invert_all
)
383 return utils_invert_color(icolour
);
389 static GeanyLexerStyle
*get_style(guint ft_id
, guint styling_index
)
391 g_assert(ft_id
< filetypes_array
->len
);
393 if (G_UNLIKELY(ft_id
== GEANY_FILETYPES_NONE
))
395 g_assert(styling_index
< GCS_MAX
);
396 return &common_style_set
.styling
[styling_index
];
400 StyleSet
*set
= &style_sets
[ft_id
];
402 g_assert(styling_index
< set
->count
);
403 return &set
->styling
[styling_index
];
408 static void set_sci_style(ScintillaObject
*sci
, guint style
, guint ft_id
, guint styling_index
)
410 GeanyLexerStyle
*style_ptr
= get_style(ft_id
, styling_index
);
412 SSM(sci
, SCI_STYLESETFORE
, style
, invert(style_ptr
->foreground
));
413 SSM(sci
, SCI_STYLESETBACK
, style
, invert(style_ptr
->background
));
414 SSM(sci
, SCI_STYLESETBOLD
, style
, style_ptr
->bold
);
415 SSM(sci
, SCI_STYLESETITALIC
, style
, style_ptr
->italic
);
419 void highlighting_free_styles()
423 for (i
= 0; i
< filetypes_array
->len
; i
++)
426 if (named_style_hash
)
427 g_hash_table_destroy(named_style_hash
);
433 static GString
*get_global_typenames(gint lang
)
437 if (app
->tm_workspace
)
439 GPtrArray
*tags_array
= app
->tm_workspace
->global_tags
;
443 s
= symbols_find_tags_as_string(tags_array
, TM_GLOBAL_TYPE_MASK
, lang
);
451 get_keyfile_whitespace_chars(GKeyFile
*config
, GKeyFile
*configh
)
453 return utils_get_setting(string
, configh
, config
,
454 "settings", "whitespace_chars", GEANY_WHITESPACE_CHARS
);
458 static void add_named_style(GKeyFile
*config
, const gchar
*key
)
460 const gchar group
[] = "named_styles";
464 list
= g_key_file_get_string_list(config
, group
, key
, &len
, NULL
);
465 /* we allow a named style to reference another style above it */
466 if (list
&& len
>= 1)
468 GeanyLexerStyle
*style
= g_new0(GeanyLexerStyle
, 1);
470 parse_keyfile_style(list
, &gsd_default
, style
);
471 g_hash_table_insert(named_style_hash
, g_strdup(key
), style
);
477 static void get_named_styles(GKeyFile
*config
)
479 const gchar group
[] = "named_styles";
480 gchar
**keys
= g_key_file_get_keys(config
, group
, NULL
, NULL
);
488 const gchar
*key
= *ptr
;
493 /* don't replace already read default style with system one */
494 if (!g_str_equal(key
, "default"))
495 add_named_style(config
, key
);
503 static GKeyFile
*utils_key_file_new(const gchar
*filename
)
505 GKeyFile
*config
= g_key_file_new();
507 g_key_file_load_from_file(config
, filename
, G_KEY_FILE_KEEP_COMMENTS
, NULL
);
512 static void load_named_styles(GKeyFile
*config
, GKeyFile
*config_home
)
514 const gchar
*scheme
= editor_prefs
.color_scheme
;
515 gboolean free_kf
= FALSE
;
517 if (named_style_hash
)
518 g_hash_table_destroy(named_style_hash
); /* reloading */
520 named_style_hash
= g_hash_table_new_full(g_str_hash
, g_str_equal
, g_free
, g_free
);
524 gchar
*path
, *path_home
;
526 path
= g_build_path(G_DIR_SEPARATOR_S
, app
->datadir
, GEANY_COLORSCHEMES_SUBDIR
, scheme
, NULL
);
527 path_home
= g_build_path(G_DIR_SEPARATOR_S
, app
->configdir
, GEANY_COLORSCHEMES_SUBDIR
, scheme
, NULL
);
529 if (g_file_test(path
, G_FILE_TEST_EXISTS
) || g_file_test(path_home
, G_FILE_TEST_EXISTS
))
531 config
= utils_key_file_new(path
);
532 config_home
= utils_key_file_new(path_home
);
535 /* if color scheme is missing, use default */
539 /* first set default to the "default" named style */
540 add_named_style(config
, "default");
541 read_named_style("default", &gsd_default
); /* in case user overrides but not with both colors */
542 add_named_style(config_home
, "default");
543 read_named_style("default", &gsd_default
);
545 get_named_styles(config
);
546 /* home overrides any system named style */
547 get_named_styles(config_home
);
551 g_key_file_free(config
);
552 g_key_file_free(config_home
);
557 static void styleset_common_init(guint ft_id
, GKeyFile
*config
, GKeyFile
*config_home
)
559 load_named_styles(config
, config_home
);
561 get_keyfile_style(config
, config_home
, "default", &common_style_set
.styling
[GCS_DEFAULT
]);
562 get_keyfile_style(config
, config_home
, "selection", &common_style_set
.styling
[GCS_SELECTION
]);
563 get_keyfile_style(config
, config_home
, "brace_good", &common_style_set
.styling
[GCS_BRACE_GOOD
]);
564 get_keyfile_style(config
, config_home
, "brace_bad", &common_style_set
.styling
[GCS_BRACE_BAD
]);
565 get_keyfile_style(config
, config_home
, "margin_linenumber", &common_style_set
.styling
[GCS_MARGIN_LINENUMBER
]);
566 get_keyfile_style(config
, config_home
, "margin_folding", &common_style_set
.styling
[GCS_MARGIN_FOLDING
]);
567 get_keyfile_style(config
, config_home
, "fold_symbol_highlight", &common_style_set
.styling
[GCS_FOLD_SYMBOL_HIGHLIGHT
]);
568 get_keyfile_style(config
, config_home
, "current_line", &common_style_set
.styling
[GCS_CURRENT_LINE
]);
569 get_keyfile_style(config
, config_home
, "caret", &common_style_set
.styling
[GCS_CARET
]);
570 get_keyfile_style(config
, config_home
, "indent_guide", &common_style_set
.styling
[GCS_INDENT_GUIDE
]);
571 get_keyfile_style(config
, config_home
, "white_space", &common_style_set
.styling
[GCS_WHITE_SPACE
]);
572 get_keyfile_style(config
, config_home
, "marker_line", &common_style_set
.styling
[GCS_MARKER_LINE
]);
573 get_keyfile_style(config
, config_home
, "marker_search", &common_style_set
.styling
[GCS_MARKER_SEARCH
]);
574 get_keyfile_style(config
, config_home
, "marker_mark", &common_style_set
.styling
[GCS_MARKER_MARK
]);
575 get_keyfile_style(config
, config_home
, "calltips", &common_style_set
.styling
[GCS_CALLTIPS
]);
577 get_keyfile_ints(config
, config_home
, "styling", "folding_style",
578 1, 1, &common_style_set
.fold_marker
, &common_style_set
.fold_lines
);
579 get_keyfile_ints(config
, config_home
, "styling", "folding_horiz_line",
580 2, 0, &common_style_set
.fold_draw_line
, NULL
);
581 get_keyfile_ints(config
, config_home
, "styling", "caret_width",
582 1, 0, &common_style_set
.styling
[GCS_CARET
].background
, NULL
); /* caret.foreground used earlier */
583 get_keyfile_int(config
, config_home
, "styling", "line_wrap_visuals",
584 3, 0, &common_style_set
.styling
[GCS_LINE_WRAP_VISUALS
]);
585 get_keyfile_int(config
, config_home
, "styling", "line_wrap_indent",
586 0, 0, &common_style_set
.styling
[GCS_LINE_WRAP_INDENT
]);
587 get_keyfile_int(config
, config_home
, "styling", "translucency",
588 256, 256, &common_style_set
.styling
[GCS_TRANSLUCENCY
]);
589 get_keyfile_int(config
, config_home
, "styling", "marker_translucency",
590 256, 256, &common_style_set
.styling
[GCS_MARKER_TRANSLUCENCY
]);
591 get_keyfile_int(config
, config_home
, "styling", "line_height",
592 0, 0, &common_style_set
.styling
[GCS_LINE_HEIGHT
]);
594 get_keyfile_wordchars(config
, config_home
, &common_style_set
.wordchars
);
595 whitespace_chars
= get_keyfile_whitespace_chars(config
, config_home
);
599 static void styleset_common(ScintillaObject
*sci
, guint ft_id
)
601 SSM(sci
, SCI_STYLECLEARALL
, 0, 0);
603 SSM(sci
, SCI_SETWORDCHARS
, 0, (sptr_t
) (ft_id
== GEANY_FILETYPES_NONE
?
604 common_style_set
.wordchars
: style_sets
[ft_id
].wordchars
));
605 /* have to set whitespace after setting wordchars */
606 SSM(sci
, SCI_SETWHITESPACECHARS
, 0, (sptr_t
) whitespace_chars
);
608 /* caret colour, style and width */
609 SSM(sci
, SCI_SETCARETFORE
, invert(common_style_set
.styling
[GCS_CARET
].foreground
), 0);
610 SSM(sci
, SCI_SETCARETWIDTH
, common_style_set
.styling
[GCS_CARET
].background
, 0);
611 if (common_style_set
.styling
[GCS_CARET
].bold
)
612 SSM(sci
, SCI_SETCARETSTYLE
, CARETSTYLE_BLOCK
, 0);
614 SSM(sci
, SCI_SETCARETSTYLE
, CARETSTYLE_LINE
, 0);
617 SSM(sci
, SCI_SETEXTRAASCENT
, common_style_set
.styling
[GCS_LINE_HEIGHT
].foreground
, 0);
618 SSM(sci
, SCI_SETEXTRADESCENT
, common_style_set
.styling
[GCS_LINE_HEIGHT
].background
, 0);
620 /* colourise the current line */
621 SSM(sci
, SCI_SETCARETLINEBACK
, invert(common_style_set
.styling
[GCS_CURRENT_LINE
].background
), 0);
622 /* bold=enable current line */
623 SSM(sci
, SCI_SETCARETLINEVISIBLE
, common_style_set
.styling
[GCS_CURRENT_LINE
].bold
, 0);
625 /* Translucency for current line and selection */
626 SSM(sci
, SCI_SETCARETLINEBACKALPHA
, common_style_set
.styling
[GCS_TRANSLUCENCY
].foreground
, 0);
627 SSM(sci
, SCI_SETSELALPHA
, common_style_set
.styling
[GCS_TRANSLUCENCY
].background
, 0);
629 /* line wrapping visuals */
630 SSM(sci
, SCI_SETWRAPVISUALFLAGS
,
631 common_style_set
.styling
[GCS_LINE_WRAP_VISUALS
].foreground
, 0);
632 SSM(sci
, SCI_SETWRAPVISUALFLAGSLOCATION
,
633 common_style_set
.styling
[GCS_LINE_WRAP_VISUALS
].background
, 0);
634 SSM(sci
, SCI_SETWRAPSTARTINDENT
, common_style_set
.styling
[GCS_LINE_WRAP_INDENT
].foreground
, 0);
635 SSM(sci
, SCI_SETWRAPINDENTMODE
, common_style_set
.styling
[GCS_LINE_WRAP_INDENT
].background
, 0);
637 /* Error indicator */
638 SSM(sci
, SCI_INDICSETSTYLE
, GEANY_INDICATOR_ERROR
, INDIC_SQUIGGLE
);
639 SSM(sci
, SCI_INDICSETFORE
, GEANY_INDICATOR_ERROR
, invert(rotate_rgb(0xff0000)));
641 /* Search indicator, used for 'Mark' matches */
642 SSM(sci
, SCI_INDICSETSTYLE
, GEANY_INDICATOR_SEARCH
, INDIC_ROUNDBOX
);
643 SSM(sci
, SCI_INDICSETFORE
, GEANY_INDICATOR_SEARCH
,
644 invert(common_style_set
.styling
[GCS_MARKER_SEARCH
].background
));
645 SSM(sci
, SCI_INDICSETALPHA
, GEANY_INDICATOR_SEARCH
, 60);
647 /* define marker symbols
648 * 0 -> line marker */
649 SSM(sci
, SCI_MARKERDEFINE
, 0, SC_MARK_SHORTARROW
);
650 SSM(sci
, SCI_MARKERSETFORE
, 0, invert(common_style_set
.styling
[GCS_MARKER_LINE
].foreground
));
651 SSM(sci
, SCI_MARKERSETBACK
, 0, invert(common_style_set
.styling
[GCS_MARKER_LINE
].background
));
652 SSM(sci
, SCI_MARKERSETALPHA
, 0, common_style_set
.styling
[GCS_MARKER_TRANSLUCENCY
].foreground
);
654 /* 1 -> user marker */
655 SSM(sci
, SCI_MARKERDEFINE
, 1, SC_MARK_PLUS
);
656 SSM(sci
, SCI_MARKERSETFORE
, 1, invert(common_style_set
.styling
[GCS_MARKER_MARK
].foreground
));
657 SSM(sci
, SCI_MARKERSETBACK
, 1, invert(common_style_set
.styling
[GCS_MARKER_MARK
].background
));
658 SSM(sci
, SCI_MARKERSETALPHA
, 1, common_style_set
.styling
[GCS_MARKER_TRANSLUCENCY
].background
);
660 /* 2 -> folding marker, other folding settings */
661 SSM(sci
, SCI_SETMARGINTYPEN
, 2, SC_MARGIN_SYMBOL
);
662 SSM(sci
, SCI_SETMARGINMASKN
, 2, SC_MASK_FOLDERS
);
664 /* drawing a horizontal line when text if folded */
665 switch (common_style_set
.fold_draw_line
)
669 SSM(sci
, SCI_SETFOLDFLAGS
, 4, 0);
674 SSM(sci
, SCI_SETFOLDFLAGS
, 16, 0);
679 SSM(sci
, SCI_SETFOLDFLAGS
, 0, 0);
684 /* choose the folding style - boxes or circles, I prefer boxes, so it is default ;-) */
685 SSM(sci
, SCI_MARKERDEFINE
, SC_MARKNUM_FOLDEREND
, SC_MARK_EMPTY
);
686 SSM(sci
, SCI_MARKERDEFINE
, SC_MARKNUM_FOLDEROPENMID
, SC_MARK_EMPTY
);
687 switch (common_style_set
.fold_marker
)
690 SSM(sci
, SCI_MARKERDEFINE
, SC_MARKNUM_FOLDEROPEN
, SC_MARK_CIRCLEMINUS
);
691 SSM(sci
, SCI_MARKERDEFINE
, SC_MARKNUM_FOLDER
, SC_MARK_CIRCLEPLUS
);
692 SSM(sci
, SCI_MARKERDEFINE
, SC_MARKNUM_FOLDEREND
, SC_MARK_CIRCLEPLUSCONNECTED
);
693 SSM(sci
, SCI_MARKERDEFINE
, SC_MARKNUM_FOLDEROPENMID
, SC_MARK_CIRCLEMINUSCONNECTED
);
696 SSM(sci
, SCI_MARKERDEFINE
, SC_MARKNUM_FOLDEROPEN
, SC_MARK_BOXMINUS
);
697 SSM(sci
, SCI_MARKERDEFINE
, SC_MARKNUM_FOLDER
, SC_MARK_BOXPLUS
);
698 SSM(sci
, SCI_MARKERDEFINE
, SC_MARKNUM_FOLDEREND
, SC_MARK_BOXPLUSCONNECTED
);
699 SSM(sci
, SCI_MARKERDEFINE
, SC_MARKNUM_FOLDEROPENMID
, SC_MARK_BOXMINUSCONNECTED
);
702 SSM(sci
, SCI_MARKERDEFINE
, SC_MARKNUM_FOLDEROPEN
, SC_MARK_ARROWDOWN
);
703 SSM(sci
, SCI_MARKERDEFINE
, SC_MARKNUM_FOLDER
, SC_MARK_ARROW
);
706 SSM(sci
, SCI_MARKERDEFINE
, SC_MARKNUM_FOLDEROPEN
, SC_MARK_MINUS
);
707 SSM(sci
, SCI_MARKERDEFINE
, SC_MARKNUM_FOLDER
, SC_MARK_PLUS
);
711 /* choose the folding style - straight or curved, I prefer straight, so it is default ;-) */
712 switch (common_style_set
.fold_lines
)
715 SSM(sci
, SCI_MARKERDEFINE
, SC_MARKNUM_FOLDERMIDTAIL
, SC_MARK_TCORNERCURVE
);
716 SSM(sci
, SCI_MARKERDEFINE
, SC_MARKNUM_FOLDERTAIL
, SC_MARK_LCORNERCURVE
);
717 SSM(sci
, SCI_MARKERDEFINE
, SC_MARKNUM_FOLDERSUB
, SC_MARK_VLINE
);
720 SSM(sci
, SCI_MARKERDEFINE
, SC_MARKNUM_FOLDERMIDTAIL
, SC_MARK_TCORNER
);
721 SSM(sci
, SCI_MARKERDEFINE
, SC_MARKNUM_FOLDERTAIL
, SC_MARK_LCORNER
);
722 SSM(sci
, SCI_MARKERDEFINE
, SC_MARKNUM_FOLDERSUB
, SC_MARK_VLINE
);
725 SSM(sci
, SCI_MARKERDEFINE
, SC_MARKNUM_FOLDERMIDTAIL
, SC_MARK_EMPTY
);
726 SSM(sci
, SCI_MARKERDEFINE
, SC_MARKNUM_FOLDERTAIL
, SC_MARK_EMPTY
);
727 SSM(sci
, SCI_MARKERDEFINE
, SC_MARKNUM_FOLDERSUB
, SC_MARK_EMPTY
);
732 SC_MARKNUM_FOLDEROPEN
,
734 SC_MARKNUM_FOLDERSUB
,
735 SC_MARKNUM_FOLDERTAIL
,
736 SC_MARKNUM_FOLDEREND
,
737 SC_MARKNUM_FOLDEROPENMID
,
738 SC_MARKNUM_FOLDERMIDTAIL
742 foreach_range(i
, G_N_ELEMENTS(markers
))
744 SSM(sci
, SCI_MARKERSETFORE
, markers
[i
],
745 invert(common_style_set
.styling
[GCS_FOLD_SYMBOL_HIGHLIGHT
].foreground
));
746 SSM(sci
, SCI_MARKERSETBACK
, markers
[i
],
747 invert(common_style_set
.styling
[GCS_MARGIN_FOLDING
].foreground
));
751 /* set some common defaults */
752 sci_set_property(sci
, "fold", "1");
753 sci_set_property(sci
, "fold.compact", "0");
754 sci_set_property(sci
, "fold.comment", "1");
755 sci_set_property(sci
, "fold.preprocessor", "1");
756 sci_set_property(sci
, "fold.at.else", "1");
758 /* bold (3rd argument) is whether to override default foreground selection */
759 if (common_style_set
.styling
[GCS_SELECTION
].bold
)
760 SSM(sci
, SCI_SETSELFORE
, 1, invert(common_style_set
.styling
[GCS_SELECTION
].foreground
));
761 /* italic (4th argument) is whether to override default background selection */
762 if (common_style_set
.styling
[GCS_SELECTION
].italic
)
763 SSM(sci
, SCI_SETSELBACK
, 1, invert(common_style_set
.styling
[GCS_SELECTION
].background
));
765 SSM(sci
, SCI_SETSTYLEBITS
, SSM(sci
, SCI_GETSTYLEBITSNEEDED
, 0, 0), 0);
767 SSM(sci
, SCI_SETFOLDMARGINCOLOUR
, 1, invert(common_style_set
.styling
[GCS_MARGIN_FOLDING
].background
));
768 SSM(sci
, SCI_SETFOLDMARGINHICOLOUR
, 1, invert(common_style_set
.styling
[GCS_MARGIN_FOLDING
].background
));
769 set_sci_style(sci
, STYLE_LINENUMBER
, GEANY_FILETYPES_NONE
, GCS_MARGIN_LINENUMBER
);
770 set_sci_style(sci
, STYLE_BRACELIGHT
, GEANY_FILETYPES_NONE
, GCS_BRACE_GOOD
);
771 set_sci_style(sci
, STYLE_BRACEBAD
, GEANY_FILETYPES_NONE
, GCS_BRACE_BAD
);
772 set_sci_style(sci
, STYLE_INDENTGUIDE
, GEANY_FILETYPES_NONE
, GCS_INDENT_GUIDE
);
774 /* bold = common whitespace settings enabled */
775 SSM(sci
, SCI_SETWHITESPACEFORE
, common_style_set
.styling
[GCS_WHITE_SPACE
].bold
,
776 invert(common_style_set
.styling
[GCS_WHITE_SPACE
].foreground
));
777 SSM(sci
, SCI_SETWHITESPACEBACK
, common_style_set
.styling
[GCS_WHITE_SPACE
].italic
,
778 invert(common_style_set
.styling
[GCS_WHITE_SPACE
].background
));
780 if (common_style_set
.styling
[GCS_CALLTIPS
].bold
)
781 SSM(sci
, SCI_CALLTIPSETFORE
, invert(common_style_set
.styling
[GCS_CALLTIPS
].foreground
), 1);
782 if (common_style_set
.styling
[GCS_CALLTIPS
].italic
)
783 SSM(sci
, SCI_CALLTIPSETBACK
, invert(common_style_set
.styling
[GCS_CALLTIPS
].background
), 1);
787 /* Merge & assign global typedefs and user secondary keywords.
788 * keyword_idx is used for both style_sets[].keywords and scintilla keyword style number */
789 static void merge_type_keywords(ScintillaObject
*sci
, guint ft_id
, guint keyword_idx
)
791 const gchar
*user_words
= style_sets
[ft_id
].keywords
[keyword_idx
];
794 s
= get_global_typenames(filetypes
[ft_id
]->lang
);
795 if (G_UNLIKELY(s
== NULL
))
796 s
= g_string_sized_new(200);
798 g_string_append_c(s
, ' '); /* append a space as delimiter to the existing list of words */
800 g_string_append(s
, user_words
);
802 sci_set_keywords(sci
, keyword_idx
, s
->str
);
803 g_string_free(s
, TRUE
);
807 static void styleset_init_from_mapping(guint ft_id
, GKeyFile
*config
, GKeyFile
*config_home
,
808 const HLStyle
*styles
, gsize n_styles
,
809 const HLKeyword
*keywords
, gsize n_keywords
)
814 new_styleset(ft_id
, n_styles
);
815 foreach_range(i
, n_styles
)
817 GeanyLexerStyle
*style
= &style_sets
[ft_id
].styling
[i
];
819 get_keyfile_style(config
, config_home
, styles
[i
].name
, style
);
824 style_sets
[ft_id
].keywords
= NULL
;
827 style_sets
[ft_id
].keywords
= g_new(gchar
*, n_keywords
+ 1);
828 foreach_range(i
, n_keywords
)
829 get_keyfile_keywords(config
, config_home
, keywords
[i
].key
, ft_id
, i
);
830 style_sets
[ft_id
].keywords
[i
] = NULL
;
835 /* STYLE_DEFAULT will be set to match the first style. */
836 static void styleset_from_mapping(ScintillaObject
*sci
, guint ft_id
, guint lexer
,
837 const HLStyle
*styles
, gsize n_styles
,
838 const HLKeyword
*keywords
, gsize n_keywords
,
839 const HLProperty
*properties
, gsize n_properties
)
843 g_assert(ft_id
!= GEANY_FILETYPES_NONE
);
846 SSM(sci
, SCI_SETLEXER
, lexer
, 0);
849 styleset_common(sci
, ft_id
);
852 /* first style is also default one */
853 set_sci_style(sci
, STYLE_DEFAULT
, ft_id
, 0);
854 foreach_range(i
, n_styles
)
856 if (styles
[i
].fill_eol
)
857 SSM(sci
, SCI_STYLESETEOLFILLED
, styles
[i
].style
, TRUE
);
858 set_sci_style(sci
, styles
[i
].style
, ft_id
, i
);
863 foreach_range(i
, n_keywords
)
865 if (keywords
[i
].merge
)
866 merge_type_keywords(sci
, ft_id
, i
);
868 sci_set_keywords(sci
, keywords
[i
].id
, style_sets
[ft_id
].keywords
[i
]);
872 foreach_range(i
, n_properties
)
873 sci_set_property(sci
, properties
[i
].property
, properties
[i
].value
);
878 static void styleset_default(ScintillaObject
*sci
, guint ft_id
)
880 SSM(sci
, SCI_SETLEXER
, SCLEX_NULL
, 0);
882 /* we need to set STYLE_DEFAULT before we call SCI_STYLECLEARALL in styleset_common() */
883 set_sci_style(sci
, STYLE_DEFAULT
, GEANY_FILETYPES_NONE
, GCS_DEFAULT
);
885 styleset_common(sci
, ft_id
);
889 static void get_key_values(GKeyFile
*config
, const gchar
*group
, gchar
**keys
, gchar
**values
)
893 gchar
*str
= g_key_file_get_string(config
, group
, *keys
, NULL
);
896 setptr(*values
, str
);
904 static void read_properties(GeanyFiletype
*ft
, GKeyFile
*config
, GKeyFile
*configh
)
906 gchar group
[] = "lexer_properties";
908 gchar
**keysh
= g_key_file_get_keys(configh
, group
, NULL
, NULL
);
911 /* remove overridden keys from system keyfile */
912 foreach_strv(ptr
, keysh
)
913 g_key_file_remove_key(config
, group
, *ptr
, NULL
);
915 /* merge sys and user keys */
916 keys
= g_key_file_get_keys(config
, group
, NULL
, NULL
);
917 keys
= utils_strv_join(keys
, keysh
);
921 gchar
**values
= g_new0(gchar
*, g_strv_length(keys
) + 1);
923 style_sets
[ft
->id
].property_keys
= keys
;
924 style_sets
[ft
->id
].property_values
= values
;
926 get_key_values(config
, group
, keys
, values
);
927 get_key_values(configh
, group
, keys
, values
);
932 static guint
get_lexer_filetype(GeanyFiletype
*ft
)
934 ft
= NVL(ft
->lexer_filetype
, ft
);
939 #define init_styleset_case(LANG_NAME) \
940 case (GEANY_FILETYPES_##LANG_NAME): \
941 styleset_init_from_mapping(filetype_idx, config, configh, \
942 highlighting_styles_##LANG_NAME, \
943 HL_N_ENTRIES(highlighting_styles_##LANG_NAME), \
944 highlighting_keywords_##LANG_NAME, \
945 HL_N_ENTRIES(highlighting_keywords_##LANG_NAME)); \
948 /* Called by filetypes_load_config(). */
949 void highlighting_init_styles(guint filetype_idx
, GKeyFile
*config
, GKeyFile
*configh
)
951 GeanyFiletype
*ft
= filetypes
[filetype_idx
];
952 guint lexer_id
= get_lexer_filetype(ft
);
955 style_sets
= g_new0(StyleSet
, filetypes_array
->len
);
957 /* Clear old information if necessary - e.g. when reloading config */
958 free_styleset(filetype_idx
);
960 read_properties(ft
, config
, configh
);
962 /* None filetype handled specially */
963 if (filetype_idx
== GEANY_FILETYPES_NONE
)
965 styleset_common_init(GEANY_FILETYPES_NONE
, config
, configh
);
968 /* All stylesets depend on filetypes.common */
969 filetypes_load_config(GEANY_FILETYPES_NONE
, FALSE
);
973 init_styleset_case(ADA
);
974 init_styleset_case(ASM
);
975 init_styleset_case(BASIC
);
976 init_styleset_case(C
);
977 init_styleset_case(CAML
);
978 init_styleset_case(CMAKE
);
979 init_styleset_case(COBOL
);
980 init_styleset_case(CONF
);
981 init_styleset_case(CSS
);
982 init_styleset_case(D
);
983 init_styleset_case(DIFF
);
984 init_styleset_case(LISP
);
985 init_styleset_case(ERLANG
);
986 init_styleset_case(DOCBOOK
);
987 init_styleset_case(FERITE
);
988 init_styleset_case(F77
);
989 init_styleset_case(FORTH
);
990 init_styleset_case(FORTRAN
);
991 init_styleset_case(HASKELL
);
992 init_styleset_case(HAXE
);
993 init_styleset_case(AS
);
994 init_styleset_case(HTML
);
995 init_styleset_case(JAVA
);
996 init_styleset_case(JS
);
997 init_styleset_case(LATEX
);
998 init_styleset_case(LUA
);
999 init_styleset_case(MAKE
);
1000 init_styleset_case(MATLAB
);
1001 init_styleset_case(MARKDOWN
);
1002 init_styleset_case(NSIS
);
1003 init_styleset_case(OBJECTIVEC
);
1004 init_styleset_case(PASCAL
);
1005 init_styleset_case(PERL
);
1006 init_styleset_case(PHP
);
1007 init_styleset_case(PO
);
1008 init_styleset_case(PYTHON
);
1009 init_styleset_case(R
);
1010 init_styleset_case(RUBY
);
1011 init_styleset_case(SH
);
1012 init_styleset_case(SQL
);
1013 init_styleset_case(TCL
);
1014 init_styleset_case(TXT2TAGS
);
1015 init_styleset_case(VHDL
);
1016 init_styleset_case(VERILOG
);
1017 init_styleset_case(XML
);
1018 init_styleset_case(YAML
);
1020 if (ft
->lexer_filetype
)
1021 geany_debug("Filetype %s has a recursive lexer_filetype %s set!",
1022 ft
->name
, ft
->lexer_filetype
->name
);
1025 /* should be done in filetypes.c really: */
1026 get_keyfile_wordchars(config
, configh
, &style_sets
[filetype_idx
].wordchars
);
1030 #define styleset_case(LANG_NAME) \
1031 case (GEANY_FILETYPES_##LANG_NAME): \
1032 styleset_from_mapping(sci, ft->id, highlighting_lexer_##LANG_NAME, \
1033 highlighting_styles_##LANG_NAME, \
1034 HL_N_ENTRIES(highlighting_styles_##LANG_NAME), \
1035 highlighting_keywords_##LANG_NAME, \
1036 HL_N_ENTRIES(highlighting_keywords_##LANG_NAME), \
1037 highlighting_properties_##LANG_NAME, \
1038 HL_N_ENTRIES(highlighting_properties_##LANG_NAME)); \
1041 /** Sets up highlighting and other visual settings.
1042 * @param sci Scintilla widget.
1043 * @param ft Filetype settings to use. */
1044 void highlighting_set_styles(ScintillaObject
*sci
, GeanyFiletype
*ft
)
1046 guint lexer_id
= get_lexer_filetype(ft
);
1048 filetypes_load_config(ft
->id
, FALSE
); /* load filetypes.ext */
1054 styleset_case(BASIC
);
1056 styleset_case(CAML
);
1057 styleset_case(CMAKE
);
1058 styleset_case(COBOL
);
1059 styleset_case(CONF
);
1062 styleset_case(DIFF
);
1063 styleset_case(LISP
);
1064 styleset_case(ERLANG
);
1065 styleset_case(DOCBOOK
);
1066 styleset_case(FERITE
);
1068 styleset_case(FORTH
);
1069 styleset_case(FORTRAN
);
1070 styleset_case(HASKELL
);
1071 styleset_case(HAXE
);
1073 styleset_case(HTML
);
1074 styleset_case(JAVA
);
1076 styleset_case(LATEX
);
1078 styleset_case(MAKE
);
1079 styleset_case(MARKDOWN
);
1080 styleset_case(MATLAB
);
1081 styleset_case(NSIS
);
1082 styleset_case(OBJECTIVEC
);
1083 styleset_case(PASCAL
);
1084 styleset_case(PERL
);
1087 styleset_case(PYTHON
);
1089 styleset_case(RUBY
);
1093 styleset_case(TXT2TAGS
);
1094 styleset_case(VHDL
);
1095 styleset_case(VERILOG
);
1097 styleset_case(YAML
);
1098 case GEANY_FILETYPES_NONE
:
1100 styleset_default(sci
, ft
->id
);
1102 /* [lexer_properties] settings */
1103 if (style_sets
[ft
->id
].property_keys
)
1105 gchar
**prop
= style_sets
[ft
->id
].property_keys
;
1106 gchar
**val
= style_sets
[ft
->id
].property_values
;
1110 sci_set_property(sci
, *prop
, *val
);
1118 /** Retrieves a style @a style_id for the filetype @a ft_id.
1119 * If the style was not already initialised
1120 * (e.g. by by opening a file of this type), it will be initialised. The returned pointer is
1121 * owned by Geany and must not be freed.
1122 * @param ft_id Filetype ID, e.g. @c GEANY_FILETYPES_DIFF.
1123 * @param style_id A Scintilla lexer style, e.g. @c SCE_DIFF_ADDED. See scintilla/include/SciLexer.h.
1124 * @return A pointer to the style struct.
1125 * @see Scintilla messages @c SCI_STYLEGETFORE, etc, for use with scintilla_send_message(). */
1126 const GeanyLexerStyle
*highlighting_get_style(gint ft_id
, gint style_id
)
1128 g_return_val_if_fail(ft_id
>= 0 && (guint
) ft_id
< filetypes_array
->len
, NULL
);
1129 g_return_val_if_fail(style_id
>= 0, NULL
);
1131 /* ensure filetype loaded */
1132 filetypes_load_config((guint
) ft_id
, FALSE
);
1134 /* TODO: style_id might not be the real array index (Scintilla styles are not always synced
1135 * with array indices) */
1136 return get_style((guint
) ft_id
, (guint
) style_id
);
1141 on_color_scheme_clicked(GtkMenuItem
*menuitem
, gpointer user_data
)
1146 /* prevent callback on setting initial value */
1147 if (!GTK_WIDGET_MAPPED(menuitem
))
1150 /* check if default item */
1153 setptr(editor_prefs
.color_scheme
, NULL
);
1157 fname
= g_strdup(g_object_get_data(G_OBJECT(menuitem
), "colorscheme_file"));
1158 setptr(fname
, utils_get_locale_from_utf8(fname
));
1160 /* fname is just the basename from the menu item, so prepend the custom files path */
1161 path
= g_build_path(G_DIR_SEPARATOR_S
, app
->configdir
, GEANY_COLORSCHEMES_SUBDIR
, fname
, NULL
);
1162 if (!g_file_test(path
, G_FILE_TEST_EXISTS
))
1164 /* try the system path */
1166 path
= g_build_path(G_DIR_SEPARATOR_S
, app
->datadir
, GEANY_COLORSCHEMES_SUBDIR
, fname
, NULL
);
1168 if (g_file_test(path
, G_FILE_TEST_EXISTS
))
1170 setptr(editor_prefs
.color_scheme
, fname
);
1176 setptr(fname
, utils_get_utf8_from_locale(fname
));
1177 ui_set_statusbar(TRUE
, _("Could not find file '%s'."), fname
);
1184 static gchar
*utils_get_setting_locale_string(GKeyFile
*keyfile
,
1185 const gchar
*group
, const gchar
*key
, const gchar
*default_value
)
1187 gchar
*result
= g_key_file_get_locale_string(keyfile
, group
, key
, NULL
, NULL
);
1189 return NVL(result
, g_strdup(default_value
));
1193 static void add_color_scheme_item(GtkWidget
*menu
, const gchar
*fname
)
1195 static GSList
*group
= NULL
;
1200 item
= gtk_radio_menu_item_new_with_mnemonic(group
, _("_Default"));
1204 GKeyFile
*hkeyfile
, *skeyfile
;
1205 gchar
*path
, *theme_name
, *tooltip
;
1206 gchar
*theme_fn
= utils_get_utf8_from_locale(fname
);
1208 path
= utils_build_path(app
->configdir
, GEANY_COLORSCHEMES_SUBDIR
, fname
, NULL
);
1209 hkeyfile
= utils_key_file_new(path
);
1210 setptr(path
, utils_build_path(app
->datadir
, GEANY_COLORSCHEMES_SUBDIR
, fname
, NULL
));
1211 skeyfile
= utils_key_file_new(path
);
1213 theme_name
= utils_get_setting(locale_string
, hkeyfile
, skeyfile
, "theme_info", "name", theme_fn
);
1214 item
= gtk_radio_menu_item_new_with_label(group
, theme_name
);
1215 g_object_set_data_full(G_OBJECT(item
), "colorscheme_file", theme_fn
, g_free
);
1217 tooltip
= utils_get_setting(locale_string
, hkeyfile
, skeyfile
, "theme_info", "description", NULL
);
1218 if (tooltip
!= NULL
)
1220 gtk_widget_set_tooltip_text(item
, tooltip
);
1225 g_key_file_free(hkeyfile
);
1226 g_key_file_free(skeyfile
);
1229 group
= gtk_radio_menu_item_get_group(GTK_RADIO_MENU_ITEM(item
));
1230 if (utils_str_equal(editor_prefs
.color_scheme
, fname
))
1231 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(item
), TRUE
);
1233 gtk_widget_show(item
);
1234 gtk_container_add(GTK_CONTAINER(menu
), item
);
1235 g_signal_connect(item
, "activate",
1236 G_CALLBACK(on_color_scheme_clicked
), GINT_TO_POINTER(fname
!= NULL
));
1240 static gboolean
add_color_scheme_items(GtkWidget
*menu
)
1242 GSList
*list
, *node
;
1244 g_return_val_if_fail(menu
, FALSE
);
1246 add_color_scheme_item(menu
, NULL
);
1247 list
= utils_get_config_files(GEANY_COLORSCHEMES_SUBDIR
);
1249 foreach_slist(node
, list
)
1251 gchar
*fname
= node
->data
;
1253 if (g_str_has_suffix(fname
, ".conf"))
1254 add_color_scheme_item(menu
, fname
);
1259 return list
!= NULL
;
1263 static void create_color_scheme_menu(void)
1265 GtkWidget
*item
, *menu
, *root
;
1267 menu
= ui_lookup_widget(main_widgets
.window
, "menu_view_editor1_menu");
1268 item
= ui_image_menu_item_new(GTK_STOCK_SELECT_COLOR
, _("_Color Schemes"));
1269 gtk_menu_shell_prepend(GTK_MENU_SHELL(menu
), item
);
1272 menu
= gtk_menu_new();
1273 gtk_menu_item_set_submenu(GTK_MENU_ITEM(item
), menu
);
1275 add_color_scheme_items(menu
);
1276 gtk_widget_show_all(root
);
1280 void highlighting_init(void)
1282 create_color_scheme_menu();
1286 /** Checks whether the given style is a string for the given lexer.
1288 * @param lexer Scintilla lexer type (@c SCLEX_*).
1289 * @param style Scintilla style (@c SCE_*).
1291 * @return @c TRUE if the style is a string, @c FALSE otherwise.
1293 gboolean
highlighting_is_string_style(gint lexer
, gint style
)
1295 /* Don't forget STRINGEOL, to prevent completion whilst typing a string with no closing char. */
1300 return (style
== SCE_C_CHARACTER
||
1301 style
== SCE_C_STRING
||
1302 style
== SCE_C_STRINGEOL
||
1303 style
== SCE_C_STRINGRAW
||
1304 style
== SCE_C_VERBATIM
||
1305 style
== SCE_C_TRIPLEVERBATIM
);
1308 return (style
== SCE_PAS_CHARACTER
||
1309 style
== SCE_PAS_STRING
||
1310 style
== SCE_PAS_STRINGEOL
);
1313 return (style
== SCE_D_STRING
||
1314 style
== SCE_D_STRINGEOL
||
1315 style
== SCE_D_CHARACTER
||
1316 style
== SCE_D_STRINGB
||
1317 style
== SCE_D_STRINGR
);
1320 return (style
== SCE_P_STRING
||
1321 style
== SCE_P_TRIPLE
||
1322 style
== SCE_P_TRIPLEDOUBLE
||
1323 style
== SCE_P_CHARACTER
||
1324 style
== SCE_P_STRINGEOL
);
1328 return (style
== SCE_F_STRING1
||
1329 style
== SCE_F_STRING2
||
1330 style
== SCE_F_STRINGEOL
);
1333 return (style
== SCE_PL_STRING
||
1334 style
== SCE_PL_CHARACTER
||
1335 style
== SCE_PL_HERE_DELIM
||
1336 style
== SCE_PL_HERE_Q
||
1337 style
== SCE_PL_HERE_QQ
||
1338 style
== SCE_PL_HERE_QX
||
1339 style
== SCE_PL_POD
||
1340 style
== SCE_PL_STRING_Q
||
1341 style
== SCE_PL_STRING_QQ
||
1342 style
== SCE_PL_STRING_QX
||
1343 style
== SCE_PL_STRING_QR
||
1344 style
== SCE_PL_STRING_QW
||
1345 style
== SCE_PL_POD_VERB
||
1346 style
== SCE_PL_XLAT
1347 /* we don't include any STRING_*_VAR for autocompletion */);
1350 return (style
== SCE_R_STRING
);
1353 return (style
== SCE_RB_CHARACTER
||
1354 style
== SCE_RB_STRING
||
1355 style
== SCE_RB_HERE_DELIM
||
1356 style
== SCE_RB_HERE_Q
||
1357 style
== SCE_RB_HERE_QQ
||
1358 style
== SCE_RB_HERE_QX
||
1359 style
== SCE_RB_POD
);
1362 return (style
== SCE_SH_STRING
);
1365 return (style
== SCE_SQL_STRING
);
1368 return (style
== SCE_TCL_IN_QUOTE
);
1371 return (style
== SCE_LUA_LITERALSTRING
||
1372 style
== SCE_LUA_CHARACTER
||
1373 style
== SCE_LUA_STRINGEOL
||
1374 style
== SCE_LUA_STRING
);
1377 return (style
== SCE_HA_CHARACTER
||
1378 style
== SCE_HA_STRING
);
1380 case SCLEX_FREEBASIC
:
1381 return (style
== SCE_B_STRING
||
1382 style
== SCE_B_STRINGEOL
);
1385 return (style
== SCE_MATLAB_STRING
||
1386 style
== SCE_MATLAB_DOUBLEQUOTESTRING
);
1390 style
== SCE_HBA_STRING
||
1391 style
== SCE_HBA_STRINGEOL
||
1392 style
== SCE_HB_STRING
||
1393 style
== SCE_HB_STRINGEOL
||
1394 style
== SCE_H_CDATA
||
1395 style
== SCE_H_DOUBLESTRING
||
1396 style
== SCE_HJA_DOUBLESTRING
||
1397 style
== SCE_HJA_SINGLESTRING
||
1398 style
== SCE_HJA_STRINGEOL
||
1399 style
== SCE_HJ_DOUBLESTRING
||
1400 style
== SCE_HJ_SINGLESTRING
||
1401 style
== SCE_HJ_STRINGEOL
||
1402 style
== SCE_HPA_CHARACTER
||
1403 style
== SCE_HPA_STRING
||
1404 style
== SCE_HPA_TRIPLE
||
1405 style
== SCE_HPA_TRIPLEDOUBLE
||
1406 style
== SCE_HP_CHARACTER
||
1407 style
== SCE_HPHP_HSTRING
|| /* HSTRING is a heredoc */
1408 style
== SCE_HPHP_HSTRING_VARIABLE
||
1409 style
== SCE_HPHP_SIMPLESTRING
||
1410 style
== SCE_HP_STRING
||
1411 style
== SCE_HP_TRIPLE
||
1412 style
== SCE_HP_TRIPLEDOUBLE
||
1413 style
== SCE_H_SGML_DOUBLESTRING
||
1414 style
== SCE_H_SGML_SIMPLESTRING
||
1415 style
== SCE_H_SINGLESTRING
);
1418 return (style
== SCE_CMAKE_STRINGDQ
||
1419 style
== SCE_CMAKE_STRINGLQ
||
1420 style
== SCE_CMAKE_STRINGRQ
||
1421 style
== SCE_CMAKE_STRINGVAR
);
1424 return (style
== SCE_NSIS_STRINGDQ
||
1425 style
== SCE_NSIS_STRINGLQ
||
1426 style
== SCE_NSIS_STRINGRQ
||
1427 style
== SCE_NSIS_STRINGVAR
);
1430 return (style
== SCE_ADA_CHARACTER
||
1431 style
== SCE_ADA_STRING
||
1432 style
== SCE_ADA_CHARACTEREOL
||
1433 style
== SCE_ADA_STRINGEOL
);
1439 /** Checks whether the given style is a comment for the given lexer.
1441 * @param lexer Scintilla lexer type (@c SCLEX_*).
1442 * @param style Scintilla style (@c SCE_*).
1444 * @return @c TRUE if the style is a comment, @c FALSE otherwise.
1446 gboolean
highlighting_is_comment_style(gint lexer
, gint style
)
1452 return (style
== SCE_C_COMMENT
||
1453 style
== SCE_C_COMMENTLINE
||
1454 style
== SCE_C_COMMENTDOC
||
1455 style
== SCE_C_COMMENTLINEDOC
||
1456 style
== SCE_C_COMMENTDOCKEYWORD
||
1457 style
== SCE_C_COMMENTDOCKEYWORDERROR
);
1460 return (style
== SCE_PAS_COMMENT
||
1461 style
== SCE_PAS_COMMENT2
||
1462 style
== SCE_PAS_COMMENTLINE
);
1465 return (style
== SCE_D_COMMENT
||
1466 style
== SCE_D_COMMENTLINE
||
1467 style
== SCE_D_COMMENTDOC
||
1468 style
== SCE_D_COMMENTNESTED
||
1469 style
== SCE_D_COMMENTLINEDOC
||
1470 style
== SCE_D_COMMENTDOCKEYWORD
||
1471 style
== SCE_D_COMMENTDOCKEYWORDERROR
);
1474 return (style
== SCE_P_COMMENTLINE
||
1475 style
== SCE_P_COMMENTBLOCK
);
1479 return (style
== SCE_F_COMMENT
);
1482 return (style
== SCE_PL_COMMENTLINE
);
1484 case SCLEX_PROPERTIES
:
1485 return (style
== SCE_PROPS_COMMENT
);
1488 return (style
== SCE_PO_COMMENT
);
1491 return (style
== SCE_L_COMMENT
||
1492 style
== SCE_L_COMMENT2
);
1494 case SCLEX_MAKEFILE
:
1495 return (style
== SCE_MAKE_COMMENT
);
1498 return (style
== SCE_RB_COMMENTLINE
);
1501 return (style
== SCE_SH_COMMENTLINE
);
1504 return (style
== SCE_R_COMMENT
);
1507 return (style
== SCE_SQL_COMMENT
||
1508 style
== SCE_SQL_COMMENTLINE
||
1509 style
== SCE_SQL_COMMENTDOC
||
1510 style
== SCE_SQL_COMMENTLINEDOC
||
1511 style
== SCE_SQL_COMMENTDOCKEYWORD
||
1512 style
== SCE_SQL_COMMENTDOCKEYWORDERROR
);
1515 return (style
== SCE_TCL_COMMENT
||
1516 style
== SCE_TCL_COMMENTLINE
||
1517 style
== SCE_TCL_COMMENT_BOX
||
1518 style
== SCE_TCL_BLOCK_COMMENT
);
1521 return (style
== SCE_MATLAB_COMMENT
);
1524 return (style
== SCE_LUA_COMMENT
||
1525 style
== SCE_LUA_COMMENTLINE
||
1526 style
== SCE_LUA_COMMENTDOC
);
1529 return (style
== SCE_HA_COMMENTLINE
||
1530 style
== SCE_HA_COMMENTBLOCK
||
1531 style
== SCE_HA_COMMENTBLOCK2
||
1532 style
== SCE_HA_COMMENTBLOCK3
);
1534 case SCLEX_FREEBASIC
:
1535 return (style
== SCE_B_COMMENT
);
1538 return (style
== SCE_YAML_COMMENT
);
1542 style
== SCE_HBA_COMMENTLINE
||
1543 style
== SCE_HB_COMMENTLINE
||
1544 style
== SCE_H_COMMENT
||
1545 style
== SCE_HJA_COMMENT
||
1546 style
== SCE_HJA_COMMENTDOC
||
1547 style
== SCE_HJA_COMMENTLINE
||
1548 style
== SCE_HJ_COMMENT
||
1549 style
== SCE_HJ_COMMENTDOC
||
1550 style
== SCE_HJ_COMMENTLINE
||
1551 style
== SCE_HPA_COMMENTLINE
||
1552 style
== SCE_HP_COMMENTLINE
||
1553 style
== SCE_HPHP_COMMENT
||
1554 style
== SCE_HPHP_COMMENTLINE
||
1555 style
== SCE_H_SGML_COMMENT
);
1558 return (style
== SCE_CMAKE_COMMENT
);
1561 return (style
== SCE_NSIS_COMMENT
||
1562 style
== SCE_NSIS_COMMENTBOX
);
1565 return (style
== SCE_ADA_COMMENTLINE
||
1566 style
== SCE_NSIS_COMMENTBOX
);
1569 return (style
== SCE_ASM_COMMENT
||
1570 style
== SCE_ASM_COMMENTBLOCK
||
1571 style
== SCE_ASM_COMMENTDIRECTIVE
);
1577 /** Checks whether the given style is normal code (not string, comment, preprocessor, etc).
1579 * @param lexer Scintilla lexer type (@c SCLEX_*).
1580 * @param style Scintilla style (@c SCE_*).
1582 * @return @c TRUE if the style is code, @c FALSE otherwise.
1584 gboolean
highlighting_is_code_style(gint lexer
, gint style
)
1589 if (style
== SCE_C_PREPROCESSOR
)
1593 return !(highlighting_is_comment_style(lexer
, style
) ||
1594 highlighting_is_string_style(lexer
, style
));