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 Lesser 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 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser 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-2000. 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/.
29 #ifdef GDK_WINDOWING_X11
30 #include <X11/Xlocale.h> /* so we get the right setlocale */
39 #ifdef HAVE_SYS_PARAM_H
40 #include <sys/param.h>
52 #include "gdkconfig.h"
54 #include "gtkcompat.h"
56 #include "gtkbindings.h"
57 #include "gtkthemes.h"
59 #include "gtkiconfactory.h"
65 typedef struct _GtkRcSet GtkRcSet;
66 typedef struct _GtkRcNode GtkRcNode;
67 typedef struct _GtkRcFile GtkRcFile;
79 gchar *canonical_name;
83 static guint gtk_rc_style_hash (const gchar *name);
84 static gboolean gtk_rc_style_equal (const gchar *a,
86 static guint gtk_rc_styles_hash (const GSList *rc_styles);
87 static gboolean gtk_rc_styles_equal (const GSList *a,
89 static GtkRcStyle* gtk_rc_style_find (const gchar *name);
90 static GSList * gtk_rc_styles_match (GSList *rc_styles,
94 const gchar *path_reversed);
95 static GtkStyle * gtk_rc_style_to_style (GtkRcStyle *rc_style);
96 static GtkStyle* gtk_rc_init_style (GSList *rc_styles);
97 static void gtk_rc_parse_file (const gchar *filename,
99 static void gtk_rc_parse_any (const gchar *input_name,
101 const gchar *input_string);
102 static guint gtk_rc_parse_statement (GScanner *scanner);
103 static guint gtk_rc_parse_style (GScanner *scanner);
104 static guint gtk_rc_parse_bg (GScanner *scanner,
106 static guint gtk_rc_parse_fg (GScanner *scanner,
108 static guint gtk_rc_parse_text (GScanner *scanner,
110 static guint gtk_rc_parse_base (GScanner *scanner,
112 static guint gtk_rc_parse_xthickness (GScanner *scanner,
114 static guint gtk_rc_parse_ythickness (GScanner *scanner,
116 static guint gtk_rc_parse_bg_pixmap (GScanner *scanner,
117 GtkRcStyle *rc_style);
118 static guint gtk_rc_parse_font (GScanner *scanner,
119 GtkRcStyle *rc_style);
120 static guint gtk_rc_parse_fontset (GScanner *scanner,
121 GtkRcStyle *rc_style);
122 static guint gtk_rc_parse_font_name (GScanner *scanner,
123 GtkRcStyle *rc_style);
124 static guint gtk_rc_parse_engine (GScanner *scanner,
125 GtkRcStyle **rc_style);
126 static guint gtk_rc_parse_pixmap_path (GScanner *scanner);
127 static void gtk_rc_parse_pixmap_path_string (gchar *pix_path);
128 static guint gtk_rc_parse_module_path (GScanner *scanner);
129 static void gtk_rc_parse_module_path_string (gchar *mod_path);
130 static guint gtk_rc_parse_im_module_path (GScanner *scanner);
131 static guint gtk_rc_parse_im_module_file (GScanner *scanner);
132 static guint gtk_rc_parse_path_pattern (GScanner *scanner);
133 static guint gtk_rc_parse_stock (GScanner *scanner,
134 GtkRcStyle *rc_style,
135 GtkIconFactory *factory);
136 static void gtk_rc_clear_hash_node (gpointer key,
139 static void gtk_rc_clear_styles (void);
140 static void gtk_rc_append_default_module_path (void);
141 static void gtk_rc_add_initial_default_files (void);
143 static void gtk_rc_style_init (GtkRcStyle *style);
144 static void gtk_rc_style_class_init (GtkRcStyleClass *klass);
145 static void gtk_rc_style_finalize (GObject *object);
146 static void gtk_rc_style_real_merge (GtkRcStyle *dest,
148 static GtkRcStyle *gtk_rc_style_real_clone (GtkRcStyle *rc_style);
149 static GtkStyle * gtk_rc_style_real_create_style (GtkRcStyle *rc_style);
151 static gpointer parent_class = NULL;
153 static const GScannerConfig gtk_rc_scanner_config =
157 ) /* cset_skip_characters */,
162 ) /* cset_identifier_first */,
167 ) /* cset_identifier_nth */,
168 ( "#\n" ) /* cpair_comment_single */,
170 TRUE /* case_sensitive */,
172 TRUE /* skip_comment_multi */,
173 TRUE /* skip_comment_single */,
174 TRUE /* scan_comment_multi */,
175 TRUE /* scan_identifier */,
176 FALSE /* scan_identifier_1char */,
177 FALSE /* scan_identifier_NULL */,
178 TRUE /* scan_symbols */,
179 TRUE /* scan_binary */,
180 TRUE /* scan_octal */,
181 TRUE /* scan_float */,
183 TRUE /* scan_hex_dollar */,
184 TRUE /* scan_string_sq */,
185 TRUE /* scan_string_dq */,
186 TRUE /* numbers_2_int */,
187 FALSE /* int_2_float */,
188 FALSE /* identifier_2_string */,
189 TRUE /* char_2_token */,
190 TRUE /* symbol_2_token */,
191 FALSE /* scope_0_fallback */,
199 { "include", GTK_RC_TOKEN_INCLUDE },
200 { "NORMAL", GTK_RC_TOKEN_NORMAL },
201 { "ACTIVE", GTK_RC_TOKEN_ACTIVE },
202 { "PRELIGHT", GTK_RC_TOKEN_PRELIGHT },
203 { "SELECTED", GTK_RC_TOKEN_SELECTED },
204 { "INSENSITIVE", GTK_RC_TOKEN_INSENSITIVE },
205 { "fg", GTK_RC_TOKEN_FG },
206 { "bg", GTK_RC_TOKEN_BG },
207 { "text", GTK_RC_TOKEN_TEXT },
208 { "base", GTK_RC_TOKEN_BASE },
209 { "xthickness", GTK_RC_TOKEN_XTHICKNESS },
210 { "ythickness", GTK_RC_TOKEN_YTHICKNESS },
211 { "font", GTK_RC_TOKEN_FONT },
212 { "fontset", GTK_RC_TOKEN_FONTSET },
213 { "font_name", GTK_RC_TOKEN_FONT_NAME },
214 { "bg_pixmap", GTK_RC_TOKEN_BG_PIXMAP },
215 { "pixmap_path", GTK_RC_TOKEN_PIXMAP_PATH },
216 { "style", GTK_RC_TOKEN_STYLE },
217 { "binding", GTK_RC_TOKEN_BINDING },
218 { "bind", GTK_RC_TOKEN_BIND },
219 { "widget", GTK_RC_TOKEN_WIDGET },
220 { "widget_class", GTK_RC_TOKEN_WIDGET_CLASS },
221 { "class", GTK_RC_TOKEN_CLASS },
222 { "lowest", GTK_RC_TOKEN_LOWEST },
223 { "gtk", GTK_RC_TOKEN_GTK },
224 { "application", GTK_RC_TOKEN_APPLICATION },
225 { "rc", GTK_RC_TOKEN_RC },
226 { "highest", GTK_RC_TOKEN_HIGHEST },
227 { "engine", GTK_RC_TOKEN_ENGINE },
228 { "module_path", GTK_RC_TOKEN_MODULE_PATH },
229 { "stock", GTK_RC_TOKEN_STOCK },
230 { "im_module_path", GTK_RC_TOKEN_IM_MODULE_PATH },
231 { "im_module_file", GTK_RC_TOKEN_IM_MODULE_FILE },
232 { "LTR", GTK_RC_TOKEN_LTR },
233 { "RTL", GTK_RC_TOKEN_RTL }
236 static const guint n_symbols = sizeof (symbols) / sizeof (symbols[0]);
238 static gchar *im_module_path = NULL;
239 static gchar *im_module_file = NULL;
241 static GHashTable *rc_style_ht = NULL;
242 static GHashTable *realized_style_ht = NULL;
243 static GSList *gtk_rc_sets_widget = NULL;
244 static GSList *gtk_rc_sets_widget_class = NULL;
245 static GSList *gtk_rc_sets_class = NULL;
247 #define GTK_RC_MAX_DEFAULT_FILES 128
248 static gchar *gtk_rc_default_files[GTK_RC_MAX_DEFAULT_FILES];
249 static gboolean gtk_rc_auto_parse = TRUE;
251 #define GTK_RC_MAX_PIXMAP_PATHS 128
252 static gchar *pixmap_path[GTK_RC_MAX_PIXMAP_PATHS];
253 #define GTK_RC_MAX_MODULE_PATHS 128
254 static gchar *module_path[GTK_RC_MAX_MODULE_PATHS];
256 /* A stack of directories for RC files we are parsing currently.
257 * these are implicitely added to the end of PIXMAP_PATHS
259 GSList *rc_dir_stack = NULL;
261 /* The files we have parsed, to reread later if necessary */
262 GSList *rc_files = NULL;
264 static GtkImageLoader image_loader = NULL;
266 /* RC file handling */
272 get_gtk_dll_name (void)
274 static gchar *gtk_dll = NULL;
277 gtk_dll = g_strdup_printf ("gtk-%d.%d.dll", GTK_MAJOR_VERSION, GTK_MINOR_VERSION);
283 get_themes_directory (void)
285 return g_win32_get_package_installation_subdirectory (GETTEXT_PACKAGE,
293 gtk_rc_make_default_dir (const gchar *type)
298 var = getenv("GTK_EXE_PREFIX");
300 path = g_strconcat (var, "/lib/gtk-2.0/" GTK_VERSION "/", type, NULL);
302 path = g_strconcat (GTK_LIBDIR "/gtk-2.0/" GTK_VERSION "/", type, NULL);
304 path = g_strconcat ("%s\\%s", get_themes_directory (), type);
311 gtk_rc_get_im_module_path (void)
313 const gchar *result = g_getenv ("GTK_IM_MODULE_PATH");
318 result = im_module_path;
320 return gtk_rc_make_default_dir ("immodules");
323 return g_strdup (result);
327 gtk_rc_get_im_module_file (void)
329 gchar *result = g_strdup (g_getenv ("GTK_IM_MODULE_FILE"));
334 result = g_strdup (im_module_file);
337 result = g_strdup (GTK_SYSCONFDIR G_DIR_SEPARATOR_S "gtk-2.0" G_DIR_SEPARATOR_S "gtk.immodules");
339 result = g_strdup_printf ("%s\\gtk.immodules", g_win32_get_package_installation_directory (GETTEXT_PACKAGE, get_gtk_dll_name ()));
347 gtk_rc_get_theme_dir(void)
352 var = getenv("GTK_DATA_PREFIX");
354 path = g_strconcat (var, "/share/themes", NULL);
356 path = g_strconcat (GTK_DATA_PREFIX, "/share/themes", NULL);
358 path = g_strdup (get_themes_directory ());
365 gtk_rc_get_module_dir(void)
367 return gtk_rc_make_default_dir ("engines");
371 gtk_rc_append_default_module_path(void)
377 for (n = 0; module_path[n]; n++) ;
378 if (n >= GTK_RC_MAX_MODULE_PATHS - 1)
382 var = getenv("GTK_EXE_PREFIX");
384 path = g_strconcat(var, "/lib/gtk-2.0/" GTK_VERSION "/engines", NULL);
386 path = g_strdup (GTK_LIBDIR "/gtk-2.0/" GTK_VERSION "/engines");
388 path = g_strconcat (get_themes_directory (), "\\engines", NULL);
390 module_path[n++] = path;
392 var = g_get_home_dir ();
396 /* Don't duplicate the directory separator, causes trouble at
399 if (var[strlen (var) -1] != G_DIR_SEPARATOR)
400 sep = G_DIR_SEPARATOR_S;
403 /* This produces something like ~/.gtk-2.0/2.0/engines */
404 path = g_strconcat (var, sep,
405 ".gtk-2.0" G_DIR_SEPARATOR_S
406 GTK_VERSION G_DIR_SEPARATOR_S
408 module_path[n++] = path;
410 module_path[n] = NULL;
414 gtk_rc_add_initial_default_files (void)
416 static gint init = FALSE;
425 gtk_rc_default_files[0] = NULL;
428 var = g_getenv("GTK_RC_FILES");
431 files = g_strsplit (var, G_SEARCHPATH_SEPARATOR_S, 128);
435 gtk_rc_add_default_file (files[i]);
443 str = g_strdup (GTK_SYSCONFDIR G_DIR_SEPARATOR_S "gtk-2.0" G_DIR_SEPARATOR_S "gtkrc");
445 str = g_strdup_printf ("%s\\gtkrc", g_win32_get_package_installation_directory (GETTEXT_PACKAGE, get_gtk_dll_name ()));
448 gtk_rc_add_default_file (str);
451 var = g_get_home_dir ();
455 if (var[strlen (var) -1] != G_DIR_SEPARATOR)
456 sep = G_DIR_SEPARATOR_S;
459 str = g_strdup_printf ("%s%s.gtkrc-2.0", var, sep);
460 gtk_rc_add_default_file (str);
467 gtk_rc_add_default_file (const gchar *file)
471 gtk_rc_add_initial_default_files ();
473 for (n = 0; gtk_rc_default_files[n]; n++) ;
474 if (n >= GTK_RC_MAX_DEFAULT_FILES - 1)
477 gtk_rc_default_files[n++] = g_strdup (file);
478 gtk_rc_default_files[n] = NULL;
482 gtk_rc_set_default_files (gchar **files)
486 gtk_rc_add_initial_default_files ();
489 while (gtk_rc_default_files[i])
491 g_free (gtk_rc_default_files[i]);
495 gtk_rc_default_files[0] = NULL;
496 gtk_rc_auto_parse = FALSE;
499 while (files[i] != NULL)
501 gtk_rc_add_default_file (files[i]);
507 gtk_rc_get_default_files (void)
509 gtk_rc_add_initial_default_files ();
511 return gtk_rc_default_files;
514 /* The following routine is based on _nl_normalize_codeset from
515 * the GNU C library. Contributed by
517 * Contributed by Ulrich Drepper <drepper@gnu.ai.mit.edu>, 1995.
518 * Copyright (C) 1995, 1996, 1997, 1998, 1999 Free Software Foundation, Inc.
520 * Normalize codeset name. There is no standard for the codeset
521 * names. Normalization allows the user to use any of the common
525 _gtk_normalize_codeset (const gchar *codeset, gint name_len)
533 for (cnt = 0; cnt < name_len; ++cnt)
534 if (isalnum (codeset[cnt]))
538 if (isalpha (codeset[cnt]))
542 retval = g_malloc ((only_digit ? 3 : 0) + len + 1);
546 memcpy (retval, "iso", 4);
552 for (cnt = 0; cnt < name_len; ++cnt)
553 if (isalpha (codeset[cnt]))
554 *wp++ = isupper(codeset[cnt]) ? tolower (codeset[cnt]) : codeset[cnt];
555 else if (isdigit (codeset[cnt]))
556 *wp++ = codeset[cnt];
566 static gchar *locale_suffixes[3];
567 static gint n_locale_suffixes = 0;
571 static gboolean initialized = FALSE;
580 locale = g_win32_getlocale ();
582 locale = setlocale (LC_CTYPE, NULL);
586 pixmap_path[0] = NULL;
587 module_path[0] = NULL;
588 gtk_rc_append_default_module_path();
590 gtk_rc_add_initial_default_files ();
592 if (strcmp (locale, "C") && strcmp (locale, "POSIX"))
594 /* Determine locale-specific suffixes for RC files
596 * We normalize the charset into a standard form,
597 * which has all '-' and '_' characters removed,
600 gchar *normalized_locale;
602 p = strchr (locale, '@');
603 length = p ? (p -locale) : strlen (locale);
605 p = strchr (locale, '.');
608 gchar *tmp1 = g_strndup (locale, p - locale + 1);
609 gchar *tmp2 = _gtk_normalize_codeset (p + 1, length - (p - locale + 1));
611 normalized_locale = g_strconcat (tmp1, tmp2, NULL);
615 locale_suffixes[n_locale_suffixes++] = g_strdup (normalized_locale);
619 normalized_locale = g_strndup (locale, length);
621 p = strchr (normalized_locale, '_');
624 locale_suffixes[n_locale_suffixes++] = g_strndup (normalized_locale, length);
625 length = p - normalized_locale;
628 locale_suffixes[n_locale_suffixes++] = g_strndup (normalized_locale, length);
630 g_free (normalized_locale);
635 while (gtk_rc_default_files[i] != NULL)
637 /* Try to find a locale specific RC file corresponding to
638 * to parse before the default file.
640 for (j=n_locale_suffixes-1; j>=0; j--)
642 gchar *name = g_strconcat (gtk_rc_default_files[i],
650 gtk_rc_parse (gtk_rc_default_files[i]);
656 gtk_rc_parse_string (const gchar *rc_string)
658 g_return_if_fail (rc_string != NULL);
660 gtk_rc_parse_any ("-", -1, rc_string);
664 gtk_rc_parse_file (const gchar *filename, gboolean reload)
666 GtkRcFile *rc_file = NULL;
670 g_return_if_fail (filename != NULL);
675 rc_file = tmp_list->data;
676 if (!strcmp (rc_file->name, filename))
679 tmp_list = tmp_list->next;
684 rc_file = g_new (GtkRcFile, 1);
685 rc_file->name = g_strdup (filename);
686 rc_file->canonical_name = NULL;
688 rc_file->reload = reload;
690 rc_files = g_slist_append (rc_files, rc_file);
693 if (!rc_file->canonical_name)
695 /* Get the absolute pathname */
697 if (g_path_is_absolute (rc_file->name))
698 rc_file->canonical_name = rc_file->name;
704 cwd = g_get_current_dir ();
706 str = g_string_new (cwd);
708 g_string_append_c (str, G_DIR_SEPARATOR);
709 g_string_append (str, rc_file->name);
711 rc_file->canonical_name = str->str;
712 g_string_free (str, FALSE);
716 if (!lstat (rc_file->canonical_name, &statbuf))
721 rc_file->mtime = statbuf.st_mtime;
723 fd = open (rc_file->canonical_name, O_RDONLY);
727 /* Temporarily push directory name for this file on
728 * a stack of directory names while parsing it
731 g_slist_prepend (rc_dir_stack,
732 g_path_get_dirname (rc_file->canonical_name));
733 gtk_rc_parse_any (filename, fd, NULL);
735 tmp_list = rc_dir_stack;
736 rc_dir_stack = rc_dir_stack->next;
738 g_free (tmp_list->data);
739 g_slist_free_1 (tmp_list);
746 gtk_rc_parse (const gchar *filename)
748 g_return_if_fail (filename != NULL);
750 gtk_rc_parse_file (filename, TRUE);
753 /* Handling of RC styles */
756 gtk_rc_style_get_type (void)
758 static GType object_type = 0;
762 static const GTypeInfo object_info =
764 sizeof (GtkRcStyleClass),
765 (GBaseInitFunc) NULL,
766 (GBaseFinalizeFunc) NULL,
767 (GClassInitFunc) gtk_rc_style_class_init,
768 NULL, /* class_finalize */
769 NULL, /* class_data */
772 (GInstanceInitFunc) gtk_rc_style_init,
775 object_type = g_type_register_static (G_TYPE_OBJECT,
784 gtk_rc_style_init (GtkRcStyle *style)
789 style->font_desc = NULL;
791 for (i = 0; i < 5; i++)
793 static const GdkColor init_color = { 0, 0, 0, 0, };
795 style->bg_pixmap_name[i] = NULL;
796 style->color_flags[i] = 0;
797 style->fg[i] = init_color;
798 style->bg[i] = init_color;
799 style->text[i] = init_color;
800 style->base[i] = init_color;
802 style->xthickness = -1;
803 style->ythickness = -1;
805 style->rc_style_lists = NULL;
806 style->icon_factories = NULL;
810 gtk_rc_style_class_init (GtkRcStyleClass *klass)
812 GObjectClass *object_class = G_OBJECT_CLASS (klass);
814 parent_class = g_type_class_peek_parent (klass);
816 object_class->finalize = gtk_rc_style_finalize;
819 klass->clone = gtk_rc_style_real_clone;
820 klass->merge = gtk_rc_style_real_merge;
821 klass->create_style = gtk_rc_style_real_create_style;
824 /* Like g_slist_remove, but remove all copies of data */
826 gtk_rc_slist_remove_all (GSList *list,
837 if (tmp->data == data)
843 prev->next = tmp->next;
845 g_slist_free_1 (tmp);
863 gtk_rc_style_finalize (GObject *object)
866 GSList *tmp_list1, *tmp_list2;
867 GtkRcStyle *rc_style;
869 rc_style = GTK_RC_STYLE (object);
872 g_free (rc_style->name);
873 if (rc_style->font_desc)
874 pango_font_description_free (rc_style->font_desc);
876 for (i=0 ; i < 5 ; i++)
877 if (rc_style->bg_pixmap_name[i])
878 g_free (rc_style->bg_pixmap_name[i]);
880 /* Now remove all references to this rc_style from
883 tmp_list1 = rc_style->rc_style_lists;
886 GSList *rc_styles = tmp_list1->data;
887 GtkStyle *style = g_hash_table_lookup (realized_style_ht, rc_styles);
888 gtk_style_unref (style);
890 /* Remove the list of styles from the other rc_styles
893 tmp_list2 = rc_styles;
896 GtkRcStyle *other_style = tmp_list2->data;
898 if (other_style != rc_style)
899 other_style->rc_style_lists =
900 gtk_rc_slist_remove_all (other_style->rc_style_lists, rc_styles);
902 tmp_list2 = tmp_list2->next;
905 /* And from the hash table itself
907 g_hash_table_remove (realized_style_ht, rc_styles);
908 g_slist_free (rc_styles);
910 tmp_list1 = tmp_list1->next;
913 g_slist_free (rc_style->rc_style_lists);
915 tmp_list1 = rc_style->icon_factories;
918 g_object_unref (G_OBJECT (tmp_list1->data));
920 tmp_list1 = tmp_list1->next;
923 g_slist_free (rc_style->icon_factories);
925 G_OBJECT_CLASS (parent_class)->finalize (object);
929 gtk_rc_style_new (void)
933 style = g_object_new (GTK_TYPE_RC_STYLE, NULL);
940 * @orig: the style to copy
942 * Make a copy of the specified #GtkRcStyle. This function
943 * will correctly copy an rc style that is a member of a class
944 * derived from #GtkRcStyle.
946 * Return value: the resulting #GtkRcStyle
949 gtk_rc_style_copy (GtkRcStyle *orig)
953 g_return_val_if_fail (GTK_IS_RC_STYLE (orig), NULL);
955 style = GTK_RC_STYLE_GET_CLASS (orig)->clone (orig);
956 GTK_RC_STYLE_GET_CLASS (style)->merge (style, orig);
962 gtk_rc_style_ref (GtkRcStyle *rc_style)
964 g_return_if_fail (GTK_IS_RC_STYLE (rc_style));
966 g_object_ref (G_OBJECT (rc_style));
970 gtk_rc_style_unref (GtkRcStyle *rc_style)
972 g_return_if_fail (GTK_IS_RC_STYLE (rc_style));
974 g_object_unref (G_OBJECT (rc_style));
978 gtk_rc_style_real_clone (GtkRcStyle *style)
980 return GTK_RC_STYLE (g_object_new (G_OBJECT_TYPE (style), NULL));
984 gtk_rc_style_real_merge (GtkRcStyle *dest,
989 for (i = 0; i < 5; i++)
991 if (!dest->bg_pixmap_name[i] && src->bg_pixmap_name[i])
992 dest->bg_pixmap_name[i] = g_strdup (src->bg_pixmap_name[i]);
994 if (!(dest->color_flags[i] & GTK_RC_FG) &&
995 src->color_flags[i] & GTK_RC_FG)
997 dest->fg[i] = src->fg[i];
998 dest->color_flags[i] |= GTK_RC_FG;
1000 if (!(dest->color_flags[i] & GTK_RC_BG) &&
1001 src->color_flags[i] & GTK_RC_BG)
1003 dest->bg[i] = src->bg[i];
1004 dest->color_flags[i] |= GTK_RC_BG;
1006 if (!(dest->color_flags[i] & GTK_RC_TEXT) &&
1007 src->color_flags[i] & GTK_RC_TEXT)
1009 dest->text[i] = src->text[i];
1010 dest->color_flags[i] |= GTK_RC_TEXT;
1012 if (!(dest->color_flags[i] & GTK_RC_BASE) &&
1013 src->color_flags[i] & GTK_RC_BASE)
1015 dest->base[i] = src->base[i];
1016 dest->color_flags[i] |= GTK_RC_BASE;
1020 if (dest->xthickness < 0 && src->xthickness >= 0)
1021 dest->xthickness = src->xthickness;
1022 if (dest->ythickness < 0 && src->ythickness >= 0)
1023 dest->ythickness = src->ythickness;
1025 if (!dest->font_desc && src->font_desc)
1026 dest->font_desc = pango_font_description_copy (src->font_desc);
1030 gtk_rc_style_real_create_style (GtkRcStyle *rc_style)
1032 return gtk_style_new ();
1036 gtk_rc_clear_hash_node (gpointer key,
1040 gtk_rc_style_unref (data);
1044 gtk_rc_free_rc_sets (GSList *slist)
1050 rc_set = slist->data;
1051 gtk_pattern_spec_free_segs (&rc_set->pspec);
1054 slist = slist->next;
1059 gtk_rc_clear_styles (void)
1061 /* Clear out all old rc_styles */
1065 g_hash_table_foreach (rc_style_ht, gtk_rc_clear_hash_node, NULL);
1066 g_hash_table_destroy (rc_style_ht);
1070 gtk_rc_free_rc_sets (gtk_rc_sets_widget);
1071 g_slist_free (gtk_rc_sets_widget);
1072 gtk_rc_sets_widget = NULL;
1074 gtk_rc_free_rc_sets (gtk_rc_sets_widget_class);
1075 g_slist_free (gtk_rc_sets_widget_class);
1076 gtk_rc_sets_widget_class = NULL;
1078 gtk_rc_free_rc_sets (gtk_rc_sets_class);
1079 g_slist_free (gtk_rc_sets_class);
1080 gtk_rc_sets_class = NULL;
1084 gtk_rc_reparse_all (void)
1087 gboolean mtime_modified = FALSE;
1090 struct stat statbuf;
1092 /* Check through and see if any of the RC's have had their
1093 * mtime modified. If so, reparse everything.
1095 tmp_list = rc_files;
1098 rc_file = tmp_list->data;
1100 if (!lstat (rc_file->name, &statbuf) &&
1101 (statbuf.st_mtime > rc_file->mtime))
1103 mtime_modified = TRUE;
1107 tmp_list = tmp_list->next;
1112 gtk_rc_clear_styles();
1114 tmp_list = rc_files;
1117 rc_file = tmp_list->data;
1118 if (rc_file->reload)
1119 gtk_rc_parse_file (rc_file->name, FALSE);
1121 tmp_list = tmp_list->next;
1125 return mtime_modified;
1129 gtk_rc_styles_match (GSList *rc_styles,
1133 const gchar *path_reversed)
1140 rc_set = sets->data;
1143 if (gtk_pattern_match (&rc_set->pspec, path_length, path, path_reversed))
1144 rc_styles = g_slist_append (rc_styles, rc_set->rc_style);
1151 gtk_rc_get_style (GtkWidget *widget)
1153 GtkRcStyle *widget_rc_style;
1154 GSList *rc_styles = NULL;
1156 static guint rc_style_key_id = 0;
1158 /* We allow the specification of a single rc style to be bound
1159 * tightly to a widget, for application modifications
1161 if (!rc_style_key_id)
1162 rc_style_key_id = g_quark_from_static_string ("gtk-rc-style");
1164 widget_rc_style = gtk_object_get_data_by_id (GTK_OBJECT (widget),
1167 if (widget_rc_style)
1168 rc_styles = g_slist_prepend (rc_styles, widget_rc_style);
1170 if (gtk_rc_sets_widget)
1172 gchar *path, *path_reversed;
1175 gtk_widget_path (widget, &path_length, &path, &path_reversed);
1176 rc_styles = gtk_rc_styles_match (rc_styles, gtk_rc_sets_widget, path_length, path, path_reversed);
1178 g_free (path_reversed);
1182 if (gtk_rc_sets_widget_class)
1184 gchar *path, *path_reversed;
1187 gtk_widget_class_path (widget, &path_length, &path, &path_reversed);
1188 rc_styles = gtk_rc_styles_match (rc_styles, gtk_rc_sets_widget_class, path_length, path, path_reversed);
1190 g_free (path_reversed);
1193 if (gtk_rc_sets_class)
1197 type = GTK_OBJECT_TYPE (widget);
1201 gchar *path_reversed;
1204 path = gtk_type_name (type);
1205 path_length = strlen (path);
1206 path_reversed = g_strdup (path);
1207 g_strreverse (path_reversed);
1209 rc_styles = gtk_rc_styles_match (rc_styles, gtk_rc_sets_class, path_length, path, path_reversed);
1210 g_free (path_reversed);
1212 type = gtk_type_parent (type);
1217 return gtk_rc_init_style (rc_styles);
1223 gtk_rc_add_rc_sets (GSList *slist,
1224 GtkRcStyle *rc_style,
1225 const gchar *pattern)
1227 GtkRcStyle *new_style;
1231 new_style = gtk_rc_style_new ();
1232 *new_style = *rc_style;
1233 new_style->name = g_strdup (rc_style->name);
1234 if (rc_style->font_desc)
1235 new_style->font_desc = pango_font_description_copy (rc_style->font_desc);
1237 for (i = 0; i < 5; i++)
1238 new_style->bg_pixmap_name[i] = g_strdup (rc_style->bg_pixmap_name[i]);
1240 rc_set = g_new (GtkRcSet, 1);
1241 gtk_pattern_spec_init (&rc_set->pspec, pattern);
1242 rc_set->rc_style = rc_style;
1244 return g_slist_prepend (slist, rc_set);
1248 gtk_rc_add_widget_name_style (GtkRcStyle *rc_style,
1249 const gchar *pattern)
1251 g_return_if_fail (rc_style != NULL);
1252 g_return_if_fail (pattern != NULL);
1254 gtk_rc_sets_widget = gtk_rc_add_rc_sets (gtk_rc_sets_widget, rc_style, pattern);
1258 gtk_rc_add_widget_class_style (GtkRcStyle *rc_style,
1259 const gchar *pattern)
1261 g_return_if_fail (rc_style != NULL);
1262 g_return_if_fail (pattern != NULL);
1264 gtk_rc_sets_widget_class = gtk_rc_add_rc_sets (gtk_rc_sets_widget_class, rc_style, pattern);
1268 gtk_rc_add_class_style (GtkRcStyle *rc_style,
1269 const gchar *pattern)
1271 g_return_if_fail (rc_style != NULL);
1272 g_return_if_fail (pattern != NULL);
1274 gtk_rc_sets_class = gtk_rc_add_rc_sets (gtk_rc_sets_class, rc_style, pattern);
1278 gtk_rc_parse_any (const gchar *input_name,
1280 const gchar *input_string)
1286 scanner = g_scanner_new ((GScannerConfig *) >k_rc_scanner_config);
1290 g_assert (input_string == NULL);
1292 g_scanner_input_file (scanner, input_fd);
1296 g_assert (input_string != NULL);
1298 g_scanner_input_text (scanner, input_string, strlen (input_string));
1300 scanner->input_name = input_name;
1302 for (i = 0; i < n_symbols; i++)
1303 g_scanner_add_symbol (scanner, symbols[i].name, GINT_TO_POINTER (symbols[i].token));
1308 if (g_scanner_peek_next_token (scanner) == G_TOKEN_EOF)
1312 guint expected_token;
1314 expected_token = gtk_rc_parse_statement (scanner);
1316 if (expected_token != G_TOKEN_NONE)
1323 if (scanner->scope_id == 0)
1325 /* if we are in scope 0, we know the symbol names
1326 * that are associated with certaintoken values.
1327 * so we look them up to make the error messages
1330 if (expected_token > GTK_RC_TOKEN_INVALID &&
1331 expected_token < GTK_RC_TOKEN_LAST)
1333 for (i = 0; i < n_symbols; i++)
1334 if (symbols[i].token == expected_token)
1335 msg = symbols[i].name;
1337 msg = g_strconcat ("e.g. `", msg, "'", NULL);
1339 if (scanner->token > GTK_RC_TOKEN_INVALID &&
1340 scanner->token < GTK_RC_TOKEN_LAST)
1342 symbol_name = "???";
1343 for (i = 0; i < n_symbols; i++)
1344 if (symbols[i].token == scanner->token)
1345 symbol_name = symbols[i].name;
1348 g_scanner_unexp_token (scanner,
1361 g_scanner_destroy (scanner);
1365 gtk_rc_styles_hash (const GSList *rc_styles)
1372 result += (result << 9) + GPOINTER_TO_UINT (rc_styles->data);
1373 rc_styles = rc_styles->next;
1380 gtk_rc_styles_equal (const GSList *a,
1385 if (a->data != b->data)
1395 gtk_rc_style_hash (const gchar *name)
1401 result += (result << 3) + *name++;
1407 gtk_rc_style_equal (const gchar *a,
1410 return (strcmp (a, b) == 0);
1414 gtk_rc_style_find (const gchar *name)
1417 return g_hash_table_lookup (rc_style_ht, (gpointer) name);
1423 gtk_rc_style_to_style (GtkRcStyle *rc_style)
1427 style = GTK_RC_STYLE_GET_CLASS (rc_style)->create_style (rc_style);
1429 style->rc_style = rc_style;
1431 gtk_rc_style_ref (rc_style);
1433 GTK_STYLE_GET_CLASS (style)->init_from_rc (style, rc_style);
1438 /* Reuses or frees rc_styles */
1440 gtk_rc_init_style (GSList *rc_styles)
1442 GtkStyle *style = NULL;
1445 g_return_val_if_fail (rc_styles != NULL, NULL);
1447 if (!realized_style_ht)
1448 realized_style_ht = g_hash_table_new ((GHashFunc) gtk_rc_styles_hash,
1449 (GEqualFunc) gtk_rc_styles_equal);
1451 style = g_hash_table_lookup (realized_style_ht, rc_styles);
1455 GtkRcStyle *base_style = NULL;
1456 GtkRcStyle *proto_style;
1457 GtkRcStyleClass *proto_style_class;
1459 GType rc_style_type = GTK_TYPE_RC_STYLE;
1461 /* Find the first derived style in the list, and use that to
1462 * create the merged style. If we only have raw GtkRcStyles, use
1463 * the first style to create the merged style.
1465 base_style = rc_styles->data;
1466 tmp_styles = rc_styles;
1469 GtkRcStyle *rc_style = tmp_styles->data;
1471 if (G_OBJECT_TYPE (rc_style) != rc_style_type)
1473 base_style = rc_style;
1477 tmp_styles = tmp_styles->next;
1480 proto_style_class = GTK_RC_STYLE_GET_CLASS (base_style);
1481 proto_style = proto_style_class->clone (base_style);
1483 tmp_styles = rc_styles;
1486 GtkRcStyle *rc_style = tmp_styles->data;
1489 proto_style_class->merge (proto_style, rc_style);
1491 /* Point from each rc_style to the list of styles */
1492 if (!g_slist_find (rc_style->rc_style_lists, rc_styles))
1493 rc_style->rc_style_lists = g_slist_prepend (rc_style->rc_style_lists, rc_styles);
1495 factories = g_slist_copy (rc_style->icon_factories);
1501 while (iter != NULL)
1503 g_object_ref (G_OBJECT (iter->data));
1504 iter = g_slist_next (iter);
1507 proto_style->icon_factories = g_slist_concat (proto_style->icon_factories,
1512 tmp_styles = tmp_styles->next;
1515 for (i = 0; i < 5; i++)
1516 if (proto_style->bg_pixmap_name[i] &&
1517 (strcmp (proto_style->bg_pixmap_name[i], "<none>") == 0))
1519 g_free (proto_style->bg_pixmap_name[i]);
1520 proto_style->bg_pixmap_name[i] = NULL;
1523 style = gtk_rc_style_to_style (proto_style);
1524 gtk_rc_style_unref (proto_style);
1526 g_hash_table_insert (realized_style_ht, rc_styles, style);
1529 g_slist_free (rc_styles);
1534 /*********************
1535 * Parsing functions *
1536 *********************/
1539 gtk_rc_parse_statement (GScanner *scanner)
1543 token = g_scanner_peek_next_token (scanner);
1547 case GTK_RC_TOKEN_INCLUDE:
1548 token = g_scanner_get_next_token (scanner);
1549 if (token != GTK_RC_TOKEN_INCLUDE)
1550 return GTK_RC_TOKEN_INCLUDE;
1552 token = g_scanner_get_next_token (scanner);
1553 if (token != G_TOKEN_STRING)
1554 return G_TOKEN_STRING;
1556 gtk_rc_parse_file (scanner->value.v_string, FALSE);
1557 return G_TOKEN_NONE;
1559 case GTK_RC_TOKEN_STYLE:
1560 return gtk_rc_parse_style (scanner);
1562 case GTK_RC_TOKEN_BINDING:
1563 return gtk_binding_parse_binding (scanner);
1565 case GTK_RC_TOKEN_PIXMAP_PATH:
1566 return gtk_rc_parse_pixmap_path (scanner);
1568 case GTK_RC_TOKEN_WIDGET:
1569 return gtk_rc_parse_path_pattern (scanner);
1571 case GTK_RC_TOKEN_WIDGET_CLASS:
1572 return gtk_rc_parse_path_pattern (scanner);
1574 case GTK_RC_TOKEN_CLASS:
1575 return gtk_rc_parse_path_pattern (scanner);
1577 case GTK_RC_TOKEN_MODULE_PATH:
1578 return gtk_rc_parse_module_path (scanner);
1580 case GTK_RC_TOKEN_IM_MODULE_PATH:
1581 return gtk_rc_parse_im_module_path (scanner);
1583 case GTK_RC_TOKEN_IM_MODULE_FILE:
1584 return gtk_rc_parse_im_module_file (scanner);
1587 g_scanner_get_next_token (scanner);
1588 return /* G_TOKEN_SYMBOL */ GTK_RC_TOKEN_STYLE;
1593 gtk_rc_parse_style (GScanner *scanner)
1595 GtkRcStyle *rc_style;
1596 GtkRcStyle *parent_style;
1600 GtkIconFactory *our_factory = NULL;
1602 token = g_scanner_get_next_token (scanner);
1603 if (token != GTK_RC_TOKEN_STYLE)
1604 return GTK_RC_TOKEN_STYLE;
1606 token = g_scanner_get_next_token (scanner);
1607 if (token != G_TOKEN_STRING)
1608 return G_TOKEN_STRING;
1611 rc_style = gtk_rc_style_find (scanner->value.v_string);
1613 /* If there's a list, its first member is always the factory belonging
1616 if (rc_style && rc_style->icon_factories)
1617 our_factory = rc_style->icon_factories->data;
1622 rc_style = gtk_rc_style_new ();
1623 rc_style->name = g_strdup (scanner->value.v_string);
1625 for (i = 0; i < 5; i++)
1626 rc_style->bg_pixmap_name[i] = NULL;
1628 for (i = 0; i < 5; i++)
1629 rc_style->color_flags[i] = 0;
1632 token = g_scanner_peek_next_token (scanner);
1633 if (token == G_TOKEN_EQUAL_SIGN)
1635 token = g_scanner_get_next_token (scanner);
1637 token = g_scanner_get_next_token (scanner);
1638 if (token != G_TOKEN_STRING)
1643 return G_TOKEN_STRING;
1646 parent_style = gtk_rc_style_find (scanner->value.v_string);
1651 for (i = 0; i < 5; i++)
1653 rc_style->color_flags[i] = parent_style->color_flags[i];
1654 rc_style->fg[i] = parent_style->fg[i];
1655 rc_style->bg[i] = parent_style->bg[i];
1656 rc_style->text[i] = parent_style->text[i];
1657 rc_style->base[i] = parent_style->base[i];
1660 rc_style->xthickness = parent_style->xthickness;
1661 rc_style->ythickness = parent_style->ythickness;
1663 if (parent_style->font_desc)
1665 if (rc_style->font_desc)
1666 pango_font_description_free (rc_style->font_desc);
1667 rc_style->font_desc = pango_font_description_copy (parent_style->font_desc);
1670 for (i = 0; i < 5; i++)
1672 if (rc_style->bg_pixmap_name[i])
1673 g_free (rc_style->bg_pixmap_name[i]);
1674 rc_style->bg_pixmap_name[i] = g_strdup (parent_style->bg_pixmap_name[i]);
1677 /* Append parent's factories, adding a ref to them */
1678 if (parent_style->icon_factories != NULL)
1680 /* Add a factory for ourselves if we have none,
1681 * in case we end up defining more stock icons.
1682 * I see no real way around this; we need to maintain
1683 * the invariant that the first factory in the list
1684 * is always our_factory, the one belonging to us,
1685 * and if we put parent factories in the list we can't
1686 * do that if the style is reopened.
1688 if (our_factory == NULL)
1690 our_factory = gtk_icon_factory_new ();
1691 rc_style->icon_factories = g_slist_prepend (rc_style->icon_factories,
1695 rc_style->icon_factories = g_slist_concat (rc_style->icon_factories,
1696 g_slist_copy (parent_style->icon_factories));
1698 factories = parent_style->icon_factories;
1699 while (factories != NULL)
1701 g_object_ref (G_OBJECT (factories->data));
1702 factories = factories->next;
1708 token = g_scanner_get_next_token (scanner);
1709 if (token != G_TOKEN_LEFT_CURLY)
1714 return G_TOKEN_LEFT_CURLY;
1717 token = g_scanner_peek_next_token (scanner);
1718 while (token != G_TOKEN_RIGHT_CURLY)
1722 case GTK_RC_TOKEN_BG:
1723 token = gtk_rc_parse_bg (scanner, rc_style);
1725 case GTK_RC_TOKEN_FG:
1726 token = gtk_rc_parse_fg (scanner, rc_style);
1728 case GTK_RC_TOKEN_TEXT:
1729 token = gtk_rc_parse_text (scanner, rc_style);
1731 case GTK_RC_TOKEN_BASE:
1732 token = gtk_rc_parse_base (scanner, rc_style);
1734 case GTK_RC_TOKEN_XTHICKNESS:
1735 token = gtk_rc_parse_xthickness (scanner, rc_style);
1737 case GTK_RC_TOKEN_YTHICKNESS:
1738 token = gtk_rc_parse_ythickness (scanner, rc_style);
1740 case GTK_RC_TOKEN_BG_PIXMAP:
1741 token = gtk_rc_parse_bg_pixmap (scanner, rc_style);
1743 case GTK_RC_TOKEN_FONT:
1744 token = gtk_rc_parse_font (scanner, rc_style);
1746 case GTK_RC_TOKEN_FONTSET:
1747 token = gtk_rc_parse_fontset (scanner, rc_style);
1749 case GTK_RC_TOKEN_FONT_NAME:
1750 token = gtk_rc_parse_font_name (scanner, rc_style);
1752 case GTK_RC_TOKEN_ENGINE:
1753 token = gtk_rc_parse_engine (scanner, &rc_style);
1755 case GTK_RC_TOKEN_STOCK:
1756 if (our_factory == NULL)
1758 our_factory = gtk_icon_factory_new ();
1759 rc_style->icon_factories = g_slist_prepend (rc_style->icon_factories,
1762 token = gtk_rc_parse_stock (scanner, rc_style, our_factory);
1765 g_scanner_get_next_token (scanner);
1766 token = G_TOKEN_RIGHT_CURLY;
1770 if (token != G_TOKEN_NONE)
1774 if (rc_style->font_desc)
1775 pango_font_description_free (rc_style->font_desc);
1777 for (i = 0; i < 5; i++)
1778 if (rc_style->bg_pixmap_name[i])
1779 g_free (rc_style->bg_pixmap_name[i]);
1784 token = g_scanner_peek_next_token (scanner);
1787 token = g_scanner_get_next_token (scanner);
1788 if (token != G_TOKEN_RIGHT_CURLY)
1792 if (rc_style->font_desc)
1793 pango_font_description_free (rc_style->font_desc);
1795 for (i = 0; i < 5; i++)
1796 if (rc_style->bg_pixmap_name[i])
1797 g_free (rc_style->bg_pixmap_name[i]);
1801 return G_TOKEN_RIGHT_CURLY;
1807 rc_style_ht = g_hash_table_new ((GHashFunc) gtk_rc_style_hash,
1808 (GEqualFunc) gtk_rc_style_equal);
1810 g_hash_table_insert (rc_style_ht, rc_style->name, rc_style);
1813 return G_TOKEN_NONE;
1817 gtk_rc_parse_bg (GScanner *scanner,
1823 token = g_scanner_get_next_token (scanner);
1824 if (token != GTK_RC_TOKEN_BG)
1825 return GTK_RC_TOKEN_BG;
1827 token = gtk_rc_parse_state (scanner, &state);
1828 if (token != G_TOKEN_NONE)
1831 token = g_scanner_get_next_token (scanner);
1832 if (token != G_TOKEN_EQUAL_SIGN)
1833 return G_TOKEN_EQUAL_SIGN;
1835 style->color_flags[state] |= GTK_RC_BG;
1836 return gtk_rc_parse_color (scanner, &style->bg[state]);
1840 gtk_rc_parse_fg (GScanner *scanner,
1846 token = g_scanner_get_next_token (scanner);
1847 if (token != GTK_RC_TOKEN_FG)
1848 return GTK_RC_TOKEN_FG;
1850 token = gtk_rc_parse_state (scanner, &state);
1851 if (token != G_TOKEN_NONE)
1854 token = g_scanner_get_next_token (scanner);
1855 if (token != G_TOKEN_EQUAL_SIGN)
1856 return G_TOKEN_EQUAL_SIGN;
1858 style->color_flags[state] |= GTK_RC_FG;
1859 return gtk_rc_parse_color (scanner, &style->fg[state]);
1863 gtk_rc_parse_text (GScanner *scanner,
1869 token = g_scanner_get_next_token (scanner);
1870 if (token != GTK_RC_TOKEN_TEXT)
1871 return GTK_RC_TOKEN_TEXT;
1873 token = gtk_rc_parse_state (scanner, &state);
1874 if (token != G_TOKEN_NONE)
1877 token = g_scanner_get_next_token (scanner);
1878 if (token != G_TOKEN_EQUAL_SIGN)
1879 return G_TOKEN_EQUAL_SIGN;
1881 style->color_flags[state] |= GTK_RC_TEXT;
1882 return gtk_rc_parse_color (scanner, &style->text[state]);
1886 gtk_rc_parse_base (GScanner *scanner,
1892 token = g_scanner_get_next_token (scanner);
1893 if (token != GTK_RC_TOKEN_BASE)
1894 return GTK_RC_TOKEN_BASE;
1896 token = gtk_rc_parse_state (scanner, &state);
1897 if (token != G_TOKEN_NONE)
1900 token = g_scanner_get_next_token (scanner);
1901 if (token != G_TOKEN_EQUAL_SIGN)
1902 return G_TOKEN_EQUAL_SIGN;
1904 style->color_flags[state] |= GTK_RC_BASE;
1905 return gtk_rc_parse_color (scanner, &style->base[state]);
1909 gtk_rc_parse_xthickness (GScanner *scanner,
1912 if (g_scanner_get_next_token (scanner) != GTK_RC_TOKEN_XTHICKNESS)
1913 return GTK_RC_TOKEN_XTHICKNESS;
1915 if (g_scanner_get_next_token (scanner) != G_TOKEN_EQUAL_SIGN)
1916 return G_TOKEN_EQUAL_SIGN;
1918 if (g_scanner_get_next_token (scanner) != G_TOKEN_INT)
1921 style->xthickness = scanner->value.v_int;
1923 return G_TOKEN_NONE;
1927 gtk_rc_parse_ythickness (GScanner *scanner,
1930 if (g_scanner_get_next_token (scanner) != GTK_RC_TOKEN_YTHICKNESS)
1931 return GTK_RC_TOKEN_YTHICKNESS;
1933 if (g_scanner_get_next_token (scanner) != G_TOKEN_EQUAL_SIGN)
1934 return G_TOKEN_EQUAL_SIGN;
1936 if (g_scanner_get_next_token (scanner) != G_TOKEN_INT)
1939 style->ythickness = scanner->value.v_int;
1941 return G_TOKEN_NONE;
1945 gtk_rc_parse_bg_pixmap (GScanner *scanner,
1946 GtkRcStyle *rc_style)
1952 token = g_scanner_get_next_token (scanner);
1953 if (token != GTK_RC_TOKEN_BG_PIXMAP)
1954 return GTK_RC_TOKEN_BG_PIXMAP;
1956 token = gtk_rc_parse_state (scanner, &state);
1957 if (token != G_TOKEN_NONE)
1960 token = g_scanner_get_next_token (scanner);
1961 if (token != G_TOKEN_EQUAL_SIGN)
1962 return G_TOKEN_EQUAL_SIGN;
1964 token = g_scanner_get_next_token (scanner);
1965 if (token != G_TOKEN_STRING)
1966 return G_TOKEN_STRING;
1968 if ((strcmp (scanner->value.v_string, "<parent>") == 0) ||
1969 (strcmp (scanner->value.v_string, "<none>") == 0))
1970 pixmap_file = g_strdup (scanner->value.v_string);
1972 pixmap_file = gtk_rc_find_pixmap_in_path (scanner, scanner->value.v_string);
1976 if (rc_style->bg_pixmap_name[state])
1977 g_free (rc_style->bg_pixmap_name[state]);
1978 rc_style->bg_pixmap_name[state] = pixmap_file;
1981 return G_TOKEN_NONE;
1985 gtk_rc_check_pixmap_dir (const gchar *dir, const gchar *pixmap_file)
1990 buf = g_strdup_printf ("%s" G_DIR_SEPARATOR_S "%s", dir, pixmap_file);
1992 fd = open (buf, O_RDONLY);
2005 gtk_rc_find_pixmap_in_path (GScanner *scanner,
2006 const gchar *pixmap_file)
2012 for (i = 0; (i < GTK_RC_MAX_PIXMAP_PATHS) && (pixmap_path[i] != NULL); i++)
2014 filename = gtk_rc_check_pixmap_dir (pixmap_path[i], pixmap_file);
2019 tmp_list = rc_dir_stack;
2022 filename = gtk_rc_check_pixmap_dir (tmp_list->data, pixmap_file);
2026 tmp_list = tmp_list->next;
2030 g_warning (_("Unable to locate image file in pixmap_path: \"%s\" line %d"),
2031 pixmap_file, scanner->line);
2033 g_warning (_("Unable to locate image file in pixmap_path: \"%s\""),
2040 gtk_rc_find_module_in_path (const gchar *module_file)
2046 for (i = 0; (i < GTK_RC_MAX_MODULE_PATHS) && (module_path[i] != NULL); i++)
2048 buf = g_strdup_printf ("%s" G_DIR_SEPARATOR_S "%s",
2049 module_path[i], module_file);
2051 fd = open (buf, O_RDONLY);
2065 gtk_rc_parse_font (GScanner *scanner,
2066 GtkRcStyle *rc_style)
2070 token = g_scanner_get_next_token (scanner);
2071 if (token != GTK_RC_TOKEN_FONT)
2072 return GTK_RC_TOKEN_FONT;
2074 token = g_scanner_get_next_token (scanner);
2075 if (token != G_TOKEN_EQUAL_SIGN)
2076 return G_TOKEN_EQUAL_SIGN;
2078 token = g_scanner_get_next_token (scanner);
2079 if (token != G_TOKEN_STRING)
2080 return G_TOKEN_STRING;
2082 /* Ignore, do nothing */
2084 return G_TOKEN_NONE;
2088 gtk_rc_parse_fontset (GScanner *scanner,
2089 GtkRcStyle *rc_style)
2093 token = g_scanner_get_next_token (scanner);
2094 if (token != GTK_RC_TOKEN_FONTSET)
2095 return GTK_RC_TOKEN_FONTSET;
2097 token = g_scanner_get_next_token (scanner);
2098 if (token != G_TOKEN_EQUAL_SIGN)
2099 return G_TOKEN_EQUAL_SIGN;
2101 token = g_scanner_get_next_token (scanner);
2102 if (token != G_TOKEN_STRING)
2103 return G_TOKEN_STRING;
2105 /* Do nothing - silently ignore */
2107 return G_TOKEN_NONE;
2111 gtk_rc_parse_font_name (GScanner *scanner,
2112 GtkRcStyle *rc_style)
2116 token = g_scanner_get_next_token (scanner);
2117 if (token != GTK_RC_TOKEN_FONT_NAME)
2118 return GTK_RC_TOKEN_FONT;
2120 token = g_scanner_get_next_token (scanner);
2121 if (token != G_TOKEN_EQUAL_SIGN)
2122 return G_TOKEN_EQUAL_SIGN;
2124 token = g_scanner_get_next_token (scanner);
2125 if (token != G_TOKEN_STRING)
2126 return G_TOKEN_STRING;
2128 rc_style->font_desc = pango_font_description_from_string (scanner->value.v_string);
2130 return G_TOKEN_NONE;
2134 gtk_rc_parse_engine (GScanner *scanner,
2135 GtkRcStyle **rc_style)
2138 GtkThemeEngine *engine;
2139 guint result = G_TOKEN_NONE;
2140 GtkRcStyle *new_style = NULL;
2141 gboolean parsed_curlies = FALSE;
2143 token = g_scanner_get_next_token (scanner);
2144 if (token != GTK_RC_TOKEN_ENGINE)
2145 return GTK_RC_TOKEN_ENGINE;
2147 token = g_scanner_get_next_token (scanner);
2148 if (token != G_TOKEN_STRING)
2149 return G_TOKEN_STRING;
2151 engine = gtk_theme_engine_get (scanner->value.v_string);
2153 token = g_scanner_get_next_token (scanner);
2154 if (token != G_TOKEN_LEFT_CURLY)
2155 return G_TOKEN_LEFT_CURLY;
2159 GtkRcStyleClass *new_class;
2161 new_style = gtk_theme_engine_create_rc_style (engine);
2162 g_type_module_unuse (G_TYPE_MODULE (engine));
2164 new_class = GTK_RC_STYLE_GET_CLASS (new_style);
2166 new_class->merge (new_style, *rc_style);
2167 if ((*rc_style)->name)
2168 new_style->name = g_strdup ((*rc_style)->name);
2170 if (new_class->parse)
2172 parsed_curlies = TRUE;
2173 result = new_class->parse (new_style, scanner);
2175 if (result != G_TOKEN_NONE)
2177 g_object_unref (G_OBJECT (new_style));
2183 if (!parsed_curlies)
2185 /* Skip over remainder, looking for nested {}'s
2189 result = G_TOKEN_RIGHT_CURLY;
2190 while ((token = g_scanner_get_next_token (scanner)) != G_TOKEN_EOF)
2192 if (token == G_TOKEN_LEFT_CURLY)
2194 else if (token == G_TOKEN_RIGHT_CURLY)
2199 result = G_TOKEN_NONE;
2207 g_object_unref (G_OBJECT (*rc_style));
2208 *rc_style = new_style;
2215 gtk_rc_parse_state (GScanner *scanner,
2216 GtkStateType *state)
2221 g_return_val_if_fail (scanner != NULL, G_TOKEN_ERROR);
2222 g_return_val_if_fail (state != NULL, G_TOKEN_ERROR);
2224 /* we don't know where we got called from, so we reset the scope here.
2225 * if we bail out due to errors, we *don't* reset the scope, so the
2226 * error messaging code can make sense of our tokens.
2228 old_scope = g_scanner_set_scope (scanner, 0);
2230 token = g_scanner_get_next_token (scanner);
2231 if (token != G_TOKEN_LEFT_BRACE)
2232 return G_TOKEN_LEFT_BRACE;
2234 token = g_scanner_get_next_token (scanner);
2237 case GTK_RC_TOKEN_ACTIVE:
2238 *state = GTK_STATE_ACTIVE;
2240 case GTK_RC_TOKEN_INSENSITIVE:
2241 *state = GTK_STATE_INSENSITIVE;
2243 case GTK_RC_TOKEN_NORMAL:
2244 *state = GTK_STATE_NORMAL;
2246 case GTK_RC_TOKEN_PRELIGHT:
2247 *state = GTK_STATE_PRELIGHT;
2249 case GTK_RC_TOKEN_SELECTED:
2250 *state = GTK_STATE_SELECTED;
2253 return /* G_TOKEN_SYMBOL */ GTK_RC_TOKEN_NORMAL;
2256 token = g_scanner_get_next_token (scanner);
2257 if (token != G_TOKEN_RIGHT_BRACE)
2258 return G_TOKEN_RIGHT_BRACE;
2260 g_scanner_set_scope (scanner, old_scope);
2262 return G_TOKEN_NONE;
2266 gtk_rc_parse_priority (GScanner *scanner,
2267 GtkPathPriorityType *priority)
2272 g_return_val_if_fail (scanner != NULL, G_TOKEN_ERROR);
2273 g_return_val_if_fail (priority != NULL, G_TOKEN_ERROR);
2275 /* we don't know where we got called from, so we reset the scope here.
2276 * if we bail out due to errors, we *don't* reset the scope, so the
2277 * error messaging code can make sense of our tokens.
2279 old_scope = g_scanner_set_scope (scanner, 0);
2281 token = g_scanner_get_next_token (scanner);
2285 token = g_scanner_get_next_token (scanner);
2288 case GTK_RC_TOKEN_LOWEST:
2289 *priority = GTK_PATH_PRIO_LOWEST;
2291 case GTK_RC_TOKEN_GTK:
2292 *priority = GTK_PATH_PRIO_GTK;
2294 case GTK_RC_TOKEN_APPLICATION:
2295 *priority = GTK_PATH_PRIO_APPLICATION;
2297 case GTK_RC_TOKEN_RC:
2298 *priority = GTK_PATH_PRIO_RC;
2300 case GTK_RC_TOKEN_HIGHEST:
2301 *priority = GTK_PATH_PRIO_HIGHEST;
2304 return /* G_TOKEN_SYMBOL */ GTK_RC_TOKEN_APPLICATION;
2307 g_scanner_set_scope (scanner, old_scope);
2309 return G_TOKEN_NONE;
2313 gtk_rc_parse_color (GScanner *scanner,
2318 g_return_val_if_fail (scanner != NULL, G_TOKEN_ERROR);
2320 /* we don't need to set our own scop here, because
2321 * we don't need own symbols
2324 token = g_scanner_get_next_token (scanner);
2333 case G_TOKEN_LEFT_CURLY:
2334 token = g_scanner_get_next_token (scanner);
2335 if (token == G_TOKEN_INT)
2336 token_int = scanner->value.v_int;
2337 else if (token == G_TOKEN_FLOAT)
2338 token_int = scanner->value.v_float * 65535.0;
2340 return G_TOKEN_FLOAT;
2341 color->red = CLAMP (token_int, 0, 65535);
2343 token = g_scanner_get_next_token (scanner);
2344 if (token != G_TOKEN_COMMA)
2345 return G_TOKEN_COMMA;
2347 token = g_scanner_get_next_token (scanner);
2348 if (token == G_TOKEN_INT)
2349 token_int = scanner->value.v_int;
2350 else if (token == G_TOKEN_FLOAT)
2351 token_int = scanner->value.v_float * 65535.0;
2353 return G_TOKEN_FLOAT;
2354 color->green = CLAMP (token_int, 0, 65535);
2356 token = g_scanner_get_next_token (scanner);
2357 if (token != G_TOKEN_COMMA)
2358 return G_TOKEN_COMMA;
2360 token = g_scanner_get_next_token (scanner);
2361 if (token == G_TOKEN_INT)
2362 token_int = scanner->value.v_int;
2363 else if (token == G_TOKEN_FLOAT)
2364 token_int = scanner->value.v_float * 65535.0;
2366 return G_TOKEN_FLOAT;
2367 color->blue = CLAMP (token_int, 0, 65535);
2369 token = g_scanner_get_next_token (scanner);
2370 if (token != G_TOKEN_RIGHT_CURLY)
2371 return G_TOKEN_RIGHT_CURLY;
2372 return G_TOKEN_NONE;
2374 case G_TOKEN_STRING:
2375 if (scanner->value.v_string[0] != '#')
2376 return G_TOKEN_STRING;
2378 length = strlen (scanner->value.v_string) - 1;
2379 if (((length % 3) != 0) || (length > 12))
2380 return G_TOKEN_STRING;
2383 for (i = 0, j = 1; i < length; i++, j++)
2384 buf[i] = scanner->value.v_string[j];
2387 sscanf (buf, "%x", &temp);
2390 for (i = 0; i < length; i++, j++)
2391 buf[i] = scanner->value.v_string[j];
2394 sscanf (buf, "%x", &temp);
2395 color->green = temp;
2397 for (i = 0; i < length; i++, j++)
2398 buf[i] = scanner->value.v_string[j];
2401 sscanf (buf, "%x", &temp);
2407 color->green *= 4369;
2408 color->blue *= 4369;
2410 else if (length == 2)
2413 color->green *= 257;
2416 else if (length == 3)
2422 return G_TOKEN_NONE;
2425 return G_TOKEN_STRING;
2430 gtk_rc_parse_pixmap_path (GScanner *scanner)
2434 token = g_scanner_get_next_token (scanner);
2435 if (token != GTK_RC_TOKEN_PIXMAP_PATH)
2436 return GTK_RC_TOKEN_PIXMAP_PATH;
2438 token = g_scanner_get_next_token (scanner);
2439 if (token != G_TOKEN_STRING)
2440 return G_TOKEN_STRING;
2442 gtk_rc_parse_pixmap_path_string (scanner->value.v_string);
2444 return G_TOKEN_NONE;
2448 gtk_rc_parse_pixmap_path_string (gchar *pix_path)
2452 gint start_offset = 0;
2456 /* free the old one, or just add to the old one ? */
2457 for (path_num=0; pixmap_path[path_num]; path_num++)
2459 g_free (pixmap_path[path_num]);
2460 pixmap_path[path_num] = NULL;
2465 path_len = strlen (pix_path);
2467 buf = g_strdup (pix_path);
2469 for (end_offset = 0; end_offset <= path_len; end_offset++)
2471 if ((buf[end_offset] == G_SEARCHPATH_SEPARATOR) ||
2472 (end_offset == path_len))
2474 buf[end_offset] = '\0';
2475 pixmap_path[path_num] = g_strdup (buf + start_offset);
2477 pixmap_path[path_num] = NULL;
2478 start_offset = end_offset + 1;
2485 gtk_rc_parse_module_path (GScanner *scanner)
2489 token = g_scanner_get_next_token (scanner);
2490 if (token != GTK_RC_TOKEN_MODULE_PATH)
2491 return GTK_RC_TOKEN_MODULE_PATH;
2493 token = g_scanner_get_next_token (scanner);
2494 if (token != G_TOKEN_STRING)
2495 return G_TOKEN_STRING;
2497 gtk_rc_parse_module_path_string (scanner->value.v_string);
2499 return G_TOKEN_NONE;
2503 gtk_rc_parse_im_module_path (GScanner *scanner)
2507 token = g_scanner_get_next_token (scanner);
2508 if (token != GTK_RC_TOKEN_IM_MODULE_FILE)
2509 return GTK_RC_TOKEN_IM_MODULE_FILE;
2511 token = g_scanner_get_next_token (scanner);
2512 if (token != G_TOKEN_STRING)
2513 return G_TOKEN_STRING;
2516 g_free (im_module_path);
2518 im_module_path = g_strdup (scanner->value.v_string);
2520 return G_TOKEN_NONE;
2524 gtk_rc_parse_im_module_file (GScanner *scanner)
2528 token = g_scanner_get_next_token (scanner);
2529 if (token != GTK_RC_TOKEN_IM_MODULE_FILE)
2530 return GTK_RC_TOKEN_IM_MODULE_FILE;
2532 token = g_scanner_get_next_token (scanner);
2533 if (token != G_TOKEN_STRING)
2534 return G_TOKEN_STRING;
2537 g_free (im_module_file);
2539 im_module_file = g_strdup (scanner->value.v_string);
2541 return G_TOKEN_NONE;
2545 gtk_rc_parse_module_path_string (gchar *mod_path)
2549 gint start_offset = 0;
2553 /* free the old one, or just add to the old one ? */
2554 for (path_num=0; module_path[path_num]; path_num++)
2556 g_free (module_path[path_num]);
2557 module_path[path_num] = NULL;
2562 path_len = strlen (mod_path);
2564 buf = g_strdup (mod_path);
2566 for (end_offset = 0; end_offset <= path_len; end_offset++)
2568 if ((buf[end_offset] == G_SEARCHPATH_SEPARATOR) ||
2569 (end_offset == path_len))
2571 buf[end_offset] = '\0';
2572 module_path[path_num] = g_strdup (buf + start_offset);
2574 module_path[path_num] = NULL;
2575 start_offset = end_offset + 1;
2579 gtk_rc_append_default_module_path();
2583 gtk_rc_parse_path_pattern (GScanner *scanner)
2586 GtkPathType path_type;
2588 gboolean is_binding;
2589 GtkPathPriorityType priority = GTK_PATH_PRIO_RC;
2591 token = g_scanner_get_next_token (scanner);
2594 case GTK_RC_TOKEN_WIDGET:
2595 path_type = GTK_PATH_WIDGET;
2597 case GTK_RC_TOKEN_WIDGET_CLASS:
2598 path_type = GTK_PATH_WIDGET_CLASS;
2600 case GTK_RC_TOKEN_CLASS:
2601 path_type = GTK_PATH_CLASS;
2604 return GTK_RC_TOKEN_WIDGET_CLASS;
2607 token = g_scanner_get_next_token (scanner);
2608 if (token != G_TOKEN_STRING)
2609 return G_TOKEN_STRING;
2611 pattern = g_strdup (scanner->value.v_string);
2613 token = g_scanner_get_next_token (scanner);
2614 if (token == GTK_RC_TOKEN_STYLE)
2616 else if (token == GTK_RC_TOKEN_BINDING)
2619 if (g_scanner_peek_next_token (scanner) == ':')
2621 token = gtk_rc_parse_priority (scanner, &priority);
2622 if (token != G_TOKEN_NONE)
2632 return GTK_RC_TOKEN_STYLE;
2635 token = g_scanner_get_next_token (scanner);
2636 if (token != G_TOKEN_STRING)
2639 return G_TOKEN_STRING;
2644 GtkBindingSet *binding;
2646 binding = gtk_binding_set_find (scanner->value.v_string);
2650 return G_TOKEN_STRING;
2652 gtk_binding_set_add_path (binding, path_type, pattern, priority);
2656 GtkRcStyle *rc_style;
2659 rc_style = gtk_rc_style_find (scanner->value.v_string);
2664 return G_TOKEN_STRING;
2667 rc_set = g_new (GtkRcSet, 1);
2668 gtk_pattern_spec_init (&rc_set->pspec, pattern);
2669 rc_set->rc_style = rc_style;
2671 if (path_type == GTK_PATH_WIDGET)
2672 gtk_rc_sets_widget = g_slist_prepend (gtk_rc_sets_widget, rc_set);
2673 else if (path_type == GTK_PATH_WIDGET_CLASS)
2674 gtk_rc_sets_widget_class = g_slist_prepend (gtk_rc_sets_widget_class, rc_set);
2676 gtk_rc_sets_class = g_slist_prepend (gtk_rc_sets_class, rc_set);
2680 return G_TOKEN_NONE;
2684 gtk_rc_parse_stock_id (GScanner *scanner,
2689 token = g_scanner_get_next_token (scanner);
2690 if (token != G_TOKEN_LEFT_BRACE)
2691 return G_TOKEN_LEFT_BRACE;
2693 token = g_scanner_get_next_token (scanner);
2695 if (token != G_TOKEN_STRING)
2696 return G_TOKEN_STRING;
2698 *stock_id = g_strdup (scanner->value.v_string);
2700 token = g_scanner_get_next_token (scanner);
2701 if (token != G_TOKEN_RIGHT_BRACE)
2704 return G_TOKEN_RIGHT_BRACE;
2707 return G_TOKEN_NONE;
2711 cleanup_source (GtkIconSource *source)
2713 g_free (source->filename);
2714 g_free (source->size);
2718 gtk_rc_parse_icon_source (GScanner *scanner,
2719 GtkIconSet *icon_set)
2722 GtkIconSource source = { NULL, NULL,
2726 token = g_scanner_get_next_token (scanner);
2727 if (token != G_TOKEN_LEFT_CURLY)
2728 return G_TOKEN_LEFT_CURLY;
2730 token = g_scanner_get_next_token (scanner);
2732 if (token != G_TOKEN_STRING)
2733 return G_TOKEN_STRING;
2735 source.filename = g_strdup (scanner->value.v_string);
2737 token = g_scanner_get_next_token (scanner);
2739 if (token == G_TOKEN_RIGHT_CURLY)
2741 gtk_icon_set_add_source (icon_set, &source);
2742 cleanup_source (&source);
2743 return G_TOKEN_NONE;
2745 else if (token != G_TOKEN_COMMA)
2747 cleanup_source (&source);
2748 return G_TOKEN_COMMA;
2751 /* Get the direction */
2753 token = g_scanner_get_next_token (scanner);
2757 case GTK_RC_TOKEN_RTL:
2758 source.any_direction = FALSE;
2759 source.direction = GTK_TEXT_DIR_RTL;
2762 case GTK_RC_TOKEN_LTR:
2763 source.any_direction = FALSE;
2764 source.direction = GTK_TEXT_DIR_LTR;
2771 cleanup_source (&source);
2772 return GTK_RC_TOKEN_RTL;
2776 token = g_scanner_get_next_token (scanner);
2778 if (token == G_TOKEN_RIGHT_CURLY)
2780 gtk_icon_set_add_source (icon_set, &source);
2781 cleanup_source (&source);
2782 return G_TOKEN_NONE;
2784 else if (token != G_TOKEN_COMMA)
2786 cleanup_source (&source);
2787 return G_TOKEN_COMMA;
2792 token = g_scanner_get_next_token (scanner);
2796 case GTK_RC_TOKEN_NORMAL:
2797 source.any_state = FALSE;
2798 source.state = GTK_STATE_NORMAL;
2801 case GTK_RC_TOKEN_PRELIGHT:
2802 source.any_state = FALSE;
2803 source.state = GTK_STATE_PRELIGHT;
2807 case GTK_RC_TOKEN_INSENSITIVE:
2808 source.any_state = FALSE;
2809 source.state = GTK_STATE_INSENSITIVE;
2812 case GTK_RC_TOKEN_ACTIVE:
2813 source.any_state = FALSE;
2814 source.state = GTK_STATE_ACTIVE;
2817 case GTK_RC_TOKEN_SELECTED:
2818 source.any_state = FALSE;
2819 source.state = GTK_STATE_SELECTED;
2826 cleanup_source (&source);
2827 return GTK_RC_TOKEN_PRELIGHT;
2831 token = g_scanner_get_next_token (scanner);
2833 if (token == G_TOKEN_RIGHT_CURLY)
2835 gtk_icon_set_add_source (icon_set, &source);
2836 cleanup_source (&source);
2837 return G_TOKEN_NONE;
2839 else if (token != G_TOKEN_COMMA)
2841 cleanup_source (&source);
2842 return G_TOKEN_COMMA;
2847 token = g_scanner_get_next_token (scanner);
2851 if (token != G_TOKEN_STRING)
2853 cleanup_source (&source);
2854 return G_TOKEN_STRING;
2857 source.size = g_strdup (scanner->value.v_string);
2858 source.any_size = FALSE;
2861 /* Check the close brace */
2863 token = g_scanner_get_next_token (scanner);
2864 if (token != G_TOKEN_RIGHT_CURLY)
2866 cleanup_source (&source);
2867 return G_TOKEN_RIGHT_CURLY;
2870 gtk_icon_set_add_source (icon_set, &source);
2872 cleanup_source (&source);
2874 return G_TOKEN_NONE;
2878 gtk_rc_parse_stock (GScanner *scanner,
2879 GtkRcStyle *rc_style,
2880 GtkIconFactory *factory)
2882 GtkIconSet *icon_set = NULL;
2883 gchar *stock_id = NULL;
2886 token = g_scanner_get_next_token (scanner);
2887 if (token != GTK_RC_TOKEN_STOCK)
2888 return GTK_RC_TOKEN_STOCK;
2890 token = gtk_rc_parse_stock_id (scanner, &stock_id);
2891 if (token != G_TOKEN_NONE)
2894 token = g_scanner_get_next_token (scanner);
2895 if (token != G_TOKEN_EQUAL_SIGN)
2898 return G_TOKEN_EQUAL_SIGN;
2901 token = g_scanner_get_next_token (scanner);
2902 if (token != G_TOKEN_LEFT_CURLY)
2905 return G_TOKEN_LEFT_CURLY;
2908 token = g_scanner_peek_next_token (scanner);
2909 while (token != G_TOKEN_RIGHT_CURLY)
2911 if (icon_set == NULL)
2912 icon_set = gtk_icon_set_new ();
2914 token = gtk_rc_parse_icon_source (scanner, icon_set);
2915 if (token != G_TOKEN_NONE)
2918 gtk_icon_set_unref (icon_set);
2922 token = g_scanner_get_next_token (scanner);
2924 if (token != G_TOKEN_COMMA &&
2925 token != G_TOKEN_RIGHT_CURLY)
2928 gtk_icon_set_unref (icon_set);
2929 return G_TOKEN_RIGHT_CURLY;
2935 gtk_icon_factory_add (factory,
2939 gtk_icon_set_unref (icon_set);
2944 return G_TOKEN_NONE;
2948 typedef GdkPixmap * (*GtkImageLoader) (GdkWindow *window,
2949 GdkColormap *colormap,
2951 GdkColor *transparent_color,
2952 const gchar *filename);
2956 gtk_rc_set_image_loader(GtkImageLoader loader)
2958 image_loader = loader;
2962 gtk_rc_load_image (GdkColormap *colormap,
2963 GdkColor *transparent_color,
2964 const gchar *filename)
2966 if (strcmp (filename, "<parent>") == 0)
2967 return (GdkPixmap*) GDK_PARENT_RELATIVE;
2971 return image_loader(NULL, colormap, NULL,
2975 return gdk_pixmap_colormap_create_from_xpm (NULL, colormap, NULL,