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 char *locale = setlocale (LC_MESSAGES, NULL);
387 rc_style_ht = g_hash_table_new ((GHashFunc) gtk_rc_style_hash,
388 (GCompareFunc) gtk_rc_style_compare);
389 pixmap_path[0] = NULL;
390 module_path[0] = NULL;
391 gtk_rc_append_default_pixmap_path();
392 gtk_rc_append_default_module_path();
394 gtk_rc_add_initial_default_files ();
396 if (strcmp (locale, "C") && strcmp (locale, "POSIX"))
398 /* Determine locale-specific suffixes for RC files
400 p = strchr (locale, '@');
401 length = p ? (p -locale) : strlen (locale);
403 p = strchr (locale, '.');
406 locale_suffixes[n_locale_suffixes++] = g_strndup (locale, length);
410 p = strchr (locale, '_');
413 locale_suffixes[n_locale_suffixes++] = g_strndup (locale, length);
417 locale_suffixes[n_locale_suffixes++] = g_strndup (locale, length);
421 while (gtk_rc_default_files[i] != NULL)
423 /* Try to find a locale specific RC file corresponding to
424 * to parse before the default file.
426 for (j=n_locale_suffixes-1; j>=0; j--)
428 gchar *name = g_strconcat (gtk_rc_default_files[i],
436 gtk_rc_parse (gtk_rc_default_files[i]);
442 gtk_rc_parse_string (const gchar *rc_string)
444 g_return_if_fail (rc_string != NULL);
446 gtk_rc_parse_any ("-", -1, rc_string);
450 gtk_rc_parse_file (const gchar *filename, gboolean reload)
452 GtkRcFile *rc_file = NULL;
456 g_return_if_fail (filename != NULL);
461 rc_file = tmp_list->data;
462 if (!strcmp (rc_file->name, filename))
465 tmp_list = tmp_list->next;
470 rc_file = g_new (GtkRcFile, 1);
471 rc_file->name = g_strdup (filename);
472 rc_file->canonical_name = NULL;
474 rc_file->reload = reload;
476 rc_files = g_slist_append (rc_files, rc_file);
479 if (!rc_file->canonical_name)
481 /* Get the absolute pathname */
483 if (rc_file->name[0] == '/')
484 rc_file->canonical_name = rc_file->name;
490 cwd = g_get_current_dir ();
492 str = g_string_new (cwd);
494 g_string_append_c (str, '/');
495 g_string_append (str, rc_file->name);
497 rc_file->canonical_name = str->str;
498 g_string_free (str, FALSE);
502 if (!lstat (rc_file->canonical_name, &statbuf))
506 rc_file->mtime = statbuf.st_mtime;
508 fd = open (rc_file->canonical_name, O_RDONLY);
516 dir = g_strdup(rc_file->canonical_name);
517 for (i = strlen(dir) - 1; (i >= 0) && (dir[i] != '/'); i--)
519 gtk_rc_append_pixmap_path(dir);
522 gtk_rc_parse_any (filename, fd, NULL);
529 gtk_rc_parse (const gchar *filename)
531 g_return_if_fail (filename != NULL);
533 gtk_rc_parse_file (filename, TRUE);
536 /* Handling of RC styles */
539 gtk_rc_style_new (void)
541 GtkRcStyle *new_style;
543 new_style = g_new0 (GtkRcStyle, 1);
544 new_style->ref_count = 1;
550 gtk_rc_style_ref (GtkRcStyle *rc_style)
552 g_return_if_fail (rc_style != NULL);
554 rc_style->ref_count++;
558 gtk_rc_style_unref (GtkRcStyle *rc_style)
562 g_return_if_fail (rc_style != NULL);
564 rc_style->ref_count--;
566 if (rc_style->ref_count == 0)
568 if (rc_style->engine)
570 rc_style->engine->destroy_rc_style (rc_style);
571 gtk_theme_engine_unref (rc_style->engine);
575 g_free (rc_style->name);
576 if (rc_style->fontset_name)
577 g_free (rc_style->fontset_name);
578 if (rc_style->font_name)
579 g_free (rc_style->font_name);
581 for (i=0 ; i<5 ; i++)
582 if (rc_style->bg_pixmap_name[i])
583 g_free (rc_style->bg_pixmap_name[i]);
590 gtk_rc_clear_realized_node (gpointer key,
594 gtk_style_unref (data);
598 gtk_rc_clear_hash_node (gpointer key,
602 gtk_rc_style_unref (data);
606 gtk_rc_free_rc_sets (GSList *slist)
612 rc_set = slist->data;
613 gtk_pattern_spec_free_segs (&rc_set->pspec);
621 gtk_rc_clear_styles (void)
623 /* Clear out all old rc_styles */
627 g_hash_table_foreach (rc_style_ht, gtk_rc_clear_hash_node, NULL);
628 g_hash_table_destroy (rc_style_ht);
632 if (realized_style_ht)
634 g_hash_table_foreach (realized_style_ht, gtk_rc_clear_realized_node, NULL);
635 g_hash_table_destroy (realized_style_ht);
636 realized_style_ht = NULL;
639 gtk_rc_free_rc_sets (gtk_rc_sets_widget);
640 g_slist_free (gtk_rc_sets_widget);
641 gtk_rc_sets_widget = NULL;
643 gtk_rc_free_rc_sets (gtk_rc_sets_widget_class);
644 g_slist_free (gtk_rc_sets_widget_class);
645 gtk_rc_sets_widget_class = NULL;
647 gtk_rc_free_rc_sets (gtk_rc_sets_class);
648 g_slist_free (gtk_rc_sets_class);
649 gtk_rc_sets_class = NULL;
655 gtk_rc_reparse_all (void)
658 gboolean mtime_modified = FALSE;
663 /* Check through and see if any of the RC's have had their
664 * mtime modified. If so, reparse everything.
669 rc_file = tmp_list->data;
671 if (!lstat (rc_file->name, &statbuf) &&
672 (statbuf.st_mtime > rc_file->mtime))
674 mtime_modified = TRUE;
678 tmp_list = tmp_list->next;
683 gtk_rc_clear_styles();
688 rc_file = tmp_list->data;
690 gtk_rc_parse_file (rc_file->name, FALSE);
692 tmp_list = tmp_list->next;
696 return mtime_modified;
700 gtk_rc_styles_match (GSList *rc_styles,
704 gchar *path_reversed)
714 if (gtk_pattern_match (&rc_set->pspec, path_length, path, path_reversed))
715 rc_styles = g_slist_append (rc_styles, rc_set->rc_style);
722 gtk_rc_get_style (GtkWidget *widget)
724 GtkRcStyle *widget_rc_style;
725 GSList *rc_styles = NULL;
727 static guint rc_style_key_id = 0;
729 /* We allow the specification of a single rc style to be bound
730 * tightly to a widget, for application modifications
732 if (!rc_style_key_id)
733 rc_style_key_id = g_quark_from_static_string ("gtk-rc-style");
735 widget_rc_style = gtk_object_get_data_by_id (GTK_OBJECT (widget),
739 rc_styles = g_slist_prepend (rc_styles, widget_rc_style);
741 if (gtk_rc_sets_widget)
743 gchar *path, *path_reversed;
746 gtk_widget_path (widget, &path_length, &path, &path_reversed);
747 rc_styles = gtk_rc_styles_match (rc_styles, gtk_rc_sets_widget, path_length, path, path_reversed);
749 g_free (path_reversed);
753 if (gtk_rc_sets_widget_class)
755 gchar *path, *path_reversed;
758 gtk_widget_class_path (widget, &path_length, &path, &path_reversed);
759 rc_styles = gtk_rc_styles_match (rc_styles, gtk_rc_sets_widget_class, path_length, path, path_reversed);
761 g_free (path_reversed);
764 if (gtk_rc_sets_class)
768 type = GTK_OBJECT_TYPE (widget);
771 gchar *path, *path_reversed;
774 path = gtk_type_name (type);
775 path_length = strlen (path);
776 path_reversed = g_strdup (path);
777 g_strreverse (path_reversed);
779 rc_styles = gtk_rc_styles_match (rc_styles, gtk_rc_sets_class, path_length, path, path_reversed);
780 g_free (path_reversed);
782 type = gtk_type_parent (type);
787 return gtk_rc_style_init (rc_styles);
793 gtk_rc_add_rc_sets (GSList *slist,
794 GtkRcStyle *rc_style,
797 GtkRcStyle *new_style;
801 new_style = gtk_rc_style_new ();
802 *new_style = *rc_style;
803 new_style->name = g_strdup (rc_style->name);
804 new_style->font_name = g_strdup (rc_style->font_name);
805 new_style->fontset_name = g_strdup (rc_style->fontset_name);
807 for (i = 0; i < 5; i++)
808 new_style->bg_pixmap_name[i] = g_strdup (rc_style->bg_pixmap_name[i]);
810 rc_set = g_new (GtkRcSet, 1);
811 gtk_pattern_spec_init (&rc_set->pspec, pattern);
812 rc_set->rc_style = rc_style;
814 return g_slist_prepend (slist, rc_set);
818 gtk_rc_add_widget_name_style (GtkRcStyle *rc_style,
819 const gchar *pattern)
821 g_return_if_fail (rc_style != NULL);
822 g_return_if_fail (pattern != NULL);
824 gtk_rc_sets_widget = gtk_rc_add_rc_sets (gtk_rc_sets_widget, rc_style, pattern);
828 gtk_rc_add_widget_class_style (GtkRcStyle *rc_style,
829 const gchar *pattern)
831 g_return_if_fail (rc_style != NULL);
832 g_return_if_fail (pattern != NULL);
834 gtk_rc_sets_widget_class = gtk_rc_add_rc_sets (gtk_rc_sets_widget_class, rc_style, pattern);
838 gtk_rc_add_class_style (GtkRcStyle *rc_style,
839 const gchar *pattern)
841 g_return_if_fail (rc_style != NULL);
842 g_return_if_fail (pattern != NULL);
844 gtk_rc_sets_class = gtk_rc_add_rc_sets (gtk_rc_sets_class, rc_style, pattern);
848 gtk_rc_parse_any (const gchar *input_name,
850 const gchar *input_string)
856 scanner = g_scanner_new ((GScannerConfig *) >k_rc_scanner_config);
860 g_assert (input_string == NULL);
862 g_scanner_input_file (scanner, input_fd);
866 g_assert (input_string != NULL);
868 g_scanner_input_text (scanner, input_string, strlen (input_string));
870 scanner->input_name = input_name;
872 g_scanner_freeze_symbol_table (scanner);
873 for (i = 0; i < n_symbols; i++)
874 g_scanner_add_symbol (scanner, symbols[i].name, GINT_TO_POINTER (symbols[i].token));
875 g_scanner_thaw_symbol_table (scanner);
880 if (g_scanner_peek_next_token (scanner) == G_TOKEN_EOF)
884 guint expected_token;
886 expected_token = gtk_rc_parse_statement (scanner);
888 if (expected_token != G_TOKEN_NONE)
895 if (scanner->scope_id == 0)
897 /* if we are in scope 0, we know the symbol names
898 * that are associated with certaintoken values.
899 * so we look them up to make the error messages
902 if (expected_token > GTK_RC_TOKEN_INVALID &&
903 expected_token < GTK_RC_TOKEN_LAST)
905 for (i = 0; i < n_symbols; i++)
906 if (symbols[i].token == expected_token)
907 msg = symbols[i].name;
909 msg = g_strconcat ("e.g. `", msg, "'", NULL);
911 if (scanner->token > GTK_RC_TOKEN_INVALID &&
912 scanner->token < GTK_RC_TOKEN_LAST)
915 for (i = 0; i < n_symbols; i++)
916 if (symbols[i].token == scanner->token)
917 symbol_name = symbols[i].name;
920 g_scanner_unexp_token (scanner,
933 g_scanner_destroy (scanner);
937 gtk_rc_styles_hash (const GSList *rc_styles)
944 result += (result << 9) + GPOINTER_TO_UINT (rc_styles->data);
945 rc_styles = rc_styles->next;
952 gtk_rc_styles_compare (const GSList *a,
957 if (a->data != b->data)
967 gtk_rc_style_hash (const char *name)
973 result += (result << 3) + *name++;
979 gtk_rc_style_compare (const char *a,
982 return (strcmp (a, b) == 0);
986 gtk_rc_style_find (const char *name)
988 GtkRcStyle *rc_style;
990 rc_style = g_hash_table_lookup (rc_style_ht, (gpointer) name);
995 /* Assumes ownership of rc_style */
997 gtk_rc_style_to_style (GtkRcStyle *rc_style)
1003 style = gtk_style_new ();
1005 style->rc_style = rc_style;
1007 if (rc_style->fontset_name)
1009 old_font = style->font;
1010 style->font = gdk_fontset_load (rc_style->fontset_name);
1012 gdk_font_unref (old_font);
1014 style->font = old_font;
1016 else if (rc_style->font_name)
1018 old_font = style->font;
1019 style->font = gdk_font_load (rc_style->font_name);
1021 gdk_font_unref (old_font);
1023 style->font = old_font;
1026 for (i = 0; i < 5; i++)
1028 if (rc_style->color_flags[i] & GTK_RC_FG)
1029 style->fg[i] = rc_style->fg[i];
1030 if (rc_style->color_flags[i] & GTK_RC_BG)
1031 style->bg[i] = rc_style->bg[i];
1032 if (rc_style->color_flags[i] & GTK_RC_TEXT)
1033 style->text[i] = rc_style->text[i];
1034 if (rc_style->color_flags[i] & GTK_RC_BASE)
1035 style->base[i] = rc_style->base[i];
1038 if (rc_style->engine)
1040 style->engine = rc_style->engine;
1041 gtk_theme_engine_ref (style->engine);
1042 rc_style->engine->rc_style_to_style (style, rc_style);
1048 /* Reuses or frees rc_styles */
1050 gtk_rc_style_init (GSList *rc_styles)
1054 GtkStyle *style = NULL;
1055 GtkRcStyle *proto_style;
1057 if (!realized_style_ht)
1058 realized_style_ht = g_hash_table_new ((GHashFunc)gtk_rc_styles_hash,
1059 (GCompareFunc)gtk_rc_styles_compare);
1061 style = g_hash_table_lookup (realized_style_ht, rc_styles);
1065 GSList *tmp_styles = rc_styles;
1067 proto_style = gtk_rc_style_new ();
1071 GtkRcStyle *rc_style = tmp_styles->data;
1075 if (!proto_style->bg_pixmap_name[i] && rc_style->bg_pixmap_name[i])
1076 proto_style->bg_pixmap_name[i] = g_strdup (rc_style->bg_pixmap_name[i]);
1078 if (!(proto_style->color_flags[i] & GTK_RC_FG) &&
1079 rc_style->color_flags[i] & GTK_RC_FG)
1081 proto_style->fg[i] = rc_style->fg[i];
1082 proto_style->color_flags[i] |= GTK_RC_FG;
1084 if (!(proto_style->color_flags[i] & GTK_RC_BG) &&
1085 rc_style->color_flags[i] & GTK_RC_BG)
1087 proto_style->bg[i] = rc_style->bg[i];
1088 proto_style->color_flags[i] |= GTK_RC_BG;
1090 if (!(proto_style->color_flags[i] & GTK_RC_TEXT) &&
1091 rc_style->color_flags[i] & GTK_RC_TEXT)
1093 proto_style->text[i] = rc_style->text[i];
1094 proto_style->color_flags[i] |= GTK_RC_TEXT;
1096 if (!(proto_style->color_flags[i] & GTK_RC_BASE) &&
1097 rc_style->color_flags[i] & GTK_RC_BASE)
1099 proto_style->base[i] = rc_style->base[i];
1100 proto_style->color_flags[i] |= GTK_RC_BASE;
1104 if (!proto_style->font_name && rc_style->font_name)
1105 proto_style->font_name = g_strdup (rc_style->font_name);
1106 if (!proto_style->fontset_name && rc_style->fontset_name)
1107 proto_style->fontset_name = g_strdup (rc_style->fontset_name);
1109 if (!proto_style->engine && rc_style->engine)
1111 proto_style->engine = rc_style->engine;
1112 gtk_theme_engine_ref (proto_style->engine);
1115 if (proto_style->engine &&
1116 (proto_style->engine == rc_style->engine))
1117 proto_style->engine->merge_rc_style (proto_style, rc_style);
1119 tmp_styles = tmp_styles->next;
1122 style = gtk_rc_style_to_style (proto_style);
1124 g_hash_table_insert (realized_style_ht, rc_styles, style);
1130 /*********************
1131 * Parsing functions *
1132 *********************/
1135 gtk_rc_parse_statement (GScanner *scanner)
1139 token = g_scanner_peek_next_token (scanner);
1143 case GTK_RC_TOKEN_INCLUDE:
1144 token = g_scanner_get_next_token (scanner);
1145 if (token != GTK_RC_TOKEN_INCLUDE)
1146 return GTK_RC_TOKEN_INCLUDE;
1148 token = g_scanner_get_next_token (scanner);
1149 if (token != G_TOKEN_STRING)
1150 return G_TOKEN_STRING;
1152 gtk_rc_parse_file (scanner->value.v_string, FALSE);
1153 return G_TOKEN_NONE;
1155 case GTK_RC_TOKEN_STYLE:
1156 return gtk_rc_parse_style (scanner);
1158 case GTK_RC_TOKEN_BINDING:
1159 return gtk_binding_parse_binding (scanner);
1161 case GTK_RC_TOKEN_PIXMAP_PATH:
1162 return gtk_rc_parse_pixmap_path (scanner);
1164 case GTK_RC_TOKEN_WIDGET:
1165 return gtk_rc_parse_path_pattern (scanner);
1167 case GTK_RC_TOKEN_WIDGET_CLASS:
1168 return gtk_rc_parse_path_pattern (scanner);
1170 case GTK_RC_TOKEN_CLASS:
1171 return gtk_rc_parse_path_pattern (scanner);
1173 case GTK_RC_TOKEN_MODULE_PATH:
1174 return gtk_rc_parse_module_path (scanner);
1177 g_scanner_get_next_token (scanner);
1178 return /* G_TOKEN_SYMBOL */ GTK_RC_TOKEN_STYLE;
1183 gtk_rc_parse_style (GScanner *scanner)
1185 GtkRcStyle *rc_style;
1186 GtkRcStyle *parent_style;
1191 token = g_scanner_get_next_token (scanner);
1192 if (token != GTK_RC_TOKEN_STYLE)
1193 return GTK_RC_TOKEN_STYLE;
1195 token = g_scanner_get_next_token (scanner);
1196 if (token != G_TOKEN_STRING)
1197 return G_TOKEN_STRING;
1200 rc_style = g_hash_table_lookup (rc_style_ht, scanner->value.v_string);
1205 rc_style = gtk_rc_style_new ();
1206 rc_style->name = g_strdup (scanner->value.v_string);
1208 for (i = 0; i < 5; i++)
1209 rc_style->bg_pixmap_name[i] = NULL;
1211 for (i = 0; i < 5; i++)
1212 rc_style->color_flags[i] = 0;
1214 rc_style->engine = NULL;
1215 rc_style->engine_data = NULL;
1218 token = g_scanner_peek_next_token (scanner);
1219 if (token == G_TOKEN_EQUAL_SIGN)
1221 token = g_scanner_get_next_token (scanner);
1223 token = g_scanner_get_next_token (scanner);
1224 if (token != G_TOKEN_STRING)
1229 return G_TOKEN_STRING;
1232 parent_style = g_hash_table_lookup (rc_style_ht, scanner->value.v_string);
1235 for (i = 0; i < 5; i++)
1237 rc_style->color_flags[i] = parent_style->color_flags[i];
1238 rc_style->fg[i] = parent_style->fg[i];
1239 rc_style->bg[i] = parent_style->bg[i];
1240 rc_style->text[i] = parent_style->text[i];
1241 rc_style->base[i] = parent_style->base[i];
1244 if (parent_style->fontset_name)
1246 if (rc_style->fontset_name)
1247 g_free (rc_style->fontset_name);
1248 rc_style->fontset_name = g_strdup (parent_style->fontset_name);
1250 else if (parent_style->font_name)
1252 if (rc_style->font_name)
1253 g_free (rc_style->font_name);
1254 rc_style->font_name = g_strdup (parent_style->font_name);
1257 for (i = 0; i < 5; i++)
1259 if (rc_style->bg_pixmap_name[i])
1260 g_free (rc_style->bg_pixmap_name[i]);
1261 rc_style->bg_pixmap_name[i] = g_strdup (parent_style->bg_pixmap_name[i]);
1266 token = g_scanner_get_next_token (scanner);
1267 if (token != G_TOKEN_LEFT_CURLY)
1272 return G_TOKEN_LEFT_CURLY;
1275 token = g_scanner_peek_next_token (scanner);
1276 while (token != G_TOKEN_RIGHT_CURLY)
1280 case GTK_RC_TOKEN_BASE:
1281 token = gtk_rc_parse_base (scanner, rc_style);
1283 case GTK_RC_TOKEN_BG:
1284 token = gtk_rc_parse_bg (scanner, rc_style);
1286 case GTK_RC_TOKEN_FG:
1287 token = gtk_rc_parse_fg (scanner, rc_style);
1289 case GTK_RC_TOKEN_TEXT:
1290 token = gtk_rc_parse_text (scanner, rc_style);
1292 case GTK_RC_TOKEN_BG_PIXMAP:
1293 token = gtk_rc_parse_bg_pixmap (scanner, rc_style);
1295 case GTK_RC_TOKEN_FONT:
1296 token = gtk_rc_parse_font (scanner, rc_style);
1298 case GTK_RC_TOKEN_FONTSET:
1299 token = gtk_rc_parse_fontset (scanner, rc_style);
1301 case GTK_RC_TOKEN_ENGINE:
1302 token = gtk_rc_parse_engine (scanner, rc_style);
1305 g_scanner_get_next_token (scanner);
1306 token = G_TOKEN_RIGHT_CURLY;
1310 if (token != G_TOKEN_NONE)
1314 if (rc_style->fontset_name)
1315 g_free (rc_style->fontset_name);
1316 if (rc_style->font_name)
1317 g_free (rc_style->font_name);
1318 for (i = 0; i < 5; i++)
1319 if (rc_style->bg_pixmap_name[i])
1320 g_free (rc_style->bg_pixmap_name[i]);
1325 token = g_scanner_peek_next_token (scanner);
1328 token = g_scanner_get_next_token (scanner);
1329 if (token != G_TOKEN_RIGHT_CURLY)
1333 if (rc_style->fontset_name)
1334 g_free (rc_style->fontset_name);
1335 if (rc_style->font_name)
1336 g_free (rc_style->font_name);
1338 for (i = 0; i < 5; i++)
1339 if (rc_style->bg_pixmap_name[i])
1340 g_free (rc_style->bg_pixmap_name[i]);
1344 return G_TOKEN_RIGHT_CURLY;
1348 g_hash_table_insert (rc_style_ht, rc_style->name, rc_style);
1350 return G_TOKEN_NONE;
1354 gtk_rc_parse_base (GScanner *scanner,
1360 token = g_scanner_get_next_token (scanner);
1361 if (token != GTK_RC_TOKEN_BASE)
1362 return GTK_RC_TOKEN_BASE;
1364 token = gtk_rc_parse_state (scanner, &state);
1365 if (token != G_TOKEN_NONE)
1368 token = g_scanner_get_next_token (scanner);
1369 if (token != G_TOKEN_EQUAL_SIGN)
1370 return G_TOKEN_EQUAL_SIGN;
1372 style->color_flags[state] |= GTK_RC_BASE;
1373 return gtk_rc_parse_color (scanner, &style->base[state]);
1377 gtk_rc_parse_bg (GScanner *scanner,
1383 token = g_scanner_get_next_token (scanner);
1384 if (token != GTK_RC_TOKEN_BG)
1385 return GTK_RC_TOKEN_BG;
1387 token = gtk_rc_parse_state (scanner, &state);
1388 if (token != G_TOKEN_NONE)
1391 token = g_scanner_get_next_token (scanner);
1392 if (token != G_TOKEN_EQUAL_SIGN)
1393 return G_TOKEN_EQUAL_SIGN;
1395 style->color_flags[state] |= GTK_RC_BG;
1396 return gtk_rc_parse_color (scanner, &style->bg[state]);
1400 gtk_rc_parse_fg (GScanner *scanner,
1406 token = g_scanner_get_next_token (scanner);
1407 if (token != GTK_RC_TOKEN_FG)
1408 return GTK_RC_TOKEN_FG;
1410 token = gtk_rc_parse_state (scanner, &state);
1411 if (token != G_TOKEN_NONE)
1414 token = g_scanner_get_next_token (scanner);
1415 if (token != G_TOKEN_EQUAL_SIGN)
1416 return G_TOKEN_EQUAL_SIGN;
1418 style->color_flags[state] |= GTK_RC_FG;
1419 return gtk_rc_parse_color (scanner, &style->fg[state]);
1423 gtk_rc_parse_text (GScanner *scanner,
1429 token = g_scanner_get_next_token (scanner);
1430 if (token != GTK_RC_TOKEN_TEXT)
1431 return GTK_RC_TOKEN_TEXT;
1433 token = gtk_rc_parse_state (scanner, &state);
1434 if (token != G_TOKEN_NONE)
1437 token = g_scanner_get_next_token (scanner);
1438 if (token != G_TOKEN_EQUAL_SIGN)
1439 return G_TOKEN_EQUAL_SIGN;
1441 style->color_flags[state] |= GTK_RC_TEXT;
1442 return gtk_rc_parse_color (scanner, &style->text[state]);
1446 gtk_rc_parse_bg_pixmap (GScanner *scanner,
1447 GtkRcStyle *rc_style)
1453 token = g_scanner_get_next_token (scanner);
1454 if (token != GTK_RC_TOKEN_BG_PIXMAP)
1455 return GTK_RC_TOKEN_BG_PIXMAP;
1457 token = gtk_rc_parse_state (scanner, &state);
1458 if (token != G_TOKEN_NONE)
1461 token = g_scanner_get_next_token (scanner);
1462 if (token != G_TOKEN_EQUAL_SIGN)
1463 return G_TOKEN_EQUAL_SIGN;
1465 token = g_scanner_get_next_token (scanner);
1466 if (token != G_TOKEN_STRING)
1467 return G_TOKEN_STRING;
1469 if (strcmp (scanner->value.v_string, "<parent>") == 0)
1470 pixmap_file = g_strdup (scanner->value.v_string);
1472 pixmap_file = gtk_rc_find_pixmap_in_path (scanner, scanner->value.v_string);
1476 if (rc_style->bg_pixmap_name[state])
1477 g_free (rc_style->bg_pixmap_name[state]);
1478 rc_style->bg_pixmap_name[state] = pixmap_file;
1481 return G_TOKEN_NONE;
1485 gtk_rc_find_pixmap_in_path (GScanner *scanner,
1486 const gchar *pixmap_file)
1492 for (i = 0; (i < GTK_RC_MAX_PIXMAP_PATHS) && (pixmap_path[i] != NULL); i++)
1494 buf = g_strdup_printf ("%s%c%s", pixmap_path[i], '/', pixmap_file);
1496 fd = open (buf, O_RDONLY);
1507 g_warning (_("Unable to locate image file in pixmap_path: \"%s\" line %d"),
1508 pixmap_file, scanner->line);
1510 g_warning (_("Unable to locate image file in pixmap_path: \"%s\""),
1517 gtk_rc_find_module_in_path (const gchar *module_file)
1523 for (i = 0; (i < GTK_RC_MAX_MODULE_PATHS) && (module_path[i] != NULL); i++)
1525 buf = g_strdup_printf ("%s%c%s", module_path[i], '/', module_file);
1527 fd = open (buf, O_RDONLY);
1541 gtk_rc_parse_font (GScanner *scanner,
1542 GtkRcStyle *rc_style)
1546 token = g_scanner_get_next_token (scanner);
1547 if (token != GTK_RC_TOKEN_FONT)
1548 return GTK_RC_TOKEN_FONT;
1550 token = g_scanner_get_next_token (scanner);
1551 if (token != G_TOKEN_EQUAL_SIGN)
1552 return G_TOKEN_EQUAL_SIGN;
1554 token = g_scanner_get_next_token (scanner);
1555 if (token != G_TOKEN_STRING)
1556 return G_TOKEN_STRING;
1558 if (rc_style->font_name)
1559 g_free (rc_style->font_name);
1560 rc_style->font_name = g_strdup (scanner->value.v_string);
1562 return G_TOKEN_NONE;
1566 gtk_rc_parse_fontset (GScanner *scanner,
1567 GtkRcStyle *rc_style)
1571 token = g_scanner_get_next_token (scanner);
1572 if (token != GTK_RC_TOKEN_FONTSET)
1573 return GTK_RC_TOKEN_FONTSET;
1575 token = g_scanner_get_next_token (scanner);
1576 if (token != G_TOKEN_EQUAL_SIGN)
1577 return G_TOKEN_EQUAL_SIGN;
1579 token = g_scanner_get_next_token (scanner);
1580 if (token != G_TOKEN_STRING)
1581 return G_TOKEN_STRING;
1583 if (rc_style->fontset_name)
1584 g_free (rc_style->fontset_name);
1585 rc_style->fontset_name = g_strdup (scanner->value.v_string);
1587 return G_TOKEN_NONE;
1591 gtk_rc_parse_engine (GScanner *scanner,
1592 GtkRcStyle *rc_style)
1596 token = g_scanner_get_next_token (scanner);
1597 if (token != GTK_RC_TOKEN_ENGINE)
1598 return GTK_RC_TOKEN_ENGINE;
1600 token = g_scanner_get_next_token (scanner);
1601 if (token != G_TOKEN_STRING)
1602 return G_TOKEN_STRING;
1604 rc_style->engine = gtk_theme_engine_get (scanner->value.v_string);
1606 token = g_scanner_get_next_token (scanner);
1607 if (token != G_TOKEN_LEFT_CURLY)
1608 return G_TOKEN_LEFT_CURLY;
1610 if (rc_style->engine)
1611 return rc_style->engine->parse_rc_style (scanner, rc_style);
1614 /* Skip over remainder, looking for nested {}'s */
1617 while ((token = g_scanner_get_next_token (scanner)) != G_TOKEN_EOF)
1619 if (token == G_TOKEN_LEFT_CURLY)
1621 else if (token == G_TOKEN_RIGHT_CURLY)
1625 return G_TOKEN_NONE;
1628 return G_TOKEN_RIGHT_CURLY;
1633 gtk_rc_parse_state (GScanner *scanner,
1634 GtkStateType *state)
1639 g_return_val_if_fail (scanner != NULL, G_TOKEN_ERROR);
1640 g_return_val_if_fail (state != NULL, G_TOKEN_ERROR);
1642 /* we don't know where we got called from, so we reset the scope here.
1643 * if we bail out due to errors, we *don't* reset the scope, so the
1644 * error messaging code can make sense of our tokens.
1646 old_scope = g_scanner_set_scope (scanner, 0);
1648 token = g_scanner_get_next_token (scanner);
1649 if (token != G_TOKEN_LEFT_BRACE)
1650 return G_TOKEN_LEFT_BRACE;
1652 token = g_scanner_get_next_token (scanner);
1655 case GTK_RC_TOKEN_ACTIVE:
1656 *state = GTK_STATE_ACTIVE;
1658 case GTK_RC_TOKEN_INSENSITIVE:
1659 *state = GTK_STATE_INSENSITIVE;
1661 case GTK_RC_TOKEN_NORMAL:
1662 *state = GTK_STATE_NORMAL;
1664 case GTK_RC_TOKEN_PRELIGHT:
1665 *state = GTK_STATE_PRELIGHT;
1667 case GTK_RC_TOKEN_SELECTED:
1668 *state = GTK_STATE_SELECTED;
1671 return /* G_TOKEN_SYMBOL */ GTK_RC_TOKEN_NORMAL;
1674 token = g_scanner_get_next_token (scanner);
1675 if (token != G_TOKEN_RIGHT_BRACE)
1676 return G_TOKEN_RIGHT_BRACE;
1678 g_scanner_set_scope (scanner, old_scope);
1680 return G_TOKEN_NONE;
1684 gtk_rc_parse_priority (GScanner *scanner,
1685 GtkPathPriorityType *priority)
1690 g_return_val_if_fail (scanner != NULL, G_TOKEN_ERROR);
1691 g_return_val_if_fail (priority != NULL, G_TOKEN_ERROR);
1693 /* we don't know where we got called from, so we reset the scope here.
1694 * if we bail out due to errors, we *don't* reset the scope, so the
1695 * error messaging code can make sense of our tokens.
1697 old_scope = g_scanner_set_scope (scanner, 0);
1699 token = g_scanner_get_next_token (scanner);
1703 token = g_scanner_get_next_token (scanner);
1706 case GTK_RC_TOKEN_LOWEST:
1707 *priority = GTK_PATH_PRIO_LOWEST;
1709 case GTK_RC_TOKEN_GTK:
1710 *priority = GTK_PATH_PRIO_GTK;
1712 case GTK_RC_TOKEN_APPLICATION:
1713 *priority = GTK_PATH_PRIO_APPLICATION;
1715 case GTK_RC_TOKEN_RC:
1716 *priority = GTK_PATH_PRIO_RC;
1718 case GTK_RC_TOKEN_HIGHEST:
1719 *priority = GTK_PATH_PRIO_HIGHEST;
1722 return /* G_TOKEN_SYMBOL */ GTK_RC_TOKEN_APPLICATION;
1725 g_scanner_set_scope (scanner, old_scope);
1727 return G_TOKEN_NONE;
1731 gtk_rc_parse_color (GScanner *scanner,
1736 g_return_val_if_fail (scanner != NULL, G_TOKEN_ERROR);
1738 /* we don't need to set our own scop here, because
1739 * we don't need own symbols
1742 token = g_scanner_get_next_token (scanner);
1751 case G_TOKEN_LEFT_CURLY:
1752 token = g_scanner_get_next_token (scanner);
1753 if (token == G_TOKEN_INT)
1754 token_int = scanner->value.v_int;
1755 else if (token == G_TOKEN_FLOAT)
1756 token_int = scanner->value.v_float * 65535.0;
1758 return G_TOKEN_FLOAT;
1759 color->red = CLAMP (token_int, 0, 65535);
1761 token = g_scanner_get_next_token (scanner);
1762 if (token != G_TOKEN_COMMA)
1763 return G_TOKEN_COMMA;
1765 token = g_scanner_get_next_token (scanner);
1766 if (token == G_TOKEN_INT)
1767 token_int = scanner->value.v_int;
1768 else if (token == G_TOKEN_FLOAT)
1769 token_int = scanner->value.v_float * 65535.0;
1771 return G_TOKEN_FLOAT;
1772 color->green = CLAMP (token_int, 0, 65535);
1774 token = g_scanner_get_next_token (scanner);
1775 if (token != G_TOKEN_COMMA)
1776 return G_TOKEN_COMMA;
1778 token = g_scanner_get_next_token (scanner);
1779 if (token == G_TOKEN_INT)
1780 token_int = scanner->value.v_int;
1781 else if (token == G_TOKEN_FLOAT)
1782 token_int = scanner->value.v_float * 65535.0;
1784 return G_TOKEN_FLOAT;
1785 color->blue = CLAMP (token_int, 0, 65535);
1787 token = g_scanner_get_next_token (scanner);
1788 if (token != G_TOKEN_RIGHT_CURLY)
1789 return G_TOKEN_RIGHT_CURLY;
1790 return G_TOKEN_NONE;
1792 case G_TOKEN_STRING:
1793 if (scanner->value.v_string[0] != '#')
1794 return G_TOKEN_STRING;
1796 length = strlen (scanner->value.v_string) - 1;
1797 if (((length % 3) != 0) || (length > 12))
1798 return G_TOKEN_STRING;
1801 for (i = 0, j = 1; i < length; i++, j++)
1802 buf[i] = scanner->value.v_string[j];
1805 sscanf (buf, "%x", &temp);
1808 for (i = 0; i < length; i++, j++)
1809 buf[i] = scanner->value.v_string[j];
1812 sscanf (buf, "%x", &temp);
1813 color->green = temp;
1815 for (i = 0; i < length; i++, j++)
1816 buf[i] = scanner->value.v_string[j];
1819 sscanf (buf, "%x", &temp);
1825 color->green *= 4369;
1826 color->blue *= 4369;
1828 else if (length == 2)
1831 color->green *= 257;
1834 else if (length == 3)
1840 return G_TOKEN_NONE;
1843 return G_TOKEN_STRING;
1848 gtk_rc_parse_pixmap_path (GScanner *scanner)
1852 token = g_scanner_get_next_token (scanner);
1853 if (token != GTK_RC_TOKEN_PIXMAP_PATH)
1854 return GTK_RC_TOKEN_PIXMAP_PATH;
1856 token = g_scanner_get_next_token (scanner);
1857 if (token != G_TOKEN_STRING)
1858 return G_TOKEN_STRING;
1860 gtk_rc_parse_pixmap_path_string (scanner->value.v_string);
1862 return G_TOKEN_NONE;
1866 gtk_rc_parse_pixmap_path_string (gchar *pix_path)
1870 gint start_offset = 0;
1874 /* free the old one, or just add to the old one ? */
1875 for (path_num=0; pixmap_path[path_num]; path_num++)
1877 g_free (pixmap_path[path_num]);
1878 pixmap_path[path_num] = NULL;
1883 path_len = strlen (pix_path);
1885 buf = g_strdup (pix_path);
1887 for (end_offset = 0; end_offset <= path_len; end_offset++)
1889 if ((buf[end_offset] == ':') ||
1890 (end_offset == path_len))
1892 buf[end_offset] = '\0';
1893 pixmap_path[path_num] = g_strdup (buf + start_offset);
1895 pixmap_path[path_num] = NULL;
1896 start_offset = end_offset + 1;
1900 gtk_rc_append_default_pixmap_path();
1904 gtk_rc_parse_module_path (GScanner *scanner)
1908 token = g_scanner_get_next_token (scanner);
1909 if (token != GTK_RC_TOKEN_MODULE_PATH)
1910 return GTK_RC_TOKEN_MODULE_PATH;
1912 token = g_scanner_get_next_token (scanner);
1913 if (token != G_TOKEN_STRING)
1914 return G_TOKEN_STRING;
1916 gtk_rc_parse_module_path_string (scanner->value.v_string);
1918 return G_TOKEN_NONE;
1922 gtk_rc_parse_module_path_string (gchar *mod_path)
1926 gint start_offset = 0;
1930 /* free the old one, or just add to the old one ? */
1931 for (path_num=0; module_path[path_num]; path_num++)
1933 g_free (module_path[path_num]);
1934 module_path[path_num] = NULL;
1939 path_len = strlen (mod_path);
1941 buf = g_strdup (mod_path);
1943 for (end_offset = 0; end_offset <= path_len; end_offset++)
1945 if ((buf[end_offset] == ':') ||
1946 (end_offset == path_len))
1948 buf[end_offset] = '\0';
1949 module_path[path_num] = g_strdup (buf + start_offset);
1951 module_path[path_num] = NULL;
1952 start_offset = end_offset + 1;
1956 gtk_rc_append_default_module_path();
1960 gtk_rc_parse_path_pattern (GScanner *scanner)
1963 GtkPathType path_type;
1965 gboolean is_binding;
1966 GtkPathPriorityType priority = GTK_PATH_PRIO_RC;
1968 token = g_scanner_get_next_token (scanner);
1971 case GTK_RC_TOKEN_WIDGET:
1972 path_type = GTK_PATH_WIDGET;
1974 case GTK_RC_TOKEN_WIDGET_CLASS:
1975 path_type = GTK_PATH_WIDGET_CLASS;
1977 case GTK_RC_TOKEN_CLASS:
1978 path_type = GTK_PATH_CLASS;
1981 return GTK_RC_TOKEN_WIDGET_CLASS;
1984 token = g_scanner_get_next_token (scanner);
1985 if (token != G_TOKEN_STRING)
1986 return G_TOKEN_STRING;
1988 pattern = g_strdup (scanner->value.v_string);
1990 token = g_scanner_get_next_token (scanner);
1991 if (token == GTK_RC_TOKEN_STYLE)
1993 else if (token == GTK_RC_TOKEN_BINDING)
1996 if (g_scanner_peek_next_token (scanner) == ':')
1998 token = gtk_rc_parse_priority (scanner, &priority);
1999 if (token != G_TOKEN_NONE)
2009 return GTK_RC_TOKEN_STYLE;
2012 token = g_scanner_get_next_token (scanner);
2013 if (token != G_TOKEN_STRING)
2016 return G_TOKEN_STRING;
2021 GtkBindingSet *binding;
2023 binding = gtk_binding_set_find (scanner->value.v_string);
2027 return G_TOKEN_STRING;
2029 gtk_binding_set_add_path (binding, path_type, pattern, priority);
2033 GtkRcStyle *rc_style;
2036 rc_style = gtk_rc_style_find (scanner->value.v_string);
2041 return G_TOKEN_STRING;
2044 rc_set = g_new (GtkRcSet, 1);
2045 gtk_pattern_spec_init (&rc_set->pspec, pattern);
2046 rc_set->rc_style = rc_style;
2048 if (path_type == GTK_PATH_WIDGET)
2049 gtk_rc_sets_widget = g_slist_prepend (gtk_rc_sets_widget, rc_set);
2050 else if (path_type == GTK_PATH_WIDGET_CLASS)
2051 gtk_rc_sets_widget_class = g_slist_prepend (gtk_rc_sets_widget_class, rc_set);
2053 gtk_rc_sets_class = g_slist_prepend (gtk_rc_sets_class, rc_set);
2057 return G_TOKEN_NONE;
2061 typedef GdkPixmap * (*GtkImageLoader) (GdkWindow *window,
2062 GdkColormap *colormap,
2064 GdkColor *transparent_color,
2065 const gchar *filename);
2069 gtk_rc_set_image_loader(GtkImageLoader loader)
2071 image_loader = loader;
2075 gtk_rc_load_image (GdkColormap *colormap,
2076 GdkColor *transparent_color,
2077 const gchar *filename)
2079 if (strcmp (filename, "<parent>") == 0)
2080 return (GdkPixmap*) GDK_PARENT_RELATIVE;
2084 return image_loader(NULL, colormap, NULL,
2088 return gdk_pixmap_colormap_create_from_xpm (NULL, colormap, NULL,