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.
19 #include <X11/Xlocale.h> /* so we get the right setlocale */
23 #include <sys/param.h>
30 #include "gtkbindings.h"
31 #include "gtkthemes.h"
34 typedef struct _GtkRcSet GtkRcSet;
35 typedef struct _GtkRcNode GtkRcNode;
36 typedef struct _GtkRcFile GtkRcFile;
48 gchar *canonical_name;
52 static guint gtk_rc_style_hash (const char *name);
53 static gint gtk_rc_style_compare (const char *a,
55 static guint gtk_rc_styles_hash (const GSList *rc_styles);
56 static gint gtk_rc_styles_compare (const GSList *a,
58 static GtkRcStyle* gtk_rc_style_find (const char *name);
59 static GSList * gtk_rc_styles_match (GSList *rc_styles,
63 gchar *path_reversed);
64 static GtkStyle * gtk_rc_style_to_style (GtkRcStyle *rc_style);
65 static GtkStyle* gtk_rc_style_init (GSList *rc_styles);
66 static void gtk_rc_parse_file (const gchar *filename,
69 static void gtk_rc_parse_any (const gchar *input_name,
71 const gchar *input_string);
72 static guint gtk_rc_parse_statement (GScanner *scanner);
73 static guint gtk_rc_parse_style (GScanner *scanner);
74 static guint gtk_rc_parse_base (GScanner *scanner,
76 static guint gtk_rc_parse_bg (GScanner *scanner,
78 static guint gtk_rc_parse_fg (GScanner *scanner,
80 static guint gtk_rc_parse_text (GScanner *scanner,
82 static guint gtk_rc_parse_bg_pixmap (GScanner *scanner,
83 GtkRcStyle *rc_style);
84 static guint gtk_rc_parse_font (GScanner *scanner,
85 GtkRcStyle *rc_style);
86 static guint gtk_rc_parse_fontset (GScanner *scanner,
87 GtkRcStyle *rc_style);
88 static guint gtk_rc_parse_engine (GScanner *scanner,
89 GtkRcStyle *rc_style);
90 static guint gtk_rc_parse_pixmap_path (GScanner *scanner);
91 static void gtk_rc_parse_pixmap_path_string (gchar *pix_path);
92 static guint gtk_rc_parse_module_path (GScanner *scanner);
93 static void gtk_rc_parse_module_path_string (gchar *mod_path);
94 static guint gtk_rc_parse_path_pattern (GScanner *scanner);
95 static void gtk_rc_clear_hash_node (gpointer key,
98 static void gtk_rc_clear_styles (void);
99 static void gtk_rc_append_default_pixmap_path (void);
100 static void gtk_rc_append_default_module_path (void);
101 static void gtk_rc_append_pixmap_path (gchar *dir);
102 static void gtk_rc_add_initial_default_files (void);
105 static const GScannerConfig gtk_rc_scanner_config =
109 ) /* cset_skip_characters */,
114 ) /* cset_identifier_first */,
119 ) /* cset_identifier_nth */,
120 ( "#\n" ) /* cpair_comment_single */,
122 TRUE /* case_sensitive */,
124 TRUE /* skip_comment_multi */,
125 TRUE /* skip_comment_single */,
126 TRUE /* scan_comment_multi */,
127 TRUE /* scan_identifier */,
128 FALSE /* scan_identifier_1char */,
129 FALSE /* scan_identifier_NULL */,
130 TRUE /* scan_symbols */,
131 TRUE /* scan_binary */,
132 TRUE /* scan_octal */,
133 TRUE /* scan_float */,
135 TRUE /* scan_hex_dollar */,
136 TRUE /* scan_string_sq */,
137 TRUE /* scan_string_dq */,
138 TRUE /* numbers_2_int */,
139 FALSE /* int_2_float */,
140 FALSE /* identifier_2_string */,
141 TRUE /* char_2_token */,
142 TRUE /* symbol_2_token */,
143 FALSE /* scope_0_fallback */,
151 { "include", GTK_RC_TOKEN_INCLUDE },
152 { "NORMAL", GTK_RC_TOKEN_NORMAL },
153 { "ACTIVE", GTK_RC_TOKEN_ACTIVE },
154 { "PRELIGHT", GTK_RC_TOKEN_PRELIGHT },
155 { "SELECTED", GTK_RC_TOKEN_SELECTED },
156 { "INSENSITIVE", GTK_RC_TOKEN_INSENSITIVE },
157 { "fg", GTK_RC_TOKEN_FG },
158 { "bg", GTK_RC_TOKEN_BG },
159 { "base", GTK_RC_TOKEN_BASE },
160 { "text", GTK_RC_TOKEN_TEXT },
161 { "font", GTK_RC_TOKEN_FONT },
162 { "fontset", GTK_RC_TOKEN_FONTSET },
163 { "bg_pixmap", GTK_RC_TOKEN_BG_PIXMAP },
164 { "pixmap_path", GTK_RC_TOKEN_PIXMAP_PATH },
165 { "style", GTK_RC_TOKEN_STYLE },
166 { "binding", GTK_RC_TOKEN_BINDING },
167 { "bind", GTK_RC_TOKEN_BIND },
168 { "widget", GTK_RC_TOKEN_WIDGET },
169 { "widget_class", GTK_RC_TOKEN_WIDGET_CLASS },
170 { "class", GTK_RC_TOKEN_CLASS },
171 { "lowest", GTK_RC_TOKEN_LOWEST },
172 { "gtk", GTK_RC_TOKEN_GTK },
173 { "application", GTK_RC_TOKEN_APPLICATION },
174 { "rc", GTK_RC_TOKEN_RC },
175 { "highest", GTK_RC_TOKEN_HIGHEST },
176 { "engine", GTK_RC_TOKEN_ENGINE },
177 { "module_path", GTK_RC_TOKEN_MODULE_PATH },
180 static const guint n_symbols = sizeof (symbols) / sizeof (symbols[0]);
182 static GHashTable *rc_style_ht = NULL;
183 static GHashTable *realized_style_ht = NULL;
184 static GSList *gtk_rc_sets_widget = NULL;
185 static GSList *gtk_rc_sets_widget_class = NULL;
186 static GSList *gtk_rc_sets_class = NULL;
188 #define GTK_RC_MAX_DEFAULT_FILES 128
189 static gchar *gtk_rc_default_files[GTK_RC_MAX_DEFAULT_FILES];
190 static gboolean gtk_rc_auto_parse = TRUE;
192 #define GTK_RC_MAX_PIXMAP_PATHS 128
193 static gchar *pixmap_path[GTK_RC_MAX_PIXMAP_PATHS];
194 #define GTK_RC_MAX_MODULE_PATHS 128
195 static gchar *module_path[GTK_RC_MAX_MODULE_PATHS];
197 /* The files we have parsed, to reread later if necessary */
198 GSList *rc_files = NULL;
200 static GtkImageLoader image_loader = NULL;
202 /* RC file handling */
206 gtk_rc_get_theme_dir(void)
210 var = getenv("GTK_DATA_PREFIX");
212 path = g_strdup_printf("%s%s", var, "/share/themes");
214 path = g_strdup_printf("%s%s", GTK_DATA_PREFIX, "/share/themes");
220 gtk_rc_get_module_dir(void)
224 var = getenv("GTK_EXE_PREFIX");
226 path = g_strdup_printf("%s%s", var, "/lib/gtk/themes/engines");
228 path = g_strdup_printf("%s%s", GTK_EXE_PREFIX, "/lib/gtk/themes/engines");
234 gtk_rc_append_default_pixmap_path(void)
239 var = getenv("GTK_DATA_PREFIX");
241 path = g_strdup_printf("%s%s", var, "/share/gtk/themes");
243 path = g_strdup_printf("%s%s", GTK_DATA_PREFIX, "/share/gtk/themes");
245 for (n = 0; pixmap_path[n]; n++) ;
246 if (n >= GTK_RC_MAX_PIXMAP_PATHS - 1)
248 pixmap_path[n++] = g_strdup(path);
249 pixmap_path[n] = NULL;
254 gtk_rc_append_pixmap_path(gchar *dir)
258 for (n = 0; pixmap_path[n]; n++) ;
259 if (n >= GTK_RC_MAX_MODULE_PATHS - 1)
261 pixmap_path[n++] = g_strdup(dir);
262 pixmap_path[n] = NULL;
266 gtk_rc_append_default_module_path(void)
271 for (n = 0; module_path[n]; n++) ;
272 if (n >= GTK_RC_MAX_MODULE_PATHS - 1)
275 var = getenv("GTK_EXE_PREFIX");
277 path = g_strdup_printf("%s%s", var, "/lib/gtk/themes/engines");
279 path = g_strdup_printf("%s%s", GTK_EXE_PREFIX, "/lib/gtk/themes/engines");
280 module_path[n++] = g_strdup(path);
283 var = getenv("HOME");
285 path = g_strdup_printf("%s%s", var, ".gtk/lib/themes/engines");
286 module_path[n++] = g_strdup(path);
287 module_path[n] = NULL;
292 gtk_rc_add_initial_default_files (void)
294 static gint init = FALSE;
302 gtk_rc_default_files[0] = NULL;
305 var = getenv("GTK_RC_FILES");
308 files = g_strsplit (var, ":", 128);
312 gtk_rc_add_default_file (files[i]);
319 str = g_strdup_printf ("%s%s", GTK_SYSCONFDIR, "/gtk/gtkrc");
320 gtk_rc_add_default_file (str);
323 str = g_strdup_printf ("%s%s", g_get_home_dir (), "/.gtkrc");
324 gtk_rc_add_default_file (str);
330 gtk_rc_add_default_file (const gchar *file)
334 gtk_rc_add_initial_default_files ();
336 for (n = 0; gtk_rc_default_files[n]; n++) ;
337 if (n >= GTK_RC_MAX_DEFAULT_FILES - 1)
340 gtk_rc_default_files[n++] = g_strdup (file);
341 gtk_rc_default_files[n] = NULL;
345 gtk_rc_set_default_files (gchar **files)
349 gtk_rc_add_initial_default_files ();
352 while (gtk_rc_default_files[i])
354 g_free (gtk_rc_default_files[i]);
358 gtk_rc_default_files[0] = NULL;
359 gtk_rc_auto_parse = FALSE;
362 while (files[i] != NULL)
364 gtk_rc_add_default_file (files[i]);
370 gtk_rc_get_default_files (void)
372 gtk_rc_add_initial_default_files ();
374 return gtk_rc_default_files;
380 gchar *locale_suffixes[3];
381 gint n_locale_suffixes = 0;
383 #ifdef HAVE_LC_MESSAGES
384 char *locale = setlocale (LC_MESSAGES, NULL);
386 char *locale = setlocale (LC_ALL, NULL);
391 rc_style_ht = g_hash_table_new ((GHashFunc) gtk_rc_style_hash,
392 (GCompareFunc) gtk_rc_style_compare);
393 pixmap_path[0] = NULL;
394 module_path[0] = NULL;
395 gtk_rc_append_default_pixmap_path();
396 gtk_rc_append_default_module_path();
398 gtk_rc_add_initial_default_files ();
400 if (strcmp (locale, "C") && strcmp (locale, "POSIX"))
402 /* Determine locale-specific suffixes for RC files
404 p = strchr (locale, '@');
405 length = p ? (p -locale) : strlen (locale);
407 p = strchr (locale, '.');
410 locale_suffixes[n_locale_suffixes++] = g_strndup (locale, length);
414 p = strchr (locale, '_');
417 locale_suffixes[n_locale_suffixes++] = g_strndup (locale, length);
421 locale_suffixes[n_locale_suffixes++] = g_strndup (locale, length);
425 while (gtk_rc_default_files[i] != NULL)
427 /* Try to find a locale specific RC file corresponding to
428 * to parse before the default file.
430 for (j=n_locale_suffixes-1; j>=0; j--)
432 gchar *name = g_strconcat (gtk_rc_default_files[i],
440 gtk_rc_parse (gtk_rc_default_files[i]);
446 gtk_rc_parse_string (const gchar *rc_string)
448 g_return_if_fail (rc_string != NULL);
450 gtk_rc_parse_any ("-", -1, rc_string);
454 gtk_rc_parse_file (const gchar *filename, gboolean reload)
456 GtkRcFile *rc_file = NULL;
460 g_return_if_fail (filename != NULL);
465 rc_file = tmp_list->data;
466 if (!strcmp (rc_file->name, filename))
469 tmp_list = tmp_list->next;
474 rc_file = g_new (GtkRcFile, 1);
475 rc_file->name = g_strdup (filename);
476 rc_file->canonical_name = NULL;
478 rc_file->reload = reload;
480 rc_files = g_slist_append (rc_files, rc_file);
483 if (!rc_file->canonical_name)
485 /* Get the absolute pathname */
487 if (rc_file->name[0] == '/')
488 rc_file->canonical_name = rc_file->name;
494 cwd = g_get_current_dir ();
496 str = g_string_new (cwd);
498 g_string_append_c (str, '/');
499 g_string_append (str, rc_file->name);
501 rc_file->canonical_name = str->str;
502 g_string_free (str, FALSE);
506 if (!lstat (rc_file->canonical_name, &statbuf))
510 rc_file->mtime = statbuf.st_mtime;
512 fd = open (rc_file->canonical_name, O_RDONLY);
520 dir = g_strdup(rc_file->canonical_name);
521 for (i = strlen(dir) - 1; (i >= 0) && (dir[i] != '/'); i--)
523 gtk_rc_append_pixmap_path(dir);
526 gtk_rc_parse_any (filename, fd, NULL);
533 gtk_rc_parse (const gchar *filename)
535 g_return_if_fail (filename != NULL);
537 gtk_rc_parse_file (filename, TRUE);
540 /* Handling of RC styles */
543 gtk_rc_style_new (void)
545 GtkRcStyle *new_style;
547 new_style = g_new0 (GtkRcStyle, 1);
548 new_style->ref_count = 1;
554 gtk_rc_style_ref (GtkRcStyle *rc_style)
556 g_return_if_fail (rc_style != NULL);
558 rc_style->ref_count++;
562 gtk_rc_style_unref (GtkRcStyle *rc_style)
566 g_return_if_fail (rc_style != NULL);
567 g_return_if_fail (rc_style->ref_count > 0);
569 rc_style->ref_count--;
571 if (rc_style->ref_count == 0)
573 if (rc_style->engine)
575 rc_style->engine->destroy_rc_style (rc_style);
576 gtk_theme_engine_unref (rc_style->engine);
580 g_free (rc_style->name);
581 if (rc_style->fontset_name)
582 g_free (rc_style->fontset_name);
583 if (rc_style->font_name)
584 g_free (rc_style->font_name);
586 for (i=0 ; i<5 ; i++)
587 if (rc_style->bg_pixmap_name[i])
588 g_free (rc_style->bg_pixmap_name[i]);
595 gtk_rc_clear_realized_node (gpointer key,
599 gtk_style_unref (data);
603 gtk_rc_clear_hash_node (gpointer key,
607 gtk_rc_style_unref (data);
611 gtk_rc_free_rc_sets (GSList *slist)
617 rc_set = slist->data;
618 gtk_pattern_spec_free_segs (&rc_set->pspec);
626 gtk_rc_clear_styles (void)
628 /* Clear out all old rc_styles */
632 g_hash_table_foreach (rc_style_ht, gtk_rc_clear_hash_node, NULL);
633 g_hash_table_destroy (rc_style_ht);
637 if (realized_style_ht)
639 g_hash_table_foreach (realized_style_ht, gtk_rc_clear_realized_node, NULL);
640 g_hash_table_destroy (realized_style_ht);
641 realized_style_ht = NULL;
644 gtk_rc_free_rc_sets (gtk_rc_sets_widget);
645 g_slist_free (gtk_rc_sets_widget);
646 gtk_rc_sets_widget = NULL;
648 gtk_rc_free_rc_sets (gtk_rc_sets_widget_class);
649 g_slist_free (gtk_rc_sets_widget_class);
650 gtk_rc_sets_widget_class = NULL;
652 gtk_rc_free_rc_sets (gtk_rc_sets_class);
653 g_slist_free (gtk_rc_sets_class);
654 gtk_rc_sets_class = NULL;
660 gtk_rc_reparse_all (void)
663 gboolean mtime_modified = FALSE;
668 /* Check through and see if any of the RC's have had their
669 * mtime modified. If so, reparse everything.
674 rc_file = tmp_list->data;
676 if (!lstat (rc_file->name, &statbuf) &&
677 (statbuf.st_mtime > rc_file->mtime))
679 mtime_modified = TRUE;
683 tmp_list = tmp_list->next;
688 gtk_rc_clear_styles();
693 rc_file = tmp_list->data;
695 gtk_rc_parse_file (rc_file->name, FALSE);
697 tmp_list = tmp_list->next;
701 return mtime_modified;
705 gtk_rc_styles_match (GSList *rc_styles,
709 gchar *path_reversed)
719 if (gtk_pattern_match (&rc_set->pspec, path_length, path, path_reversed))
720 rc_styles = g_slist_append (rc_styles, rc_set->rc_style);
727 gtk_rc_get_style (GtkWidget *widget)
729 GtkRcStyle *widget_rc_style;
730 GSList *rc_styles = NULL;
732 static guint rc_style_key_id = 0;
734 /* We allow the specification of a single rc style to be bound
735 * tightly to a widget, for application modifications
737 if (!rc_style_key_id)
738 rc_style_key_id = g_quark_from_static_string ("gtk-rc-style");
740 widget_rc_style = gtk_object_get_data_by_id (GTK_OBJECT (widget),
744 rc_styles = g_slist_prepend (rc_styles, widget_rc_style);
746 if (gtk_rc_sets_widget)
748 gchar *path, *path_reversed;
751 gtk_widget_path (widget, &path_length, &path, &path_reversed);
752 rc_styles = gtk_rc_styles_match (rc_styles, gtk_rc_sets_widget, path_length, path, path_reversed);
754 g_free (path_reversed);
758 if (gtk_rc_sets_widget_class)
760 gchar *path, *path_reversed;
763 gtk_widget_class_path (widget, &path_length, &path, &path_reversed);
764 rc_styles = gtk_rc_styles_match (rc_styles, gtk_rc_sets_widget_class, path_length, path, path_reversed);
766 g_free (path_reversed);
769 if (gtk_rc_sets_class)
773 type = GTK_OBJECT_TYPE (widget);
776 gchar *path, *path_reversed;
779 path = gtk_type_name (type);
780 path_length = strlen (path);
781 path_reversed = g_strdup (path);
782 g_strreverse (path_reversed);
784 rc_styles = gtk_rc_styles_match (rc_styles, gtk_rc_sets_class, path_length, path, path_reversed);
785 g_free (path_reversed);
787 type = gtk_type_parent (type);
792 return gtk_rc_style_init (rc_styles);
798 gtk_rc_add_rc_sets (GSList *slist,
799 GtkRcStyle *rc_style,
802 GtkRcStyle *new_style;
806 new_style = gtk_rc_style_new ();
807 *new_style = *rc_style;
808 new_style->name = g_strdup (rc_style->name);
809 new_style->font_name = g_strdup (rc_style->font_name);
810 new_style->fontset_name = g_strdup (rc_style->fontset_name);
812 for (i = 0; i < 5; i++)
813 new_style->bg_pixmap_name[i] = g_strdup (rc_style->bg_pixmap_name[i]);
815 rc_set = g_new (GtkRcSet, 1);
816 gtk_pattern_spec_init (&rc_set->pspec, pattern);
817 rc_set->rc_style = rc_style;
819 return g_slist_prepend (slist, rc_set);
823 gtk_rc_add_widget_name_style (GtkRcStyle *rc_style,
824 const gchar *pattern)
826 g_return_if_fail (rc_style != NULL);
827 g_return_if_fail (pattern != NULL);
829 gtk_rc_sets_widget = gtk_rc_add_rc_sets (gtk_rc_sets_widget, rc_style, pattern);
833 gtk_rc_add_widget_class_style (GtkRcStyle *rc_style,
834 const gchar *pattern)
836 g_return_if_fail (rc_style != NULL);
837 g_return_if_fail (pattern != NULL);
839 gtk_rc_sets_widget_class = gtk_rc_add_rc_sets (gtk_rc_sets_widget_class, rc_style, pattern);
843 gtk_rc_add_class_style (GtkRcStyle *rc_style,
844 const gchar *pattern)
846 g_return_if_fail (rc_style != NULL);
847 g_return_if_fail (pattern != NULL);
849 gtk_rc_sets_class = gtk_rc_add_rc_sets (gtk_rc_sets_class, rc_style, pattern);
853 gtk_rc_parse_any (const gchar *input_name,
855 const gchar *input_string)
861 scanner = g_scanner_new ((GScannerConfig *) >k_rc_scanner_config);
865 g_assert (input_string == NULL);
867 g_scanner_input_file (scanner, input_fd);
871 g_assert (input_string != NULL);
873 g_scanner_input_text (scanner, input_string, strlen (input_string));
875 scanner->input_name = input_name;
877 g_scanner_freeze_symbol_table (scanner);
878 for (i = 0; i < n_symbols; i++)
879 g_scanner_add_symbol (scanner, symbols[i].name, GINT_TO_POINTER (symbols[i].token));
880 g_scanner_thaw_symbol_table (scanner);
885 if (g_scanner_peek_next_token (scanner) == G_TOKEN_EOF)
889 guint expected_token;
891 expected_token = gtk_rc_parse_statement (scanner);
893 if (expected_token != G_TOKEN_NONE)
900 if (scanner->scope_id == 0)
902 /* if we are in scope 0, we know the symbol names
903 * that are associated with certaintoken values.
904 * so we look them up to make the error messages
907 if (expected_token > GTK_RC_TOKEN_INVALID &&
908 expected_token < GTK_RC_TOKEN_LAST)
910 for (i = 0; i < n_symbols; i++)
911 if (symbols[i].token == expected_token)
912 msg = symbols[i].name;
914 msg = g_strconcat ("e.g. `", msg, "'", NULL);
916 if (scanner->token > GTK_RC_TOKEN_INVALID &&
917 scanner->token < GTK_RC_TOKEN_LAST)
920 for (i = 0; i < n_symbols; i++)
921 if (symbols[i].token == scanner->token)
922 symbol_name = symbols[i].name;
925 g_scanner_unexp_token (scanner,
938 g_scanner_destroy (scanner);
942 gtk_rc_styles_hash (const GSList *rc_styles)
949 result += (result << 9) + GPOINTER_TO_UINT (rc_styles->data);
950 rc_styles = rc_styles->next;
957 gtk_rc_styles_compare (const GSList *a,
962 if (a->data != b->data)
972 gtk_rc_style_hash (const char *name)
978 result += (result << 3) + *name++;
984 gtk_rc_style_compare (const char *a,
987 return (strcmp (a, b) == 0);
991 gtk_rc_style_find (const char *name)
993 GtkRcStyle *rc_style;
995 rc_style = g_hash_table_lookup (rc_style_ht, (gpointer) name);
1000 /* Assumes ownership of rc_style */
1002 gtk_rc_style_to_style (GtkRcStyle *rc_style)
1008 style = gtk_style_new ();
1010 style->rc_style = rc_style;
1012 if (rc_style->fontset_name)
1014 old_font = style->font;
1015 style->font = gdk_fontset_load (rc_style->fontset_name);
1017 gdk_font_unref (old_font);
1019 style->font = old_font;
1021 else if (rc_style->font_name)
1023 old_font = style->font;
1024 style->font = gdk_font_load (rc_style->font_name);
1026 gdk_font_unref (old_font);
1028 style->font = old_font;
1031 for (i = 0; i < 5; i++)
1033 if (rc_style->color_flags[i] & GTK_RC_FG)
1034 style->fg[i] = rc_style->fg[i];
1035 if (rc_style->color_flags[i] & GTK_RC_BG)
1036 style->bg[i] = rc_style->bg[i];
1037 if (rc_style->color_flags[i] & GTK_RC_TEXT)
1038 style->text[i] = rc_style->text[i];
1039 if (rc_style->color_flags[i] & GTK_RC_BASE)
1040 style->base[i] = rc_style->base[i];
1043 if (rc_style->engine)
1045 style->engine = rc_style->engine;
1046 gtk_theme_engine_ref (style->engine);
1047 rc_style->engine->rc_style_to_style (style, rc_style);
1053 /* Reuses or frees rc_styles */
1055 gtk_rc_style_init (GSList *rc_styles)
1059 GtkStyle *style = NULL;
1060 GtkRcStyle *proto_style;
1062 if (!realized_style_ht)
1063 realized_style_ht = g_hash_table_new ((GHashFunc)gtk_rc_styles_hash,
1064 (GCompareFunc)gtk_rc_styles_compare);
1066 style = g_hash_table_lookup (realized_style_ht, rc_styles);
1070 GSList *tmp_styles = rc_styles;
1072 proto_style = gtk_rc_style_new ();
1076 GtkRcStyle *rc_style = tmp_styles->data;
1080 if (!proto_style->bg_pixmap_name[i] && rc_style->bg_pixmap_name[i])
1081 proto_style->bg_pixmap_name[i] = g_strdup (rc_style->bg_pixmap_name[i]);
1083 if (!(proto_style->color_flags[i] & GTK_RC_FG) &&
1084 rc_style->color_flags[i] & GTK_RC_FG)
1086 proto_style->fg[i] = rc_style->fg[i];
1087 proto_style->color_flags[i] |= GTK_RC_FG;
1089 if (!(proto_style->color_flags[i] & GTK_RC_BG) &&
1090 rc_style->color_flags[i] & GTK_RC_BG)
1092 proto_style->bg[i] = rc_style->bg[i];
1093 proto_style->color_flags[i] |= GTK_RC_BG;
1095 if (!(proto_style->color_flags[i] & GTK_RC_TEXT) &&
1096 rc_style->color_flags[i] & GTK_RC_TEXT)
1098 proto_style->text[i] = rc_style->text[i];
1099 proto_style->color_flags[i] |= GTK_RC_TEXT;
1101 if (!(proto_style->color_flags[i] & GTK_RC_BASE) &&
1102 rc_style->color_flags[i] & GTK_RC_BASE)
1104 proto_style->base[i] = rc_style->base[i];
1105 proto_style->color_flags[i] |= GTK_RC_BASE;
1109 if (!proto_style->font_name && rc_style->font_name)
1110 proto_style->font_name = g_strdup (rc_style->font_name);
1111 if (!proto_style->fontset_name && rc_style->fontset_name)
1112 proto_style->fontset_name = g_strdup (rc_style->fontset_name);
1114 if (!proto_style->engine && rc_style->engine)
1116 proto_style->engine = rc_style->engine;
1117 gtk_theme_engine_ref (proto_style->engine);
1120 if (proto_style->engine &&
1121 (proto_style->engine == rc_style->engine))
1122 proto_style->engine->merge_rc_style (proto_style, rc_style);
1124 tmp_styles = tmp_styles->next;
1128 if (proto_style->bg_pixmap_name[i] &&
1129 (strcmp (proto_style->bg_pixmap_name[i], "<none>") == 0))
1131 g_free (proto_style->bg_pixmap_name[i]);
1132 proto_style->bg_pixmap_name[i] = NULL;
1135 style = gtk_rc_style_to_style (proto_style);
1137 g_hash_table_insert (realized_style_ht, rc_styles, style);
1143 /*********************
1144 * Parsing functions *
1145 *********************/
1148 gtk_rc_parse_statement (GScanner *scanner)
1152 token = g_scanner_peek_next_token (scanner);
1156 case GTK_RC_TOKEN_INCLUDE:
1157 token = g_scanner_get_next_token (scanner);
1158 if (token != GTK_RC_TOKEN_INCLUDE)
1159 return GTK_RC_TOKEN_INCLUDE;
1161 token = g_scanner_get_next_token (scanner);
1162 if (token != G_TOKEN_STRING)
1163 return G_TOKEN_STRING;
1165 gtk_rc_parse_file (scanner->value.v_string, FALSE);
1166 return G_TOKEN_NONE;
1168 case GTK_RC_TOKEN_STYLE:
1169 return gtk_rc_parse_style (scanner);
1171 case GTK_RC_TOKEN_BINDING:
1172 return gtk_binding_parse_binding (scanner);
1174 case GTK_RC_TOKEN_PIXMAP_PATH:
1175 return gtk_rc_parse_pixmap_path (scanner);
1177 case GTK_RC_TOKEN_WIDGET:
1178 return gtk_rc_parse_path_pattern (scanner);
1180 case GTK_RC_TOKEN_WIDGET_CLASS:
1181 return gtk_rc_parse_path_pattern (scanner);
1183 case GTK_RC_TOKEN_CLASS:
1184 return gtk_rc_parse_path_pattern (scanner);
1186 case GTK_RC_TOKEN_MODULE_PATH:
1187 return gtk_rc_parse_module_path (scanner);
1190 g_scanner_get_next_token (scanner);
1191 return /* G_TOKEN_SYMBOL */ GTK_RC_TOKEN_STYLE;
1196 gtk_rc_parse_style (GScanner *scanner)
1198 GtkRcStyle *rc_style;
1199 GtkRcStyle *parent_style;
1204 token = g_scanner_get_next_token (scanner);
1205 if (token != GTK_RC_TOKEN_STYLE)
1206 return GTK_RC_TOKEN_STYLE;
1208 token = g_scanner_get_next_token (scanner);
1209 if (token != G_TOKEN_STRING)
1210 return G_TOKEN_STRING;
1213 rc_style = g_hash_table_lookup (rc_style_ht, scanner->value.v_string);
1218 rc_style = gtk_rc_style_new ();
1219 rc_style->name = g_strdup (scanner->value.v_string);
1221 for (i = 0; i < 5; i++)
1222 rc_style->bg_pixmap_name[i] = NULL;
1224 for (i = 0; i < 5; i++)
1225 rc_style->color_flags[i] = 0;
1227 rc_style->engine = NULL;
1228 rc_style->engine_data = NULL;
1231 token = g_scanner_peek_next_token (scanner);
1232 if (token == G_TOKEN_EQUAL_SIGN)
1234 token = g_scanner_get_next_token (scanner);
1236 token = g_scanner_get_next_token (scanner);
1237 if (token != G_TOKEN_STRING)
1242 return G_TOKEN_STRING;
1245 parent_style = g_hash_table_lookup (rc_style_ht, scanner->value.v_string);
1248 for (i = 0; i < 5; i++)
1250 rc_style->color_flags[i] = parent_style->color_flags[i];
1251 rc_style->fg[i] = parent_style->fg[i];
1252 rc_style->bg[i] = parent_style->bg[i];
1253 rc_style->text[i] = parent_style->text[i];
1254 rc_style->base[i] = parent_style->base[i];
1257 if (parent_style->fontset_name)
1259 if (rc_style->fontset_name)
1260 g_free (rc_style->fontset_name);
1261 rc_style->fontset_name = g_strdup (parent_style->fontset_name);
1263 else if (parent_style->font_name)
1265 if (rc_style->font_name)
1266 g_free (rc_style->font_name);
1267 rc_style->font_name = g_strdup (parent_style->font_name);
1270 for (i = 0; i < 5; i++)
1272 if (rc_style->bg_pixmap_name[i])
1273 g_free (rc_style->bg_pixmap_name[i]);
1274 rc_style->bg_pixmap_name[i] = g_strdup (parent_style->bg_pixmap_name[i]);
1279 token = g_scanner_get_next_token (scanner);
1280 if (token != G_TOKEN_LEFT_CURLY)
1285 return G_TOKEN_LEFT_CURLY;
1288 token = g_scanner_peek_next_token (scanner);
1289 while (token != G_TOKEN_RIGHT_CURLY)
1293 case GTK_RC_TOKEN_BASE:
1294 token = gtk_rc_parse_base (scanner, rc_style);
1296 case GTK_RC_TOKEN_BG:
1297 token = gtk_rc_parse_bg (scanner, rc_style);
1299 case GTK_RC_TOKEN_FG:
1300 token = gtk_rc_parse_fg (scanner, rc_style);
1302 case GTK_RC_TOKEN_TEXT:
1303 token = gtk_rc_parse_text (scanner, rc_style);
1305 case GTK_RC_TOKEN_BG_PIXMAP:
1306 token = gtk_rc_parse_bg_pixmap (scanner, rc_style);
1308 case GTK_RC_TOKEN_FONT:
1309 token = gtk_rc_parse_font (scanner, rc_style);
1311 case GTK_RC_TOKEN_FONTSET:
1312 token = gtk_rc_parse_fontset (scanner, rc_style);
1314 case GTK_RC_TOKEN_ENGINE:
1315 token = gtk_rc_parse_engine (scanner, rc_style);
1318 g_scanner_get_next_token (scanner);
1319 token = G_TOKEN_RIGHT_CURLY;
1323 if (token != G_TOKEN_NONE)
1327 if (rc_style->fontset_name)
1328 g_free (rc_style->fontset_name);
1329 if (rc_style->font_name)
1330 g_free (rc_style->font_name);
1331 for (i = 0; i < 5; i++)
1332 if (rc_style->bg_pixmap_name[i])
1333 g_free (rc_style->bg_pixmap_name[i]);
1338 token = g_scanner_peek_next_token (scanner);
1341 token = g_scanner_get_next_token (scanner);
1342 if (token != G_TOKEN_RIGHT_CURLY)
1346 if (rc_style->fontset_name)
1347 g_free (rc_style->fontset_name);
1348 if (rc_style->font_name)
1349 g_free (rc_style->font_name);
1351 for (i = 0; i < 5; i++)
1352 if (rc_style->bg_pixmap_name[i])
1353 g_free (rc_style->bg_pixmap_name[i]);
1357 return G_TOKEN_RIGHT_CURLY;
1361 g_hash_table_insert (rc_style_ht, rc_style->name, rc_style);
1363 return G_TOKEN_NONE;
1367 gtk_rc_parse_base (GScanner *scanner,
1373 token = g_scanner_get_next_token (scanner);
1374 if (token != GTK_RC_TOKEN_BASE)
1375 return GTK_RC_TOKEN_BASE;
1377 token = gtk_rc_parse_state (scanner, &state);
1378 if (token != G_TOKEN_NONE)
1381 token = g_scanner_get_next_token (scanner);
1382 if (token != G_TOKEN_EQUAL_SIGN)
1383 return G_TOKEN_EQUAL_SIGN;
1385 style->color_flags[state] |= GTK_RC_BASE;
1386 return gtk_rc_parse_color (scanner, &style->base[state]);
1390 gtk_rc_parse_bg (GScanner *scanner,
1396 token = g_scanner_get_next_token (scanner);
1397 if (token != GTK_RC_TOKEN_BG)
1398 return GTK_RC_TOKEN_BG;
1400 token = gtk_rc_parse_state (scanner, &state);
1401 if (token != G_TOKEN_NONE)
1404 token = g_scanner_get_next_token (scanner);
1405 if (token != G_TOKEN_EQUAL_SIGN)
1406 return G_TOKEN_EQUAL_SIGN;
1408 style->color_flags[state] |= GTK_RC_BG;
1409 return gtk_rc_parse_color (scanner, &style->bg[state]);
1413 gtk_rc_parse_fg (GScanner *scanner,
1419 token = g_scanner_get_next_token (scanner);
1420 if (token != GTK_RC_TOKEN_FG)
1421 return GTK_RC_TOKEN_FG;
1423 token = gtk_rc_parse_state (scanner, &state);
1424 if (token != G_TOKEN_NONE)
1427 token = g_scanner_get_next_token (scanner);
1428 if (token != G_TOKEN_EQUAL_SIGN)
1429 return G_TOKEN_EQUAL_SIGN;
1431 style->color_flags[state] |= GTK_RC_FG;
1432 return gtk_rc_parse_color (scanner, &style->fg[state]);
1436 gtk_rc_parse_text (GScanner *scanner,
1442 token = g_scanner_get_next_token (scanner);
1443 if (token != GTK_RC_TOKEN_TEXT)
1444 return GTK_RC_TOKEN_TEXT;
1446 token = gtk_rc_parse_state (scanner, &state);
1447 if (token != G_TOKEN_NONE)
1450 token = g_scanner_get_next_token (scanner);
1451 if (token != G_TOKEN_EQUAL_SIGN)
1452 return G_TOKEN_EQUAL_SIGN;
1454 style->color_flags[state] |= GTK_RC_TEXT;
1455 return gtk_rc_parse_color (scanner, &style->text[state]);
1459 gtk_rc_parse_bg_pixmap (GScanner *scanner,
1460 GtkRcStyle *rc_style)
1466 token = g_scanner_get_next_token (scanner);
1467 if (token != GTK_RC_TOKEN_BG_PIXMAP)
1468 return GTK_RC_TOKEN_BG_PIXMAP;
1470 token = gtk_rc_parse_state (scanner, &state);
1471 if (token != G_TOKEN_NONE)
1474 token = g_scanner_get_next_token (scanner);
1475 if (token != G_TOKEN_EQUAL_SIGN)
1476 return G_TOKEN_EQUAL_SIGN;
1478 token = g_scanner_get_next_token (scanner);
1479 if (token != G_TOKEN_STRING)
1480 return G_TOKEN_STRING;
1482 if ((strcmp (scanner->value.v_string, "<parent>") == 0) ||
1483 (strcmp (scanner->value.v_string, "<none>") == 0))
1484 pixmap_file = g_strdup (scanner->value.v_string);
1486 pixmap_file = gtk_rc_find_pixmap_in_path (scanner, scanner->value.v_string);
1490 if (rc_style->bg_pixmap_name[state])
1491 g_free (rc_style->bg_pixmap_name[state]);
1492 rc_style->bg_pixmap_name[state] = pixmap_file;
1495 return G_TOKEN_NONE;
1499 gtk_rc_find_pixmap_in_path (GScanner *scanner,
1500 const gchar *pixmap_file)
1506 for (i = 0; (i < GTK_RC_MAX_PIXMAP_PATHS) && (pixmap_path[i] != NULL); i++)
1508 buf = g_strdup_printf ("%s%c%s", pixmap_path[i], '/', pixmap_file);
1510 fd = open (buf, O_RDONLY);
1521 g_warning (_("Unable to locate image file in pixmap_path: \"%s\" line %d"),
1522 pixmap_file, scanner->line);
1524 g_warning (_("Unable to locate image file in pixmap_path: \"%s\""),
1531 gtk_rc_find_module_in_path (const gchar *module_file)
1537 for (i = 0; (i < GTK_RC_MAX_MODULE_PATHS) && (module_path[i] != NULL); i++)
1539 buf = g_strdup_printf ("%s%c%s", module_path[i], '/', module_file);
1541 fd = open (buf, O_RDONLY);
1555 gtk_rc_parse_font (GScanner *scanner,
1556 GtkRcStyle *rc_style)
1560 token = g_scanner_get_next_token (scanner);
1561 if (token != GTK_RC_TOKEN_FONT)
1562 return GTK_RC_TOKEN_FONT;
1564 token = g_scanner_get_next_token (scanner);
1565 if (token != G_TOKEN_EQUAL_SIGN)
1566 return G_TOKEN_EQUAL_SIGN;
1568 token = g_scanner_get_next_token (scanner);
1569 if (token != G_TOKEN_STRING)
1570 return G_TOKEN_STRING;
1572 if (rc_style->font_name)
1573 g_free (rc_style->font_name);
1574 rc_style->font_name = g_strdup (scanner->value.v_string);
1576 return G_TOKEN_NONE;
1580 gtk_rc_parse_fontset (GScanner *scanner,
1581 GtkRcStyle *rc_style)
1585 token = g_scanner_get_next_token (scanner);
1586 if (token != GTK_RC_TOKEN_FONTSET)
1587 return GTK_RC_TOKEN_FONTSET;
1589 token = g_scanner_get_next_token (scanner);
1590 if (token != G_TOKEN_EQUAL_SIGN)
1591 return G_TOKEN_EQUAL_SIGN;
1593 token = g_scanner_get_next_token (scanner);
1594 if (token != G_TOKEN_STRING)
1595 return G_TOKEN_STRING;
1597 if (rc_style->fontset_name)
1598 g_free (rc_style->fontset_name);
1599 rc_style->fontset_name = g_strdup (scanner->value.v_string);
1601 return G_TOKEN_NONE;
1605 gtk_rc_parse_engine (GScanner *scanner,
1606 GtkRcStyle *rc_style)
1610 token = g_scanner_get_next_token (scanner);
1611 if (token != GTK_RC_TOKEN_ENGINE)
1612 return GTK_RC_TOKEN_ENGINE;
1614 token = g_scanner_get_next_token (scanner);
1615 if (token != G_TOKEN_STRING)
1616 return G_TOKEN_STRING;
1618 rc_style->engine = gtk_theme_engine_get (scanner->value.v_string);
1620 token = g_scanner_get_next_token (scanner);
1621 if (token != G_TOKEN_LEFT_CURLY)
1622 return G_TOKEN_LEFT_CURLY;
1624 if (rc_style->engine)
1625 return rc_style->engine->parse_rc_style (scanner, rc_style);
1628 /* Skip over remainder, looking for nested {}'s */
1631 while ((token = g_scanner_get_next_token (scanner)) != G_TOKEN_EOF)
1633 if (token == G_TOKEN_LEFT_CURLY)
1635 else if (token == G_TOKEN_RIGHT_CURLY)
1639 return G_TOKEN_NONE;
1642 return G_TOKEN_RIGHT_CURLY;
1647 gtk_rc_parse_state (GScanner *scanner,
1648 GtkStateType *state)
1653 g_return_val_if_fail (scanner != NULL, G_TOKEN_ERROR);
1654 g_return_val_if_fail (state != NULL, G_TOKEN_ERROR);
1656 /* we don't know where we got called from, so we reset the scope here.
1657 * if we bail out due to errors, we *don't* reset the scope, so the
1658 * error messaging code can make sense of our tokens.
1660 old_scope = g_scanner_set_scope (scanner, 0);
1662 token = g_scanner_get_next_token (scanner);
1663 if (token != G_TOKEN_LEFT_BRACE)
1664 return G_TOKEN_LEFT_BRACE;
1666 token = g_scanner_get_next_token (scanner);
1669 case GTK_RC_TOKEN_ACTIVE:
1670 *state = GTK_STATE_ACTIVE;
1672 case GTK_RC_TOKEN_INSENSITIVE:
1673 *state = GTK_STATE_INSENSITIVE;
1675 case GTK_RC_TOKEN_NORMAL:
1676 *state = GTK_STATE_NORMAL;
1678 case GTK_RC_TOKEN_PRELIGHT:
1679 *state = GTK_STATE_PRELIGHT;
1681 case GTK_RC_TOKEN_SELECTED:
1682 *state = GTK_STATE_SELECTED;
1685 return /* G_TOKEN_SYMBOL */ GTK_RC_TOKEN_NORMAL;
1688 token = g_scanner_get_next_token (scanner);
1689 if (token != G_TOKEN_RIGHT_BRACE)
1690 return G_TOKEN_RIGHT_BRACE;
1692 g_scanner_set_scope (scanner, old_scope);
1694 return G_TOKEN_NONE;
1698 gtk_rc_parse_priority (GScanner *scanner,
1699 GtkPathPriorityType *priority)
1704 g_return_val_if_fail (scanner != NULL, G_TOKEN_ERROR);
1705 g_return_val_if_fail (priority != NULL, G_TOKEN_ERROR);
1707 /* we don't know where we got called from, so we reset the scope here.
1708 * if we bail out due to errors, we *don't* reset the scope, so the
1709 * error messaging code can make sense of our tokens.
1711 old_scope = g_scanner_set_scope (scanner, 0);
1713 token = g_scanner_get_next_token (scanner);
1717 token = g_scanner_get_next_token (scanner);
1720 case GTK_RC_TOKEN_LOWEST:
1721 *priority = GTK_PATH_PRIO_LOWEST;
1723 case GTK_RC_TOKEN_GTK:
1724 *priority = GTK_PATH_PRIO_GTK;
1726 case GTK_RC_TOKEN_APPLICATION:
1727 *priority = GTK_PATH_PRIO_APPLICATION;
1729 case GTK_RC_TOKEN_RC:
1730 *priority = GTK_PATH_PRIO_RC;
1732 case GTK_RC_TOKEN_HIGHEST:
1733 *priority = GTK_PATH_PRIO_HIGHEST;
1736 return /* G_TOKEN_SYMBOL */ GTK_RC_TOKEN_APPLICATION;
1739 g_scanner_set_scope (scanner, old_scope);
1741 return G_TOKEN_NONE;
1745 gtk_rc_parse_color (GScanner *scanner,
1750 g_return_val_if_fail (scanner != NULL, G_TOKEN_ERROR);
1752 /* we don't need to set our own scop here, because
1753 * we don't need own symbols
1756 token = g_scanner_get_next_token (scanner);
1765 case G_TOKEN_LEFT_CURLY:
1766 token = g_scanner_get_next_token (scanner);
1767 if (token == G_TOKEN_INT)
1768 token_int = scanner->value.v_int;
1769 else if (token == G_TOKEN_FLOAT)
1770 token_int = scanner->value.v_float * 65535.0;
1772 return G_TOKEN_FLOAT;
1773 color->red = CLAMP (token_int, 0, 65535);
1775 token = g_scanner_get_next_token (scanner);
1776 if (token != G_TOKEN_COMMA)
1777 return G_TOKEN_COMMA;
1779 token = g_scanner_get_next_token (scanner);
1780 if (token == G_TOKEN_INT)
1781 token_int = scanner->value.v_int;
1782 else if (token == G_TOKEN_FLOAT)
1783 token_int = scanner->value.v_float * 65535.0;
1785 return G_TOKEN_FLOAT;
1786 color->green = CLAMP (token_int, 0, 65535);
1788 token = g_scanner_get_next_token (scanner);
1789 if (token != G_TOKEN_COMMA)
1790 return G_TOKEN_COMMA;
1792 token = g_scanner_get_next_token (scanner);
1793 if (token == G_TOKEN_INT)
1794 token_int = scanner->value.v_int;
1795 else if (token == G_TOKEN_FLOAT)
1796 token_int = scanner->value.v_float * 65535.0;
1798 return G_TOKEN_FLOAT;
1799 color->blue = CLAMP (token_int, 0, 65535);
1801 token = g_scanner_get_next_token (scanner);
1802 if (token != G_TOKEN_RIGHT_CURLY)
1803 return G_TOKEN_RIGHT_CURLY;
1804 return G_TOKEN_NONE;
1806 case G_TOKEN_STRING:
1807 if (scanner->value.v_string[0] != '#')
1808 return G_TOKEN_STRING;
1810 length = strlen (scanner->value.v_string) - 1;
1811 if (((length % 3) != 0) || (length > 12))
1812 return G_TOKEN_STRING;
1815 for (i = 0, j = 1; i < length; i++, j++)
1816 buf[i] = scanner->value.v_string[j];
1819 sscanf (buf, "%x", &temp);
1822 for (i = 0; i < length; i++, j++)
1823 buf[i] = scanner->value.v_string[j];
1826 sscanf (buf, "%x", &temp);
1827 color->green = temp;
1829 for (i = 0; i < length; i++, j++)
1830 buf[i] = scanner->value.v_string[j];
1833 sscanf (buf, "%x", &temp);
1839 color->green *= 4369;
1840 color->blue *= 4369;
1842 else if (length == 2)
1845 color->green *= 257;
1848 else if (length == 3)
1854 return G_TOKEN_NONE;
1857 return G_TOKEN_STRING;
1862 gtk_rc_parse_pixmap_path (GScanner *scanner)
1866 token = g_scanner_get_next_token (scanner);
1867 if (token != GTK_RC_TOKEN_PIXMAP_PATH)
1868 return GTK_RC_TOKEN_PIXMAP_PATH;
1870 token = g_scanner_get_next_token (scanner);
1871 if (token != G_TOKEN_STRING)
1872 return G_TOKEN_STRING;
1874 gtk_rc_parse_pixmap_path_string (scanner->value.v_string);
1876 return G_TOKEN_NONE;
1880 gtk_rc_parse_pixmap_path_string (gchar *pix_path)
1884 gint start_offset = 0;
1888 /* free the old one, or just add to the old one ? */
1889 for (path_num=0; pixmap_path[path_num]; path_num++)
1891 g_free (pixmap_path[path_num]);
1892 pixmap_path[path_num] = NULL;
1897 path_len = strlen (pix_path);
1899 buf = g_strdup (pix_path);
1901 for (end_offset = 0; end_offset <= path_len; end_offset++)
1903 if ((buf[end_offset] == ':') ||
1904 (end_offset == path_len))
1906 buf[end_offset] = '\0';
1907 pixmap_path[path_num] = g_strdup (buf + start_offset);
1909 pixmap_path[path_num] = NULL;
1910 start_offset = end_offset + 1;
1914 gtk_rc_append_default_pixmap_path();
1918 gtk_rc_parse_module_path (GScanner *scanner)
1922 token = g_scanner_get_next_token (scanner);
1923 if (token != GTK_RC_TOKEN_MODULE_PATH)
1924 return GTK_RC_TOKEN_MODULE_PATH;
1926 token = g_scanner_get_next_token (scanner);
1927 if (token != G_TOKEN_STRING)
1928 return G_TOKEN_STRING;
1930 gtk_rc_parse_module_path_string (scanner->value.v_string);
1932 return G_TOKEN_NONE;
1936 gtk_rc_parse_module_path_string (gchar *mod_path)
1940 gint start_offset = 0;
1944 /* free the old one, or just add to the old one ? */
1945 for (path_num=0; module_path[path_num]; path_num++)
1947 g_free (module_path[path_num]);
1948 module_path[path_num] = NULL;
1953 path_len = strlen (mod_path);
1955 buf = g_strdup (mod_path);
1957 for (end_offset = 0; end_offset <= path_len; end_offset++)
1959 if ((buf[end_offset] == ':') ||
1960 (end_offset == path_len))
1962 buf[end_offset] = '\0';
1963 module_path[path_num] = g_strdup (buf + start_offset);
1965 module_path[path_num] = NULL;
1966 start_offset = end_offset + 1;
1970 gtk_rc_append_default_module_path();
1974 gtk_rc_parse_path_pattern (GScanner *scanner)
1977 GtkPathType path_type;
1979 gboolean is_binding;
1980 GtkPathPriorityType priority = GTK_PATH_PRIO_RC;
1982 token = g_scanner_get_next_token (scanner);
1985 case GTK_RC_TOKEN_WIDGET:
1986 path_type = GTK_PATH_WIDGET;
1988 case GTK_RC_TOKEN_WIDGET_CLASS:
1989 path_type = GTK_PATH_WIDGET_CLASS;
1991 case GTK_RC_TOKEN_CLASS:
1992 path_type = GTK_PATH_CLASS;
1995 return GTK_RC_TOKEN_WIDGET_CLASS;
1998 token = g_scanner_get_next_token (scanner);
1999 if (token != G_TOKEN_STRING)
2000 return G_TOKEN_STRING;
2002 pattern = g_strdup (scanner->value.v_string);
2004 token = g_scanner_get_next_token (scanner);
2005 if (token == GTK_RC_TOKEN_STYLE)
2007 else if (token == GTK_RC_TOKEN_BINDING)
2010 if (g_scanner_peek_next_token (scanner) == ':')
2012 token = gtk_rc_parse_priority (scanner, &priority);
2013 if (token != G_TOKEN_NONE)
2023 return GTK_RC_TOKEN_STYLE;
2026 token = g_scanner_get_next_token (scanner);
2027 if (token != G_TOKEN_STRING)
2030 return G_TOKEN_STRING;
2035 GtkBindingSet *binding;
2037 binding = gtk_binding_set_find (scanner->value.v_string);
2041 return G_TOKEN_STRING;
2043 gtk_binding_set_add_path (binding, path_type, pattern, priority);
2047 GtkRcStyle *rc_style;
2050 rc_style = gtk_rc_style_find (scanner->value.v_string);
2055 return G_TOKEN_STRING;
2058 rc_set = g_new (GtkRcSet, 1);
2059 gtk_pattern_spec_init (&rc_set->pspec, pattern);
2060 rc_set->rc_style = rc_style;
2062 if (path_type == GTK_PATH_WIDGET)
2063 gtk_rc_sets_widget = g_slist_prepend (gtk_rc_sets_widget, rc_set);
2064 else if (path_type == GTK_PATH_WIDGET_CLASS)
2065 gtk_rc_sets_widget_class = g_slist_prepend (gtk_rc_sets_widget_class, rc_set);
2067 gtk_rc_sets_class = g_slist_prepend (gtk_rc_sets_class, rc_set);
2071 return G_TOKEN_NONE;
2075 typedef GdkPixmap * (*GtkImageLoader) (GdkWindow *window,
2076 GdkColormap *colormap,
2078 GdkColor *transparent_color,
2079 const gchar *filename);
2083 gtk_rc_set_image_loader(GtkImageLoader loader)
2085 image_loader = loader;
2089 gtk_rc_load_image (GdkColormap *colormap,
2090 GdkColor *transparent_color,
2091 const gchar *filename)
2093 if (strcmp (filename, "<parent>") == 0)
2094 return (GdkPixmap*) GDK_PARENT_RELATIVE;
2098 return image_loader(NULL, colormap, NULL,
2102 return gdk_pixmap_colormap_create_from_xpm (NULL, colormap, NULL,