1 /* GTK - The GIMP Toolkit
2 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
22 #include <sys/param.h>
27 #include "gtkbindings.h"
30 typedef struct _GtkRcStyle GtkRcStyle;
31 typedef struct _GtkRcSet GtkRcSet;
32 typedef struct _GtkRcNode GtkRcNode;
33 typedef struct _GtkRcFile GtkRcFile;
46 char *bg_pixmap_name[5];
47 GtkStyle *proto_style;
61 gchar *canonical_name;
65 static guint gtk_rc_style_hash (const char *name);
66 static gint gtk_rc_style_compare (const char *a,
68 static GtkRcStyle* gtk_rc_style_find (const char *name);
69 static GtkRcStyle* gtk_rc_styles_match (GSList *sets,
72 gchar *path_reversed);
73 static GtkStyle* gtk_rc_style_init (GtkRcStyle *rc_style,
75 static void gtk_rc_parse_file (const gchar *filename,
78 static void gtk_rc_parse_any (const gchar *input_name,
80 const gchar *input_string);
81 static guint gtk_rc_parse_statement (GScanner *scanner);
82 static guint gtk_rc_parse_style (GScanner *scanner);
83 static guint gtk_rc_parse_base (GScanner *scanner,
85 static guint gtk_rc_parse_bg (GScanner *scanner,
87 static guint gtk_rc_parse_fg (GScanner *scanner,
89 static guint gtk_rc_parse_text (GScanner *scanner,
91 static guint gtk_rc_parse_bg_pixmap (GScanner *scanner,
92 GtkRcStyle *rc_style);
93 static guint gtk_rc_parse_font (GScanner *scanner,
94 GtkRcStyle *rc_style);
95 static guint gtk_rc_parse_fontset (GScanner *scanner,
96 GtkRcStyle *rc_style);
97 static guint gtk_rc_parse_pixmap_path (GScanner *scanner);
98 static void gtk_rc_parse_pixmap_path_string (gchar *pix_path);
99 static char* gtk_rc_find_pixmap_in_path (GScanner *scanner,
101 static guint gtk_rc_parse_path_pattern (GScanner *scanner);
102 static void gtk_rc_clear_hash_node (gpointer key,
105 static void gtk_rc_clear_styles (void);
109 static GScannerConfig gtk_rc_scanner_config =
113 ) /* cset_skip_characters */,
118 ) /* cset_identifier_first */,
123 ) /* cset_identifier_nth */,
124 ( "#\n" ) /* cpair_comment_single */,
126 TRUE /* case_sensitive */,
128 TRUE /* skip_comment_multi */,
129 TRUE /* skip_comment_single */,
130 TRUE /* scan_comment_multi */,
131 TRUE /* scan_identifier */,
132 FALSE /* scan_identifier_1char */,
133 FALSE /* scan_identifier_NULL */,
134 TRUE /* scan_symbols */,
135 TRUE /* scan_binary */,
136 TRUE /* scan_octal */,
137 TRUE /* scan_float */,
139 TRUE /* scan_hex_dollar */,
140 TRUE /* scan_string_sq */,
141 TRUE /* scan_string_dq */,
142 TRUE /* numbers_2_int */,
143 FALSE /* int_2_float */,
144 FALSE /* identifier_2_string */,
145 TRUE /* char_2_token */,
146 TRUE /* symbol_2_token */,
147 FALSE /* scope_0_fallback */,
155 { "include", GTK_RC_TOKEN_INCLUDE },
156 { "NORMAL", GTK_RC_TOKEN_NORMAL },
157 { "ACTIVE", GTK_RC_TOKEN_ACTIVE },
158 { "PRELIGHT", GTK_RC_TOKEN_PRELIGHT },
159 { "SELECTED", GTK_RC_TOKEN_SELECTED },
160 { "INSENSITIVE", GTK_RC_TOKEN_INSENSITIVE },
161 { "fg", GTK_RC_TOKEN_FG },
162 { "bg", GTK_RC_TOKEN_BG },
163 { "base", GTK_RC_TOKEN_BASE },
164 { "text", GTK_RC_TOKEN_TEXT },
165 { "font", GTK_RC_TOKEN_FONT },
166 { "fontset", GTK_RC_TOKEN_FONTSET },
167 { "bg_pixmap", GTK_RC_TOKEN_BG_PIXMAP },
168 { "pixmap_path", GTK_RC_TOKEN_PIXMAP_PATH },
169 { "style", GTK_RC_TOKEN_STYLE },
170 { "binding", GTK_RC_TOKEN_BINDING },
171 { "bind", GTK_RC_TOKEN_BIND },
172 { "widget", GTK_RC_TOKEN_WIDGET },
173 { "widget_class", GTK_RC_TOKEN_WIDGET_CLASS },
174 { "class", GTK_RC_TOKEN_CLASS },
175 { "lowest", GTK_RC_TOKEN_LOWEST },
176 { "gtk", GTK_RC_TOKEN_GTK },
177 { "application", GTK_RC_TOKEN_APPLICATION },
178 { "rc", GTK_RC_TOKEN_RC },
179 { "highest", GTK_RC_TOKEN_HIGHEST },
182 static guint n_symbols = sizeof (symbols) / sizeof (symbols[0]);
184 static GHashTable *rc_style_ht = NULL;
185 static GSList *gtk_rc_sets_widget = NULL;
186 static GSList *gtk_rc_sets_widget_class = NULL;
187 static GSList *gtk_rc_sets_class = NULL;
189 #define GTK_RC_MAX_PIXMAP_PATHS 128
190 static gchar *pixmap_path[GTK_RC_MAX_PIXMAP_PATHS];
192 /* The files we have parsed, to reread later if necessary */
193 GSList *rc_files = NULL;
195 static GtkImageLoader image_loader = NULL;
200 rc_style_ht = g_hash_table_new ((GHashFunc) gtk_rc_style_hash,
201 (GCompareFunc) gtk_rc_style_compare);
205 gtk_rc_parse_string (const gchar *rc_string)
207 g_return_if_fail (rc_string != NULL);
209 gtk_rc_parse_any ("-", -1, rc_string);
213 gtk_rc_parse_file (const gchar *filename, gboolean reload)
215 GtkRcFile *rc_file = NULL;
219 g_return_if_fail (filename != NULL);
224 rc_file = tmp_list->data;
225 if (!strcmp (rc_file->name, filename))
228 tmp_list = tmp_list->next;
233 rc_file = g_new (GtkRcFile, 1);
234 rc_file->name = g_strdup (filename);
235 rc_file->canonical_name = NULL;
237 rc_file->reload = reload;
239 rc_files = g_slist_append (rc_files, rc_file);
242 if (!rc_file->canonical_name)
244 /* Get the absolute pathname */
246 if (rc_file->name[0] == '/')
247 rc_file->canonical_name = rc_file->name;
253 cwd = g_get_current_dir ();
255 str = g_string_new (cwd);
257 g_string_append_c (str, '/');
258 g_string_append (str, rc_file->name);
260 rc_file->canonical_name = str->str;
261 g_string_free (str, FALSE);
265 if (!lstat (rc_file->canonical_name, &statbuf))
269 rc_file->mtime = statbuf.st_mtime;
271 fd = open (rc_file->canonical_name, O_RDONLY);
275 gtk_rc_parse_any (filename, fd, NULL);
282 gtk_rc_parse (const gchar *filename)
284 g_return_if_fail (filename != NULL);
286 gtk_rc_parse_file (filename, TRUE);
290 gtk_rc_clear_hash_node (gpointer key,
295 GtkRcStyle *rc_style = data;
298 g_free (rc_style->name);
299 g_free (rc_style->font_name);
300 g_free (rc_style->fontset_name);
302 for (i=0 ; i<5 ; i++)
303 g_free (rc_style->bg_pixmap_name[i]);
305 gtk_style_unref (rc_style->proto_style);
307 tmp_list = rc_style->styles;
310 GtkRcNode *node = tmp_list->data;
312 gdk_colormap_unref (node->cmap);
313 gtk_style_unref (node->style);
316 tmp_list = tmp_list->next;
323 gtk_rc_free_rc_sets (GSList *slist)
329 rc_set = slist->data;
330 gtk_pattern_spec_free_segs (&rc_set->pspec);
338 gtk_rc_clear_styles (void)
340 /* Clear out all old rc_styles */
342 g_hash_table_foreach (rc_style_ht, gtk_rc_clear_hash_node, NULL);
343 g_hash_table_destroy (rc_style_ht);
346 gtk_rc_free_rc_sets (gtk_rc_sets_widget);
347 g_slist_free (gtk_rc_sets_widget);
348 gtk_rc_sets_widget = NULL;
350 gtk_rc_free_rc_sets (gtk_rc_sets_widget_class);
351 g_slist_free (gtk_rc_sets_widget_class);
352 gtk_rc_sets_widget_class = NULL;
354 gtk_rc_free_rc_sets (gtk_rc_sets_class);
355 g_slist_free (gtk_rc_sets_class);
356 gtk_rc_sets_class = NULL;
362 gtk_rc_reparse_all (void)
365 gboolean mtime_modified = FALSE;
370 /* Check through and see if any of the RC's have had their
371 * mtime modified. If so, reparse everything.
376 rc_file = tmp_list->data;
378 if (!lstat (rc_file->name, &statbuf) &&
379 (statbuf.st_mtime > rc_file->mtime))
381 mtime_modified = TRUE;
385 tmp_list = tmp_list->next;
390 gtk_rc_clear_styles();
395 rc_file = tmp_list->data;
397 gtk_rc_parse_file (rc_file->name, FALSE);
399 tmp_list = tmp_list->next;
403 return mtime_modified;
407 gtk_rc_styles_match (GSList *sets,
410 gchar *path_reversed)
419 if (gtk_pattern_match (&rc_set->pspec, path_length, path, path_reversed))
420 return rc_set->rc_style;
427 gtk_rc_get_style (GtkWidget *widget)
429 GtkRcStyle *rc_style;
431 if (gtk_rc_sets_widget)
433 gchar *path, *path_reversed;
436 gtk_widget_path (widget, &path_length, &path, &path_reversed);
437 rc_style = gtk_rc_styles_match (gtk_rc_sets_widget, path_length, path, path_reversed);
439 g_free (path_reversed);
442 return gtk_rc_style_init (rc_style, gtk_widget_get_colormap (widget));
445 if (gtk_rc_sets_widget_class)
447 gchar *path, *path_reversed;
450 gtk_widget_class_path (widget, &path_length, &path, &path_reversed);
451 rc_style = gtk_rc_styles_match (gtk_rc_sets_widget_class, path_length, path, path_reversed);
453 g_free (path_reversed);
456 return gtk_rc_style_init (rc_style, gtk_widget_get_colormap (widget));
459 if (gtk_rc_sets_class)
463 type = GTK_OBJECT_TYPE (widget);
466 gchar *path, *path_reversed;
469 path = gtk_type_name (type);
470 path_length = strlen (path);
471 path_reversed = g_strdup (path);
472 g_strreverse (path_reversed);
474 rc_style = gtk_rc_styles_match (gtk_rc_sets_class, path_length, path, path_reversed);
475 g_free (path_reversed);
478 return gtk_rc_style_init (rc_style, gtk_widget_get_colormap (widget));
480 type = gtk_type_parent (type);
488 gtk_rc_add_rc_sets (GSList *slist,
492 GtkRcStyle *rc_style;
496 gtk_style_ref (style);
498 rc_style = g_new (GtkRcStyle, 1);
499 rc_style->name = NULL;
500 rc_style->font_name = NULL;
501 rc_style->fontset_name = NULL;
503 for (i = 0; i < 5; i++)
504 rc_style->bg_pixmap_name[i] = NULL;
506 rc_style->styles = g_list_append (NULL, style);
508 rc_set = g_new (GtkRcSet, 1);
509 gtk_pattern_spec_init (&rc_set->pspec, pattern);
510 rc_set->rc_style = rc_style;
512 return g_slist_prepend (slist, rc_set);
516 gtk_rc_add_widget_name_style (GtkStyle *style,
517 const gchar *pattern)
519 g_return_if_fail (style != NULL);
520 g_return_if_fail (pattern != NULL);
522 gtk_rc_sets_widget = gtk_rc_add_rc_sets (gtk_rc_sets_widget, style, pattern);
526 gtk_rc_add_widget_class_style (GtkStyle *style,
527 const gchar *pattern)
529 g_return_if_fail (style != NULL);
530 g_return_if_fail (pattern != NULL);
532 gtk_rc_sets_widget_class = gtk_rc_add_rc_sets (gtk_rc_sets_widget_class, style, pattern);
536 gtk_rc_add_class_style (GtkStyle *style,
537 const gchar *pattern)
539 g_return_if_fail (style != NULL);
540 g_return_if_fail (pattern != NULL);
542 gtk_rc_sets_class = gtk_rc_add_rc_sets (gtk_rc_sets_class, style, pattern);
546 gtk_rc_parse_any (const gchar *input_name,
548 const gchar *input_string)
554 scanner = g_scanner_new (>k_rc_scanner_config);
558 g_assert (input_string == NULL);
560 g_scanner_input_file (scanner, input_fd);
564 g_assert (input_string != NULL);
566 g_scanner_input_text (scanner, input_string, strlen (input_string));
568 scanner->input_name = input_name;
570 g_scanner_freeze_symbol_table (scanner);
571 for (i = 0; i < n_symbols; i++)
572 g_scanner_add_symbol (scanner, symbols[i].name, GINT_TO_POINTER (symbols[i].token));
573 g_scanner_thaw_symbol_table (scanner);
578 if (g_scanner_peek_next_token (scanner) == G_TOKEN_EOF)
582 guint expected_token;
584 expected_token = gtk_rc_parse_statement (scanner);
586 if (expected_token != G_TOKEN_NONE)
593 if (scanner->scope_id == 0)
595 /* if we are in scope 0, we know the symbol names
596 * that are associated with certaintoken values.
597 * so we look them up to make the error messages
600 if (expected_token > GTK_RC_TOKEN_INVALID &&
601 expected_token < GTK_RC_TOKEN_LAST)
603 for (i = 0; i < n_symbols; i++)
604 if (symbols[i].token == expected_token)
605 msg = symbols[i].name;
607 msg = g_strconcat ("e.g. `", msg, "'", NULL);
609 if (scanner->token > GTK_RC_TOKEN_INVALID &&
610 scanner->token < GTK_RC_TOKEN_LAST)
613 for (i = 0; i < n_symbols; i++)
614 if (symbols[i].token == scanner->token)
615 symbol_name = symbols[i].name;
618 g_scanner_unexp_token (scanner,
631 g_scanner_destroy (scanner);
635 gtk_rc_style_hash (const char *name)
641 result += (result << 3) + *name++;
647 gtk_rc_style_compare (const char *a,
650 return (strcmp (a, b) == 0);
654 gtk_rc_style_find (const char *name)
656 GtkRcStyle *rc_style;
658 rc_style = g_hash_table_lookup (rc_style_ht, (gpointer) name);
664 gtk_rc_style_init (GtkRcStyle *rc_style, GdkColormap *cmap)
667 gboolean match_cmap = FALSE;
671 GtkStyle *style = NULL;
674 tmp_list = rc_style->styles;
677 if (rc_style->bg_pixmap_name[i])
682 node = (GtkRcNode *)tmp_list->data;
684 if (!match_cmap || (node->cmap == cmap))
690 tmp_list = tmp_list->next;
695 node = g_new (GtkRcNode, 1);
696 style = gtk_style_copy (rc_style->proto_style);
698 /* FIXME, this leaks colormaps, but if we don't do this, then we'll
699 * be screwed, because we identify colormaps by address equality
701 gdk_colormap_ref (cmap);
706 if (rc_style->fontset_name)
708 old_font = style->font;
709 style->font = gdk_fontset_load (rc_style->fontset_name);
711 gdk_font_unref (old_font);
713 style->font = old_font;
715 else if (rc_style->font_name)
717 old_font = style->font;
718 style->font = gdk_font_load (rc_style->font_name);
720 gdk_font_unref (old_font);
722 style->font = old_font;
725 for (i = 0; i < 5; i++)
726 if (rc_style->bg_pixmap_name[i])
728 if (strcmp (rc_style->bg_pixmap_name[i], "<parent>") == 0)
729 style->bg_pixmap[i] = (GdkPixmap*) GDK_PARENT_RELATIVE;
733 style->bg_pixmap[i] = image_loader(NULL, cmap, NULL,
735 rc_style->bg_pixmap_name[i]);
737 style->bg_pixmap[i] =
738 gdk_pixmap_colormap_create_from_xpm (NULL, cmap,
741 rc_style->bg_pixmap_name[i]);
745 rc_style->styles = g_list_append (rc_style->styles, node);
752 gtk_rc_parse_statement (GScanner *scanner)
756 token = g_scanner_peek_next_token (scanner);
760 case GTK_RC_TOKEN_INCLUDE:
761 token = g_scanner_get_next_token (scanner);
762 if (token != GTK_RC_TOKEN_INCLUDE)
763 return GTK_RC_TOKEN_INCLUDE;
765 token = g_scanner_get_next_token (scanner);
766 if (token != G_TOKEN_STRING)
767 return G_TOKEN_STRING;
769 gtk_rc_parse_file (scanner->value.v_string, FALSE);
772 case GTK_RC_TOKEN_STYLE:
773 return gtk_rc_parse_style (scanner);
775 case GTK_RC_TOKEN_BINDING:
776 return gtk_binding_parse_binding (scanner);
778 case GTK_RC_TOKEN_PIXMAP_PATH:
779 return gtk_rc_parse_pixmap_path (scanner);
781 case GTK_RC_TOKEN_WIDGET:
782 return gtk_rc_parse_path_pattern (scanner);
784 case GTK_RC_TOKEN_WIDGET_CLASS:
785 return gtk_rc_parse_path_pattern (scanner);
787 case GTK_RC_TOKEN_CLASS:
788 return gtk_rc_parse_path_pattern (scanner);
791 g_scanner_get_next_token (scanner);
792 return /* G_TOKEN_SYMBOL */ GTK_RC_TOKEN_STYLE;
797 gtk_rc_parse_style (GScanner *scanner)
799 GtkRcStyle *rc_style;
800 GtkRcStyle *parent_style;
805 token = g_scanner_get_next_token (scanner);
806 if (token != GTK_RC_TOKEN_STYLE)
807 return GTK_RC_TOKEN_STYLE;
809 token = g_scanner_get_next_token (scanner);
810 if (token != G_TOKEN_STRING)
811 return G_TOKEN_STRING;
814 rc_style = g_hash_table_lookup (rc_style_ht, scanner->value.v_string);
819 rc_style = g_new (GtkRcStyle, 1);
820 rc_style->name = g_strdup (scanner->value.v_string);
821 rc_style->font_name = NULL;
822 rc_style->fontset_name = NULL;
824 for (i = 0; i < 5; i++)
825 rc_style->bg_pixmap_name[i] = NULL;
827 rc_style->proto_style = gtk_style_new();
828 rc_style->styles = NULL;
831 token = g_scanner_peek_next_token (scanner);
832 if (token == G_TOKEN_EQUAL_SIGN)
834 token = g_scanner_get_next_token (scanner);
836 token = g_scanner_get_next_token (scanner);
837 if (token != G_TOKEN_STRING)
841 gtk_style_unref (rc_style->proto_style);
844 return G_TOKEN_STRING;
847 parent_style = g_hash_table_lookup (rc_style_ht, scanner->value.v_string);
850 for (i = 0; i < 5; i++)
852 rc_style->proto_style->fg[i] = parent_style->proto_style->fg[i];
853 rc_style->proto_style->bg[i] = parent_style->proto_style->bg[i];
854 rc_style->proto_style->light[i] = parent_style->proto_style->light[i];
855 rc_style->proto_style->dark[i] = parent_style->proto_style->dark[i];
856 rc_style->proto_style->mid[i] = parent_style->proto_style->mid[i];
857 rc_style->proto_style->text[i] = parent_style->proto_style->text[i];
858 rc_style->proto_style->base[i] = parent_style->proto_style->base[i];
861 rc_style->proto_style->black = parent_style->proto_style->black;
862 rc_style->proto_style->white = parent_style->proto_style->white;
864 if (rc_style->fontset_name)
866 g_free (rc_style->fontset_name);
867 rc_style->fontset_name = g_strdup (parent_style->fontset_name);
869 else if (rc_style->font_name)
871 g_free (rc_style->font_name);
872 rc_style->font_name = g_strdup (parent_style->font_name);
875 for (i = 0; i < 5; i++)
877 if (rc_style->bg_pixmap_name[i])
878 g_free (rc_style->bg_pixmap_name[i]);
879 rc_style->bg_pixmap_name[i] = g_strdup (parent_style->bg_pixmap_name[i]);
884 token = g_scanner_get_next_token (scanner);
885 if (token != G_TOKEN_LEFT_CURLY)
889 gtk_style_unref (rc_style->proto_style);
892 return G_TOKEN_LEFT_CURLY;
895 token = g_scanner_peek_next_token (scanner);
896 while (token != G_TOKEN_RIGHT_CURLY)
900 case GTK_RC_TOKEN_BASE:
901 token = gtk_rc_parse_base (scanner, rc_style->proto_style);
903 case GTK_RC_TOKEN_BG:
904 token = gtk_rc_parse_bg (scanner, rc_style->proto_style);
906 case GTK_RC_TOKEN_FG:
907 token = gtk_rc_parse_fg (scanner, rc_style->proto_style);
909 case GTK_RC_TOKEN_TEXT:
910 token = gtk_rc_parse_text (scanner, rc_style->proto_style);
912 case GTK_RC_TOKEN_BG_PIXMAP:
913 token = gtk_rc_parse_bg_pixmap (scanner, rc_style);
915 case GTK_RC_TOKEN_FONT:
916 token = gtk_rc_parse_font (scanner, rc_style);
918 case GTK_RC_TOKEN_FONTSET:
919 token = gtk_rc_parse_fontset (scanner, rc_style);
922 g_scanner_get_next_token (scanner);
923 token = G_TOKEN_RIGHT_CURLY;
927 if (token != G_TOKEN_NONE)
931 if (rc_style->fontset_name)
932 g_free (rc_style->fontset_name);
933 if (rc_style->font_name)
934 g_free (rc_style->font_name);
935 for (i = 0; i < 5; i++)
936 if (rc_style->bg_pixmap_name[i])
937 g_free (rc_style->bg_pixmap_name[i]);
938 gtk_style_unref (rc_style->proto_style);
943 token = g_scanner_peek_next_token (scanner);
946 token = g_scanner_get_next_token (scanner);
947 if (token != G_TOKEN_RIGHT_CURLY)
951 if (rc_style->fontset_name)
952 g_free (rc_style->fontset_name);
953 if (rc_style->font_name)
954 g_free (rc_style->font_name);
956 for (i = 0; i < 5; i++)
957 if (rc_style->bg_pixmap_name[i])
958 g_free (rc_style->bg_pixmap_name[i]);
960 gtk_style_unref (rc_style->proto_style);
963 return G_TOKEN_RIGHT_CURLY;
967 g_hash_table_insert (rc_style_ht, rc_style->name, rc_style);
973 gtk_rc_parse_base (GScanner *scanner,
979 token = g_scanner_get_next_token (scanner);
980 if (token != GTK_RC_TOKEN_BASE)
981 return GTK_RC_TOKEN_BASE;
983 token = gtk_rc_parse_state (scanner, &state);
984 if (token != G_TOKEN_NONE)
987 token = g_scanner_get_next_token (scanner);
988 if (token != G_TOKEN_EQUAL_SIGN)
989 return G_TOKEN_EQUAL_SIGN;
991 return gtk_rc_parse_color (scanner, &style->base[state]);
995 gtk_rc_parse_bg (GScanner *scanner,
1001 token = g_scanner_get_next_token (scanner);
1002 if (token != GTK_RC_TOKEN_BG)
1003 return GTK_RC_TOKEN_BG;
1005 token = gtk_rc_parse_state (scanner, &state);
1006 if (token != G_TOKEN_NONE)
1009 token = g_scanner_get_next_token (scanner);
1010 if (token != G_TOKEN_EQUAL_SIGN)
1011 return G_TOKEN_EQUAL_SIGN;
1013 return gtk_rc_parse_color (scanner, &style->bg[state]);
1017 gtk_rc_parse_fg (GScanner *scanner,
1023 token = g_scanner_get_next_token (scanner);
1024 if (token != GTK_RC_TOKEN_FG)
1025 return GTK_RC_TOKEN_FG;
1027 token = gtk_rc_parse_state (scanner, &state);
1028 if (token != G_TOKEN_NONE)
1031 token = g_scanner_get_next_token (scanner);
1032 if (token != G_TOKEN_EQUAL_SIGN)
1033 return G_TOKEN_EQUAL_SIGN;
1035 return gtk_rc_parse_color (scanner, &style->fg[state]);
1039 gtk_rc_parse_text (GScanner *scanner,
1045 token = g_scanner_get_next_token (scanner);
1046 if (token != GTK_RC_TOKEN_TEXT)
1047 return GTK_RC_TOKEN_TEXT;
1049 token = gtk_rc_parse_state (scanner, &state);
1050 if (token != G_TOKEN_NONE)
1053 token = g_scanner_get_next_token (scanner);
1054 if (token != G_TOKEN_EQUAL_SIGN)
1055 return G_TOKEN_EQUAL_SIGN;
1057 return gtk_rc_parse_color (scanner, &style->text[state]);
1061 gtk_rc_parse_bg_pixmap (GScanner *scanner,
1062 GtkRcStyle *rc_style)
1068 token = g_scanner_get_next_token (scanner);
1069 if (token != GTK_RC_TOKEN_BG_PIXMAP)
1070 return GTK_RC_TOKEN_BG_PIXMAP;
1072 token = gtk_rc_parse_state (scanner, &state);
1073 if (token != G_TOKEN_NONE)
1076 token = g_scanner_get_next_token (scanner);
1077 if (token != G_TOKEN_EQUAL_SIGN)
1078 return G_TOKEN_EQUAL_SIGN;
1080 token = g_scanner_get_next_token (scanner);
1081 if (token != G_TOKEN_STRING)
1082 return G_TOKEN_STRING;
1084 if (strcmp (scanner->value.v_string, "<parent>"))
1085 pixmap_file = gtk_rc_find_pixmap_in_path (scanner, scanner->value.v_string);
1087 pixmap_file = g_strdup (scanner->value.v_string);
1091 if (rc_style->bg_pixmap_name[state])
1092 g_free (rc_style->bg_pixmap_name[state]);
1093 rc_style->bg_pixmap_name[state] = pixmap_file;
1096 return G_TOKEN_NONE;
1100 gtk_rc_find_pixmap_in_path (GScanner *scanner,
1107 for (i = 0; (i < GTK_RC_MAX_PIXMAP_PATHS) && (pixmap_path[i] != NULL); i++)
1109 buf = g_malloc (strlen (pixmap_path[i]) + strlen (pixmap_file) + 2);
1110 sprintf (buf, "%s%c%s", pixmap_path[i], '/', pixmap_file);
1112 fd = open (buf, O_RDONLY);
1122 g_warning ("Unable to locate image file in pixmap_path: \"%s\" line %d",
1123 pixmap_file, scanner->line);
1129 gtk_rc_parse_font (GScanner *scanner,
1130 GtkRcStyle *rc_style)
1134 token = g_scanner_get_next_token (scanner);
1135 if (token != GTK_RC_TOKEN_FONT)
1136 return GTK_RC_TOKEN_FONT;
1138 token = g_scanner_get_next_token (scanner);
1139 if (token != G_TOKEN_EQUAL_SIGN)
1140 return G_TOKEN_EQUAL_SIGN;
1142 token = g_scanner_get_next_token (scanner);
1143 if (token != G_TOKEN_STRING)
1144 return G_TOKEN_STRING;
1146 if (rc_style->font_name)
1147 g_free (rc_style->font_name);
1148 rc_style->font_name = g_strdup (scanner->value.v_string);
1150 return G_TOKEN_NONE;
1154 gtk_rc_parse_fontset (GScanner *scanner,
1155 GtkRcStyle *rc_style)
1159 token = g_scanner_get_next_token (scanner);
1160 if (token != GTK_RC_TOKEN_FONTSET)
1161 return GTK_RC_TOKEN_FONTSET;
1163 token = g_scanner_get_next_token (scanner);
1164 if (token != G_TOKEN_EQUAL_SIGN)
1165 return G_TOKEN_EQUAL_SIGN;
1167 token = g_scanner_get_next_token (scanner);
1168 if (token != G_TOKEN_STRING)
1169 return G_TOKEN_STRING;
1171 if (rc_style->fontset_name)
1172 g_free (rc_style->fontset_name);
1173 rc_style->fontset_name = g_strdup (scanner->value.v_string);
1175 return G_TOKEN_NONE;
1179 gtk_rc_parse_state (GScanner *scanner,
1180 GtkStateType *state)
1185 g_return_val_if_fail (scanner != NULL, G_TOKEN_ERROR);
1186 g_return_val_if_fail (state != NULL, G_TOKEN_ERROR);
1188 /* we don't know where we got called from, so we reset the scope here.
1189 * if we bail out due to errors, we *don't* reset the scope, so the
1190 * error messaging code can make sense of our tokens.
1192 old_scope = g_scanner_set_scope (scanner, 0);
1194 token = g_scanner_get_next_token (scanner);
1195 if (token != G_TOKEN_LEFT_BRACE)
1196 return G_TOKEN_LEFT_BRACE;
1198 token = g_scanner_get_next_token (scanner);
1201 case GTK_RC_TOKEN_ACTIVE:
1202 *state = GTK_STATE_ACTIVE;
1204 case GTK_RC_TOKEN_INSENSITIVE:
1205 *state = GTK_STATE_INSENSITIVE;
1207 case GTK_RC_TOKEN_NORMAL:
1208 *state = GTK_STATE_NORMAL;
1210 case GTK_RC_TOKEN_PRELIGHT:
1211 *state = GTK_STATE_PRELIGHT;
1213 case GTK_RC_TOKEN_SELECTED:
1214 *state = GTK_STATE_SELECTED;
1217 return /* G_TOKEN_SYMBOL */ GTK_RC_TOKEN_NORMAL;
1220 token = g_scanner_get_next_token (scanner);
1221 if (token != G_TOKEN_RIGHT_BRACE)
1222 return G_TOKEN_RIGHT_BRACE;
1224 g_scanner_set_scope (scanner, old_scope);
1226 return G_TOKEN_NONE;
1230 gtk_rc_parse_priority (GScanner *scanner,
1231 GtkPathPriorityType *priority)
1236 g_return_val_if_fail (scanner != NULL, G_TOKEN_ERROR);
1237 g_return_val_if_fail (priority != NULL, G_TOKEN_ERROR);
1239 /* we don't know where we got called from, so we reset the scope here.
1240 * if we bail out due to errors, we *don't* reset the scope, so the
1241 * error messaging code can make sense of our tokens.
1243 old_scope = g_scanner_set_scope (scanner, 0);
1245 token = g_scanner_get_next_token (scanner);
1249 token = g_scanner_get_next_token (scanner);
1252 case GTK_RC_TOKEN_LOWEST:
1253 *priority = GTK_PATH_PRIO_LOWEST;
1255 case GTK_RC_TOKEN_GTK:
1256 *priority = GTK_PATH_PRIO_GTK;
1258 case GTK_RC_TOKEN_APPLICATION:
1259 *priority = GTK_PATH_PRIO_APPLICATION;
1261 case GTK_RC_TOKEN_RC:
1262 *priority = GTK_PATH_PRIO_RC;
1264 case GTK_RC_TOKEN_HIGHEST:
1265 *priority = GTK_PATH_PRIO_HIGHEST;
1268 return /* G_TOKEN_SYMBOL */ GTK_RC_TOKEN_APPLICATION;
1271 g_scanner_set_scope (scanner, old_scope);
1273 return G_TOKEN_NONE;
1277 gtk_rc_parse_color (GScanner *scanner,
1282 g_return_val_if_fail (scanner != NULL, G_TOKEN_ERROR);
1284 /* we don't need to set our own scop here, because
1285 * we don't need own symbols
1288 token = g_scanner_get_next_token (scanner);
1297 case G_TOKEN_LEFT_CURLY:
1298 token = g_scanner_get_next_token (scanner);
1299 if (token == G_TOKEN_INT)
1300 token_int = scanner->value.v_int;
1301 else if (token == G_TOKEN_FLOAT)
1302 token_int = scanner->value.v_float * 65535.0;
1304 return G_TOKEN_FLOAT;
1305 color->red = CLAMP (token_int, 0, 65535);
1307 token = g_scanner_get_next_token (scanner);
1308 if (token != G_TOKEN_COMMA)
1309 return G_TOKEN_COMMA;
1311 token = g_scanner_get_next_token (scanner);
1312 if (token == G_TOKEN_INT)
1313 token_int = scanner->value.v_int;
1314 else if (token == G_TOKEN_FLOAT)
1315 token_int = scanner->value.v_float * 65535.0;
1317 return G_TOKEN_FLOAT;
1318 color->green = CLAMP (token_int, 0, 65535);
1320 token = g_scanner_get_next_token (scanner);
1321 if (token != G_TOKEN_COMMA)
1322 return G_TOKEN_COMMA;
1324 token = g_scanner_get_next_token (scanner);
1325 if (token == G_TOKEN_INT)
1326 token_int = scanner->value.v_int;
1327 else if (token == G_TOKEN_FLOAT)
1328 token_int = scanner->value.v_float * 65535.0;
1330 return G_TOKEN_FLOAT;
1331 color->blue = CLAMP (token_int, 0, 65535);
1333 token = g_scanner_get_next_token (scanner);
1334 if (token != G_TOKEN_RIGHT_CURLY)
1335 return G_TOKEN_RIGHT_CURLY;
1336 return G_TOKEN_NONE;
1338 case G_TOKEN_STRING:
1339 if (scanner->value.v_string[0] != '#')
1340 return G_TOKEN_STRING;
1342 length = strlen (scanner->value.v_string) - 1;
1343 if (((length % 3) != 0) || (length > 12))
1344 return G_TOKEN_STRING;
1347 for (i = 0, j = 1; i < length; i++, j++)
1348 buf[i] = scanner->value.v_string[j];
1351 sscanf (buf, "%x", &temp);
1354 for (i = 0; i < length; i++, j++)
1355 buf[i] = scanner->value.v_string[j];
1358 sscanf (buf, "%x", &temp);
1359 color->green = temp;
1361 for (i = 0; i < length; i++, j++)
1362 buf[i] = scanner->value.v_string[j];
1365 sscanf (buf, "%x", &temp);
1371 color->green *= 4369;
1372 color->blue *= 4369;
1374 else if (length == 2)
1377 color->green *= 257;
1380 else if (length == 3)
1386 return G_TOKEN_NONE;
1389 return G_TOKEN_STRING;
1394 gtk_rc_parse_pixmap_path (GScanner *scanner)
1398 token = g_scanner_get_next_token (scanner);
1399 if (token != GTK_RC_TOKEN_PIXMAP_PATH)
1400 return GTK_RC_TOKEN_PIXMAP_PATH;
1402 token = g_scanner_get_next_token (scanner);
1403 if (token != G_TOKEN_STRING)
1404 return G_TOKEN_STRING;
1406 gtk_rc_parse_pixmap_path_string (scanner->value.v_string);
1408 return G_TOKEN_NONE;
1412 gtk_rc_parse_pixmap_path_string (gchar *pix_path)
1416 gint start_offset = 0;
1420 /* free the old one, or just add to the old one ? */
1421 for (path_num=0; pixmap_path[path_num]; path_num++)
1423 g_free (pixmap_path[path_num]);
1424 pixmap_path[path_num] = NULL;
1429 path_len = strlen (pix_path);
1431 buf = g_strdup (pix_path);
1433 for (end_offset = 0; end_offset <= path_len; end_offset++)
1435 if ((buf[end_offset] == ':') ||
1436 (end_offset == path_len))
1438 buf[end_offset] = '\0';
1439 pixmap_path[path_num] = g_strdup (buf + start_offset);
1441 pixmap_path[path_num] = NULL;
1442 start_offset = end_offset + 1;
1449 gtk_rc_parse_path_pattern (GScanner *scanner)
1452 GtkPathType path_type;
1454 gboolean is_binding;
1455 GtkPathPriorityType priority = GTK_PATH_PRIO_RC;
1457 token = g_scanner_get_next_token (scanner);
1460 case GTK_RC_TOKEN_WIDGET:
1461 path_type = GTK_PATH_WIDGET;
1463 case GTK_RC_TOKEN_WIDGET_CLASS:
1464 path_type = GTK_PATH_WIDGET_CLASS;
1466 case GTK_RC_TOKEN_CLASS:
1467 path_type = GTK_PATH_CLASS;
1470 return GTK_RC_TOKEN_WIDGET_CLASS;
1473 token = g_scanner_get_next_token (scanner);
1474 if (token != G_TOKEN_STRING)
1475 return G_TOKEN_STRING;
1477 pattern = g_strdup (scanner->value.v_string);
1479 token = g_scanner_get_next_token (scanner);
1480 if (token == GTK_RC_TOKEN_STYLE)
1482 else if (token == GTK_RC_TOKEN_BINDING)
1485 if (g_scanner_peek_next_token (scanner) == ':')
1487 token = gtk_rc_parse_priority (scanner, &priority);
1488 if (token != G_TOKEN_NONE)
1498 return GTK_RC_TOKEN_STYLE;
1501 token = g_scanner_get_next_token (scanner);
1502 if (token != G_TOKEN_STRING)
1505 return G_TOKEN_STRING;
1510 GtkBindingSet *binding;
1512 binding = gtk_binding_set_find (scanner->value.v_string);
1516 return G_TOKEN_STRING;
1518 gtk_binding_set_add_path (binding, path_type, pattern, priority);
1522 GtkRcStyle *rc_style;
1525 rc_style = gtk_rc_style_find (scanner->value.v_string);
1530 return G_TOKEN_STRING;
1533 rc_set = g_new (GtkRcSet, 1);
1534 gtk_pattern_spec_init (&rc_set->pspec, pattern);
1535 rc_set->rc_style = rc_style;
1537 if (path_type == GTK_PATH_WIDGET)
1538 gtk_rc_sets_widget = g_slist_prepend (gtk_rc_sets_widget, rc_set);
1539 else if (path_type == GTK_PATH_WIDGET_CLASS)
1540 gtk_rc_sets_widget_class = g_slist_prepend (gtk_rc_sets_widget_class, rc_set);
1542 gtk_rc_sets_class = g_slist_prepend (gtk_rc_sets_class, rc_set);
1546 return G_TOKEN_NONE;
1550 typedef GdkPixmap * (*GtkImageLoader) (GdkWindow *window,
1551 GdkColormap *colormap,
1553 GdkColor *transparent_color,
1554 const gchar *filename);
1558 gtk_rc_set_image_loader(GtkImageLoader loader)
1560 image_loader = loader;