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"
33 typedef struct _GtkRcSet GtkRcSet;
34 typedef struct _GtkRcNode GtkRcNode;
35 typedef struct _GtkRcFile GtkRcFile;
47 gchar *canonical_name;
51 static guint gtk_rc_style_hash (const char *name);
52 static gint gtk_rc_style_compare (const char *a,
54 static guint gtk_rc_styles_hash (const GSList *rc_styles);
55 static gint gtk_rc_styles_compare (const GSList *a,
57 static GtkRcStyle* gtk_rc_style_find (const char *name);
58 static GSList * gtk_rc_styles_match (GSList *rc_styles,
62 gchar *path_reversed);
63 static GtkStyle * gtk_rc_style_to_style (GtkRcStyle *rc_style);
64 static GtkStyle* gtk_rc_style_init (GSList *rc_styles);
65 static void gtk_rc_parse_file (const gchar *filename,
68 static void gtk_rc_parse_any (const gchar *input_name,
70 const gchar *input_string);
71 static guint gtk_rc_parse_statement (GScanner *scanner);
72 static guint gtk_rc_parse_style (GScanner *scanner);
73 static guint gtk_rc_parse_base (GScanner *scanner,
75 static guint gtk_rc_parse_bg (GScanner *scanner,
77 static guint gtk_rc_parse_fg (GScanner *scanner,
79 static guint gtk_rc_parse_text (GScanner *scanner,
81 static guint gtk_rc_parse_bg_pixmap (GScanner *scanner,
82 GtkRcStyle *rc_style);
83 static guint gtk_rc_parse_font (GScanner *scanner,
84 GtkRcStyle *rc_style);
85 static guint gtk_rc_parse_fontset (GScanner *scanner,
86 GtkRcStyle *rc_style);
87 static guint gtk_rc_parse_engine (GScanner *scanner,
88 GtkRcStyle *rc_style);
89 static guint gtk_rc_parse_pixmap_path (GScanner *scanner);
90 static void gtk_rc_parse_pixmap_path_string (gchar *pix_path);
91 static guint gtk_rc_parse_module_path (GScanner *scanner);
92 static void gtk_rc_parse_module_path_string (gchar *mod_path);
93 static guint gtk_rc_parse_path_pattern (GScanner *scanner);
94 static void gtk_rc_clear_hash_node (gpointer key,
97 static void gtk_rc_clear_styles (void);
98 static void gtk_rc_append_default_pixmap_path (void);
99 static void gtk_rc_append_default_module_path (void);
100 static void gtk_rc_append_pixmap_path (gchar *dir);
101 static void gtk_rc_add_initial_default_files (void);
104 static const GScannerConfig gtk_rc_scanner_config =
108 ) /* cset_skip_characters */,
113 ) /* cset_identifier_first */,
118 ) /* cset_identifier_nth */,
119 ( "#\n" ) /* cpair_comment_single */,
121 TRUE /* case_sensitive */,
123 TRUE /* skip_comment_multi */,
124 TRUE /* skip_comment_single */,
125 TRUE /* scan_comment_multi */,
126 TRUE /* scan_identifier */,
127 FALSE /* scan_identifier_1char */,
128 FALSE /* scan_identifier_NULL */,
129 TRUE /* scan_symbols */,
130 TRUE /* scan_binary */,
131 TRUE /* scan_octal */,
132 TRUE /* scan_float */,
134 TRUE /* scan_hex_dollar */,
135 TRUE /* scan_string_sq */,
136 TRUE /* scan_string_dq */,
137 TRUE /* numbers_2_int */,
138 FALSE /* int_2_float */,
139 FALSE /* identifier_2_string */,
140 TRUE /* char_2_token */,
141 TRUE /* symbol_2_token */,
142 FALSE /* scope_0_fallback */,
150 { "include", GTK_RC_TOKEN_INCLUDE },
151 { "NORMAL", GTK_RC_TOKEN_NORMAL },
152 { "ACTIVE", GTK_RC_TOKEN_ACTIVE },
153 { "PRELIGHT", GTK_RC_TOKEN_PRELIGHT },
154 { "SELECTED", GTK_RC_TOKEN_SELECTED },
155 { "INSENSITIVE", GTK_RC_TOKEN_INSENSITIVE },
156 { "fg", GTK_RC_TOKEN_FG },
157 { "bg", GTK_RC_TOKEN_BG },
158 { "base", GTK_RC_TOKEN_BASE },
159 { "text", GTK_RC_TOKEN_TEXT },
160 { "font", GTK_RC_TOKEN_FONT },
161 { "fontset", GTK_RC_TOKEN_FONTSET },
162 { "bg_pixmap", GTK_RC_TOKEN_BG_PIXMAP },
163 { "pixmap_path", GTK_RC_TOKEN_PIXMAP_PATH },
164 { "style", GTK_RC_TOKEN_STYLE },
165 { "binding", GTK_RC_TOKEN_BINDING },
166 { "bind", GTK_RC_TOKEN_BIND },
167 { "widget", GTK_RC_TOKEN_WIDGET },
168 { "widget_class", GTK_RC_TOKEN_WIDGET_CLASS },
169 { "class", GTK_RC_TOKEN_CLASS },
170 { "lowest", GTK_RC_TOKEN_LOWEST },
171 { "gtk", GTK_RC_TOKEN_GTK },
172 { "application", GTK_RC_TOKEN_APPLICATION },
173 { "rc", GTK_RC_TOKEN_RC },
174 { "highest", GTK_RC_TOKEN_HIGHEST },
175 { "engine", GTK_RC_TOKEN_ENGINE },
176 { "module_path", GTK_RC_TOKEN_MODULE_PATH },
179 static const guint n_symbols = sizeof (symbols) / sizeof (symbols[0]);
181 static GHashTable *rc_style_ht = NULL;
182 static GHashTable *realized_style_ht = NULL;
183 static GSList *gtk_rc_sets_widget = NULL;
184 static GSList *gtk_rc_sets_widget_class = NULL;
185 static GSList *gtk_rc_sets_class = NULL;
187 #define GTK_RC_MAX_DEFAULT_FILES 128
188 static gchar *gtk_rc_default_files[GTK_RC_MAX_DEFAULT_FILES];
189 static gboolean gtk_rc_auto_parse = TRUE;
191 #define GTK_RC_MAX_PIXMAP_PATHS 128
192 static gchar *pixmap_path[GTK_RC_MAX_PIXMAP_PATHS];
193 #define GTK_RC_MAX_MODULE_PATHS 128
194 static gchar *module_path[GTK_RC_MAX_MODULE_PATHS];
196 /* The files we have parsed, to reread later if necessary */
197 GSList *rc_files = NULL;
199 static GtkImageLoader image_loader = NULL;
201 /* RC file handling */
205 gtk_rc_get_theme_dir(void)
209 var = getenv("GTK_DATA_PREFIX");
212 path = g_malloc(strlen(var) + strlen("/share/themes") +1);
213 sprintf(path, "%s%s", var, "/share/themes");
217 path = g_malloc(strlen(GTK_DATA_PREFIX) + strlen("/share/themes") +1);
218 sprintf(path, "%s%s", GTK_DATA_PREFIX, "/share/themes");
224 gtk_rc_get_module_dir(void)
228 var = getenv("GTK_EXE_PREFIX");
231 path = g_malloc(strlen(var) + strlen("/lib/gtk/themes/engines") +1);
232 sprintf(path, "%s%s", var, "/lib/gtk/themes/engines");
236 path = g_malloc(strlen(GTK_EXE_PREFIX) + strlen("/lib/gtk/themes/engines") +1);
237 sprintf(path, "%s%s", GTK_EXE_PREFIX, "/lib/gtk/themes/engines");
243 gtk_rc_append_default_pixmap_path(void)
248 var = getenv("GTK_DATA_PREFIX");
251 path = g_malloc(strlen(var) + strlen("/share/gtk/themes") +1);
252 sprintf(path, "%s%s", var, "/share/gtk/themes");
256 path = g_malloc(strlen(GTK_DATA_PREFIX) + strlen("/share/gtk/themes") +1);
257 sprintf(path, "%s%s", GTK_DATA_PREFIX, "/share/gtk/themes");
260 for (n = 0; pixmap_path[n]; n++) ;
261 if (n >= GTK_RC_MAX_PIXMAP_PATHS - 1)
263 pixmap_path[n++] = g_strdup(path);
264 pixmap_path[n] = NULL;
269 gtk_rc_append_pixmap_path(gchar *dir)
273 for (n = 0; pixmap_path[n]; n++) ;
274 if (n >= GTK_RC_MAX_MODULE_PATHS - 1)
276 pixmap_path[n++] = g_strdup(dir);
277 pixmap_path[n] = NULL;
281 gtk_rc_append_default_module_path(void)
286 for (n = 0; module_path[n]; n++) ;
287 if (n >= GTK_RC_MAX_MODULE_PATHS - 1)
290 var = getenv("GTK_EXE_PREFIX");
293 path = g_malloc(strlen(var) + strlen("/lib/gtk/themes/engines") +1);
294 sprintf(path, "%s%s", var, "/lib/gtk/themes/engines");
298 path = g_malloc(strlen(GTK_EXE_PREFIX) + strlen("/lib/gtk/themes/engines") +1);
299 sprintf(path, "%s%s", GTK_EXE_PREFIX, "/lib/gtk/themes/engines");
301 module_path[n++] = g_strdup(path);
303 var = getenv("HOME");
306 path = g_malloc(strlen(var) + strlen(".gtk/lib/themes/engines") +1);
307 sprintf(path, "%s%s", var, ".gtk/lib/themes/engines");
309 module_path[n++] = g_strdup(path);
310 module_path[n] = NULL;
315 gtk_rc_add_initial_default_files (void)
317 static gint init = FALSE;
325 gtk_rc_default_files[0] = NULL;
328 var = getenv("GTK_RC_FILES");
331 files = g_strsplit (var, ":", 128);
335 gtk_rc_add_default_file (files[i]);
342 str = g_malloc (strlen(GTK_SYSCONFDIR) + strlen("/gtk/gtkrc") + 1);
343 sprintf (str, "%s%s", GTK_SYSCONFDIR, "/gtk/gtkrc");
344 gtk_rc_add_default_file (str);
346 var = g_get_home_dir ();
347 str = g_malloc (strlen(var) + strlen("/.gtkrc") + 1);
348 sprintf (str, "%s%s", var, "/.gtkrc");
349 gtk_rc_add_default_file (str);
354 gtk_rc_add_default_file (const gchar *file)
358 gtk_rc_add_initial_default_files ();
360 for (n = 0; gtk_rc_default_files[n]; n++) ;
361 if (n >= GTK_RC_MAX_DEFAULT_FILES - 1)
364 gtk_rc_default_files[n++] = g_strdup (file);
365 gtk_rc_default_files[n] = NULL;
369 gtk_rc_set_default_files (gchar **files)
373 gtk_rc_add_initial_default_files ();
376 while (gtk_rc_default_files[i])
378 g_free (gtk_rc_default_files[i]);
382 gtk_rc_default_files[0] = NULL;
383 gtk_rc_auto_parse = FALSE;
386 while (files[i] != NULL)
388 gtk_rc_add_default_file (files[i]);
394 gtk_rc_get_default_files (void)
396 gtk_rc_add_initial_default_files ();
398 return gtk_rc_default_files;
404 gchar *locale_suffixes[3];
405 gint n_locale_suffixes = 0;
407 char *locale = setlocale (LC_MESSAGES, NULL);
411 rc_style_ht = g_hash_table_new ((GHashFunc) gtk_rc_style_hash,
412 (GCompareFunc) gtk_rc_style_compare);
413 pixmap_path[0] = NULL;
414 module_path[0] = NULL;
415 gtk_rc_append_default_pixmap_path();
416 gtk_rc_append_default_module_path();
418 gtk_rc_add_initial_default_files ();
420 if (strcmp (locale, "C") && strcmp (locale, "POSIX"))
422 /* Determine locale-specific suffixes for RC files
424 p = strchr (locale, '@');
425 length = p ? (p -locale) : strlen (locale);
427 p = strchr (locale, '.');
430 locale_suffixes[n_locale_suffixes++] = g_strndup (locale, length);
434 p = strchr (locale, '_');
437 locale_suffixes[n_locale_suffixes++] = g_strndup (locale, length);
441 locale_suffixes[n_locale_suffixes++] = g_strndup (locale, length);
445 while (gtk_rc_default_files[i] != NULL)
447 /* Try to find a locale specific RC file corresponding to
448 * to parse before the default file.
450 for (j=n_locale_suffixes-1; j>=0; j--)
452 gchar *name = g_strconcat (gtk_rc_default_files[i],
460 gtk_rc_parse (gtk_rc_default_files[i]);
466 gtk_rc_parse_string (const gchar *rc_string)
468 g_return_if_fail (rc_string != NULL);
470 gtk_rc_parse_any ("-", -1, rc_string);
474 gtk_rc_parse_file (const gchar *filename, gboolean reload)
476 GtkRcFile *rc_file = NULL;
480 g_return_if_fail (filename != NULL);
485 rc_file = tmp_list->data;
486 if (!strcmp (rc_file->name, filename))
489 tmp_list = tmp_list->next;
494 rc_file = g_new (GtkRcFile, 1);
495 rc_file->name = g_strdup (filename);
496 rc_file->canonical_name = NULL;
498 rc_file->reload = reload;
500 rc_files = g_slist_append (rc_files, rc_file);
503 if (!rc_file->canonical_name)
505 /* Get the absolute pathname */
507 if (rc_file->name[0] == '/')
508 rc_file->canonical_name = rc_file->name;
514 cwd = g_get_current_dir ();
516 str = g_string_new (cwd);
518 g_string_append_c (str, '/');
519 g_string_append (str, rc_file->name);
521 rc_file->canonical_name = str->str;
522 g_string_free (str, FALSE);
526 if (!lstat (rc_file->canonical_name, &statbuf))
530 rc_file->mtime = statbuf.st_mtime;
532 fd = open (rc_file->canonical_name, O_RDONLY);
540 dir = g_strdup(rc_file->canonical_name);
541 for (i = strlen(dir) - 1; (i >= 0) && (dir[i] != '/'); i--)
543 gtk_rc_append_pixmap_path(dir);
546 gtk_rc_parse_any (filename, fd, NULL);
553 gtk_rc_parse (const gchar *filename)
555 g_return_if_fail (filename != NULL);
557 gtk_rc_parse_file (filename, TRUE);
560 /* Handling of RC styles */
563 gtk_rc_style_new (void)
565 GtkRcStyle *new_style;
567 new_style = g_new0 (GtkRcStyle, 1);
568 new_style->ref_count = 1;
574 gtk_rc_style_ref (GtkRcStyle *rc_style)
576 g_return_if_fail (rc_style != NULL);
578 rc_style->ref_count++;
582 gtk_rc_style_unref (GtkRcStyle *rc_style)
586 g_return_if_fail (rc_style != NULL);
588 rc_style->ref_count--;
590 if (rc_style->ref_count == 0)
592 if (rc_style->engine)
594 rc_style->engine->destroy_rc_style (rc_style);
595 gtk_theme_engine_unref (rc_style->engine);
599 g_free (rc_style->name);
600 if (rc_style->fontset_name)
601 g_free (rc_style->fontset_name);
602 if (rc_style->font_name)
603 g_free (rc_style->font_name);
605 for (i=0 ; i<5 ; i++)
606 if (rc_style->bg_pixmap_name[i])
607 g_free (rc_style->bg_pixmap_name[i]);
614 gtk_rc_clear_realized_node (gpointer key,
618 gtk_style_unref (data);
622 gtk_rc_clear_hash_node (gpointer key,
626 gtk_rc_style_unref (data);
630 gtk_rc_free_rc_sets (GSList *slist)
636 rc_set = slist->data;
637 gtk_pattern_spec_free_segs (&rc_set->pspec);
645 gtk_rc_clear_styles (void)
647 /* Clear out all old rc_styles */
651 g_hash_table_foreach (rc_style_ht, gtk_rc_clear_hash_node, NULL);
652 g_hash_table_destroy (rc_style_ht);
656 if (realized_style_ht)
658 g_hash_table_foreach (realized_style_ht, gtk_rc_clear_realized_node, NULL);
659 g_hash_table_destroy (realized_style_ht);
660 realized_style_ht = NULL;
663 gtk_rc_free_rc_sets (gtk_rc_sets_widget);
664 g_slist_free (gtk_rc_sets_widget);
665 gtk_rc_sets_widget = NULL;
667 gtk_rc_free_rc_sets (gtk_rc_sets_widget_class);
668 g_slist_free (gtk_rc_sets_widget_class);
669 gtk_rc_sets_widget_class = NULL;
671 gtk_rc_free_rc_sets (gtk_rc_sets_class);
672 g_slist_free (gtk_rc_sets_class);
673 gtk_rc_sets_class = NULL;
679 gtk_rc_reparse_all (void)
682 gboolean mtime_modified = FALSE;
687 /* Check through and see if any of the RC's have had their
688 * mtime modified. If so, reparse everything.
693 rc_file = tmp_list->data;
695 if (!lstat (rc_file->name, &statbuf) &&
696 (statbuf.st_mtime > rc_file->mtime))
698 mtime_modified = TRUE;
702 tmp_list = tmp_list->next;
707 gtk_rc_clear_styles();
712 rc_file = tmp_list->data;
714 gtk_rc_parse_file (rc_file->name, FALSE);
716 tmp_list = tmp_list->next;
720 return mtime_modified;
724 gtk_rc_styles_match (GSList *rc_styles,
728 gchar *path_reversed)
738 if (gtk_pattern_match (&rc_set->pspec, path_length, path, path_reversed))
739 rc_styles = g_slist_append (rc_styles, rc_set->rc_style);
746 gtk_rc_get_style (GtkWidget *widget)
748 GtkRcStyle *widget_rc_style;
749 GSList *rc_styles = NULL;
751 static guint rc_style_key_id = 0;
753 /* We allow the specification of a single rc style to be bound
754 * tightly to a widget, for application modifications
756 if (!rc_style_key_id)
757 rc_style_key_id = g_quark_from_static_string ("gtk-rc-style");
759 widget_rc_style = gtk_object_get_data_by_id (GTK_OBJECT (widget),
763 rc_styles = g_slist_prepend (rc_styles, widget_rc_style);
765 if (gtk_rc_sets_widget)
767 gchar *path, *path_reversed;
770 gtk_widget_path (widget, &path_length, &path, &path_reversed);
771 rc_styles = gtk_rc_styles_match (rc_styles, gtk_rc_sets_widget, path_length, path, path_reversed);
773 g_free (path_reversed);
777 if (gtk_rc_sets_widget_class)
779 gchar *path, *path_reversed;
782 gtk_widget_class_path (widget, &path_length, &path, &path_reversed);
783 rc_styles = gtk_rc_styles_match (rc_styles, gtk_rc_sets_widget_class, path_length, path, path_reversed);
785 g_free (path_reversed);
788 if (gtk_rc_sets_class)
792 type = GTK_OBJECT_TYPE (widget);
795 gchar *path, *path_reversed;
798 path = gtk_type_name (type);
799 path_length = strlen (path);
800 path_reversed = g_strdup (path);
801 g_strreverse (path_reversed);
803 rc_styles = gtk_rc_styles_match (rc_styles, gtk_rc_sets_class, path_length, path, path_reversed);
804 g_free (path_reversed);
806 type = gtk_type_parent (type);
811 return gtk_rc_style_init (rc_styles);
817 gtk_rc_add_rc_sets (GSList *slist,
818 GtkRcStyle *rc_style,
821 GtkRcStyle *new_style;
825 new_style = gtk_rc_style_new ();
826 *new_style = *rc_style;
827 new_style->name = g_strdup (rc_style->name);
828 new_style->font_name = g_strdup (rc_style->font_name);
829 new_style->fontset_name = g_strdup (rc_style->fontset_name);
831 for (i = 0; i < 5; i++)
832 new_style->bg_pixmap_name[i] = g_strdup (rc_style->bg_pixmap_name[i]);
834 rc_set = g_new (GtkRcSet, 1);
835 gtk_pattern_spec_init (&rc_set->pspec, pattern);
836 rc_set->rc_style = rc_style;
838 return g_slist_prepend (slist, rc_set);
842 gtk_rc_add_widget_name_style (GtkRcStyle *rc_style,
843 const gchar *pattern)
845 g_return_if_fail (rc_style != NULL);
846 g_return_if_fail (pattern != NULL);
848 gtk_rc_sets_widget = gtk_rc_add_rc_sets (gtk_rc_sets_widget, rc_style, pattern);
852 gtk_rc_add_widget_class_style (GtkRcStyle *rc_style,
853 const gchar *pattern)
855 g_return_if_fail (rc_style != NULL);
856 g_return_if_fail (pattern != NULL);
858 gtk_rc_sets_widget_class = gtk_rc_add_rc_sets (gtk_rc_sets_widget_class, rc_style, pattern);
862 gtk_rc_add_class_style (GtkRcStyle *rc_style,
863 const gchar *pattern)
865 g_return_if_fail (rc_style != NULL);
866 g_return_if_fail (pattern != NULL);
868 gtk_rc_sets_class = gtk_rc_add_rc_sets (gtk_rc_sets_class, rc_style, pattern);
872 gtk_rc_parse_any (const gchar *input_name,
874 const gchar *input_string)
880 scanner = g_scanner_new (>k_rc_scanner_config);
884 g_assert (input_string == NULL);
886 g_scanner_input_file (scanner, input_fd);
890 g_assert (input_string != NULL);
892 g_scanner_input_text (scanner, input_string, strlen (input_string));
894 scanner->input_name = input_name;
896 g_scanner_freeze_symbol_table (scanner);
897 for (i = 0; i < n_symbols; i++)
898 g_scanner_add_symbol (scanner, symbols[i].name, GINT_TO_POINTER (symbols[i].token));
899 g_scanner_thaw_symbol_table (scanner);
904 if (g_scanner_peek_next_token (scanner) == G_TOKEN_EOF)
908 guint expected_token;
910 expected_token = gtk_rc_parse_statement (scanner);
912 if (expected_token != G_TOKEN_NONE)
919 if (scanner->scope_id == 0)
921 /* if we are in scope 0, we know the symbol names
922 * that are associated with certaintoken values.
923 * so we look them up to make the error messages
926 if (expected_token > GTK_RC_TOKEN_INVALID &&
927 expected_token < GTK_RC_TOKEN_LAST)
929 for (i = 0; i < n_symbols; i++)
930 if (symbols[i].token == expected_token)
931 msg = symbols[i].name;
933 msg = g_strconcat ("e.g. `", msg, "'", NULL);
935 if (scanner->token > GTK_RC_TOKEN_INVALID &&
936 scanner->token < GTK_RC_TOKEN_LAST)
939 for (i = 0; i < n_symbols; i++)
940 if (symbols[i].token == scanner->token)
941 symbol_name = symbols[i].name;
944 g_scanner_unexp_token (scanner,
957 g_scanner_destroy (scanner);
961 gtk_rc_styles_hash (const GSList *rc_styles)
968 result += (result << 9) + GPOINTER_TO_UINT (rc_styles->data);
969 rc_styles = rc_styles->next;
976 gtk_rc_styles_compare (const GSList *a,
981 if (a->data != b->data)
991 gtk_rc_style_hash (const char *name)
997 result += (result << 3) + *name++;
1003 gtk_rc_style_compare (const char *a,
1006 return (strcmp (a, b) == 0);
1010 gtk_rc_style_find (const char *name)
1012 GtkRcStyle *rc_style;
1014 rc_style = g_hash_table_lookup (rc_style_ht, (gpointer) name);
1019 /* Assumes ownership of rc_style */
1021 gtk_rc_style_to_style (GtkRcStyle *rc_style)
1027 style = gtk_style_new ();
1029 style->rc_style = rc_style;
1031 if (rc_style->fontset_name)
1033 old_font = style->font;
1034 style->font = gdk_fontset_load (rc_style->fontset_name);
1036 gdk_font_unref (old_font);
1038 style->font = old_font;
1040 else if (rc_style->font_name)
1042 old_font = style->font;
1043 style->font = gdk_font_load (rc_style->font_name);
1045 gdk_font_unref (old_font);
1047 style->font = old_font;
1050 for (i = 0; i < 5; i++)
1052 if (rc_style->color_flags[i] & GTK_RC_FG)
1053 style->fg[i] = rc_style->fg[i];
1054 if (rc_style->color_flags[i] & GTK_RC_BG)
1055 style->bg[i] = rc_style->bg[i];
1056 if (rc_style->color_flags[i] & GTK_RC_TEXT)
1057 style->text[i] = rc_style->text[i];
1058 if (rc_style->color_flags[i] & GTK_RC_BASE)
1059 style->base[i] = rc_style->base[i];
1062 if (rc_style->engine)
1064 style->engine = rc_style->engine;
1065 gtk_theme_engine_ref (style->engine);
1066 rc_style->engine->rc_style_to_style (style, rc_style);
1072 /* Reuses or frees rc_styles */
1074 gtk_rc_style_init (GSList *rc_styles)
1078 GtkStyle *style = NULL;
1079 GtkRcStyle *proto_style;
1081 if (!realized_style_ht)
1082 realized_style_ht = g_hash_table_new ((GHashFunc)gtk_rc_styles_hash,
1083 (GCompareFunc)gtk_rc_styles_compare);
1085 style = g_hash_table_lookup (realized_style_ht, rc_styles);
1089 GSList *tmp_styles = rc_styles;
1091 proto_style = gtk_rc_style_new ();
1095 GtkRcStyle *rc_style = tmp_styles->data;
1099 if (!proto_style->bg_pixmap_name[i] && rc_style->bg_pixmap_name[i])
1100 proto_style->bg_pixmap_name[i] = g_strdup (rc_style->bg_pixmap_name[i]);
1102 if (!(proto_style->color_flags[i] & GTK_RC_FG) &&
1103 rc_style->color_flags[i] & GTK_RC_FG)
1105 proto_style->fg[i] = rc_style->fg[i];
1106 proto_style->color_flags[i] |= GTK_RC_FG;
1108 if (!(proto_style->color_flags[i] & GTK_RC_BG) &&
1109 rc_style->color_flags[i] & GTK_RC_BG)
1111 proto_style->bg[i] = rc_style->bg[i];
1112 proto_style->color_flags[i] |= GTK_RC_BG;
1114 if (!(proto_style->color_flags[i] & GTK_RC_TEXT) &&
1115 rc_style->color_flags[i] & GTK_RC_TEXT)
1117 proto_style->text[i] = rc_style->text[i];
1118 proto_style->color_flags[i] |= GTK_RC_TEXT;
1120 if (!(proto_style->color_flags[i] & GTK_RC_BASE) &&
1121 rc_style->color_flags[i] & GTK_RC_BASE)
1123 proto_style->base[i] = rc_style->base[i];
1124 proto_style->color_flags[i] |= GTK_RC_BASE;
1128 if (!proto_style->font_name && rc_style->font_name)
1129 proto_style->font_name = g_strdup (rc_style->font_name);
1130 if (!proto_style->fontset_name && rc_style->fontset_name)
1131 proto_style->fontset_name = g_strdup (rc_style->fontset_name);
1133 if (!proto_style->engine && rc_style->engine)
1135 proto_style->engine = rc_style->engine;
1136 gtk_theme_engine_ref (proto_style->engine);
1139 if (proto_style->engine &&
1140 (proto_style->engine == rc_style->engine))
1141 proto_style->engine->merge_rc_style (proto_style, rc_style);
1143 tmp_styles = tmp_styles->next;
1146 style = gtk_rc_style_to_style (proto_style);
1148 g_hash_table_insert (realized_style_ht, rc_styles, style);
1154 /*********************
1155 * Parsing functions *
1156 *********************/
1159 gtk_rc_parse_statement (GScanner *scanner)
1163 token = g_scanner_peek_next_token (scanner);
1167 case GTK_RC_TOKEN_INCLUDE:
1168 token = g_scanner_get_next_token (scanner);
1169 if (token != GTK_RC_TOKEN_INCLUDE)
1170 return GTK_RC_TOKEN_INCLUDE;
1172 token = g_scanner_get_next_token (scanner);
1173 if (token != G_TOKEN_STRING)
1174 return G_TOKEN_STRING;
1176 gtk_rc_parse_file (scanner->value.v_string, FALSE);
1177 return G_TOKEN_NONE;
1179 case GTK_RC_TOKEN_STYLE:
1180 return gtk_rc_parse_style (scanner);
1182 case GTK_RC_TOKEN_BINDING:
1183 return gtk_binding_parse_binding (scanner);
1185 case GTK_RC_TOKEN_PIXMAP_PATH:
1186 return gtk_rc_parse_pixmap_path (scanner);
1188 case GTK_RC_TOKEN_WIDGET:
1189 return gtk_rc_parse_path_pattern (scanner);
1191 case GTK_RC_TOKEN_WIDGET_CLASS:
1192 return gtk_rc_parse_path_pattern (scanner);
1194 case GTK_RC_TOKEN_CLASS:
1195 return gtk_rc_parse_path_pattern (scanner);
1197 case GTK_RC_TOKEN_MODULE_PATH:
1198 return gtk_rc_parse_module_path (scanner);
1201 g_scanner_get_next_token (scanner);
1202 return /* G_TOKEN_SYMBOL */ GTK_RC_TOKEN_STYLE;
1207 gtk_rc_parse_style (GScanner *scanner)
1209 GtkRcStyle *rc_style;
1210 GtkRcStyle *parent_style;
1215 token = g_scanner_get_next_token (scanner);
1216 if (token != GTK_RC_TOKEN_STYLE)
1217 return GTK_RC_TOKEN_STYLE;
1219 token = g_scanner_get_next_token (scanner);
1220 if (token != G_TOKEN_STRING)
1221 return G_TOKEN_STRING;
1224 rc_style = g_hash_table_lookup (rc_style_ht, scanner->value.v_string);
1229 rc_style = gtk_rc_style_new ();
1230 rc_style->name = g_strdup (scanner->value.v_string);
1232 for (i = 0; i < 5; i++)
1233 rc_style->bg_pixmap_name[i] = NULL;
1235 for (i = 0; i < 5; i++)
1236 rc_style->color_flags[i] = 0;
1238 rc_style->engine = NULL;
1239 rc_style->engine_data = NULL;
1242 token = g_scanner_peek_next_token (scanner);
1243 if (token == G_TOKEN_EQUAL_SIGN)
1245 token = g_scanner_get_next_token (scanner);
1247 token = g_scanner_get_next_token (scanner);
1248 if (token != G_TOKEN_STRING)
1253 return G_TOKEN_STRING;
1256 parent_style = g_hash_table_lookup (rc_style_ht, scanner->value.v_string);
1259 for (i = 0; i < 5; i++)
1261 rc_style->color_flags[i] = parent_style->color_flags[i];
1262 rc_style->fg[i] = parent_style->fg[i];
1263 rc_style->bg[i] = parent_style->bg[i];
1264 rc_style->text[i] = parent_style->text[i];
1265 rc_style->base[i] = parent_style->base[i];
1268 if (parent_style->fontset_name)
1270 if (rc_style->fontset_name)
1271 g_free (rc_style->fontset_name);
1272 rc_style->fontset_name = g_strdup (parent_style->fontset_name);
1274 else if (parent_style->font_name)
1276 if (rc_style->font_name)
1277 g_free (rc_style->font_name);
1278 rc_style->font_name = g_strdup (parent_style->font_name);
1281 for (i = 0; i < 5; i++)
1283 if (rc_style->bg_pixmap_name[i])
1284 g_free (rc_style->bg_pixmap_name[i]);
1285 rc_style->bg_pixmap_name[i] = g_strdup (parent_style->bg_pixmap_name[i]);
1290 token = g_scanner_get_next_token (scanner);
1291 if (token != G_TOKEN_LEFT_CURLY)
1296 return G_TOKEN_LEFT_CURLY;
1299 token = g_scanner_peek_next_token (scanner);
1300 while (token != G_TOKEN_RIGHT_CURLY)
1304 case GTK_RC_TOKEN_BASE:
1305 token = gtk_rc_parse_base (scanner, rc_style);
1307 case GTK_RC_TOKEN_BG:
1308 token = gtk_rc_parse_bg (scanner, rc_style);
1310 case GTK_RC_TOKEN_FG:
1311 token = gtk_rc_parse_fg (scanner, rc_style);
1313 case GTK_RC_TOKEN_TEXT:
1314 token = gtk_rc_parse_text (scanner, rc_style);
1316 case GTK_RC_TOKEN_BG_PIXMAP:
1317 token = gtk_rc_parse_bg_pixmap (scanner, rc_style);
1319 case GTK_RC_TOKEN_FONT:
1320 token = gtk_rc_parse_font (scanner, rc_style);
1322 case GTK_RC_TOKEN_FONTSET:
1323 token = gtk_rc_parse_fontset (scanner, rc_style);
1325 case GTK_RC_TOKEN_ENGINE:
1326 token = gtk_rc_parse_engine (scanner, rc_style);
1329 g_scanner_get_next_token (scanner);
1330 token = G_TOKEN_RIGHT_CURLY;
1334 if (token != G_TOKEN_NONE)
1338 if (rc_style->fontset_name)
1339 g_free (rc_style->fontset_name);
1340 if (rc_style->font_name)
1341 g_free (rc_style->font_name);
1342 for (i = 0; i < 5; i++)
1343 if (rc_style->bg_pixmap_name[i])
1344 g_free (rc_style->bg_pixmap_name[i]);
1349 token = g_scanner_peek_next_token (scanner);
1352 token = g_scanner_get_next_token (scanner);
1353 if (token != G_TOKEN_RIGHT_CURLY)
1357 if (rc_style->fontset_name)
1358 g_free (rc_style->fontset_name);
1359 if (rc_style->font_name)
1360 g_free (rc_style->font_name);
1362 for (i = 0; i < 5; i++)
1363 if (rc_style->bg_pixmap_name[i])
1364 g_free (rc_style->bg_pixmap_name[i]);
1368 return G_TOKEN_RIGHT_CURLY;
1372 g_hash_table_insert (rc_style_ht, rc_style->name, rc_style);
1374 return G_TOKEN_NONE;
1378 gtk_rc_parse_base (GScanner *scanner,
1384 token = g_scanner_get_next_token (scanner);
1385 if (token != GTK_RC_TOKEN_BASE)
1386 return GTK_RC_TOKEN_BASE;
1388 token = gtk_rc_parse_state (scanner, &state);
1389 if (token != G_TOKEN_NONE)
1392 token = g_scanner_get_next_token (scanner);
1393 if (token != G_TOKEN_EQUAL_SIGN)
1394 return G_TOKEN_EQUAL_SIGN;
1396 style->color_flags[state] |= GTK_RC_BASE;
1397 return gtk_rc_parse_color (scanner, &style->base[state]);
1401 gtk_rc_parse_bg (GScanner *scanner,
1407 token = g_scanner_get_next_token (scanner);
1408 if (token != GTK_RC_TOKEN_BG)
1409 return GTK_RC_TOKEN_BG;
1411 token = gtk_rc_parse_state (scanner, &state);
1412 if (token != G_TOKEN_NONE)
1415 token = g_scanner_get_next_token (scanner);
1416 if (token != G_TOKEN_EQUAL_SIGN)
1417 return G_TOKEN_EQUAL_SIGN;
1419 style->color_flags[state] |= GTK_RC_BG;
1420 return gtk_rc_parse_color (scanner, &style->bg[state]);
1424 gtk_rc_parse_fg (GScanner *scanner,
1430 token = g_scanner_get_next_token (scanner);
1431 if (token != GTK_RC_TOKEN_FG)
1432 return GTK_RC_TOKEN_FG;
1434 token = gtk_rc_parse_state (scanner, &state);
1435 if (token != G_TOKEN_NONE)
1438 token = g_scanner_get_next_token (scanner);
1439 if (token != G_TOKEN_EQUAL_SIGN)
1440 return G_TOKEN_EQUAL_SIGN;
1442 style->color_flags[state] |= GTK_RC_FG;
1443 return gtk_rc_parse_color (scanner, &style->fg[state]);
1447 gtk_rc_parse_text (GScanner *scanner,
1453 token = g_scanner_get_next_token (scanner);
1454 if (token != GTK_RC_TOKEN_TEXT)
1455 return GTK_RC_TOKEN_TEXT;
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 style->color_flags[state] |= GTK_RC_TEXT;
1466 return gtk_rc_parse_color (scanner, &style->text[state]);
1470 gtk_rc_parse_bg_pixmap (GScanner *scanner,
1471 GtkRcStyle *rc_style)
1477 token = g_scanner_get_next_token (scanner);
1478 if (token != GTK_RC_TOKEN_BG_PIXMAP)
1479 return GTK_RC_TOKEN_BG_PIXMAP;
1481 token = gtk_rc_parse_state (scanner, &state);
1482 if (token != G_TOKEN_NONE)
1485 token = g_scanner_get_next_token (scanner);
1486 if (token != G_TOKEN_EQUAL_SIGN)
1487 return G_TOKEN_EQUAL_SIGN;
1489 token = g_scanner_get_next_token (scanner);
1490 if (token != G_TOKEN_STRING)
1491 return G_TOKEN_STRING;
1493 if (strcmp (scanner->value.v_string, "<parent>"))
1494 pixmap_file = gtk_rc_find_pixmap_in_path (scanner, scanner->value.v_string);
1496 pixmap_file = g_strdup (scanner->value.v_string);
1500 if (rc_style->bg_pixmap_name[state])
1501 g_free (rc_style->bg_pixmap_name[state]);
1502 rc_style->bg_pixmap_name[state] = pixmap_file;
1505 return G_TOKEN_NONE;
1509 gtk_rc_find_pixmap_in_path (GScanner *scanner,
1510 const gchar *pixmap_file)
1516 for (i = 0; (i < GTK_RC_MAX_PIXMAP_PATHS) && (pixmap_path[i] != NULL); i++)
1518 buf = g_malloc (strlen (pixmap_path[i]) + strlen (pixmap_file) + 2);
1519 sprintf (buf, "%s%c%s", pixmap_path[i], '/', pixmap_file);
1521 fd = open (buf, O_RDONLY);
1532 g_warning ("Unable to locate image file in pixmap_path: \"%s\" line %d",
1533 pixmap_file, scanner->line);
1535 g_warning ("Unable to locate image file in pixmap_path: \"%s\"",
1542 gtk_rc_find_module_in_path (const gchar *module_file)
1548 for (i = 0; (i < GTK_RC_MAX_MODULE_PATHS) && (module_path[i] != NULL); i++)
1550 buf = g_malloc (strlen (module_path[i]) + strlen (module_file) + 2);
1551 sprintf (buf, "%s%c%s", module_path[i], '/', module_file);
1553 fd = open (buf, O_RDONLY);
1567 gtk_rc_parse_font (GScanner *scanner,
1568 GtkRcStyle *rc_style)
1572 token = g_scanner_get_next_token (scanner);
1573 if (token != GTK_RC_TOKEN_FONT)
1574 return GTK_RC_TOKEN_FONT;
1576 token = g_scanner_get_next_token (scanner);
1577 if (token != G_TOKEN_EQUAL_SIGN)
1578 return G_TOKEN_EQUAL_SIGN;
1580 token = g_scanner_get_next_token (scanner);
1581 if (token != G_TOKEN_STRING)
1582 return G_TOKEN_STRING;
1584 if (rc_style->font_name)
1585 g_free (rc_style->font_name);
1586 rc_style->font_name = g_strdup (scanner->value.v_string);
1588 return G_TOKEN_NONE;
1592 gtk_rc_parse_fontset (GScanner *scanner,
1593 GtkRcStyle *rc_style)
1597 token = g_scanner_get_next_token (scanner);
1598 if (token != GTK_RC_TOKEN_FONTSET)
1599 return GTK_RC_TOKEN_FONTSET;
1601 token = g_scanner_get_next_token (scanner);
1602 if (token != G_TOKEN_EQUAL_SIGN)
1603 return G_TOKEN_EQUAL_SIGN;
1605 token = g_scanner_get_next_token (scanner);
1606 if (token != G_TOKEN_STRING)
1607 return G_TOKEN_STRING;
1609 if (rc_style->fontset_name)
1610 g_free (rc_style->fontset_name);
1611 rc_style->fontset_name = g_strdup (scanner->value.v_string);
1613 return G_TOKEN_NONE;
1617 gtk_rc_parse_engine (GScanner *scanner,
1618 GtkRcStyle *rc_style)
1622 token = g_scanner_get_next_token (scanner);
1623 if (token != GTK_RC_TOKEN_ENGINE)
1624 return GTK_RC_TOKEN_ENGINE;
1626 token = g_scanner_get_next_token (scanner);
1627 if (token != G_TOKEN_STRING)
1628 return G_TOKEN_STRING;
1630 rc_style->engine = gtk_theme_engine_get (scanner->value.v_string);
1632 token = g_scanner_get_next_token (scanner);
1633 if (token != G_TOKEN_LEFT_CURLY)
1634 return G_TOKEN_LEFT_CURLY;
1636 if (rc_style->engine)
1637 return rc_style->engine->parse_rc_style (scanner, rc_style);
1640 /* Skip over remainder, looking for nested {}'s */
1643 while ((token = g_scanner_get_next_token (scanner)) != G_TOKEN_EOF)
1645 if (token == G_TOKEN_LEFT_CURLY)
1647 else if (token == G_TOKEN_RIGHT_CURLY)
1651 return G_TOKEN_NONE;
1654 return G_TOKEN_RIGHT_CURLY;
1659 gtk_rc_parse_state (GScanner *scanner,
1660 GtkStateType *state)
1665 g_return_val_if_fail (scanner != NULL, G_TOKEN_ERROR);
1666 g_return_val_if_fail (state != NULL, G_TOKEN_ERROR);
1668 /* we don't know where we got called from, so we reset the scope here.
1669 * if we bail out due to errors, we *don't* reset the scope, so the
1670 * error messaging code can make sense of our tokens.
1672 old_scope = g_scanner_set_scope (scanner, 0);
1674 token = g_scanner_get_next_token (scanner);
1675 if (token != G_TOKEN_LEFT_BRACE)
1676 return G_TOKEN_LEFT_BRACE;
1678 token = g_scanner_get_next_token (scanner);
1681 case GTK_RC_TOKEN_ACTIVE:
1682 *state = GTK_STATE_ACTIVE;
1684 case GTK_RC_TOKEN_INSENSITIVE:
1685 *state = GTK_STATE_INSENSITIVE;
1687 case GTK_RC_TOKEN_NORMAL:
1688 *state = GTK_STATE_NORMAL;
1690 case GTK_RC_TOKEN_PRELIGHT:
1691 *state = GTK_STATE_PRELIGHT;
1693 case GTK_RC_TOKEN_SELECTED:
1694 *state = GTK_STATE_SELECTED;
1697 return /* G_TOKEN_SYMBOL */ GTK_RC_TOKEN_NORMAL;
1700 token = g_scanner_get_next_token (scanner);
1701 if (token != G_TOKEN_RIGHT_BRACE)
1702 return G_TOKEN_RIGHT_BRACE;
1704 g_scanner_set_scope (scanner, old_scope);
1706 return G_TOKEN_NONE;
1710 gtk_rc_parse_priority (GScanner *scanner,
1711 GtkPathPriorityType *priority)
1716 g_return_val_if_fail (scanner != NULL, G_TOKEN_ERROR);
1717 g_return_val_if_fail (priority != NULL, G_TOKEN_ERROR);
1719 /* we don't know where we got called from, so we reset the scope here.
1720 * if we bail out due to errors, we *don't* reset the scope, so the
1721 * error messaging code can make sense of our tokens.
1723 old_scope = g_scanner_set_scope (scanner, 0);
1725 token = g_scanner_get_next_token (scanner);
1729 token = g_scanner_get_next_token (scanner);
1732 case GTK_RC_TOKEN_LOWEST:
1733 *priority = GTK_PATH_PRIO_LOWEST;
1735 case GTK_RC_TOKEN_GTK:
1736 *priority = GTK_PATH_PRIO_GTK;
1738 case GTK_RC_TOKEN_APPLICATION:
1739 *priority = GTK_PATH_PRIO_APPLICATION;
1741 case GTK_RC_TOKEN_RC:
1742 *priority = GTK_PATH_PRIO_RC;
1744 case GTK_RC_TOKEN_HIGHEST:
1745 *priority = GTK_PATH_PRIO_HIGHEST;
1748 return /* G_TOKEN_SYMBOL */ GTK_RC_TOKEN_APPLICATION;
1751 g_scanner_set_scope (scanner, old_scope);
1753 return G_TOKEN_NONE;
1757 gtk_rc_parse_color (GScanner *scanner,
1762 g_return_val_if_fail (scanner != NULL, G_TOKEN_ERROR);
1764 /* we don't need to set our own scop here, because
1765 * we don't need own symbols
1768 token = g_scanner_get_next_token (scanner);
1777 case G_TOKEN_LEFT_CURLY:
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->red = CLAMP (token_int, 0, 65535);
1787 token = g_scanner_get_next_token (scanner);
1788 if (token != G_TOKEN_COMMA)
1789 return G_TOKEN_COMMA;
1791 token = g_scanner_get_next_token (scanner);
1792 if (token == G_TOKEN_INT)
1793 token_int = scanner->value.v_int;
1794 else if (token == G_TOKEN_FLOAT)
1795 token_int = scanner->value.v_float * 65535.0;
1797 return G_TOKEN_FLOAT;
1798 color->green = CLAMP (token_int, 0, 65535);
1800 token = g_scanner_get_next_token (scanner);
1801 if (token != G_TOKEN_COMMA)
1802 return G_TOKEN_COMMA;
1804 token = g_scanner_get_next_token (scanner);
1805 if (token == G_TOKEN_INT)
1806 token_int = scanner->value.v_int;
1807 else if (token == G_TOKEN_FLOAT)
1808 token_int = scanner->value.v_float * 65535.0;
1810 return G_TOKEN_FLOAT;
1811 color->blue = CLAMP (token_int, 0, 65535);
1813 token = g_scanner_get_next_token (scanner);
1814 if (token != G_TOKEN_RIGHT_CURLY)
1815 return G_TOKEN_RIGHT_CURLY;
1816 return G_TOKEN_NONE;
1818 case G_TOKEN_STRING:
1819 if (scanner->value.v_string[0] != '#')
1820 return G_TOKEN_STRING;
1822 length = strlen (scanner->value.v_string) - 1;
1823 if (((length % 3) != 0) || (length > 12))
1824 return G_TOKEN_STRING;
1827 for (i = 0, j = 1; i < length; i++, j++)
1828 buf[i] = scanner->value.v_string[j];
1831 sscanf (buf, "%x", &temp);
1834 for (i = 0; i < length; i++, j++)
1835 buf[i] = scanner->value.v_string[j];
1838 sscanf (buf, "%x", &temp);
1839 color->green = temp;
1841 for (i = 0; i < length; i++, j++)
1842 buf[i] = scanner->value.v_string[j];
1845 sscanf (buf, "%x", &temp);
1851 color->green *= 4369;
1852 color->blue *= 4369;
1854 else if (length == 2)
1857 color->green *= 257;
1860 else if (length == 3)
1866 return G_TOKEN_NONE;
1869 return G_TOKEN_STRING;
1874 gtk_rc_parse_pixmap_path (GScanner *scanner)
1878 token = g_scanner_get_next_token (scanner);
1879 if (token != GTK_RC_TOKEN_PIXMAP_PATH)
1880 return GTK_RC_TOKEN_PIXMAP_PATH;
1882 token = g_scanner_get_next_token (scanner);
1883 if (token != G_TOKEN_STRING)
1884 return G_TOKEN_STRING;
1886 gtk_rc_parse_pixmap_path_string (scanner->value.v_string);
1888 return G_TOKEN_NONE;
1892 gtk_rc_parse_pixmap_path_string (gchar *pix_path)
1896 gint start_offset = 0;
1900 /* free the old one, or just add to the old one ? */
1901 for (path_num=0; pixmap_path[path_num]; path_num++)
1903 g_free (pixmap_path[path_num]);
1904 pixmap_path[path_num] = NULL;
1909 path_len = strlen (pix_path);
1911 buf = g_strdup (pix_path);
1913 for (end_offset = 0; end_offset <= path_len; end_offset++)
1915 if ((buf[end_offset] == ':') ||
1916 (end_offset == path_len))
1918 buf[end_offset] = '\0';
1919 pixmap_path[path_num] = g_strdup (buf + start_offset);
1921 pixmap_path[path_num] = NULL;
1922 start_offset = end_offset + 1;
1926 gtk_rc_append_default_pixmap_path();
1930 gtk_rc_parse_module_path (GScanner *scanner)
1934 token = g_scanner_get_next_token (scanner);
1935 if (token != GTK_RC_TOKEN_MODULE_PATH)
1936 return GTK_RC_TOKEN_MODULE_PATH;
1938 token = g_scanner_get_next_token (scanner);
1939 if (token != G_TOKEN_STRING)
1940 return G_TOKEN_STRING;
1942 gtk_rc_parse_module_path_string (scanner->value.v_string);
1944 return G_TOKEN_NONE;
1948 gtk_rc_parse_module_path_string (gchar *mod_path)
1952 gint start_offset = 0;
1956 /* free the old one, or just add to the old one ? */
1957 for (path_num=0; module_path[path_num]; path_num++)
1959 g_free (module_path[path_num]);
1960 module_path[path_num] = NULL;
1965 path_len = strlen (mod_path);
1967 buf = g_strdup (mod_path);
1969 for (end_offset = 0; end_offset <= path_len; end_offset++)
1971 if ((buf[end_offset] == ':') ||
1972 (end_offset == path_len))
1974 buf[end_offset] = '\0';
1975 module_path[path_num] = g_strdup (buf + start_offset);
1977 module_path[path_num] = NULL;
1978 start_offset = end_offset + 1;
1982 gtk_rc_append_default_module_path();
1986 gtk_rc_parse_path_pattern (GScanner *scanner)
1989 GtkPathType path_type;
1991 gboolean is_binding;
1992 GtkPathPriorityType priority = GTK_PATH_PRIO_RC;
1994 token = g_scanner_get_next_token (scanner);
1997 case GTK_RC_TOKEN_WIDGET:
1998 path_type = GTK_PATH_WIDGET;
2000 case GTK_RC_TOKEN_WIDGET_CLASS:
2001 path_type = GTK_PATH_WIDGET_CLASS;
2003 case GTK_RC_TOKEN_CLASS:
2004 path_type = GTK_PATH_CLASS;
2007 return GTK_RC_TOKEN_WIDGET_CLASS;
2010 token = g_scanner_get_next_token (scanner);
2011 if (token != G_TOKEN_STRING)
2012 return G_TOKEN_STRING;
2014 pattern = g_strdup (scanner->value.v_string);
2016 token = g_scanner_get_next_token (scanner);
2017 if (token == GTK_RC_TOKEN_STYLE)
2019 else if (token == GTK_RC_TOKEN_BINDING)
2022 if (g_scanner_peek_next_token (scanner) == ':')
2024 token = gtk_rc_parse_priority (scanner, &priority);
2025 if (token != G_TOKEN_NONE)
2035 return GTK_RC_TOKEN_STYLE;
2038 token = g_scanner_get_next_token (scanner);
2039 if (token != G_TOKEN_STRING)
2042 return G_TOKEN_STRING;
2047 GtkBindingSet *binding;
2049 binding = gtk_binding_set_find (scanner->value.v_string);
2053 return G_TOKEN_STRING;
2055 gtk_binding_set_add_path (binding, path_type, pattern, priority);
2059 GtkRcStyle *rc_style;
2062 rc_style = gtk_rc_style_find (scanner->value.v_string);
2067 return G_TOKEN_STRING;
2070 rc_set = g_new (GtkRcSet, 1);
2071 gtk_pattern_spec_init (&rc_set->pspec, pattern);
2072 rc_set->rc_style = rc_style;
2074 if (path_type == GTK_PATH_WIDGET)
2075 gtk_rc_sets_widget = g_slist_prepend (gtk_rc_sets_widget, rc_set);
2076 else if (path_type == GTK_PATH_WIDGET_CLASS)
2077 gtk_rc_sets_widget_class = g_slist_prepend (gtk_rc_sets_widget_class, rc_set);
2079 gtk_rc_sets_class = g_slist_prepend (gtk_rc_sets_class, rc_set);
2083 return G_TOKEN_NONE;
2087 typedef GdkPixmap * (*GtkImageLoader) (GdkWindow *window,
2088 GdkColormap *colormap,
2090 GdkColor *transparent_color,
2091 const gchar *filename);
2095 gtk_rc_set_image_loader(GtkImageLoader loader)
2097 image_loader = loader;
2101 gtk_rc_load_image (GdkColormap *colormap,
2102 GdkColor *transparent_color,
2103 const gchar *filename)
2105 if (strcmp (filename, "<parent>") == 0)
2106 return (GdkPixmap*) GDK_PARENT_RELATIVE;
2110 return image_loader(NULL, colormap, NULL,
2114 return gdk_pixmap_colormap_create_from_xpm (NULL, colormap, NULL,