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");
213 path = g_malloc(strlen(var) + strlen("/share/themes") +1);
214 sprintf(path, "%s%s", var, "/share/themes");
218 path = g_malloc(strlen(GTK_DATA_PREFIX) + strlen("/share/themes") +1);
219 sprintf(path, "%s%s", GTK_DATA_PREFIX, "/share/themes");
225 gtk_rc_get_module_dir(void)
229 var = getenv("GTK_EXE_PREFIX");
232 path = g_malloc(strlen(var) + strlen("/lib/gtk/themes/engines") +1);
233 sprintf(path, "%s%s", var, "/lib/gtk/themes/engines");
237 path = g_malloc(strlen(GTK_EXE_PREFIX) + strlen("/lib/gtk/themes/engines") +1);
238 sprintf(path, "%s%s", GTK_EXE_PREFIX, "/lib/gtk/themes/engines");
244 gtk_rc_append_default_pixmap_path(void)
249 var = getenv("GTK_DATA_PREFIX");
252 path = g_malloc(strlen(var) + strlen("/share/gtk/themes") +1);
253 sprintf(path, "%s%s", var, "/share/gtk/themes");
257 path = g_malloc(strlen(GTK_DATA_PREFIX) + strlen("/share/gtk/themes") +1);
258 sprintf(path, "%s%s", GTK_DATA_PREFIX, "/share/gtk/themes");
261 for (n = 0; pixmap_path[n]; n++) ;
262 if (n >= GTK_RC_MAX_PIXMAP_PATHS - 1)
264 pixmap_path[n++] = g_strdup(path);
265 pixmap_path[n] = NULL;
270 gtk_rc_append_pixmap_path(gchar *dir)
274 for (n = 0; pixmap_path[n]; n++) ;
275 if (n >= GTK_RC_MAX_MODULE_PATHS - 1)
277 pixmap_path[n++] = g_strdup(dir);
278 pixmap_path[n] = NULL;
282 gtk_rc_append_default_module_path(void)
287 for (n = 0; module_path[n]; n++) ;
288 if (n >= GTK_RC_MAX_MODULE_PATHS - 1)
291 var = getenv("GTK_EXE_PREFIX");
294 path = g_malloc(strlen(var) + strlen("/lib/gtk/themes/engines") +1);
295 sprintf(path, "%s%s", var, "/lib/gtk/themes/engines");
299 path = g_malloc(strlen(GTK_EXE_PREFIX) + strlen("/lib/gtk/themes/engines") +1);
300 sprintf(path, "%s%s", GTK_EXE_PREFIX, "/lib/gtk/themes/engines");
302 module_path[n++] = g_strdup(path);
304 var = getenv("HOME");
307 path = g_malloc(strlen(var) + strlen(".gtk/lib/themes/engines") +1);
308 sprintf(path, "%s%s", var, ".gtk/lib/themes/engines");
310 module_path[n++] = g_strdup(path);
311 module_path[n] = NULL;
316 gtk_rc_add_initial_default_files (void)
318 static gint init = FALSE;
326 gtk_rc_default_files[0] = NULL;
329 var = getenv("GTK_RC_FILES");
332 files = g_strsplit (var, ":", 128);
336 gtk_rc_add_default_file (files[i]);
343 str = g_malloc (strlen(GTK_SYSCONFDIR) + strlen("/gtk/gtkrc") + 1);
344 sprintf (str, "%s%s", GTK_SYSCONFDIR, "/gtk/gtkrc");
345 gtk_rc_add_default_file (str);
347 var = g_get_home_dir ();
348 str = g_malloc (strlen(var) + strlen("/.gtkrc") + 1);
349 sprintf (str, "%s%s", var, "/.gtkrc");
350 gtk_rc_add_default_file (str);
355 gtk_rc_add_default_file (const gchar *file)
359 gtk_rc_add_initial_default_files ();
361 for (n = 0; gtk_rc_default_files[n]; n++) ;
362 if (n >= GTK_RC_MAX_DEFAULT_FILES - 1)
365 gtk_rc_default_files[n++] = g_strdup (file);
366 gtk_rc_default_files[n] = NULL;
370 gtk_rc_set_default_files (gchar **files)
374 gtk_rc_add_initial_default_files ();
377 while (gtk_rc_default_files[i])
379 g_free (gtk_rc_default_files[i]);
383 gtk_rc_default_files[0] = NULL;
384 gtk_rc_auto_parse = FALSE;
387 while (files[i] != NULL)
389 gtk_rc_add_default_file (files[i]);
395 gtk_rc_get_default_files (void)
397 gtk_rc_add_initial_default_files ();
399 return gtk_rc_default_files;
405 gchar *locale_suffixes[3];
406 gint n_locale_suffixes = 0;
408 char *locale = setlocale (LC_MESSAGES, NULL);
412 rc_style_ht = g_hash_table_new ((GHashFunc) gtk_rc_style_hash,
413 (GCompareFunc) gtk_rc_style_compare);
414 pixmap_path[0] = NULL;
415 module_path[0] = NULL;
416 gtk_rc_append_default_pixmap_path();
417 gtk_rc_append_default_module_path();
419 gtk_rc_add_initial_default_files ();
421 if (strcmp (locale, "C") && strcmp (locale, "POSIX"))
423 /* Determine locale-specific suffixes for RC files
425 p = strchr (locale, '@');
426 length = p ? (p -locale) : strlen (locale);
428 p = strchr (locale, '.');
431 locale_suffixes[n_locale_suffixes++] = g_strndup (locale, length);
435 p = strchr (locale, '_');
438 locale_suffixes[n_locale_suffixes++] = g_strndup (locale, length);
442 locale_suffixes[n_locale_suffixes++] = g_strndup (locale, length);
446 while (gtk_rc_default_files[i] != NULL)
448 /* Try to find a locale specific RC file corresponding to
449 * to parse before the default file.
451 for (j=n_locale_suffixes-1; j>=0; j--)
453 gchar *name = g_strconcat (gtk_rc_default_files[i],
461 gtk_rc_parse (gtk_rc_default_files[i]);
467 gtk_rc_parse_string (const gchar *rc_string)
469 g_return_if_fail (rc_string != NULL);
471 gtk_rc_parse_any ("-", -1, rc_string);
475 gtk_rc_parse_file (const gchar *filename, gboolean reload)
477 GtkRcFile *rc_file = NULL;
481 g_return_if_fail (filename != NULL);
486 rc_file = tmp_list->data;
487 if (!strcmp (rc_file->name, filename))
490 tmp_list = tmp_list->next;
495 rc_file = g_new (GtkRcFile, 1);
496 rc_file->name = g_strdup (filename);
497 rc_file->canonical_name = NULL;
499 rc_file->reload = reload;
501 rc_files = g_slist_append (rc_files, rc_file);
504 if (!rc_file->canonical_name)
506 /* Get the absolute pathname */
508 if (rc_file->name[0] == '/')
509 rc_file->canonical_name = rc_file->name;
515 cwd = g_get_current_dir ();
517 str = g_string_new (cwd);
519 g_string_append_c (str, '/');
520 g_string_append (str, rc_file->name);
522 rc_file->canonical_name = str->str;
523 g_string_free (str, FALSE);
527 if (!lstat (rc_file->canonical_name, &statbuf))
531 rc_file->mtime = statbuf.st_mtime;
533 fd = open (rc_file->canonical_name, O_RDONLY);
541 dir = g_strdup(rc_file->canonical_name);
542 for (i = strlen(dir) - 1; (i >= 0) && (dir[i] != '/'); i--)
544 gtk_rc_append_pixmap_path(dir);
547 gtk_rc_parse_any (filename, fd, NULL);
554 gtk_rc_parse (const gchar *filename)
556 g_return_if_fail (filename != NULL);
558 gtk_rc_parse_file (filename, TRUE);
561 /* Handling of RC styles */
564 gtk_rc_style_new (void)
566 GtkRcStyle *new_style;
568 new_style = g_new0 (GtkRcStyle, 1);
569 new_style->ref_count = 1;
575 gtk_rc_style_ref (GtkRcStyle *rc_style)
577 g_return_if_fail (rc_style != NULL);
579 rc_style->ref_count++;
583 gtk_rc_style_unref (GtkRcStyle *rc_style)
587 g_return_if_fail (rc_style != NULL);
589 rc_style->ref_count--;
591 if (rc_style->ref_count == 0)
593 if (rc_style->engine)
595 rc_style->engine->destroy_rc_style (rc_style);
596 gtk_theme_engine_unref (rc_style->engine);
600 g_free (rc_style->name);
601 if (rc_style->fontset_name)
602 g_free (rc_style->fontset_name);
603 if (rc_style->font_name)
604 g_free (rc_style->font_name);
606 for (i=0 ; i<5 ; i++)
607 if (rc_style->bg_pixmap_name[i])
608 g_free (rc_style->bg_pixmap_name[i]);
615 gtk_rc_clear_realized_node (gpointer key,
619 gtk_style_unref (data);
623 gtk_rc_clear_hash_node (gpointer key,
627 gtk_rc_style_unref (data);
631 gtk_rc_free_rc_sets (GSList *slist)
637 rc_set = slist->data;
638 gtk_pattern_spec_free_segs (&rc_set->pspec);
646 gtk_rc_clear_styles (void)
648 /* Clear out all old rc_styles */
652 g_hash_table_foreach (rc_style_ht, gtk_rc_clear_hash_node, NULL);
653 g_hash_table_destroy (rc_style_ht);
657 if (realized_style_ht)
659 g_hash_table_foreach (realized_style_ht, gtk_rc_clear_realized_node, NULL);
660 g_hash_table_destroy (realized_style_ht);
661 realized_style_ht = NULL;
664 gtk_rc_free_rc_sets (gtk_rc_sets_widget);
665 g_slist_free (gtk_rc_sets_widget);
666 gtk_rc_sets_widget = NULL;
668 gtk_rc_free_rc_sets (gtk_rc_sets_widget_class);
669 g_slist_free (gtk_rc_sets_widget_class);
670 gtk_rc_sets_widget_class = NULL;
672 gtk_rc_free_rc_sets (gtk_rc_sets_class);
673 g_slist_free (gtk_rc_sets_class);
674 gtk_rc_sets_class = NULL;
680 gtk_rc_reparse_all (void)
683 gboolean mtime_modified = FALSE;
688 /* Check through and see if any of the RC's have had their
689 * mtime modified. If so, reparse everything.
694 rc_file = tmp_list->data;
696 if (!lstat (rc_file->name, &statbuf) &&
697 (statbuf.st_mtime > rc_file->mtime))
699 mtime_modified = TRUE;
703 tmp_list = tmp_list->next;
708 gtk_rc_clear_styles();
713 rc_file = tmp_list->data;
715 gtk_rc_parse_file (rc_file->name, FALSE);
717 tmp_list = tmp_list->next;
721 return mtime_modified;
725 gtk_rc_styles_match (GSList *rc_styles,
729 gchar *path_reversed)
739 if (gtk_pattern_match (&rc_set->pspec, path_length, path, path_reversed))
740 rc_styles = g_slist_append (rc_styles, rc_set->rc_style);
747 gtk_rc_get_style (GtkWidget *widget)
749 GtkRcStyle *widget_rc_style;
750 GSList *rc_styles = NULL;
752 static guint rc_style_key_id = 0;
754 /* We allow the specification of a single rc style to be bound
755 * tightly to a widget, for application modifications
757 if (!rc_style_key_id)
758 rc_style_key_id = g_quark_from_static_string ("gtk-rc-style");
760 widget_rc_style = gtk_object_get_data_by_id (GTK_OBJECT (widget),
764 rc_styles = g_slist_prepend (rc_styles, widget_rc_style);
766 if (gtk_rc_sets_widget)
768 gchar *path, *path_reversed;
771 gtk_widget_path (widget, &path_length, &path, &path_reversed);
772 rc_styles = gtk_rc_styles_match (rc_styles, gtk_rc_sets_widget, path_length, path, path_reversed);
774 g_free (path_reversed);
778 if (gtk_rc_sets_widget_class)
780 gchar *path, *path_reversed;
783 gtk_widget_class_path (widget, &path_length, &path, &path_reversed);
784 rc_styles = gtk_rc_styles_match (rc_styles, gtk_rc_sets_widget_class, path_length, path, path_reversed);
786 g_free (path_reversed);
789 if (gtk_rc_sets_class)
793 type = GTK_OBJECT_TYPE (widget);
796 gchar *path, *path_reversed;
799 path = gtk_type_name (type);
800 path_length = strlen (path);
801 path_reversed = g_strdup (path);
802 g_strreverse (path_reversed);
804 rc_styles = gtk_rc_styles_match (rc_styles, gtk_rc_sets_class, path_length, path, path_reversed);
805 g_free (path_reversed);
807 type = gtk_type_parent (type);
812 return gtk_rc_style_init (rc_styles);
818 gtk_rc_add_rc_sets (GSList *slist,
819 GtkRcStyle *rc_style,
822 GtkRcStyle *new_style;
826 new_style = gtk_rc_style_new ();
827 *new_style = *rc_style;
828 new_style->name = g_strdup (rc_style->name);
829 new_style->font_name = g_strdup (rc_style->font_name);
830 new_style->fontset_name = g_strdup (rc_style->fontset_name);
832 for (i = 0; i < 5; i++)
833 new_style->bg_pixmap_name[i] = g_strdup (rc_style->bg_pixmap_name[i]);
835 rc_set = g_new (GtkRcSet, 1);
836 gtk_pattern_spec_init (&rc_set->pspec, pattern);
837 rc_set->rc_style = rc_style;
839 return g_slist_prepend (slist, rc_set);
843 gtk_rc_add_widget_name_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_widget = gtk_rc_add_rc_sets (gtk_rc_sets_widget, rc_style, pattern);
853 gtk_rc_add_widget_class_style (GtkRcStyle *rc_style,
854 const gchar *pattern)
856 g_return_if_fail (rc_style != NULL);
857 g_return_if_fail (pattern != NULL);
859 gtk_rc_sets_widget_class = gtk_rc_add_rc_sets (gtk_rc_sets_widget_class, rc_style, pattern);
863 gtk_rc_add_class_style (GtkRcStyle *rc_style,
864 const gchar *pattern)
866 g_return_if_fail (rc_style != NULL);
867 g_return_if_fail (pattern != NULL);
869 gtk_rc_sets_class = gtk_rc_add_rc_sets (gtk_rc_sets_class, rc_style, pattern);
873 gtk_rc_parse_any (const gchar *input_name,
875 const gchar *input_string)
881 scanner = g_scanner_new (>k_rc_scanner_config);
885 g_assert (input_string == NULL);
887 g_scanner_input_file (scanner, input_fd);
891 g_assert (input_string != NULL);
893 g_scanner_input_text (scanner, input_string, strlen (input_string));
895 scanner->input_name = input_name;
897 g_scanner_freeze_symbol_table (scanner);
898 for (i = 0; i < n_symbols; i++)
899 g_scanner_add_symbol (scanner, symbols[i].name, GINT_TO_POINTER (symbols[i].token));
900 g_scanner_thaw_symbol_table (scanner);
905 if (g_scanner_peek_next_token (scanner) == G_TOKEN_EOF)
909 guint expected_token;
911 expected_token = gtk_rc_parse_statement (scanner);
913 if (expected_token != G_TOKEN_NONE)
920 if (scanner->scope_id == 0)
922 /* if we are in scope 0, we know the symbol names
923 * that are associated with certaintoken values.
924 * so we look them up to make the error messages
927 if (expected_token > GTK_RC_TOKEN_INVALID &&
928 expected_token < GTK_RC_TOKEN_LAST)
930 for (i = 0; i < n_symbols; i++)
931 if (symbols[i].token == expected_token)
932 msg = symbols[i].name;
934 msg = g_strconcat ("e.g. `", msg, "'", NULL);
936 if (scanner->token > GTK_RC_TOKEN_INVALID &&
937 scanner->token < GTK_RC_TOKEN_LAST)
940 for (i = 0; i < n_symbols; i++)
941 if (symbols[i].token == scanner->token)
942 symbol_name = symbols[i].name;
945 g_scanner_unexp_token (scanner,
958 g_scanner_destroy (scanner);
962 gtk_rc_styles_hash (const GSList *rc_styles)
969 result += (result << 9) + GPOINTER_TO_UINT (rc_styles->data);
970 rc_styles = rc_styles->next;
977 gtk_rc_styles_compare (const GSList *a,
982 if (a->data != b->data)
992 gtk_rc_style_hash (const char *name)
998 result += (result << 3) + *name++;
1004 gtk_rc_style_compare (const char *a,
1007 return (strcmp (a, b) == 0);
1011 gtk_rc_style_find (const char *name)
1013 GtkRcStyle *rc_style;
1015 rc_style = g_hash_table_lookup (rc_style_ht, (gpointer) name);
1020 /* Assumes ownership of rc_style */
1022 gtk_rc_style_to_style (GtkRcStyle *rc_style)
1028 style = gtk_style_new ();
1030 style->rc_style = rc_style;
1032 if (rc_style->fontset_name)
1034 old_font = style->font;
1035 style->font = gdk_fontset_load (rc_style->fontset_name);
1037 gdk_font_unref (old_font);
1039 style->font = old_font;
1041 else if (rc_style->font_name)
1043 old_font = style->font;
1044 style->font = gdk_font_load (rc_style->font_name);
1046 gdk_font_unref (old_font);
1048 style->font = old_font;
1051 for (i = 0; i < 5; i++)
1053 if (rc_style->color_flags[i] & GTK_RC_FG)
1054 style->fg[i] = rc_style->fg[i];
1055 if (rc_style->color_flags[i] & GTK_RC_BG)
1056 style->bg[i] = rc_style->bg[i];
1057 if (rc_style->color_flags[i] & GTK_RC_TEXT)
1058 style->text[i] = rc_style->text[i];
1059 if (rc_style->color_flags[i] & GTK_RC_BASE)
1060 style->base[i] = rc_style->base[i];
1063 if (rc_style->engine)
1065 style->engine = rc_style->engine;
1066 gtk_theme_engine_ref (style->engine);
1067 rc_style->engine->rc_style_to_style (style, rc_style);
1073 /* Reuses or frees rc_styles */
1075 gtk_rc_style_init (GSList *rc_styles)
1079 GtkStyle *style = NULL;
1080 GtkRcStyle *proto_style;
1082 if (!realized_style_ht)
1083 realized_style_ht = g_hash_table_new ((GHashFunc)gtk_rc_styles_hash,
1084 (GCompareFunc)gtk_rc_styles_compare);
1086 style = g_hash_table_lookup (realized_style_ht, rc_styles);
1090 GSList *tmp_styles = rc_styles;
1092 proto_style = gtk_rc_style_new ();
1096 GtkRcStyle *rc_style = tmp_styles->data;
1100 if (!proto_style->bg_pixmap_name[i] && rc_style->bg_pixmap_name[i])
1101 proto_style->bg_pixmap_name[i] = g_strdup (rc_style->bg_pixmap_name[i]);
1103 if (!(proto_style->color_flags[i] & GTK_RC_FG) &&
1104 rc_style->color_flags[i] & GTK_RC_FG)
1106 proto_style->fg[i] = rc_style->fg[i];
1107 proto_style->color_flags[i] |= GTK_RC_FG;
1109 if (!(proto_style->color_flags[i] & GTK_RC_BG) &&
1110 rc_style->color_flags[i] & GTK_RC_BG)
1112 proto_style->bg[i] = rc_style->bg[i];
1113 proto_style->color_flags[i] |= GTK_RC_BG;
1115 if (!(proto_style->color_flags[i] & GTK_RC_TEXT) &&
1116 rc_style->color_flags[i] & GTK_RC_TEXT)
1118 proto_style->text[i] = rc_style->text[i];
1119 proto_style->color_flags[i] |= GTK_RC_TEXT;
1121 if (!(proto_style->color_flags[i] & GTK_RC_BASE) &&
1122 rc_style->color_flags[i] & GTK_RC_BASE)
1124 proto_style->base[i] = rc_style->base[i];
1125 proto_style->color_flags[i] |= GTK_RC_BASE;
1129 if (!proto_style->font_name && rc_style->font_name)
1130 proto_style->font_name = g_strdup (rc_style->font_name);
1131 if (!proto_style->fontset_name && rc_style->fontset_name)
1132 proto_style->fontset_name = g_strdup (rc_style->fontset_name);
1134 if (!proto_style->engine && rc_style->engine)
1136 proto_style->engine = rc_style->engine;
1137 gtk_theme_engine_ref (proto_style->engine);
1140 if (proto_style->engine &&
1141 (proto_style->engine == rc_style->engine))
1142 proto_style->engine->merge_rc_style (proto_style, rc_style);
1144 tmp_styles = tmp_styles->next;
1147 style = gtk_rc_style_to_style (proto_style);
1149 g_hash_table_insert (realized_style_ht, rc_styles, style);
1155 /*********************
1156 * Parsing functions *
1157 *********************/
1160 gtk_rc_parse_statement (GScanner *scanner)
1164 token = g_scanner_peek_next_token (scanner);
1168 case GTK_RC_TOKEN_INCLUDE:
1169 token = g_scanner_get_next_token (scanner);
1170 if (token != GTK_RC_TOKEN_INCLUDE)
1171 return GTK_RC_TOKEN_INCLUDE;
1173 token = g_scanner_get_next_token (scanner);
1174 if (token != G_TOKEN_STRING)
1175 return G_TOKEN_STRING;
1177 gtk_rc_parse_file (scanner->value.v_string, FALSE);
1178 return G_TOKEN_NONE;
1180 case GTK_RC_TOKEN_STYLE:
1181 return gtk_rc_parse_style (scanner);
1183 case GTK_RC_TOKEN_BINDING:
1184 return gtk_binding_parse_binding (scanner);
1186 case GTK_RC_TOKEN_PIXMAP_PATH:
1187 return gtk_rc_parse_pixmap_path (scanner);
1189 case GTK_RC_TOKEN_WIDGET:
1190 return gtk_rc_parse_path_pattern (scanner);
1192 case GTK_RC_TOKEN_WIDGET_CLASS:
1193 return gtk_rc_parse_path_pattern (scanner);
1195 case GTK_RC_TOKEN_CLASS:
1196 return gtk_rc_parse_path_pattern (scanner);
1198 case GTK_RC_TOKEN_MODULE_PATH:
1199 return gtk_rc_parse_module_path (scanner);
1202 g_scanner_get_next_token (scanner);
1203 return /* G_TOKEN_SYMBOL */ GTK_RC_TOKEN_STYLE;
1208 gtk_rc_parse_style (GScanner *scanner)
1210 GtkRcStyle *rc_style;
1211 GtkRcStyle *parent_style;
1216 token = g_scanner_get_next_token (scanner);
1217 if (token != GTK_RC_TOKEN_STYLE)
1218 return GTK_RC_TOKEN_STYLE;
1220 token = g_scanner_get_next_token (scanner);
1221 if (token != G_TOKEN_STRING)
1222 return G_TOKEN_STRING;
1225 rc_style = g_hash_table_lookup (rc_style_ht, scanner->value.v_string);
1230 rc_style = gtk_rc_style_new ();
1231 rc_style->name = g_strdup (scanner->value.v_string);
1233 for (i = 0; i < 5; i++)
1234 rc_style->bg_pixmap_name[i] = NULL;
1236 for (i = 0; i < 5; i++)
1237 rc_style->color_flags[i] = 0;
1239 rc_style->engine = NULL;
1240 rc_style->engine_data = NULL;
1243 token = g_scanner_peek_next_token (scanner);
1244 if (token == G_TOKEN_EQUAL_SIGN)
1246 token = g_scanner_get_next_token (scanner);
1248 token = g_scanner_get_next_token (scanner);
1249 if (token != G_TOKEN_STRING)
1254 return G_TOKEN_STRING;
1257 parent_style = g_hash_table_lookup (rc_style_ht, scanner->value.v_string);
1260 for (i = 0; i < 5; i++)
1262 rc_style->color_flags[i] = parent_style->color_flags[i];
1263 rc_style->fg[i] = parent_style->fg[i];
1264 rc_style->bg[i] = parent_style->bg[i];
1265 rc_style->text[i] = parent_style->text[i];
1266 rc_style->base[i] = parent_style->base[i];
1269 if (parent_style->fontset_name)
1271 if (rc_style->fontset_name)
1272 g_free (rc_style->fontset_name);
1273 rc_style->fontset_name = g_strdup (parent_style->fontset_name);
1275 else if (parent_style->font_name)
1277 if (rc_style->font_name)
1278 g_free (rc_style->font_name);
1279 rc_style->font_name = g_strdup (parent_style->font_name);
1282 for (i = 0; i < 5; i++)
1284 if (rc_style->bg_pixmap_name[i])
1285 g_free (rc_style->bg_pixmap_name[i]);
1286 rc_style->bg_pixmap_name[i] = g_strdup (parent_style->bg_pixmap_name[i]);
1291 token = g_scanner_get_next_token (scanner);
1292 if (token != G_TOKEN_LEFT_CURLY)
1297 return G_TOKEN_LEFT_CURLY;
1300 token = g_scanner_peek_next_token (scanner);
1301 while (token != G_TOKEN_RIGHT_CURLY)
1305 case GTK_RC_TOKEN_BASE:
1306 token = gtk_rc_parse_base (scanner, rc_style);
1308 case GTK_RC_TOKEN_BG:
1309 token = gtk_rc_parse_bg (scanner, rc_style);
1311 case GTK_RC_TOKEN_FG:
1312 token = gtk_rc_parse_fg (scanner, rc_style);
1314 case GTK_RC_TOKEN_TEXT:
1315 token = gtk_rc_parse_text (scanner, rc_style);
1317 case GTK_RC_TOKEN_BG_PIXMAP:
1318 token = gtk_rc_parse_bg_pixmap (scanner, rc_style);
1320 case GTK_RC_TOKEN_FONT:
1321 token = gtk_rc_parse_font (scanner, rc_style);
1323 case GTK_RC_TOKEN_FONTSET:
1324 token = gtk_rc_parse_fontset (scanner, rc_style);
1326 case GTK_RC_TOKEN_ENGINE:
1327 token = gtk_rc_parse_engine (scanner, rc_style);
1330 g_scanner_get_next_token (scanner);
1331 token = G_TOKEN_RIGHT_CURLY;
1335 if (token != G_TOKEN_NONE)
1339 if (rc_style->fontset_name)
1340 g_free (rc_style->fontset_name);
1341 if (rc_style->font_name)
1342 g_free (rc_style->font_name);
1343 for (i = 0; i < 5; i++)
1344 if (rc_style->bg_pixmap_name[i])
1345 g_free (rc_style->bg_pixmap_name[i]);
1350 token = g_scanner_peek_next_token (scanner);
1353 token = g_scanner_get_next_token (scanner);
1354 if (token != G_TOKEN_RIGHT_CURLY)
1358 if (rc_style->fontset_name)
1359 g_free (rc_style->fontset_name);
1360 if (rc_style->font_name)
1361 g_free (rc_style->font_name);
1363 for (i = 0; i < 5; i++)
1364 if (rc_style->bg_pixmap_name[i])
1365 g_free (rc_style->bg_pixmap_name[i]);
1369 return G_TOKEN_RIGHT_CURLY;
1373 g_hash_table_insert (rc_style_ht, rc_style->name, rc_style);
1375 return G_TOKEN_NONE;
1379 gtk_rc_parse_base (GScanner *scanner,
1385 token = g_scanner_get_next_token (scanner);
1386 if (token != GTK_RC_TOKEN_BASE)
1387 return GTK_RC_TOKEN_BASE;
1389 token = gtk_rc_parse_state (scanner, &state);
1390 if (token != G_TOKEN_NONE)
1393 token = g_scanner_get_next_token (scanner);
1394 if (token != G_TOKEN_EQUAL_SIGN)
1395 return G_TOKEN_EQUAL_SIGN;
1397 style->color_flags[state] |= GTK_RC_BASE;
1398 return gtk_rc_parse_color (scanner, &style->base[state]);
1402 gtk_rc_parse_bg (GScanner *scanner,
1408 token = g_scanner_get_next_token (scanner);
1409 if (token != GTK_RC_TOKEN_BG)
1410 return GTK_RC_TOKEN_BG;
1412 token = gtk_rc_parse_state (scanner, &state);
1413 if (token != G_TOKEN_NONE)
1416 token = g_scanner_get_next_token (scanner);
1417 if (token != G_TOKEN_EQUAL_SIGN)
1418 return G_TOKEN_EQUAL_SIGN;
1420 style->color_flags[state] |= GTK_RC_BG;
1421 return gtk_rc_parse_color (scanner, &style->bg[state]);
1425 gtk_rc_parse_fg (GScanner *scanner,
1431 token = g_scanner_get_next_token (scanner);
1432 if (token != GTK_RC_TOKEN_FG)
1433 return GTK_RC_TOKEN_FG;
1435 token = gtk_rc_parse_state (scanner, &state);
1436 if (token != G_TOKEN_NONE)
1439 token = g_scanner_get_next_token (scanner);
1440 if (token != G_TOKEN_EQUAL_SIGN)
1441 return G_TOKEN_EQUAL_SIGN;
1443 style->color_flags[state] |= GTK_RC_FG;
1444 return gtk_rc_parse_color (scanner, &style->fg[state]);
1448 gtk_rc_parse_text (GScanner *scanner,
1454 token = g_scanner_get_next_token (scanner);
1455 if (token != GTK_RC_TOKEN_TEXT)
1456 return GTK_RC_TOKEN_TEXT;
1458 token = gtk_rc_parse_state (scanner, &state);
1459 if (token != G_TOKEN_NONE)
1462 token = g_scanner_get_next_token (scanner);
1463 if (token != G_TOKEN_EQUAL_SIGN)
1464 return G_TOKEN_EQUAL_SIGN;
1466 style->color_flags[state] |= GTK_RC_TEXT;
1467 return gtk_rc_parse_color (scanner, &style->text[state]);
1471 gtk_rc_parse_bg_pixmap (GScanner *scanner,
1472 GtkRcStyle *rc_style)
1478 token = g_scanner_get_next_token (scanner);
1479 if (token != GTK_RC_TOKEN_BG_PIXMAP)
1480 return GTK_RC_TOKEN_BG_PIXMAP;
1482 token = gtk_rc_parse_state (scanner, &state);
1483 if (token != G_TOKEN_NONE)
1486 token = g_scanner_get_next_token (scanner);
1487 if (token != G_TOKEN_EQUAL_SIGN)
1488 return G_TOKEN_EQUAL_SIGN;
1490 token = g_scanner_get_next_token (scanner);
1491 if (token != G_TOKEN_STRING)
1492 return G_TOKEN_STRING;
1494 if (strcmp (scanner->value.v_string, "<parent>"))
1495 pixmap_file = gtk_rc_find_pixmap_in_path (scanner, scanner->value.v_string);
1497 pixmap_file = g_strdup (scanner->value.v_string);
1501 if (rc_style->bg_pixmap_name[state])
1502 g_free (rc_style->bg_pixmap_name[state]);
1503 rc_style->bg_pixmap_name[state] = pixmap_file;
1506 return G_TOKEN_NONE;
1510 gtk_rc_find_pixmap_in_path (GScanner *scanner,
1511 const gchar *pixmap_file)
1517 for (i = 0; (i < GTK_RC_MAX_PIXMAP_PATHS) && (pixmap_path[i] != NULL); i++)
1519 buf = g_malloc (strlen (pixmap_path[i]) + strlen (pixmap_file) + 2);
1520 sprintf (buf, "%s%c%s", pixmap_path[i], '/', pixmap_file);
1522 fd = open (buf, O_RDONLY);
1533 g_warning (_("Unable to locate image file in pixmap_path: \"%s\" line %d"),
1534 pixmap_file, scanner->line);
1536 g_warning (_("Unable to locate image file in pixmap_path: \"%s\""),
1543 gtk_rc_find_module_in_path (const gchar *module_file)
1549 for (i = 0; (i < GTK_RC_MAX_MODULE_PATHS) && (module_path[i] != NULL); i++)
1551 buf = g_malloc (strlen (module_path[i]) + strlen (module_file) + 2);
1552 sprintf (buf, "%s%c%s", module_path[i], '/', module_file);
1554 fd = open (buf, O_RDONLY);
1568 gtk_rc_parse_font (GScanner *scanner,
1569 GtkRcStyle *rc_style)
1573 token = g_scanner_get_next_token (scanner);
1574 if (token != GTK_RC_TOKEN_FONT)
1575 return GTK_RC_TOKEN_FONT;
1577 token = g_scanner_get_next_token (scanner);
1578 if (token != G_TOKEN_EQUAL_SIGN)
1579 return G_TOKEN_EQUAL_SIGN;
1581 token = g_scanner_get_next_token (scanner);
1582 if (token != G_TOKEN_STRING)
1583 return G_TOKEN_STRING;
1585 if (rc_style->font_name)
1586 g_free (rc_style->font_name);
1587 rc_style->font_name = g_strdup (scanner->value.v_string);
1589 return G_TOKEN_NONE;
1593 gtk_rc_parse_fontset (GScanner *scanner,
1594 GtkRcStyle *rc_style)
1598 token = g_scanner_get_next_token (scanner);
1599 if (token != GTK_RC_TOKEN_FONTSET)
1600 return GTK_RC_TOKEN_FONTSET;
1602 token = g_scanner_get_next_token (scanner);
1603 if (token != G_TOKEN_EQUAL_SIGN)
1604 return G_TOKEN_EQUAL_SIGN;
1606 token = g_scanner_get_next_token (scanner);
1607 if (token != G_TOKEN_STRING)
1608 return G_TOKEN_STRING;
1610 if (rc_style->fontset_name)
1611 g_free (rc_style->fontset_name);
1612 rc_style->fontset_name = g_strdup (scanner->value.v_string);
1614 return G_TOKEN_NONE;
1618 gtk_rc_parse_engine (GScanner *scanner,
1619 GtkRcStyle *rc_style)
1623 token = g_scanner_get_next_token (scanner);
1624 if (token != GTK_RC_TOKEN_ENGINE)
1625 return GTK_RC_TOKEN_ENGINE;
1627 token = g_scanner_get_next_token (scanner);
1628 if (token != G_TOKEN_STRING)
1629 return G_TOKEN_STRING;
1631 rc_style->engine = gtk_theme_engine_get (scanner->value.v_string);
1633 token = g_scanner_get_next_token (scanner);
1634 if (token != G_TOKEN_LEFT_CURLY)
1635 return G_TOKEN_LEFT_CURLY;
1637 if (rc_style->engine)
1638 return rc_style->engine->parse_rc_style (scanner, rc_style);
1641 /* Skip over remainder, looking for nested {}'s */
1644 while ((token = g_scanner_get_next_token (scanner)) != G_TOKEN_EOF)
1646 if (token == G_TOKEN_LEFT_CURLY)
1648 else if (token == G_TOKEN_RIGHT_CURLY)
1652 return G_TOKEN_NONE;
1655 return G_TOKEN_RIGHT_CURLY;
1660 gtk_rc_parse_state (GScanner *scanner,
1661 GtkStateType *state)
1666 g_return_val_if_fail (scanner != NULL, G_TOKEN_ERROR);
1667 g_return_val_if_fail (state != NULL, G_TOKEN_ERROR);
1669 /* we don't know where we got called from, so we reset the scope here.
1670 * if we bail out due to errors, we *don't* reset the scope, so the
1671 * error messaging code can make sense of our tokens.
1673 old_scope = g_scanner_set_scope (scanner, 0);
1675 token = g_scanner_get_next_token (scanner);
1676 if (token != G_TOKEN_LEFT_BRACE)
1677 return G_TOKEN_LEFT_BRACE;
1679 token = g_scanner_get_next_token (scanner);
1682 case GTK_RC_TOKEN_ACTIVE:
1683 *state = GTK_STATE_ACTIVE;
1685 case GTK_RC_TOKEN_INSENSITIVE:
1686 *state = GTK_STATE_INSENSITIVE;
1688 case GTK_RC_TOKEN_NORMAL:
1689 *state = GTK_STATE_NORMAL;
1691 case GTK_RC_TOKEN_PRELIGHT:
1692 *state = GTK_STATE_PRELIGHT;
1694 case GTK_RC_TOKEN_SELECTED:
1695 *state = GTK_STATE_SELECTED;
1698 return /* G_TOKEN_SYMBOL */ GTK_RC_TOKEN_NORMAL;
1701 token = g_scanner_get_next_token (scanner);
1702 if (token != G_TOKEN_RIGHT_BRACE)
1703 return G_TOKEN_RIGHT_BRACE;
1705 g_scanner_set_scope (scanner, old_scope);
1707 return G_TOKEN_NONE;
1711 gtk_rc_parse_priority (GScanner *scanner,
1712 GtkPathPriorityType *priority)
1717 g_return_val_if_fail (scanner != NULL, G_TOKEN_ERROR);
1718 g_return_val_if_fail (priority != NULL, G_TOKEN_ERROR);
1720 /* we don't know where we got called from, so we reset the scope here.
1721 * if we bail out due to errors, we *don't* reset the scope, so the
1722 * error messaging code can make sense of our tokens.
1724 old_scope = g_scanner_set_scope (scanner, 0);
1726 token = g_scanner_get_next_token (scanner);
1730 token = g_scanner_get_next_token (scanner);
1733 case GTK_RC_TOKEN_LOWEST:
1734 *priority = GTK_PATH_PRIO_LOWEST;
1736 case GTK_RC_TOKEN_GTK:
1737 *priority = GTK_PATH_PRIO_GTK;
1739 case GTK_RC_TOKEN_APPLICATION:
1740 *priority = GTK_PATH_PRIO_APPLICATION;
1742 case GTK_RC_TOKEN_RC:
1743 *priority = GTK_PATH_PRIO_RC;
1745 case GTK_RC_TOKEN_HIGHEST:
1746 *priority = GTK_PATH_PRIO_HIGHEST;
1749 return /* G_TOKEN_SYMBOL */ GTK_RC_TOKEN_APPLICATION;
1752 g_scanner_set_scope (scanner, old_scope);
1754 return G_TOKEN_NONE;
1758 gtk_rc_parse_color (GScanner *scanner,
1763 g_return_val_if_fail (scanner != NULL, G_TOKEN_ERROR);
1765 /* we don't need to set our own scop here, because
1766 * we don't need own symbols
1769 token = g_scanner_get_next_token (scanner);
1778 case G_TOKEN_LEFT_CURLY:
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->red = 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->green = CLAMP (token_int, 0, 65535);
1801 token = g_scanner_get_next_token (scanner);
1802 if (token != G_TOKEN_COMMA)
1803 return G_TOKEN_COMMA;
1805 token = g_scanner_get_next_token (scanner);
1806 if (token == G_TOKEN_INT)
1807 token_int = scanner->value.v_int;
1808 else if (token == G_TOKEN_FLOAT)
1809 token_int = scanner->value.v_float * 65535.0;
1811 return G_TOKEN_FLOAT;
1812 color->blue = CLAMP (token_int, 0, 65535);
1814 token = g_scanner_get_next_token (scanner);
1815 if (token != G_TOKEN_RIGHT_CURLY)
1816 return G_TOKEN_RIGHT_CURLY;
1817 return G_TOKEN_NONE;
1819 case G_TOKEN_STRING:
1820 if (scanner->value.v_string[0] != '#')
1821 return G_TOKEN_STRING;
1823 length = strlen (scanner->value.v_string) - 1;
1824 if (((length % 3) != 0) || (length > 12))
1825 return G_TOKEN_STRING;
1828 for (i = 0, j = 1; i < length; i++, j++)
1829 buf[i] = scanner->value.v_string[j];
1832 sscanf (buf, "%x", &temp);
1835 for (i = 0; i < length; i++, j++)
1836 buf[i] = scanner->value.v_string[j];
1839 sscanf (buf, "%x", &temp);
1840 color->green = temp;
1842 for (i = 0; i < length; i++, j++)
1843 buf[i] = scanner->value.v_string[j];
1846 sscanf (buf, "%x", &temp);
1852 color->green *= 4369;
1853 color->blue *= 4369;
1855 else if (length == 2)
1858 color->green *= 257;
1861 else if (length == 3)
1867 return G_TOKEN_NONE;
1870 return G_TOKEN_STRING;
1875 gtk_rc_parse_pixmap_path (GScanner *scanner)
1879 token = g_scanner_get_next_token (scanner);
1880 if (token != GTK_RC_TOKEN_PIXMAP_PATH)
1881 return GTK_RC_TOKEN_PIXMAP_PATH;
1883 token = g_scanner_get_next_token (scanner);
1884 if (token != G_TOKEN_STRING)
1885 return G_TOKEN_STRING;
1887 gtk_rc_parse_pixmap_path_string (scanner->value.v_string);
1889 return G_TOKEN_NONE;
1893 gtk_rc_parse_pixmap_path_string (gchar *pix_path)
1897 gint start_offset = 0;
1901 /* free the old one, or just add to the old one ? */
1902 for (path_num=0; pixmap_path[path_num]; path_num++)
1904 g_free (pixmap_path[path_num]);
1905 pixmap_path[path_num] = NULL;
1910 path_len = strlen (pix_path);
1912 buf = g_strdup (pix_path);
1914 for (end_offset = 0; end_offset <= path_len; end_offset++)
1916 if ((buf[end_offset] == ':') ||
1917 (end_offset == path_len))
1919 buf[end_offset] = '\0';
1920 pixmap_path[path_num] = g_strdup (buf + start_offset);
1922 pixmap_path[path_num] = NULL;
1923 start_offset = end_offset + 1;
1927 gtk_rc_append_default_pixmap_path();
1931 gtk_rc_parse_module_path (GScanner *scanner)
1935 token = g_scanner_get_next_token (scanner);
1936 if (token != GTK_RC_TOKEN_MODULE_PATH)
1937 return GTK_RC_TOKEN_MODULE_PATH;
1939 token = g_scanner_get_next_token (scanner);
1940 if (token != G_TOKEN_STRING)
1941 return G_TOKEN_STRING;
1943 gtk_rc_parse_module_path_string (scanner->value.v_string);
1945 return G_TOKEN_NONE;
1949 gtk_rc_parse_module_path_string (gchar *mod_path)
1953 gint start_offset = 0;
1957 /* free the old one, or just add to the old one ? */
1958 for (path_num=0; module_path[path_num]; path_num++)
1960 g_free (module_path[path_num]);
1961 module_path[path_num] = NULL;
1966 path_len = strlen (mod_path);
1968 buf = g_strdup (mod_path);
1970 for (end_offset = 0; end_offset <= path_len; end_offset++)
1972 if ((buf[end_offset] == ':') ||
1973 (end_offset == path_len))
1975 buf[end_offset] = '\0';
1976 module_path[path_num] = g_strdup (buf + start_offset);
1978 module_path[path_num] = NULL;
1979 start_offset = end_offset + 1;
1983 gtk_rc_append_default_module_path();
1987 gtk_rc_parse_path_pattern (GScanner *scanner)
1990 GtkPathType path_type;
1992 gboolean is_binding;
1993 GtkPathPriorityType priority = GTK_PATH_PRIO_RC;
1995 token = g_scanner_get_next_token (scanner);
1998 case GTK_RC_TOKEN_WIDGET:
1999 path_type = GTK_PATH_WIDGET;
2001 case GTK_RC_TOKEN_WIDGET_CLASS:
2002 path_type = GTK_PATH_WIDGET_CLASS;
2004 case GTK_RC_TOKEN_CLASS:
2005 path_type = GTK_PATH_CLASS;
2008 return GTK_RC_TOKEN_WIDGET_CLASS;
2011 token = g_scanner_get_next_token (scanner);
2012 if (token != G_TOKEN_STRING)
2013 return G_TOKEN_STRING;
2015 pattern = g_strdup (scanner->value.v_string);
2017 token = g_scanner_get_next_token (scanner);
2018 if (token == GTK_RC_TOKEN_STYLE)
2020 else if (token == GTK_RC_TOKEN_BINDING)
2023 if (g_scanner_peek_next_token (scanner) == ':')
2025 token = gtk_rc_parse_priority (scanner, &priority);
2026 if (token != G_TOKEN_NONE)
2036 return GTK_RC_TOKEN_STYLE;
2039 token = g_scanner_get_next_token (scanner);
2040 if (token != G_TOKEN_STRING)
2043 return G_TOKEN_STRING;
2048 GtkBindingSet *binding;
2050 binding = gtk_binding_set_find (scanner->value.v_string);
2054 return G_TOKEN_STRING;
2056 gtk_binding_set_add_path (binding, path_type, pattern, priority);
2060 GtkRcStyle *rc_style;
2063 rc_style = gtk_rc_style_find (scanner->value.v_string);
2068 return G_TOKEN_STRING;
2071 rc_set = g_new (GtkRcSet, 1);
2072 gtk_pattern_spec_init (&rc_set->pspec, pattern);
2073 rc_set->rc_style = rc_style;
2075 if (path_type == GTK_PATH_WIDGET)
2076 gtk_rc_sets_widget = g_slist_prepend (gtk_rc_sets_widget, rc_set);
2077 else if (path_type == GTK_PATH_WIDGET_CLASS)
2078 gtk_rc_sets_widget_class = g_slist_prepend (gtk_rc_sets_widget_class, rc_set);
2080 gtk_rc_sets_class = g_slist_prepend (gtk_rc_sets_class, rc_set);
2084 return G_TOKEN_NONE;
2088 typedef GdkPixmap * (*GtkImageLoader) (GdkWindow *window,
2089 GdkColormap *colormap,
2091 GdkColor *transparent_color,
2092 const gchar *filename);
2096 gtk_rc_set_image_loader(GtkImageLoader loader)
2098 image_loader = loader;
2102 gtk_rc_load_image (GdkColormap *colormap,
2103 GdkColor *transparent_color,
2104 const gchar *filename)
2106 if (strcmp (filename, "<parent>") == 0)
2107 return (GdkPixmap*) GDK_PARENT_RELATIVE;
2111 return image_loader(NULL, colormap, NULL,
2115 return gdk_pixmap_colormap_create_from_xpm (NULL, colormap, NULL,