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.
21 * Modified by the GTK+ Team and others 1997-1999. See the AUTHORS
22 * file for a list of people on the GTK+ Team. See the ChangeLog
23 * files for a list of changes. These files are distributed with
24 * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
27 #include <X11/Xlocale.h> /* so we get the right setlocale */
31 #include <sys/param.h>
38 #include "gtkbindings.h"
39 #include "gtkthemes.h"
42 typedef struct _GtkRcSet GtkRcSet;
43 typedef struct _GtkRcNode GtkRcNode;
44 typedef struct _GtkRcFile GtkRcFile;
56 gchar *canonical_name;
60 static guint gtk_rc_style_hash (const char *name);
61 static gint gtk_rc_style_compare (const char *a,
63 static guint gtk_rc_styles_hash (const GSList *rc_styles);
64 static gint gtk_rc_styles_compare (const GSList *a,
66 static GtkRcStyle* gtk_rc_style_find (const char *name);
67 static GSList * gtk_rc_styles_match (GSList *rc_styles,
71 gchar *path_reversed);
72 static GtkStyle * gtk_rc_style_to_style (GtkRcStyle *rc_style);
73 static GtkStyle* gtk_rc_style_init (GSList *rc_styles);
74 static void gtk_rc_parse_file (const gchar *filename,
77 static void gtk_rc_parse_any (const gchar *input_name,
79 const gchar *input_string);
80 static guint gtk_rc_parse_statement (GScanner *scanner);
81 static guint gtk_rc_parse_style (GScanner *scanner);
82 static guint gtk_rc_parse_base (GScanner *scanner,
84 static guint gtk_rc_parse_bg (GScanner *scanner,
86 static guint gtk_rc_parse_fg (GScanner *scanner,
88 static guint gtk_rc_parse_text (GScanner *scanner,
90 static guint gtk_rc_parse_bg_pixmap (GScanner *scanner,
91 GtkRcStyle *rc_style);
92 static guint gtk_rc_parse_font (GScanner *scanner,
93 GtkRcStyle *rc_style);
94 static guint gtk_rc_parse_fontset (GScanner *scanner,
95 GtkRcStyle *rc_style);
96 static guint gtk_rc_parse_engine (GScanner *scanner,
97 GtkRcStyle *rc_style);
98 static guint gtk_rc_parse_pixmap_path (GScanner *scanner);
99 static void gtk_rc_parse_pixmap_path_string (gchar *pix_path);
100 static guint gtk_rc_parse_module_path (GScanner *scanner);
101 static void gtk_rc_parse_module_path_string (gchar *mod_path);
102 static guint gtk_rc_parse_path_pattern (GScanner *scanner);
103 static void gtk_rc_clear_hash_node (gpointer key,
106 static void gtk_rc_clear_styles (void);
107 static void gtk_rc_append_default_pixmap_path (void);
108 static void gtk_rc_append_default_module_path (void);
109 static void gtk_rc_append_pixmap_path (gchar *dir);
110 static void gtk_rc_add_initial_default_files (void);
113 static const GScannerConfig gtk_rc_scanner_config =
117 ) /* cset_skip_characters */,
122 ) /* cset_identifier_first */,
127 ) /* cset_identifier_nth */,
128 ( "#\n" ) /* cpair_comment_single */,
130 TRUE /* case_sensitive */,
132 TRUE /* skip_comment_multi */,
133 TRUE /* skip_comment_single */,
134 TRUE /* scan_comment_multi */,
135 TRUE /* scan_identifier */,
136 FALSE /* scan_identifier_1char */,
137 FALSE /* scan_identifier_NULL */,
138 TRUE /* scan_symbols */,
139 TRUE /* scan_binary */,
140 TRUE /* scan_octal */,
141 TRUE /* scan_float */,
143 TRUE /* scan_hex_dollar */,
144 TRUE /* scan_string_sq */,
145 TRUE /* scan_string_dq */,
146 TRUE /* numbers_2_int */,
147 FALSE /* int_2_float */,
148 FALSE /* identifier_2_string */,
149 TRUE /* char_2_token */,
150 TRUE /* symbol_2_token */,
151 FALSE /* scope_0_fallback */,
159 { "include", GTK_RC_TOKEN_INCLUDE },
160 { "NORMAL", GTK_RC_TOKEN_NORMAL },
161 { "ACTIVE", GTK_RC_TOKEN_ACTIVE },
162 { "PRELIGHT", GTK_RC_TOKEN_PRELIGHT },
163 { "SELECTED", GTK_RC_TOKEN_SELECTED },
164 { "INSENSITIVE", GTK_RC_TOKEN_INSENSITIVE },
165 { "fg", GTK_RC_TOKEN_FG },
166 { "bg", GTK_RC_TOKEN_BG },
167 { "base", GTK_RC_TOKEN_BASE },
168 { "text", GTK_RC_TOKEN_TEXT },
169 { "font", GTK_RC_TOKEN_FONT },
170 { "fontset", GTK_RC_TOKEN_FONTSET },
171 { "bg_pixmap", GTK_RC_TOKEN_BG_PIXMAP },
172 { "pixmap_path", GTK_RC_TOKEN_PIXMAP_PATH },
173 { "style", GTK_RC_TOKEN_STYLE },
174 { "binding", GTK_RC_TOKEN_BINDING },
175 { "bind", GTK_RC_TOKEN_BIND },
176 { "widget", GTK_RC_TOKEN_WIDGET },
177 { "widget_class", GTK_RC_TOKEN_WIDGET_CLASS },
178 { "class", GTK_RC_TOKEN_CLASS },
179 { "lowest", GTK_RC_TOKEN_LOWEST },
180 { "gtk", GTK_RC_TOKEN_GTK },
181 { "application", GTK_RC_TOKEN_APPLICATION },
182 { "rc", GTK_RC_TOKEN_RC },
183 { "highest", GTK_RC_TOKEN_HIGHEST },
184 { "engine", GTK_RC_TOKEN_ENGINE },
185 { "module_path", GTK_RC_TOKEN_MODULE_PATH },
188 static const guint n_symbols = sizeof (symbols) / sizeof (symbols[0]);
190 static GHashTable *rc_style_ht = NULL;
191 static GHashTable *realized_style_ht = NULL;
192 static GSList *gtk_rc_sets_widget = NULL;
193 static GSList *gtk_rc_sets_widget_class = NULL;
194 static GSList *gtk_rc_sets_class = NULL;
196 #define GTK_RC_MAX_DEFAULT_FILES 128
197 static gchar *gtk_rc_default_files[GTK_RC_MAX_DEFAULT_FILES];
198 static gboolean gtk_rc_auto_parse = TRUE;
200 #define GTK_RC_MAX_PIXMAP_PATHS 128
201 static gchar *pixmap_path[GTK_RC_MAX_PIXMAP_PATHS];
202 #define GTK_RC_MAX_MODULE_PATHS 128
203 static gchar *module_path[GTK_RC_MAX_MODULE_PATHS];
205 /* The files we have parsed, to reread later if necessary */
206 GSList *rc_files = NULL;
208 static GtkImageLoader image_loader = NULL;
210 /* RC file handling */
214 gtk_rc_get_theme_dir(void)
218 var = getenv("GTK_DATA_PREFIX");
220 path = g_strdup_printf("%s%s", var, "/share/themes");
222 path = g_strdup_printf("%s%s", GTK_DATA_PREFIX, "/share/themes");
228 gtk_rc_get_module_dir(void)
232 var = getenv("GTK_EXE_PREFIX");
234 path = g_strdup_printf("%s%s", var, "/lib/gtk/themes/engines");
236 path = g_strdup_printf("%s%s", GTK_EXE_PREFIX, "/lib/gtk/themes/engines");
242 gtk_rc_append_default_pixmap_path(void)
247 var = getenv("GTK_DATA_PREFIX");
249 path = g_strdup_printf("%s%s", var, "/share/gtk/themes");
251 path = g_strdup_printf("%s%s", GTK_DATA_PREFIX, "/share/gtk/themes");
253 for (n = 0; pixmap_path[n]; n++) ;
254 if (n >= GTK_RC_MAX_PIXMAP_PATHS - 1)
256 pixmap_path[n++] = g_strdup(path);
257 pixmap_path[n] = NULL;
262 gtk_rc_append_pixmap_path(gchar *dir)
266 for (n = 0; pixmap_path[n]; n++) ;
267 if (n >= GTK_RC_MAX_MODULE_PATHS - 1)
269 pixmap_path[n++] = g_strdup(dir);
270 pixmap_path[n] = NULL;
274 gtk_rc_append_default_module_path(void)
279 for (n = 0; module_path[n]; n++) ;
280 if (n >= GTK_RC_MAX_MODULE_PATHS - 1)
283 var = getenv("GTK_EXE_PREFIX");
285 path = g_strdup_printf("%s%s", var, "/lib/gtk/themes/engines");
287 path = g_strdup_printf("%s%s", GTK_EXE_PREFIX, "/lib/gtk/themes/engines");
288 module_path[n++] = g_strdup(path);
291 var = getenv("HOME");
293 path = g_strdup_printf("%s%s", var, ".gtk/lib/themes/engines");
294 module_path[n++] = g_strdup(path);
295 module_path[n] = NULL;
300 gtk_rc_add_initial_default_files (void)
302 static gint init = FALSE;
310 gtk_rc_default_files[0] = NULL;
313 var = getenv("GTK_RC_FILES");
316 files = g_strsplit (var, ":", 128);
320 gtk_rc_add_default_file (files[i]);
327 str = g_strdup_printf ("%s%s", GTK_SYSCONFDIR, "/gtk/gtkrc");
328 gtk_rc_add_default_file (str);
331 str = g_strdup_printf ("%s%s", g_get_home_dir (), "/.gtkrc");
332 gtk_rc_add_default_file (str);
338 gtk_rc_add_default_file (const gchar *file)
342 gtk_rc_add_initial_default_files ();
344 for (n = 0; gtk_rc_default_files[n]; n++) ;
345 if (n >= GTK_RC_MAX_DEFAULT_FILES - 1)
348 gtk_rc_default_files[n++] = g_strdup (file);
349 gtk_rc_default_files[n] = NULL;
353 gtk_rc_set_default_files (gchar **files)
357 gtk_rc_add_initial_default_files ();
360 while (gtk_rc_default_files[i])
362 g_free (gtk_rc_default_files[i]);
366 gtk_rc_default_files[0] = NULL;
367 gtk_rc_auto_parse = FALSE;
370 while (files[i] != NULL)
372 gtk_rc_add_default_file (files[i]);
378 gtk_rc_get_default_files (void)
380 gtk_rc_add_initial_default_files ();
382 return gtk_rc_default_files;
388 gchar *locale_suffixes[3];
389 gint n_locale_suffixes = 0;
391 #ifdef HAVE_LC_MESSAGES
392 char *locale = setlocale (LC_MESSAGES, NULL);
394 char *locale = setlocale (LC_CTYPE, NULL);
399 rc_style_ht = g_hash_table_new ((GHashFunc) gtk_rc_style_hash,
400 (GCompareFunc) gtk_rc_style_compare);
401 pixmap_path[0] = NULL;
402 module_path[0] = NULL;
403 gtk_rc_append_default_pixmap_path();
404 gtk_rc_append_default_module_path();
406 gtk_rc_add_initial_default_files ();
408 if (strcmp (locale, "C") && strcmp (locale, "POSIX"))
410 /* Determine locale-specific suffixes for RC files
412 p = strchr (locale, '@');
413 length = p ? (p -locale) : strlen (locale);
415 p = strchr (locale, '.');
418 locale_suffixes[n_locale_suffixes++] = g_strndup (locale, length);
422 p = strchr (locale, '_');
425 locale_suffixes[n_locale_suffixes++] = g_strndup (locale, length);
429 locale_suffixes[n_locale_suffixes++] = g_strndup (locale, length);
433 while (gtk_rc_default_files[i] != NULL)
435 /* Try to find a locale specific RC file corresponding to
436 * to parse before the default file.
438 for (j=n_locale_suffixes-1; j>=0; j--)
440 gchar *name = g_strconcat (gtk_rc_default_files[i],
448 gtk_rc_parse (gtk_rc_default_files[i]);
454 gtk_rc_parse_string (const gchar *rc_string)
456 g_return_if_fail (rc_string != NULL);
458 gtk_rc_parse_any ("-", -1, rc_string);
462 gtk_rc_parse_file (const gchar *filename, gboolean reload)
464 GtkRcFile *rc_file = NULL;
468 g_return_if_fail (filename != NULL);
473 rc_file = tmp_list->data;
474 if (!strcmp (rc_file->name, filename))
477 tmp_list = tmp_list->next;
482 rc_file = g_new (GtkRcFile, 1);
483 rc_file->name = g_strdup (filename);
484 rc_file->canonical_name = NULL;
486 rc_file->reload = reload;
488 rc_files = g_slist_append (rc_files, rc_file);
491 if (!rc_file->canonical_name)
493 /* Get the absolute pathname */
495 if (rc_file->name[0] == '/')
496 rc_file->canonical_name = rc_file->name;
502 cwd = g_get_current_dir ();
504 str = g_string_new (cwd);
506 g_string_append_c (str, '/');
507 g_string_append (str, rc_file->name);
509 rc_file->canonical_name = str->str;
510 g_string_free (str, FALSE);
514 if (!lstat (rc_file->canonical_name, &statbuf))
518 rc_file->mtime = statbuf.st_mtime;
520 fd = open (rc_file->canonical_name, O_RDONLY);
528 dir = g_strdup(rc_file->canonical_name);
529 for (i = strlen(dir) - 1; (i >= 0) && (dir[i] != '/'); i--)
531 gtk_rc_append_pixmap_path(dir);
534 gtk_rc_parse_any (filename, fd, NULL);
541 gtk_rc_parse (const gchar *filename)
543 g_return_if_fail (filename != NULL);
545 gtk_rc_parse_file (filename, TRUE);
548 /* Handling of RC styles */
551 gtk_rc_style_new (void)
553 GtkRcStyle *new_style;
555 new_style = g_new0 (GtkRcStyle, 1);
556 new_style->ref_count = 1;
562 gtk_rc_style_ref (GtkRcStyle *rc_style)
564 g_return_if_fail (rc_style != NULL);
566 rc_style->ref_count++;
570 gtk_rc_style_unref (GtkRcStyle *rc_style)
574 g_return_if_fail (rc_style != NULL);
575 g_return_if_fail (rc_style->ref_count > 0);
577 rc_style->ref_count--;
579 if (rc_style->ref_count == 0)
581 if (rc_style->engine)
583 rc_style->engine->destroy_rc_style (rc_style);
584 gtk_theme_engine_unref (rc_style->engine);
588 g_free (rc_style->name);
589 if (rc_style->fontset_name)
590 g_free (rc_style->fontset_name);
591 if (rc_style->font_name)
592 g_free (rc_style->font_name);
594 for (i=0 ; i<5 ; i++)
595 if (rc_style->bg_pixmap_name[i])
596 g_free (rc_style->bg_pixmap_name[i]);
603 gtk_rc_clear_realized_node (gpointer key,
607 gtk_style_unref (data);
611 gtk_rc_clear_hash_node (gpointer key,
615 gtk_rc_style_unref (data);
619 gtk_rc_free_rc_sets (GSList *slist)
625 rc_set = slist->data;
626 gtk_pattern_spec_free_segs (&rc_set->pspec);
634 gtk_rc_clear_styles (void)
636 /* Clear out all old rc_styles */
640 g_hash_table_foreach (rc_style_ht, gtk_rc_clear_hash_node, NULL);
641 g_hash_table_destroy (rc_style_ht);
645 if (realized_style_ht)
647 g_hash_table_foreach (realized_style_ht, gtk_rc_clear_realized_node, NULL);
648 g_hash_table_destroy (realized_style_ht);
649 realized_style_ht = NULL;
652 gtk_rc_free_rc_sets (gtk_rc_sets_widget);
653 g_slist_free (gtk_rc_sets_widget);
654 gtk_rc_sets_widget = NULL;
656 gtk_rc_free_rc_sets (gtk_rc_sets_widget_class);
657 g_slist_free (gtk_rc_sets_widget_class);
658 gtk_rc_sets_widget_class = NULL;
660 gtk_rc_free_rc_sets (gtk_rc_sets_class);
661 g_slist_free (gtk_rc_sets_class);
662 gtk_rc_sets_class = NULL;
668 gtk_rc_reparse_all (void)
671 gboolean mtime_modified = FALSE;
676 /* Check through and see if any of the RC's have had their
677 * mtime modified. If so, reparse everything.
682 rc_file = tmp_list->data;
684 if (!lstat (rc_file->name, &statbuf) &&
685 (statbuf.st_mtime > rc_file->mtime))
687 mtime_modified = TRUE;
691 tmp_list = tmp_list->next;
696 gtk_rc_clear_styles();
701 rc_file = tmp_list->data;
703 gtk_rc_parse_file (rc_file->name, FALSE);
705 tmp_list = tmp_list->next;
709 return mtime_modified;
713 gtk_rc_styles_match (GSList *rc_styles,
717 gchar *path_reversed)
727 if (gtk_pattern_match (&rc_set->pspec, path_length, path, path_reversed))
728 rc_styles = g_slist_append (rc_styles, rc_set->rc_style);
735 gtk_rc_get_style (GtkWidget *widget)
737 GtkRcStyle *widget_rc_style;
738 GSList *rc_styles = NULL;
740 static guint rc_style_key_id = 0;
742 /* We allow the specification of a single rc style to be bound
743 * tightly to a widget, for application modifications
745 if (!rc_style_key_id)
746 rc_style_key_id = g_quark_from_static_string ("gtk-rc-style");
748 widget_rc_style = gtk_object_get_data_by_id (GTK_OBJECT (widget),
752 rc_styles = g_slist_prepend (rc_styles, widget_rc_style);
754 if (gtk_rc_sets_widget)
756 gchar *path, *path_reversed;
759 gtk_widget_path (widget, &path_length, &path, &path_reversed);
760 rc_styles = gtk_rc_styles_match (rc_styles, gtk_rc_sets_widget, path_length, path, path_reversed);
762 g_free (path_reversed);
766 if (gtk_rc_sets_widget_class)
768 gchar *path, *path_reversed;
771 gtk_widget_class_path (widget, &path_length, &path, &path_reversed);
772 rc_styles = gtk_rc_styles_match (rc_styles, gtk_rc_sets_widget_class, path_length, path, path_reversed);
774 g_free (path_reversed);
777 if (gtk_rc_sets_class)
781 type = GTK_OBJECT_TYPE (widget);
784 gchar *path, *path_reversed;
787 path = gtk_type_name (type);
788 path_length = strlen (path);
789 path_reversed = g_strdup (path);
790 g_strreverse (path_reversed);
792 rc_styles = gtk_rc_styles_match (rc_styles, gtk_rc_sets_class, path_length, path, path_reversed);
793 g_free (path_reversed);
795 type = gtk_type_parent (type);
800 return gtk_rc_style_init (rc_styles);
806 gtk_rc_add_rc_sets (GSList *slist,
807 GtkRcStyle *rc_style,
810 GtkRcStyle *new_style;
814 new_style = gtk_rc_style_new ();
815 *new_style = *rc_style;
816 new_style->name = g_strdup (rc_style->name);
817 new_style->font_name = g_strdup (rc_style->font_name);
818 new_style->fontset_name = g_strdup (rc_style->fontset_name);
820 for (i = 0; i < 5; i++)
821 new_style->bg_pixmap_name[i] = g_strdup (rc_style->bg_pixmap_name[i]);
823 rc_set = g_new (GtkRcSet, 1);
824 gtk_pattern_spec_init (&rc_set->pspec, pattern);
825 rc_set->rc_style = rc_style;
827 return g_slist_prepend (slist, rc_set);
831 gtk_rc_add_widget_name_style (GtkRcStyle *rc_style,
832 const gchar *pattern)
834 g_return_if_fail (rc_style != NULL);
835 g_return_if_fail (pattern != NULL);
837 gtk_rc_sets_widget = gtk_rc_add_rc_sets (gtk_rc_sets_widget, rc_style, pattern);
841 gtk_rc_add_widget_class_style (GtkRcStyle *rc_style,
842 const gchar *pattern)
844 g_return_if_fail (rc_style != NULL);
845 g_return_if_fail (pattern != NULL);
847 gtk_rc_sets_widget_class = gtk_rc_add_rc_sets (gtk_rc_sets_widget_class, rc_style, pattern);
851 gtk_rc_add_class_style (GtkRcStyle *rc_style,
852 const gchar *pattern)
854 g_return_if_fail (rc_style != NULL);
855 g_return_if_fail (pattern != NULL);
857 gtk_rc_sets_class = gtk_rc_add_rc_sets (gtk_rc_sets_class, rc_style, pattern);
861 gtk_rc_parse_any (const gchar *input_name,
863 const gchar *input_string)
869 scanner = g_scanner_new ((GScannerConfig *) >k_rc_scanner_config);
873 g_assert (input_string == NULL);
875 g_scanner_input_file (scanner, input_fd);
879 g_assert (input_string != NULL);
881 g_scanner_input_text (scanner, input_string, strlen (input_string));
883 scanner->input_name = input_name;
885 g_scanner_freeze_symbol_table (scanner);
886 for (i = 0; i < n_symbols; i++)
887 g_scanner_add_symbol (scanner, symbols[i].name, GINT_TO_POINTER (symbols[i].token));
888 g_scanner_thaw_symbol_table (scanner);
893 if (g_scanner_peek_next_token (scanner) == G_TOKEN_EOF)
897 guint expected_token;
899 expected_token = gtk_rc_parse_statement (scanner);
901 if (expected_token != G_TOKEN_NONE)
908 if (scanner->scope_id == 0)
910 /* if we are in scope 0, we know the symbol names
911 * that are associated with certaintoken values.
912 * so we look them up to make the error messages
915 if (expected_token > GTK_RC_TOKEN_INVALID &&
916 expected_token < GTK_RC_TOKEN_LAST)
918 for (i = 0; i < n_symbols; i++)
919 if (symbols[i].token == expected_token)
920 msg = symbols[i].name;
922 msg = g_strconcat ("e.g. `", msg, "'", NULL);
924 if (scanner->token > GTK_RC_TOKEN_INVALID &&
925 scanner->token < GTK_RC_TOKEN_LAST)
928 for (i = 0; i < n_symbols; i++)
929 if (symbols[i].token == scanner->token)
930 symbol_name = symbols[i].name;
933 g_scanner_unexp_token (scanner,
946 g_scanner_destroy (scanner);
950 gtk_rc_styles_hash (const GSList *rc_styles)
957 result += (result << 9) + GPOINTER_TO_UINT (rc_styles->data);
958 rc_styles = rc_styles->next;
965 gtk_rc_styles_compare (const GSList *a,
970 if (a->data != b->data)
980 gtk_rc_style_hash (const char *name)
986 result += (result << 3) + *name++;
992 gtk_rc_style_compare (const char *a,
995 return (strcmp (a, b) == 0);
999 gtk_rc_style_find (const char *name)
1001 GtkRcStyle *rc_style;
1003 rc_style = g_hash_table_lookup (rc_style_ht, (gpointer) name);
1008 /* Assumes ownership of rc_style */
1010 gtk_rc_style_to_style (GtkRcStyle *rc_style)
1016 style = gtk_style_new ();
1018 style->rc_style = rc_style;
1020 if (rc_style->fontset_name)
1022 old_font = style->font;
1023 style->font = gdk_fontset_load (rc_style->fontset_name);
1025 gdk_font_unref (old_font);
1027 style->font = old_font;
1029 else if (rc_style->font_name)
1031 old_font = style->font;
1032 style->font = gdk_font_load (rc_style->font_name);
1034 gdk_font_unref (old_font);
1036 style->font = old_font;
1039 for (i = 0; i < 5; i++)
1041 if (rc_style->color_flags[i] & GTK_RC_FG)
1042 style->fg[i] = rc_style->fg[i];
1043 if (rc_style->color_flags[i] & GTK_RC_BG)
1044 style->bg[i] = rc_style->bg[i];
1045 if (rc_style->color_flags[i] & GTK_RC_TEXT)
1046 style->text[i] = rc_style->text[i];
1047 if (rc_style->color_flags[i] & GTK_RC_BASE)
1048 style->base[i] = rc_style->base[i];
1051 if (rc_style->engine)
1053 style->engine = rc_style->engine;
1054 gtk_theme_engine_ref (style->engine);
1055 rc_style->engine->rc_style_to_style (style, rc_style);
1061 /* Reuses or frees rc_styles */
1063 gtk_rc_style_init (GSList *rc_styles)
1067 GtkStyle *style = NULL;
1068 GtkRcStyle *proto_style;
1070 if (!realized_style_ht)
1071 realized_style_ht = g_hash_table_new ((GHashFunc)gtk_rc_styles_hash,
1072 (GCompareFunc)gtk_rc_styles_compare);
1074 style = g_hash_table_lookup (realized_style_ht, rc_styles);
1078 GSList *tmp_styles = rc_styles;
1080 proto_style = gtk_rc_style_new ();
1084 GtkRcStyle *rc_style = tmp_styles->data;
1088 if (!proto_style->bg_pixmap_name[i] && rc_style->bg_pixmap_name[i])
1089 proto_style->bg_pixmap_name[i] = g_strdup (rc_style->bg_pixmap_name[i]);
1091 if (!(proto_style->color_flags[i] & GTK_RC_FG) &&
1092 rc_style->color_flags[i] & GTK_RC_FG)
1094 proto_style->fg[i] = rc_style->fg[i];
1095 proto_style->color_flags[i] |= GTK_RC_FG;
1097 if (!(proto_style->color_flags[i] & GTK_RC_BG) &&
1098 rc_style->color_flags[i] & GTK_RC_BG)
1100 proto_style->bg[i] = rc_style->bg[i];
1101 proto_style->color_flags[i] |= GTK_RC_BG;
1103 if (!(proto_style->color_flags[i] & GTK_RC_TEXT) &&
1104 rc_style->color_flags[i] & GTK_RC_TEXT)
1106 proto_style->text[i] = rc_style->text[i];
1107 proto_style->color_flags[i] |= GTK_RC_TEXT;
1109 if (!(proto_style->color_flags[i] & GTK_RC_BASE) &&
1110 rc_style->color_flags[i] & GTK_RC_BASE)
1112 proto_style->base[i] = rc_style->base[i];
1113 proto_style->color_flags[i] |= GTK_RC_BASE;
1117 if (!proto_style->font_name && rc_style->font_name)
1118 proto_style->font_name = g_strdup (rc_style->font_name);
1119 if (!proto_style->fontset_name && rc_style->fontset_name)
1120 proto_style->fontset_name = g_strdup (rc_style->fontset_name);
1122 if (!proto_style->engine && rc_style->engine)
1124 proto_style->engine = rc_style->engine;
1125 gtk_theme_engine_ref (proto_style->engine);
1128 if (proto_style->engine &&
1129 (proto_style->engine == rc_style->engine))
1130 proto_style->engine->merge_rc_style (proto_style, rc_style);
1132 tmp_styles = tmp_styles->next;
1136 if (proto_style->bg_pixmap_name[i] &&
1137 (strcmp (proto_style->bg_pixmap_name[i], "<none>") == 0))
1139 g_free (proto_style->bg_pixmap_name[i]);
1140 proto_style->bg_pixmap_name[i] = NULL;
1143 style = gtk_rc_style_to_style (proto_style);
1145 g_hash_table_insert (realized_style_ht, rc_styles, style);
1151 /*********************
1152 * Parsing functions *
1153 *********************/
1156 gtk_rc_parse_statement (GScanner *scanner)
1160 token = g_scanner_peek_next_token (scanner);
1164 case GTK_RC_TOKEN_INCLUDE:
1165 token = g_scanner_get_next_token (scanner);
1166 if (token != GTK_RC_TOKEN_INCLUDE)
1167 return GTK_RC_TOKEN_INCLUDE;
1169 token = g_scanner_get_next_token (scanner);
1170 if (token != G_TOKEN_STRING)
1171 return G_TOKEN_STRING;
1173 gtk_rc_parse_file (scanner->value.v_string, FALSE);
1174 return G_TOKEN_NONE;
1176 case GTK_RC_TOKEN_STYLE:
1177 return gtk_rc_parse_style (scanner);
1179 case GTK_RC_TOKEN_BINDING:
1180 return gtk_binding_parse_binding (scanner);
1182 case GTK_RC_TOKEN_PIXMAP_PATH:
1183 return gtk_rc_parse_pixmap_path (scanner);
1185 case GTK_RC_TOKEN_WIDGET:
1186 return gtk_rc_parse_path_pattern (scanner);
1188 case GTK_RC_TOKEN_WIDGET_CLASS:
1189 return gtk_rc_parse_path_pattern (scanner);
1191 case GTK_RC_TOKEN_CLASS:
1192 return gtk_rc_parse_path_pattern (scanner);
1194 case GTK_RC_TOKEN_MODULE_PATH:
1195 return gtk_rc_parse_module_path (scanner);
1198 g_scanner_get_next_token (scanner);
1199 return /* G_TOKEN_SYMBOL */ GTK_RC_TOKEN_STYLE;
1204 gtk_rc_parse_style (GScanner *scanner)
1206 GtkRcStyle *rc_style;
1207 GtkRcStyle *parent_style;
1212 token = g_scanner_get_next_token (scanner);
1213 if (token != GTK_RC_TOKEN_STYLE)
1214 return GTK_RC_TOKEN_STYLE;
1216 token = g_scanner_get_next_token (scanner);
1217 if (token != G_TOKEN_STRING)
1218 return G_TOKEN_STRING;
1221 rc_style = g_hash_table_lookup (rc_style_ht, scanner->value.v_string);
1226 rc_style = gtk_rc_style_new ();
1227 rc_style->name = g_strdup (scanner->value.v_string);
1229 for (i = 0; i < 5; i++)
1230 rc_style->bg_pixmap_name[i] = NULL;
1232 for (i = 0; i < 5; i++)
1233 rc_style->color_flags[i] = 0;
1235 rc_style->engine = NULL;
1236 rc_style->engine_data = NULL;
1239 token = g_scanner_peek_next_token (scanner);
1240 if (token == G_TOKEN_EQUAL_SIGN)
1242 token = g_scanner_get_next_token (scanner);
1244 token = g_scanner_get_next_token (scanner);
1245 if (token != G_TOKEN_STRING)
1250 return G_TOKEN_STRING;
1253 parent_style = g_hash_table_lookup (rc_style_ht, scanner->value.v_string);
1256 for (i = 0; i < 5; i++)
1258 rc_style->color_flags[i] = parent_style->color_flags[i];
1259 rc_style->fg[i] = parent_style->fg[i];
1260 rc_style->bg[i] = parent_style->bg[i];
1261 rc_style->text[i] = parent_style->text[i];
1262 rc_style->base[i] = parent_style->base[i];
1265 if (parent_style->fontset_name)
1267 if (rc_style->fontset_name)
1268 g_free (rc_style->fontset_name);
1269 rc_style->fontset_name = g_strdup (parent_style->fontset_name);
1271 else if (parent_style->font_name)
1273 if (rc_style->font_name)
1274 g_free (rc_style->font_name);
1275 rc_style->font_name = g_strdup (parent_style->font_name);
1278 for (i = 0; i < 5; i++)
1280 if (rc_style->bg_pixmap_name[i])
1281 g_free (rc_style->bg_pixmap_name[i]);
1282 rc_style->bg_pixmap_name[i] = g_strdup (parent_style->bg_pixmap_name[i]);
1287 token = g_scanner_get_next_token (scanner);
1288 if (token != G_TOKEN_LEFT_CURLY)
1293 return G_TOKEN_LEFT_CURLY;
1296 token = g_scanner_peek_next_token (scanner);
1297 while (token != G_TOKEN_RIGHT_CURLY)
1301 case GTK_RC_TOKEN_BASE:
1302 token = gtk_rc_parse_base (scanner, rc_style);
1304 case GTK_RC_TOKEN_BG:
1305 token = gtk_rc_parse_bg (scanner, rc_style);
1307 case GTK_RC_TOKEN_FG:
1308 token = gtk_rc_parse_fg (scanner, rc_style);
1310 case GTK_RC_TOKEN_TEXT:
1311 token = gtk_rc_parse_text (scanner, rc_style);
1313 case GTK_RC_TOKEN_BG_PIXMAP:
1314 token = gtk_rc_parse_bg_pixmap (scanner, rc_style);
1316 case GTK_RC_TOKEN_FONT:
1317 token = gtk_rc_parse_font (scanner, rc_style);
1319 case GTK_RC_TOKEN_FONTSET:
1320 token = gtk_rc_parse_fontset (scanner, rc_style);
1322 case GTK_RC_TOKEN_ENGINE:
1323 token = gtk_rc_parse_engine (scanner, rc_style);
1326 g_scanner_get_next_token (scanner);
1327 token = G_TOKEN_RIGHT_CURLY;
1331 if (token != G_TOKEN_NONE)
1335 if (rc_style->fontset_name)
1336 g_free (rc_style->fontset_name);
1337 if (rc_style->font_name)
1338 g_free (rc_style->font_name);
1339 for (i = 0; i < 5; i++)
1340 if (rc_style->bg_pixmap_name[i])
1341 g_free (rc_style->bg_pixmap_name[i]);
1346 token = g_scanner_peek_next_token (scanner);
1349 token = g_scanner_get_next_token (scanner);
1350 if (token != G_TOKEN_RIGHT_CURLY)
1354 if (rc_style->fontset_name)
1355 g_free (rc_style->fontset_name);
1356 if (rc_style->font_name)
1357 g_free (rc_style->font_name);
1359 for (i = 0; i < 5; i++)
1360 if (rc_style->bg_pixmap_name[i])
1361 g_free (rc_style->bg_pixmap_name[i]);
1365 return G_TOKEN_RIGHT_CURLY;
1369 g_hash_table_insert (rc_style_ht, rc_style->name, rc_style);
1371 return G_TOKEN_NONE;
1375 gtk_rc_parse_base (GScanner *scanner,
1381 token = g_scanner_get_next_token (scanner);
1382 if (token != GTK_RC_TOKEN_BASE)
1383 return GTK_RC_TOKEN_BASE;
1385 token = gtk_rc_parse_state (scanner, &state);
1386 if (token != G_TOKEN_NONE)
1389 token = g_scanner_get_next_token (scanner);
1390 if (token != G_TOKEN_EQUAL_SIGN)
1391 return G_TOKEN_EQUAL_SIGN;
1393 style->color_flags[state] |= GTK_RC_BASE;
1394 return gtk_rc_parse_color (scanner, &style->base[state]);
1398 gtk_rc_parse_bg (GScanner *scanner,
1404 token = g_scanner_get_next_token (scanner);
1405 if (token != GTK_RC_TOKEN_BG)
1406 return GTK_RC_TOKEN_BG;
1408 token = gtk_rc_parse_state (scanner, &state);
1409 if (token != G_TOKEN_NONE)
1412 token = g_scanner_get_next_token (scanner);
1413 if (token != G_TOKEN_EQUAL_SIGN)
1414 return G_TOKEN_EQUAL_SIGN;
1416 style->color_flags[state] |= GTK_RC_BG;
1417 return gtk_rc_parse_color (scanner, &style->bg[state]);
1421 gtk_rc_parse_fg (GScanner *scanner,
1427 token = g_scanner_get_next_token (scanner);
1428 if (token != GTK_RC_TOKEN_FG)
1429 return GTK_RC_TOKEN_FG;
1431 token = gtk_rc_parse_state (scanner, &state);
1432 if (token != G_TOKEN_NONE)
1435 token = g_scanner_get_next_token (scanner);
1436 if (token != G_TOKEN_EQUAL_SIGN)
1437 return G_TOKEN_EQUAL_SIGN;
1439 style->color_flags[state] |= GTK_RC_FG;
1440 return gtk_rc_parse_color (scanner, &style->fg[state]);
1444 gtk_rc_parse_text (GScanner *scanner,
1450 token = g_scanner_get_next_token (scanner);
1451 if (token != GTK_RC_TOKEN_TEXT)
1452 return GTK_RC_TOKEN_TEXT;
1454 token = gtk_rc_parse_state (scanner, &state);
1455 if (token != G_TOKEN_NONE)
1458 token = g_scanner_get_next_token (scanner);
1459 if (token != G_TOKEN_EQUAL_SIGN)
1460 return G_TOKEN_EQUAL_SIGN;
1462 style->color_flags[state] |= GTK_RC_TEXT;
1463 return gtk_rc_parse_color (scanner, &style->text[state]);
1467 gtk_rc_parse_bg_pixmap (GScanner *scanner,
1468 GtkRcStyle *rc_style)
1474 token = g_scanner_get_next_token (scanner);
1475 if (token != GTK_RC_TOKEN_BG_PIXMAP)
1476 return GTK_RC_TOKEN_BG_PIXMAP;
1478 token = gtk_rc_parse_state (scanner, &state);
1479 if (token != G_TOKEN_NONE)
1482 token = g_scanner_get_next_token (scanner);
1483 if (token != G_TOKEN_EQUAL_SIGN)
1484 return G_TOKEN_EQUAL_SIGN;
1486 token = g_scanner_get_next_token (scanner);
1487 if (token != G_TOKEN_STRING)
1488 return G_TOKEN_STRING;
1490 if ((strcmp (scanner->value.v_string, "<parent>") == 0) ||
1491 (strcmp (scanner->value.v_string, "<none>") == 0))
1492 pixmap_file = g_strdup (scanner->value.v_string);
1494 pixmap_file = gtk_rc_find_pixmap_in_path (scanner, scanner->value.v_string);
1498 if (rc_style->bg_pixmap_name[state])
1499 g_free (rc_style->bg_pixmap_name[state]);
1500 rc_style->bg_pixmap_name[state] = pixmap_file;
1503 return G_TOKEN_NONE;
1507 gtk_rc_find_pixmap_in_path (GScanner *scanner,
1508 const gchar *pixmap_file)
1514 for (i = 0; (i < GTK_RC_MAX_PIXMAP_PATHS) && (pixmap_path[i] != NULL); i++)
1516 buf = g_strdup_printf ("%s%c%s", pixmap_path[i], '/', pixmap_file);
1518 fd = open (buf, O_RDONLY);
1529 g_warning (_("Unable to locate image file in pixmap_path: \"%s\" line %d"),
1530 pixmap_file, scanner->line);
1532 g_warning (_("Unable to locate image file in pixmap_path: \"%s\""),
1539 gtk_rc_find_module_in_path (const gchar *module_file)
1545 for (i = 0; (i < GTK_RC_MAX_MODULE_PATHS) && (module_path[i] != NULL); i++)
1547 buf = g_strdup_printf ("%s%c%s", module_path[i], '/', module_file);
1549 fd = open (buf, O_RDONLY);
1563 gtk_rc_parse_font (GScanner *scanner,
1564 GtkRcStyle *rc_style)
1568 token = g_scanner_get_next_token (scanner);
1569 if (token != GTK_RC_TOKEN_FONT)
1570 return GTK_RC_TOKEN_FONT;
1572 token = g_scanner_get_next_token (scanner);
1573 if (token != G_TOKEN_EQUAL_SIGN)
1574 return G_TOKEN_EQUAL_SIGN;
1576 token = g_scanner_get_next_token (scanner);
1577 if (token != G_TOKEN_STRING)
1578 return G_TOKEN_STRING;
1580 if (rc_style->font_name)
1581 g_free (rc_style->font_name);
1582 rc_style->font_name = g_strdup (scanner->value.v_string);
1584 return G_TOKEN_NONE;
1588 gtk_rc_parse_fontset (GScanner *scanner,
1589 GtkRcStyle *rc_style)
1593 token = g_scanner_get_next_token (scanner);
1594 if (token != GTK_RC_TOKEN_FONTSET)
1595 return GTK_RC_TOKEN_FONTSET;
1597 token = g_scanner_get_next_token (scanner);
1598 if (token != G_TOKEN_EQUAL_SIGN)
1599 return G_TOKEN_EQUAL_SIGN;
1601 token = g_scanner_get_next_token (scanner);
1602 if (token != G_TOKEN_STRING)
1603 return G_TOKEN_STRING;
1605 if (rc_style->fontset_name)
1606 g_free (rc_style->fontset_name);
1607 rc_style->fontset_name = g_strdup (scanner->value.v_string);
1609 return G_TOKEN_NONE;
1613 gtk_rc_parse_engine (GScanner *scanner,
1614 GtkRcStyle *rc_style)
1618 token = g_scanner_get_next_token (scanner);
1619 if (token != GTK_RC_TOKEN_ENGINE)
1620 return GTK_RC_TOKEN_ENGINE;
1622 token = g_scanner_get_next_token (scanner);
1623 if (token != G_TOKEN_STRING)
1624 return G_TOKEN_STRING;
1626 rc_style->engine = gtk_theme_engine_get (scanner->value.v_string);
1628 token = g_scanner_get_next_token (scanner);
1629 if (token != G_TOKEN_LEFT_CURLY)
1630 return G_TOKEN_LEFT_CURLY;
1632 if (rc_style->engine)
1633 return rc_style->engine->parse_rc_style (scanner, rc_style);
1636 /* Skip over remainder, looking for nested {}'s */
1639 while ((token = g_scanner_get_next_token (scanner)) != G_TOKEN_EOF)
1641 if (token == G_TOKEN_LEFT_CURLY)
1643 else if (token == G_TOKEN_RIGHT_CURLY)
1647 return G_TOKEN_NONE;
1650 return G_TOKEN_RIGHT_CURLY;
1655 gtk_rc_parse_state (GScanner *scanner,
1656 GtkStateType *state)
1661 g_return_val_if_fail (scanner != NULL, G_TOKEN_ERROR);
1662 g_return_val_if_fail (state != NULL, G_TOKEN_ERROR);
1664 /* we don't know where we got called from, so we reset the scope here.
1665 * if we bail out due to errors, we *don't* reset the scope, so the
1666 * error messaging code can make sense of our tokens.
1668 old_scope = g_scanner_set_scope (scanner, 0);
1670 token = g_scanner_get_next_token (scanner);
1671 if (token != G_TOKEN_LEFT_BRACE)
1672 return G_TOKEN_LEFT_BRACE;
1674 token = g_scanner_get_next_token (scanner);
1677 case GTK_RC_TOKEN_ACTIVE:
1678 *state = GTK_STATE_ACTIVE;
1680 case GTK_RC_TOKEN_INSENSITIVE:
1681 *state = GTK_STATE_INSENSITIVE;
1683 case GTK_RC_TOKEN_NORMAL:
1684 *state = GTK_STATE_NORMAL;
1686 case GTK_RC_TOKEN_PRELIGHT:
1687 *state = GTK_STATE_PRELIGHT;
1689 case GTK_RC_TOKEN_SELECTED:
1690 *state = GTK_STATE_SELECTED;
1693 return /* G_TOKEN_SYMBOL */ GTK_RC_TOKEN_NORMAL;
1696 token = g_scanner_get_next_token (scanner);
1697 if (token != G_TOKEN_RIGHT_BRACE)
1698 return G_TOKEN_RIGHT_BRACE;
1700 g_scanner_set_scope (scanner, old_scope);
1702 return G_TOKEN_NONE;
1706 gtk_rc_parse_priority (GScanner *scanner,
1707 GtkPathPriorityType *priority)
1712 g_return_val_if_fail (scanner != NULL, G_TOKEN_ERROR);
1713 g_return_val_if_fail (priority != NULL, G_TOKEN_ERROR);
1715 /* we don't know where we got called from, so we reset the scope here.
1716 * if we bail out due to errors, we *don't* reset the scope, so the
1717 * error messaging code can make sense of our tokens.
1719 old_scope = g_scanner_set_scope (scanner, 0);
1721 token = g_scanner_get_next_token (scanner);
1725 token = g_scanner_get_next_token (scanner);
1728 case GTK_RC_TOKEN_LOWEST:
1729 *priority = GTK_PATH_PRIO_LOWEST;
1731 case GTK_RC_TOKEN_GTK:
1732 *priority = GTK_PATH_PRIO_GTK;
1734 case GTK_RC_TOKEN_APPLICATION:
1735 *priority = GTK_PATH_PRIO_APPLICATION;
1737 case GTK_RC_TOKEN_RC:
1738 *priority = GTK_PATH_PRIO_RC;
1740 case GTK_RC_TOKEN_HIGHEST:
1741 *priority = GTK_PATH_PRIO_HIGHEST;
1744 return /* G_TOKEN_SYMBOL */ GTK_RC_TOKEN_APPLICATION;
1747 g_scanner_set_scope (scanner, old_scope);
1749 return G_TOKEN_NONE;
1753 gtk_rc_parse_color (GScanner *scanner,
1758 g_return_val_if_fail (scanner != NULL, G_TOKEN_ERROR);
1760 /* we don't need to set our own scop here, because
1761 * we don't need own symbols
1764 token = g_scanner_get_next_token (scanner);
1773 case G_TOKEN_LEFT_CURLY:
1774 token = g_scanner_get_next_token (scanner);
1775 if (token == G_TOKEN_INT)
1776 token_int = scanner->value.v_int;
1777 else if (token == G_TOKEN_FLOAT)
1778 token_int = scanner->value.v_float * 65535.0;
1780 return G_TOKEN_FLOAT;
1781 color->red = CLAMP (token_int, 0, 65535);
1783 token = g_scanner_get_next_token (scanner);
1784 if (token != G_TOKEN_COMMA)
1785 return G_TOKEN_COMMA;
1787 token = g_scanner_get_next_token (scanner);
1788 if (token == G_TOKEN_INT)
1789 token_int = scanner->value.v_int;
1790 else if (token == G_TOKEN_FLOAT)
1791 token_int = scanner->value.v_float * 65535.0;
1793 return G_TOKEN_FLOAT;
1794 color->green = CLAMP (token_int, 0, 65535);
1796 token = g_scanner_get_next_token (scanner);
1797 if (token != G_TOKEN_COMMA)
1798 return G_TOKEN_COMMA;
1800 token = g_scanner_get_next_token (scanner);
1801 if (token == G_TOKEN_INT)
1802 token_int = scanner->value.v_int;
1803 else if (token == G_TOKEN_FLOAT)
1804 token_int = scanner->value.v_float * 65535.0;
1806 return G_TOKEN_FLOAT;
1807 color->blue = CLAMP (token_int, 0, 65535);
1809 token = g_scanner_get_next_token (scanner);
1810 if (token != G_TOKEN_RIGHT_CURLY)
1811 return G_TOKEN_RIGHT_CURLY;
1812 return G_TOKEN_NONE;
1814 case G_TOKEN_STRING:
1815 if (scanner->value.v_string[0] != '#')
1816 return G_TOKEN_STRING;
1818 length = strlen (scanner->value.v_string) - 1;
1819 if (((length % 3) != 0) || (length > 12))
1820 return G_TOKEN_STRING;
1823 for (i = 0, j = 1; i < length; i++, j++)
1824 buf[i] = scanner->value.v_string[j];
1827 sscanf (buf, "%x", &temp);
1830 for (i = 0; i < length; i++, j++)
1831 buf[i] = scanner->value.v_string[j];
1834 sscanf (buf, "%x", &temp);
1835 color->green = temp;
1837 for (i = 0; i < length; i++, j++)
1838 buf[i] = scanner->value.v_string[j];
1841 sscanf (buf, "%x", &temp);
1847 color->green *= 4369;
1848 color->blue *= 4369;
1850 else if (length == 2)
1853 color->green *= 257;
1856 else if (length == 3)
1862 return G_TOKEN_NONE;
1865 return G_TOKEN_STRING;
1870 gtk_rc_parse_pixmap_path (GScanner *scanner)
1874 token = g_scanner_get_next_token (scanner);
1875 if (token != GTK_RC_TOKEN_PIXMAP_PATH)
1876 return GTK_RC_TOKEN_PIXMAP_PATH;
1878 token = g_scanner_get_next_token (scanner);
1879 if (token != G_TOKEN_STRING)
1880 return G_TOKEN_STRING;
1882 gtk_rc_parse_pixmap_path_string (scanner->value.v_string);
1884 return G_TOKEN_NONE;
1888 gtk_rc_parse_pixmap_path_string (gchar *pix_path)
1892 gint start_offset = 0;
1896 /* free the old one, or just add to the old one ? */
1897 for (path_num=0; pixmap_path[path_num]; path_num++)
1899 g_free (pixmap_path[path_num]);
1900 pixmap_path[path_num] = NULL;
1905 path_len = strlen (pix_path);
1907 buf = g_strdup (pix_path);
1909 for (end_offset = 0; end_offset <= path_len; end_offset++)
1911 if ((buf[end_offset] == ':') ||
1912 (end_offset == path_len))
1914 buf[end_offset] = '\0';
1915 pixmap_path[path_num] = g_strdup (buf + start_offset);
1917 pixmap_path[path_num] = NULL;
1918 start_offset = end_offset + 1;
1922 gtk_rc_append_default_pixmap_path();
1926 gtk_rc_parse_module_path (GScanner *scanner)
1930 token = g_scanner_get_next_token (scanner);
1931 if (token != GTK_RC_TOKEN_MODULE_PATH)
1932 return GTK_RC_TOKEN_MODULE_PATH;
1934 token = g_scanner_get_next_token (scanner);
1935 if (token != G_TOKEN_STRING)
1936 return G_TOKEN_STRING;
1938 gtk_rc_parse_module_path_string (scanner->value.v_string);
1940 return G_TOKEN_NONE;
1944 gtk_rc_parse_module_path_string (gchar *mod_path)
1948 gint start_offset = 0;
1952 /* free the old one, or just add to the old one ? */
1953 for (path_num=0; module_path[path_num]; path_num++)
1955 g_free (module_path[path_num]);
1956 module_path[path_num] = NULL;
1961 path_len = strlen (mod_path);
1963 buf = g_strdup (mod_path);
1965 for (end_offset = 0; end_offset <= path_len; end_offset++)
1967 if ((buf[end_offset] == ':') ||
1968 (end_offset == path_len))
1970 buf[end_offset] = '\0';
1971 module_path[path_num] = g_strdup (buf + start_offset);
1973 module_path[path_num] = NULL;
1974 start_offset = end_offset + 1;
1978 gtk_rc_append_default_module_path();
1982 gtk_rc_parse_path_pattern (GScanner *scanner)
1985 GtkPathType path_type;
1987 gboolean is_binding;
1988 GtkPathPriorityType priority = GTK_PATH_PRIO_RC;
1990 token = g_scanner_get_next_token (scanner);
1993 case GTK_RC_TOKEN_WIDGET:
1994 path_type = GTK_PATH_WIDGET;
1996 case GTK_RC_TOKEN_WIDGET_CLASS:
1997 path_type = GTK_PATH_WIDGET_CLASS;
1999 case GTK_RC_TOKEN_CLASS:
2000 path_type = GTK_PATH_CLASS;
2003 return GTK_RC_TOKEN_WIDGET_CLASS;
2006 token = g_scanner_get_next_token (scanner);
2007 if (token != G_TOKEN_STRING)
2008 return G_TOKEN_STRING;
2010 pattern = g_strdup (scanner->value.v_string);
2012 token = g_scanner_get_next_token (scanner);
2013 if (token == GTK_RC_TOKEN_STYLE)
2015 else if (token == GTK_RC_TOKEN_BINDING)
2018 if (g_scanner_peek_next_token (scanner) == ':')
2020 token = gtk_rc_parse_priority (scanner, &priority);
2021 if (token != G_TOKEN_NONE)
2031 return GTK_RC_TOKEN_STYLE;
2034 token = g_scanner_get_next_token (scanner);
2035 if (token != G_TOKEN_STRING)
2038 return G_TOKEN_STRING;
2043 GtkBindingSet *binding;
2045 binding = gtk_binding_set_find (scanner->value.v_string);
2049 return G_TOKEN_STRING;
2051 gtk_binding_set_add_path (binding, path_type, pattern, priority);
2055 GtkRcStyle *rc_style;
2058 rc_style = gtk_rc_style_find (scanner->value.v_string);
2063 return G_TOKEN_STRING;
2066 rc_set = g_new (GtkRcSet, 1);
2067 gtk_pattern_spec_init (&rc_set->pspec, pattern);
2068 rc_set->rc_style = rc_style;
2070 if (path_type == GTK_PATH_WIDGET)
2071 gtk_rc_sets_widget = g_slist_prepend (gtk_rc_sets_widget, rc_set);
2072 else if (path_type == GTK_PATH_WIDGET_CLASS)
2073 gtk_rc_sets_widget_class = g_slist_prepend (gtk_rc_sets_widget_class, rc_set);
2075 gtk_rc_sets_class = g_slist_prepend (gtk_rc_sets_class, rc_set);
2079 return G_TOKEN_NONE;
2083 typedef GdkPixmap * (*GtkImageLoader) (GdkWindow *window,
2084 GdkColormap *colormap,
2086 GdkColor *transparent_color,
2087 const gchar *filename);
2091 gtk_rc_set_image_loader(GtkImageLoader loader)
2093 image_loader = loader;
2097 gtk_rc_load_image (GdkColormap *colormap,
2098 GdkColor *transparent_color,
2099 const gchar *filename)
2101 if (strcmp (filename, "<parent>") == 0)
2102 return (GdkPixmap*) GDK_PARENT_RELATIVE;
2106 return image_loader(NULL, colormap, NULL,
2110 return gdk_pixmap_colormap_create_from_xpm (NULL, colormap, NULL,