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 char *name);
84 static gboolean gtk_rc_style_equal (const char *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 char *name);
90 static GSList * gtk_rc_styles_match (GSList *rc_styles,
94 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_strdup_printf("%s%s%s", var, "/lib/gtk-2.0/" GTK_VERSION "/", type);
302 path = g_strdup_printf("%s%s%s", GTK_EXE_PREFIX, "/lib/gtk-2.0/" GTK_VERSION "/", type);
304 path = g_strdup_printf ("%s\\%s", get_themes_directory (), type);
311 gtk_rc_get_im_module_path (void)
313 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_strdup_printf("%s%s", var, "/share/themes");
356 path = g_strdup_printf("%s%s", GTK_DATA_PREFIX, "/share/themes");
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)
376 for (n = 0; module_path[n]; n++) ;
377 if (n >= GTK_RC_MAX_MODULE_PATHS - 1)
381 var = getenv("GTK_EXE_PREFIX");
383 path = g_strdup_printf("%s%s", var, "/lib/gtk-2.0/" GTK_VERSION "/engines");
385 path = g_strdup_printf("%s%s", GTK_EXE_PREFIX, "/lib/gtk-2.0/" GTK_VERSION "/engines");
387 path = g_strdup_printf ("%s%s", get_themes_directory (), "\\engines");
389 module_path[n++] = path;
391 var = g_get_home_dir ();
395 /* Don't duplicate the directory separator, causes trouble at
398 if (var[strlen (var) -1] != G_DIR_SEPARATOR)
399 sep = G_DIR_SEPARATOR_S;
402 /* This produces something like ~/.gtk-2.0/2.0/engines */
403 path = g_strdup_printf ("%s%s%s", var, sep,
404 ".gtk-2.0" G_DIR_SEPARATOR_S
405 GTK_VERSION G_DIR_SEPARATOR_S
407 module_path[n++] = path;
409 module_path[n] = NULL;
413 gtk_rc_add_initial_default_files (void)
415 static gint init = FALSE;
423 gtk_rc_default_files[0] = NULL;
426 var = g_getenv("GTK_RC_FILES");
429 files = g_strsplit (var, G_SEARCHPATH_SEPARATOR_S, 128);
433 gtk_rc_add_default_file (files[i]);
441 str = g_strdup (GTK_SYSCONFDIR G_DIR_SEPARATOR_S "gtk-2.0" G_DIR_SEPARATOR_S "gtkrc");
443 str = g_strdup_printf ("%s\\gtkrc", g_win32_get_package_installation_directory (GETTEXT_PACKAGE, get_gtk_dll_name ()));
446 gtk_rc_add_default_file (str);
449 var = g_get_home_dir ();
453 if (var[strlen (var) -1] != G_DIR_SEPARATOR)
454 sep = G_DIR_SEPARATOR_S;
457 str = g_strdup_printf ("%s%s.gtkrc-2.0", var, sep);
458 gtk_rc_add_default_file (str);
465 gtk_rc_add_default_file (const gchar *file)
469 gtk_rc_add_initial_default_files ();
471 for (n = 0; gtk_rc_default_files[n]; n++) ;
472 if (n >= GTK_RC_MAX_DEFAULT_FILES - 1)
475 gtk_rc_default_files[n++] = g_strdup (file);
476 gtk_rc_default_files[n] = NULL;
480 gtk_rc_set_default_files (gchar **files)
484 gtk_rc_add_initial_default_files ();
487 while (gtk_rc_default_files[i])
489 g_free (gtk_rc_default_files[i]);
493 gtk_rc_default_files[0] = NULL;
494 gtk_rc_auto_parse = FALSE;
497 while (files[i] != NULL)
499 gtk_rc_add_default_file (files[i]);
505 gtk_rc_get_default_files (void)
507 gtk_rc_add_initial_default_files ();
509 return gtk_rc_default_files;
512 /* The following routine is based on _nl_normalize_codeset from
513 * the GNU C library. Contributed by
515 * Contributed by Ulrich Drepper <drepper@gnu.ai.mit.edu>, 1995.
516 * Copyright (C) 1995, 1996, 1997, 1998, 1999 Free Software Foundation, Inc.
518 * Normalize codeset name. There is no standard for the codeset
519 * names. Normalization allows the user to use any of the common
523 _gtk_normalize_codeset (const char *codeset, int name_len)
531 for (cnt = 0; cnt < name_len; ++cnt)
532 if (isalnum (codeset[cnt]))
536 if (isalpha (codeset[cnt]))
540 retval = g_malloc ((only_digit ? 3 : 0) + len + 1);
544 memcpy (retval, "iso", 4);
550 for (cnt = 0; cnt < name_len; ++cnt)
551 if (isalpha (codeset[cnt]))
552 *wp++ = isupper(codeset[cnt]) ? tolower (codeset[cnt]) : codeset[cnt];
553 else if (isdigit (codeset[cnt]))
554 *wp++ = codeset[cnt];
564 static gchar *locale_suffixes[3];
565 static gint n_locale_suffixes = 0;
569 static gboolean initted = FALSE;
578 locale = g_win32_getlocale ();
580 locale = setlocale (LC_CTYPE, NULL);
585 pixmap_path[0] = NULL;
586 module_path[0] = NULL;
587 gtk_rc_append_default_module_path();
589 gtk_rc_add_initial_default_files ();
591 if (strcmp (locale, "C") && strcmp (locale, "POSIX"))
593 /* Determine locale-specific suffixes for RC files
595 * We normalize the charset into a standard form,
596 * which has all '-' and '_' characters removed,
599 gchar *normalized_locale;
601 p = strchr (locale, '@');
602 length = p ? (p -locale) : strlen (locale);
604 p = strchr (locale, '.');
607 gchar *tmp1 = g_strndup (locale, p - locale + 1);
608 gchar *tmp2 = _gtk_normalize_codeset (p + 1, length - (p - locale + 1));
610 normalized_locale = g_strconcat (tmp1, tmp2, NULL);
614 locale_suffixes[n_locale_suffixes++] = g_strdup (normalized_locale);
618 normalized_locale = g_strndup (locale, length);
620 p = strchr (normalized_locale, '_');
623 locale_suffixes[n_locale_suffixes++] = g_strndup (normalized_locale, length);
624 length = p - normalized_locale;
627 locale_suffixes[n_locale_suffixes++] = g_strndup (normalized_locale, length);
629 g_free (normalized_locale);
634 while (gtk_rc_default_files[i] != NULL)
636 /* Try to find a locale specific RC file corresponding to
637 * to parse before the default file.
639 for (j=n_locale_suffixes-1; j>=0; j--)
641 gchar *name = g_strconcat (gtk_rc_default_files[i],
649 gtk_rc_parse (gtk_rc_default_files[i]);
655 gtk_rc_parse_string (const gchar *rc_string)
657 g_return_if_fail (rc_string != NULL);
659 gtk_rc_parse_any ("-", -1, rc_string);
663 gtk_rc_parse_file (const gchar *filename, gboolean reload)
665 GtkRcFile *rc_file = NULL;
669 g_return_if_fail (filename != NULL);
674 rc_file = tmp_list->data;
675 if (!strcmp (rc_file->name, filename))
678 tmp_list = tmp_list->next;
683 rc_file = g_new (GtkRcFile, 1);
684 rc_file->name = g_strdup (filename);
685 rc_file->canonical_name = NULL;
687 rc_file->reload = reload;
689 rc_files = g_slist_append (rc_files, rc_file);
692 if (!rc_file->canonical_name)
694 /* Get the absolute pathname */
696 if (g_path_is_absolute (rc_file->name))
697 rc_file->canonical_name = rc_file->name;
703 cwd = g_get_current_dir ();
705 str = g_string_new (cwd);
707 g_string_append_c (str, G_DIR_SEPARATOR);
708 g_string_append (str, rc_file->name);
710 rc_file->canonical_name = str->str;
711 g_string_free (str, FALSE);
715 if (!lstat (rc_file->canonical_name, &statbuf))
720 rc_file->mtime = statbuf.st_mtime;
722 fd = open (rc_file->canonical_name, O_RDONLY);
726 /* Temporarily push directory name for this file on
727 * a stack of directory names while parsing it
730 g_slist_prepend (rc_dir_stack,
731 g_path_get_dirname (rc_file->canonical_name));
732 gtk_rc_parse_any (filename, fd, NULL);
734 tmp_list = rc_dir_stack;
735 rc_dir_stack = rc_dir_stack->next;
737 g_free (tmp_list->data);
738 g_slist_free_1 (tmp_list);
745 gtk_rc_parse (const gchar *filename)
747 g_return_if_fail (filename != NULL);
749 gtk_rc_parse_file (filename, TRUE);
752 /* Handling of RC styles */
755 gtk_rc_style_get_type (void)
757 static GType object_type = 0;
761 static const GTypeInfo object_info =
763 sizeof (GtkRcStyleClass),
764 (GBaseInitFunc) NULL,
765 (GBaseFinalizeFunc) NULL,
766 (GClassInitFunc) gtk_rc_style_class_init,
767 NULL, /* class_finalize */
768 NULL, /* class_data */
771 (GInstanceInitFunc) gtk_rc_style_init,
774 object_type = g_type_register_static (G_TYPE_OBJECT,
783 gtk_rc_style_init (GtkRcStyle *style)
788 for (i = 0; i < 5; i++)
790 static const GdkColor init_color = { 0, 0, 0, 0, };
792 style->bg_pixmap_name[i] = NULL;
793 style->color_flags[i] = 0;
794 style->fg[i] = init_color;
795 style->bg[i] = init_color;
796 style->text[i] = init_color;
797 style->base[i] = init_color;
799 style->xthickness = -1;
800 style->ythickness = -1;
801 style->rc_style_lists = NULL;
805 gtk_rc_style_class_init (GtkRcStyleClass *klass)
807 GObjectClass *object_class = G_OBJECT_CLASS (klass);
809 parent_class = g_type_class_peek_parent (klass);
811 object_class->finalize = gtk_rc_style_finalize;
814 klass->clone = gtk_rc_style_real_clone;
815 klass->merge = gtk_rc_style_real_merge;
816 klass->create_style = gtk_rc_style_real_create_style;
819 /* Like g_slist_remove, but remove all copies of data */
821 gtk_rc_slist_remove_all (GSList *list,
832 if (tmp->data == data)
838 prev->next = tmp->next;
840 g_slist_free_1 (tmp);
858 gtk_rc_style_finalize (GObject *object)
861 GSList *tmp_list1, *tmp_list2;
862 GtkRcStyle *rc_style;
864 rc_style = GTK_RC_STYLE (object);
867 g_free (rc_style->name);
868 if (rc_style->font_desc)
869 pango_font_description_free (rc_style->font_desc);
871 for (i=0 ; i < 5 ; i++)
872 if (rc_style->bg_pixmap_name[i])
873 g_free (rc_style->bg_pixmap_name[i]);
875 /* Now remove all references to this rc_style from
878 tmp_list1 = rc_style->rc_style_lists;
881 GSList *rc_styles = tmp_list1->data;
882 GtkStyle *style = g_hash_table_lookup (realized_style_ht, rc_styles);
883 gtk_style_unref (style);
885 /* Remove the list of styles from the other rc_styles
888 tmp_list2 = rc_styles;
891 GtkRcStyle *other_style = tmp_list2->data;
893 if (other_style != rc_style)
894 other_style->rc_style_lists =
895 gtk_rc_slist_remove_all (other_style->rc_style_lists, rc_styles);
897 tmp_list2 = tmp_list2->next;
900 /* And from the hash table itself
902 g_hash_table_remove (realized_style_ht, rc_styles);
903 g_slist_free (rc_styles);
905 tmp_list1 = tmp_list1->next;
908 g_slist_free (rc_style->rc_style_lists);
910 tmp_list1 = rc_style->icon_factories;
913 g_object_unref (G_OBJECT (tmp_list1->data));
915 tmp_list1 = tmp_list1->next;
918 g_slist_free (rc_style->icon_factories);
920 G_OBJECT_CLASS (parent_class)->finalize (object);
924 gtk_rc_style_new (void)
928 style = g_object_new (GTK_TYPE_RC_STYLE, NULL);
935 * @orig: the style to copy
937 * Make a copy of the specified #GtkRcStyle. This function
938 * will correctly copy an rc style that is a member of a class
939 * derived from #GtkRcStyle.
941 * Return value: the resulting #GtkRcStyle
944 gtk_rc_style_copy (GtkRcStyle *orig)
948 g_return_val_if_fail (GTK_IS_RC_STYLE (orig), NULL);
950 style = GTK_RC_STYLE_GET_CLASS (orig)->clone (orig);
951 GTK_RC_STYLE_GET_CLASS (style)->merge (style, orig);
957 gtk_rc_style_ref (GtkRcStyle *rc_style)
959 g_return_if_fail (GTK_IS_RC_STYLE (rc_style));
961 g_object_ref (G_OBJECT (rc_style));
965 gtk_rc_style_unref (GtkRcStyle *rc_style)
967 g_return_if_fail (GTK_IS_RC_STYLE (rc_style));
969 g_object_unref (G_OBJECT (rc_style));
973 gtk_rc_style_real_clone (GtkRcStyle *style)
975 return GTK_RC_STYLE (g_object_new (G_OBJECT_TYPE (style), NULL));
979 gtk_rc_style_real_merge (GtkRcStyle *dest,
984 for (i = 0; i < 5; i++)
986 if (!dest->bg_pixmap_name[i] && src->bg_pixmap_name[i])
987 dest->bg_pixmap_name[i] = g_strdup (src->bg_pixmap_name[i]);
989 if (!(dest->color_flags[i] & GTK_RC_FG) &&
990 src->color_flags[i] & GTK_RC_FG)
992 dest->fg[i] = src->fg[i];
993 dest->color_flags[i] |= GTK_RC_FG;
995 if (!(dest->color_flags[i] & GTK_RC_BG) &&
996 src->color_flags[i] & GTK_RC_BG)
998 dest->bg[i] = src->bg[i];
999 dest->color_flags[i] |= GTK_RC_BG;
1001 if (!(dest->color_flags[i] & GTK_RC_TEXT) &&
1002 src->color_flags[i] & GTK_RC_TEXT)
1004 dest->text[i] = src->text[i];
1005 dest->color_flags[i] |= GTK_RC_TEXT;
1007 if (!(dest->color_flags[i] & GTK_RC_BASE) &&
1008 src->color_flags[i] & GTK_RC_BASE)
1010 dest->base[i] = src->base[i];
1011 dest->color_flags[i] |= GTK_RC_BASE;
1015 if (dest->xthickness < 0 && src->xthickness >= 0)
1016 dest->xthickness = src->xthickness;
1017 if (dest->ythickness < 0 && src->ythickness >= 0)
1018 dest->ythickness = src->ythickness;
1020 if (!dest->font_desc && src->font_desc)
1021 dest->font_desc = pango_font_description_copy (src->font_desc);
1025 gtk_rc_style_real_create_style (GtkRcStyle *rc_style)
1027 return gtk_style_new ();
1031 gtk_rc_clear_hash_node (gpointer key,
1035 gtk_rc_style_unref (data);
1039 gtk_rc_free_rc_sets (GSList *slist)
1045 rc_set = slist->data;
1046 gtk_pattern_spec_free_segs (&rc_set->pspec);
1049 slist = slist->next;
1054 gtk_rc_clear_styles (void)
1056 /* Clear out all old rc_styles */
1060 g_hash_table_foreach (rc_style_ht, gtk_rc_clear_hash_node, NULL);
1061 g_hash_table_destroy (rc_style_ht);
1065 gtk_rc_free_rc_sets (gtk_rc_sets_widget);
1066 g_slist_free (gtk_rc_sets_widget);
1067 gtk_rc_sets_widget = NULL;
1069 gtk_rc_free_rc_sets (gtk_rc_sets_widget_class);
1070 g_slist_free (gtk_rc_sets_widget_class);
1071 gtk_rc_sets_widget_class = NULL;
1073 gtk_rc_free_rc_sets (gtk_rc_sets_class);
1074 g_slist_free (gtk_rc_sets_class);
1075 gtk_rc_sets_class = NULL;
1079 gtk_rc_reparse_all (void)
1082 gboolean mtime_modified = FALSE;
1085 struct stat statbuf;
1087 /* Check through and see if any of the RC's have had their
1088 * mtime modified. If so, reparse everything.
1090 tmp_list = rc_files;
1093 rc_file = tmp_list->data;
1095 if (!lstat (rc_file->name, &statbuf) &&
1096 (statbuf.st_mtime > rc_file->mtime))
1098 mtime_modified = TRUE;
1102 tmp_list = tmp_list->next;
1107 gtk_rc_clear_styles();
1109 tmp_list = rc_files;
1112 rc_file = tmp_list->data;
1113 if (rc_file->reload)
1114 gtk_rc_parse_file (rc_file->name, FALSE);
1116 tmp_list = tmp_list->next;
1120 return mtime_modified;
1124 gtk_rc_styles_match (GSList *rc_styles,
1128 gchar *path_reversed)
1135 rc_set = sets->data;
1138 if (gtk_pattern_match (&rc_set->pspec, path_length, path, path_reversed))
1139 rc_styles = g_slist_append (rc_styles, rc_set->rc_style);
1146 gtk_rc_get_style (GtkWidget *widget)
1148 GtkRcStyle *widget_rc_style;
1149 GSList *rc_styles = NULL;
1151 static guint rc_style_key_id = 0;
1153 /* We allow the specification of a single rc style to be bound
1154 * tightly to a widget, for application modifications
1156 if (!rc_style_key_id)
1157 rc_style_key_id = g_quark_from_static_string ("gtk-rc-style");
1159 widget_rc_style = gtk_object_get_data_by_id (GTK_OBJECT (widget),
1162 if (widget_rc_style)
1163 rc_styles = g_slist_prepend (rc_styles, widget_rc_style);
1165 if (gtk_rc_sets_widget)
1167 gchar *path, *path_reversed;
1170 gtk_widget_path (widget, &path_length, &path, &path_reversed);
1171 rc_styles = gtk_rc_styles_match (rc_styles, gtk_rc_sets_widget, path_length, path, path_reversed);
1173 g_free (path_reversed);
1177 if (gtk_rc_sets_widget_class)
1179 gchar *path, *path_reversed;
1182 gtk_widget_class_path (widget, &path_length, &path, &path_reversed);
1183 rc_styles = gtk_rc_styles_match (rc_styles, gtk_rc_sets_widget_class, path_length, path, path_reversed);
1185 g_free (path_reversed);
1188 if (gtk_rc_sets_class)
1192 type = GTK_OBJECT_TYPE (widget);
1195 gchar *path, *path_reversed;
1198 path = gtk_type_name (type);
1199 path_length = strlen (path);
1200 path_reversed = g_strdup (path);
1201 g_strreverse (path_reversed);
1203 rc_styles = gtk_rc_styles_match (rc_styles, gtk_rc_sets_class, path_length, path, path_reversed);
1204 g_free (path_reversed);
1206 type = gtk_type_parent (type);
1211 return gtk_rc_init_style (rc_styles);
1217 gtk_rc_add_rc_sets (GSList *slist,
1218 GtkRcStyle *rc_style,
1219 const char *pattern)
1221 GtkRcStyle *new_style;
1225 new_style = gtk_rc_style_new ();
1226 *new_style = *rc_style;
1227 new_style->name = g_strdup (rc_style->name);
1228 if (rc_style->font_desc)
1229 new_style->font_desc = pango_font_description_copy (rc_style->font_desc);
1231 for (i = 0; i < 5; i++)
1232 new_style->bg_pixmap_name[i] = g_strdup (rc_style->bg_pixmap_name[i]);
1234 rc_set = g_new (GtkRcSet, 1);
1235 gtk_pattern_spec_init (&rc_set->pspec, pattern);
1236 rc_set->rc_style = rc_style;
1238 return g_slist_prepend (slist, rc_set);
1242 gtk_rc_add_widget_name_style (GtkRcStyle *rc_style,
1243 const gchar *pattern)
1245 g_return_if_fail (rc_style != NULL);
1246 g_return_if_fail (pattern != NULL);
1248 gtk_rc_sets_widget = gtk_rc_add_rc_sets (gtk_rc_sets_widget, rc_style, pattern);
1252 gtk_rc_add_widget_class_style (GtkRcStyle *rc_style,
1253 const gchar *pattern)
1255 g_return_if_fail (rc_style != NULL);
1256 g_return_if_fail (pattern != NULL);
1258 gtk_rc_sets_widget_class = gtk_rc_add_rc_sets (gtk_rc_sets_widget_class, rc_style, pattern);
1262 gtk_rc_add_class_style (GtkRcStyle *rc_style,
1263 const gchar *pattern)
1265 g_return_if_fail (rc_style != NULL);
1266 g_return_if_fail (pattern != NULL);
1268 gtk_rc_sets_class = gtk_rc_add_rc_sets (gtk_rc_sets_class, rc_style, pattern);
1272 gtk_rc_parse_any (const gchar *input_name,
1274 const gchar *input_string)
1280 scanner = g_scanner_new ((GScannerConfig *) >k_rc_scanner_config);
1284 g_assert (input_string == NULL);
1286 g_scanner_input_file (scanner, input_fd);
1290 g_assert (input_string != NULL);
1292 g_scanner_input_text (scanner, input_string, strlen (input_string));
1294 scanner->input_name = input_name;
1296 for (i = 0; i < n_symbols; i++)
1297 g_scanner_add_symbol (scanner, symbols[i].name, GINT_TO_POINTER (symbols[i].token));
1302 if (g_scanner_peek_next_token (scanner) == G_TOKEN_EOF)
1306 guint expected_token;
1308 expected_token = gtk_rc_parse_statement (scanner);
1310 if (expected_token != G_TOKEN_NONE)
1317 if (scanner->scope_id == 0)
1319 /* if we are in scope 0, we know the symbol names
1320 * that are associated with certaintoken values.
1321 * so we look them up to make the error messages
1324 if (expected_token > GTK_RC_TOKEN_INVALID &&
1325 expected_token < GTK_RC_TOKEN_LAST)
1327 for (i = 0; i < n_symbols; i++)
1328 if (symbols[i].token == expected_token)
1329 msg = symbols[i].name;
1331 msg = g_strconcat ("e.g. `", msg, "'", NULL);
1333 if (scanner->token > GTK_RC_TOKEN_INVALID &&
1334 scanner->token < GTK_RC_TOKEN_LAST)
1336 symbol_name = "???";
1337 for (i = 0; i < n_symbols; i++)
1338 if (symbols[i].token == scanner->token)
1339 symbol_name = symbols[i].name;
1342 g_scanner_unexp_token (scanner,
1355 g_scanner_destroy (scanner);
1359 gtk_rc_styles_hash (const GSList *rc_styles)
1366 result += (result << 9) + GPOINTER_TO_UINT (rc_styles->data);
1367 rc_styles = rc_styles->next;
1374 gtk_rc_styles_equal (const GSList *a,
1379 if (a->data != b->data)
1389 gtk_rc_style_hash (const char *name)
1395 result += (result << 3) + *name++;
1401 gtk_rc_style_equal (const char *a,
1404 return (strcmp (a, b) == 0);
1408 gtk_rc_style_find (const char *name)
1411 return g_hash_table_lookup (rc_style_ht, (gpointer) name);
1417 gtk_rc_style_to_style (GtkRcStyle *rc_style)
1421 style = GTK_RC_STYLE_GET_CLASS (rc_style)->create_style (rc_style);
1423 style->rc_style = rc_style;
1425 gtk_rc_style_ref (rc_style);
1427 GTK_STYLE_GET_CLASS (style)->init_from_rc (style, rc_style);
1432 /* Reuses or frees rc_styles */
1434 gtk_rc_init_style (GSList *rc_styles)
1436 GtkStyle *style = NULL;
1439 g_return_val_if_fail (rc_styles != NULL, NULL);
1441 if (!realized_style_ht)
1442 realized_style_ht = g_hash_table_new ((GHashFunc) gtk_rc_styles_hash,
1443 (GEqualFunc) gtk_rc_styles_equal);
1445 style = g_hash_table_lookup (realized_style_ht, rc_styles);
1449 GtkRcStyle *base_style = NULL;
1450 GtkRcStyle *proto_style;
1451 GtkRcStyleClass *proto_style_class;
1453 GType rc_style_type = GTK_TYPE_RC_STYLE;
1455 /* Find the first derived style in the list, and use that to
1456 * create the merged style. If we only have raw GtkRcStyles, use
1457 * the first style to create the merged style.
1459 base_style = rc_styles->data;
1460 tmp_styles = rc_styles;
1463 GtkRcStyle *rc_style = tmp_styles->data;
1465 if (G_OBJECT_TYPE (rc_style) != rc_style_type)
1467 base_style = rc_style;
1471 tmp_styles = tmp_styles->next;
1474 proto_style_class = GTK_RC_STYLE_GET_CLASS (base_style);
1475 proto_style = proto_style_class->clone (base_style);
1477 tmp_styles = rc_styles;
1480 GtkRcStyle *rc_style = tmp_styles->data;
1483 proto_style_class->merge (proto_style, rc_style);
1485 /* Point from each rc_style to the list of styles */
1486 if (!g_slist_find (rc_style->rc_style_lists, rc_styles))
1487 rc_style->rc_style_lists = g_slist_prepend (rc_style->rc_style_lists, rc_styles);
1489 factories = g_slist_copy (rc_style->icon_factories);
1495 while (iter != NULL)
1497 g_object_ref (G_OBJECT (iter->data));
1498 iter = g_slist_next (iter);
1501 proto_style->icon_factories = g_slist_concat (proto_style->icon_factories,
1506 tmp_styles = tmp_styles->next;
1509 for (i = 0; i < 5; i++)
1510 if (proto_style->bg_pixmap_name[i] &&
1511 (strcmp (proto_style->bg_pixmap_name[i], "<none>") == 0))
1513 g_free (proto_style->bg_pixmap_name[i]);
1514 proto_style->bg_pixmap_name[i] = NULL;
1517 style = gtk_rc_style_to_style (proto_style);
1518 gtk_rc_style_unref (proto_style);
1520 g_hash_table_insert (realized_style_ht, rc_styles, style);
1523 g_slist_free (rc_styles);
1528 /*********************
1529 * Parsing functions *
1530 *********************/
1533 gtk_rc_parse_statement (GScanner *scanner)
1537 token = g_scanner_peek_next_token (scanner);
1541 case GTK_RC_TOKEN_INCLUDE:
1542 token = g_scanner_get_next_token (scanner);
1543 if (token != GTK_RC_TOKEN_INCLUDE)
1544 return GTK_RC_TOKEN_INCLUDE;
1546 token = g_scanner_get_next_token (scanner);
1547 if (token != G_TOKEN_STRING)
1548 return G_TOKEN_STRING;
1550 gtk_rc_parse_file (scanner->value.v_string, FALSE);
1551 return G_TOKEN_NONE;
1553 case GTK_RC_TOKEN_STYLE:
1554 return gtk_rc_parse_style (scanner);
1556 case GTK_RC_TOKEN_BINDING:
1557 return gtk_binding_parse_binding (scanner);
1559 case GTK_RC_TOKEN_PIXMAP_PATH:
1560 return gtk_rc_parse_pixmap_path (scanner);
1562 case GTK_RC_TOKEN_WIDGET:
1563 return gtk_rc_parse_path_pattern (scanner);
1565 case GTK_RC_TOKEN_WIDGET_CLASS:
1566 return gtk_rc_parse_path_pattern (scanner);
1568 case GTK_RC_TOKEN_CLASS:
1569 return gtk_rc_parse_path_pattern (scanner);
1571 case GTK_RC_TOKEN_MODULE_PATH:
1572 return gtk_rc_parse_module_path (scanner);
1574 case GTK_RC_TOKEN_IM_MODULE_PATH:
1575 return gtk_rc_parse_im_module_path (scanner);
1577 case GTK_RC_TOKEN_IM_MODULE_FILE:
1578 return gtk_rc_parse_im_module_file (scanner);
1581 g_scanner_get_next_token (scanner);
1582 return /* G_TOKEN_SYMBOL */ GTK_RC_TOKEN_STYLE;
1587 gtk_rc_parse_style (GScanner *scanner)
1589 GtkRcStyle *rc_style;
1590 GtkRcStyle *parent_style;
1594 GtkIconFactory *our_factory = NULL;
1596 token = g_scanner_get_next_token (scanner);
1597 if (token != GTK_RC_TOKEN_STYLE)
1598 return GTK_RC_TOKEN_STYLE;
1600 token = g_scanner_get_next_token (scanner);
1601 if (token != G_TOKEN_STRING)
1602 return G_TOKEN_STRING;
1605 rc_style = gtk_rc_style_find (scanner->value.v_string);
1607 /* If there's a list, its first member is always the factory belonging
1610 if (rc_style && rc_style->icon_factories)
1611 our_factory = rc_style->icon_factories->data;
1616 rc_style = gtk_rc_style_new ();
1617 rc_style->name = g_strdup (scanner->value.v_string);
1619 for (i = 0; i < 5; i++)
1620 rc_style->bg_pixmap_name[i] = NULL;
1622 for (i = 0; i < 5; i++)
1623 rc_style->color_flags[i] = 0;
1626 token = g_scanner_peek_next_token (scanner);
1627 if (token == G_TOKEN_EQUAL_SIGN)
1629 token = g_scanner_get_next_token (scanner);
1631 token = g_scanner_get_next_token (scanner);
1632 if (token != G_TOKEN_STRING)
1637 return G_TOKEN_STRING;
1640 parent_style = gtk_rc_style_find (scanner->value.v_string);
1645 for (i = 0; i < 5; i++)
1647 rc_style->color_flags[i] = parent_style->color_flags[i];
1648 rc_style->fg[i] = parent_style->fg[i];
1649 rc_style->bg[i] = parent_style->bg[i];
1650 rc_style->text[i] = parent_style->text[i];
1651 rc_style->base[i] = parent_style->base[i];
1654 rc_style->xthickness = parent_style->xthickness;
1655 rc_style->ythickness = parent_style->ythickness;
1657 if (parent_style->font_desc)
1659 if (rc_style->font_desc)
1660 pango_font_description_free (rc_style->font_desc);
1661 rc_style->font_desc = pango_font_description_copy (parent_style->font_desc);
1664 for (i = 0; i < 5; i++)
1666 if (rc_style->bg_pixmap_name[i])
1667 g_free (rc_style->bg_pixmap_name[i]);
1668 rc_style->bg_pixmap_name[i] = g_strdup (parent_style->bg_pixmap_name[i]);
1671 /* Append parent's factories, adding a ref to them */
1672 if (parent_style->icon_factories != NULL)
1674 /* Add a factory for ourselves if we have none,
1675 * in case we end up defining more stock icons.
1676 * I see no real way around this; we need to maintain
1677 * the invariant that the first factory in the list
1678 * is always our_factory, the one belonging to us,
1679 * and if we put parent factories in the list we can't
1680 * do that if the style is reopened.
1682 if (our_factory == NULL)
1684 our_factory = gtk_icon_factory_new ();
1685 rc_style->icon_factories = g_slist_prepend (rc_style->icon_factories,
1689 rc_style->icon_factories = g_slist_concat (rc_style->icon_factories,
1690 g_slist_copy (parent_style->icon_factories));
1692 factories = parent_style->icon_factories;
1693 while (factories != NULL)
1695 g_object_ref (G_OBJECT (factories->data));
1696 factories = factories->next;
1702 token = g_scanner_get_next_token (scanner);
1703 if (token != G_TOKEN_LEFT_CURLY)
1708 return G_TOKEN_LEFT_CURLY;
1711 token = g_scanner_peek_next_token (scanner);
1712 while (token != G_TOKEN_RIGHT_CURLY)
1716 case GTK_RC_TOKEN_BG:
1717 token = gtk_rc_parse_bg (scanner, rc_style);
1719 case GTK_RC_TOKEN_FG:
1720 token = gtk_rc_parse_fg (scanner, rc_style);
1722 case GTK_RC_TOKEN_TEXT:
1723 token = gtk_rc_parse_text (scanner, rc_style);
1725 case GTK_RC_TOKEN_BASE:
1726 token = gtk_rc_parse_base (scanner, rc_style);
1728 case GTK_RC_TOKEN_XTHICKNESS:
1729 token = gtk_rc_parse_xthickness (scanner, rc_style);
1731 case GTK_RC_TOKEN_YTHICKNESS:
1732 token = gtk_rc_parse_ythickness (scanner, rc_style);
1734 case GTK_RC_TOKEN_BG_PIXMAP:
1735 token = gtk_rc_parse_bg_pixmap (scanner, rc_style);
1737 case GTK_RC_TOKEN_FONT:
1738 token = gtk_rc_parse_font (scanner, rc_style);
1740 case GTK_RC_TOKEN_FONTSET:
1741 token = gtk_rc_parse_fontset (scanner, rc_style);
1743 case GTK_RC_TOKEN_FONT_NAME:
1744 token = gtk_rc_parse_font_name (scanner, rc_style);
1746 case GTK_RC_TOKEN_ENGINE:
1747 token = gtk_rc_parse_engine (scanner, &rc_style);
1749 case GTK_RC_TOKEN_STOCK:
1750 if (our_factory == NULL)
1752 our_factory = gtk_icon_factory_new ();
1753 rc_style->icon_factories = g_slist_prepend (rc_style->icon_factories,
1756 token = gtk_rc_parse_stock (scanner, rc_style, our_factory);
1759 g_scanner_get_next_token (scanner);
1760 token = G_TOKEN_RIGHT_CURLY;
1764 if (token != G_TOKEN_NONE)
1768 if (rc_style->font_desc)
1769 pango_font_description_free (rc_style->font_desc);
1771 for (i = 0; i < 5; i++)
1772 if (rc_style->bg_pixmap_name[i])
1773 g_free (rc_style->bg_pixmap_name[i]);
1778 token = g_scanner_peek_next_token (scanner);
1781 token = g_scanner_get_next_token (scanner);
1782 if (token != G_TOKEN_RIGHT_CURLY)
1786 if (rc_style->font_desc)
1787 pango_font_description_free (rc_style->font_desc);
1789 for (i = 0; i < 5; i++)
1790 if (rc_style->bg_pixmap_name[i])
1791 g_free (rc_style->bg_pixmap_name[i]);
1795 return G_TOKEN_RIGHT_CURLY;
1801 rc_style_ht = g_hash_table_new ((GHashFunc) gtk_rc_style_hash,
1802 (GEqualFunc) gtk_rc_style_equal);
1804 g_hash_table_insert (rc_style_ht, rc_style->name, rc_style);
1807 return G_TOKEN_NONE;
1811 gtk_rc_parse_bg (GScanner *scanner,
1817 token = g_scanner_get_next_token (scanner);
1818 if (token != GTK_RC_TOKEN_BG)
1819 return GTK_RC_TOKEN_BG;
1821 token = gtk_rc_parse_state (scanner, &state);
1822 if (token != G_TOKEN_NONE)
1825 token = g_scanner_get_next_token (scanner);
1826 if (token != G_TOKEN_EQUAL_SIGN)
1827 return G_TOKEN_EQUAL_SIGN;
1829 style->color_flags[state] |= GTK_RC_BG;
1830 return gtk_rc_parse_color (scanner, &style->bg[state]);
1834 gtk_rc_parse_fg (GScanner *scanner,
1840 token = g_scanner_get_next_token (scanner);
1841 if (token != GTK_RC_TOKEN_FG)
1842 return GTK_RC_TOKEN_FG;
1844 token = gtk_rc_parse_state (scanner, &state);
1845 if (token != G_TOKEN_NONE)
1848 token = g_scanner_get_next_token (scanner);
1849 if (token != G_TOKEN_EQUAL_SIGN)
1850 return G_TOKEN_EQUAL_SIGN;
1852 style->color_flags[state] |= GTK_RC_FG;
1853 return gtk_rc_parse_color (scanner, &style->fg[state]);
1857 gtk_rc_parse_text (GScanner *scanner,
1863 token = g_scanner_get_next_token (scanner);
1864 if (token != GTK_RC_TOKEN_TEXT)
1865 return GTK_RC_TOKEN_TEXT;
1867 token = gtk_rc_parse_state (scanner, &state);
1868 if (token != G_TOKEN_NONE)
1871 token = g_scanner_get_next_token (scanner);
1872 if (token != G_TOKEN_EQUAL_SIGN)
1873 return G_TOKEN_EQUAL_SIGN;
1875 style->color_flags[state] |= GTK_RC_TEXT;
1876 return gtk_rc_parse_color (scanner, &style->text[state]);
1880 gtk_rc_parse_base (GScanner *scanner,
1886 token = g_scanner_get_next_token (scanner);
1887 if (token != GTK_RC_TOKEN_BASE)
1888 return GTK_RC_TOKEN_BASE;
1890 token = gtk_rc_parse_state (scanner, &state);
1891 if (token != G_TOKEN_NONE)
1894 token = g_scanner_get_next_token (scanner);
1895 if (token != G_TOKEN_EQUAL_SIGN)
1896 return G_TOKEN_EQUAL_SIGN;
1898 style->color_flags[state] |= GTK_RC_BASE;
1899 return gtk_rc_parse_color (scanner, &style->base[state]);
1903 gtk_rc_parse_xthickness (GScanner *scanner,
1906 if (g_scanner_get_next_token (scanner) != GTK_RC_TOKEN_XTHICKNESS)
1907 return GTK_RC_TOKEN_XTHICKNESS;
1909 if (g_scanner_get_next_token (scanner) != G_TOKEN_EQUAL_SIGN)
1910 return G_TOKEN_EQUAL_SIGN;
1912 if (g_scanner_get_next_token (scanner) != G_TOKEN_INT)
1915 style->xthickness = scanner->value.v_int;
1917 return G_TOKEN_NONE;
1921 gtk_rc_parse_ythickness (GScanner *scanner,
1924 if (g_scanner_get_next_token (scanner) != GTK_RC_TOKEN_YTHICKNESS)
1925 return GTK_RC_TOKEN_YTHICKNESS;
1927 if (g_scanner_get_next_token (scanner) != G_TOKEN_EQUAL_SIGN)
1928 return G_TOKEN_EQUAL_SIGN;
1930 if (g_scanner_get_next_token (scanner) != G_TOKEN_INT)
1933 style->ythickness = scanner->value.v_int;
1935 return G_TOKEN_NONE;
1939 gtk_rc_parse_bg_pixmap (GScanner *scanner,
1940 GtkRcStyle *rc_style)
1946 token = g_scanner_get_next_token (scanner);
1947 if (token != GTK_RC_TOKEN_BG_PIXMAP)
1948 return GTK_RC_TOKEN_BG_PIXMAP;
1950 token = gtk_rc_parse_state (scanner, &state);
1951 if (token != G_TOKEN_NONE)
1954 token = g_scanner_get_next_token (scanner);
1955 if (token != G_TOKEN_EQUAL_SIGN)
1956 return G_TOKEN_EQUAL_SIGN;
1958 token = g_scanner_get_next_token (scanner);
1959 if (token != G_TOKEN_STRING)
1960 return G_TOKEN_STRING;
1962 if ((strcmp (scanner->value.v_string, "<parent>") == 0) ||
1963 (strcmp (scanner->value.v_string, "<none>") == 0))
1964 pixmap_file = g_strdup (scanner->value.v_string);
1966 pixmap_file = gtk_rc_find_pixmap_in_path (scanner, scanner->value.v_string);
1970 if (rc_style->bg_pixmap_name[state])
1971 g_free (rc_style->bg_pixmap_name[state]);
1972 rc_style->bg_pixmap_name[state] = pixmap_file;
1975 return G_TOKEN_NONE;
1979 gtk_rc_check_pixmap_dir (const gchar *dir, const gchar *pixmap_file)
1984 buf = g_strdup_printf ("%s" G_DIR_SEPARATOR_S "%s", dir, pixmap_file);
1986 fd = open (buf, O_RDONLY);
1999 gtk_rc_find_pixmap_in_path (GScanner *scanner,
2000 const gchar *pixmap_file)
2006 for (i = 0; (i < GTK_RC_MAX_PIXMAP_PATHS) && (pixmap_path[i] != NULL); i++)
2008 filename = gtk_rc_check_pixmap_dir (pixmap_path[i], pixmap_file);
2013 tmp_list = rc_dir_stack;
2016 filename = gtk_rc_check_pixmap_dir (tmp_list->data, pixmap_file);
2020 tmp_list = tmp_list->next;
2024 g_warning (_("Unable to locate image file in pixmap_path: \"%s\" line %d"),
2025 pixmap_file, scanner->line);
2027 g_warning (_("Unable to locate image file in pixmap_path: \"%s\""),
2034 gtk_rc_find_module_in_path (const gchar *module_file)
2040 for (i = 0; (i < GTK_RC_MAX_MODULE_PATHS) && (module_path[i] != NULL); i++)
2042 buf = g_strdup_printf ("%s" G_DIR_SEPARATOR_S "%s",
2043 module_path[i], module_file);
2045 fd = open (buf, O_RDONLY);
2059 gtk_rc_parse_font (GScanner *scanner,
2060 GtkRcStyle *rc_style)
2064 token = g_scanner_get_next_token (scanner);
2065 if (token != GTK_RC_TOKEN_FONT)
2066 return GTK_RC_TOKEN_FONT;
2068 token = g_scanner_get_next_token (scanner);
2069 if (token != G_TOKEN_EQUAL_SIGN)
2070 return G_TOKEN_EQUAL_SIGN;
2072 token = g_scanner_get_next_token (scanner);
2073 if (token != G_TOKEN_STRING)
2074 return G_TOKEN_STRING;
2076 /* Ignore, do nothing */
2078 return G_TOKEN_NONE;
2082 gtk_rc_parse_fontset (GScanner *scanner,
2083 GtkRcStyle *rc_style)
2087 token = g_scanner_get_next_token (scanner);
2088 if (token != GTK_RC_TOKEN_FONTSET)
2089 return GTK_RC_TOKEN_FONTSET;
2091 token = g_scanner_get_next_token (scanner);
2092 if (token != G_TOKEN_EQUAL_SIGN)
2093 return G_TOKEN_EQUAL_SIGN;
2095 token = g_scanner_get_next_token (scanner);
2096 if (token != G_TOKEN_STRING)
2097 return G_TOKEN_STRING;
2099 /* Do nothing - silently ignore */
2101 return G_TOKEN_NONE;
2105 gtk_rc_parse_font_name (GScanner *scanner,
2106 GtkRcStyle *rc_style)
2110 token = g_scanner_get_next_token (scanner);
2111 if (token != GTK_RC_TOKEN_FONT_NAME)
2112 return GTK_RC_TOKEN_FONT;
2114 token = g_scanner_get_next_token (scanner);
2115 if (token != G_TOKEN_EQUAL_SIGN)
2116 return G_TOKEN_EQUAL_SIGN;
2118 token = g_scanner_get_next_token (scanner);
2119 if (token != G_TOKEN_STRING)
2120 return G_TOKEN_STRING;
2122 rc_style->font_desc = pango_font_description_from_string (scanner->value.v_string);
2124 return G_TOKEN_NONE;
2128 gtk_rc_parse_engine (GScanner *scanner,
2129 GtkRcStyle **rc_style)
2132 GtkThemeEngine *engine;
2133 guint result = G_TOKEN_NONE;
2134 GtkRcStyle *new_style = NULL;
2135 gboolean parsed_curlies = FALSE;
2137 token = g_scanner_get_next_token (scanner);
2138 if (token != GTK_RC_TOKEN_ENGINE)
2139 return GTK_RC_TOKEN_ENGINE;
2141 token = g_scanner_get_next_token (scanner);
2142 if (token != G_TOKEN_STRING)
2143 return G_TOKEN_STRING;
2145 engine = gtk_theme_engine_get (scanner->value.v_string);
2147 token = g_scanner_get_next_token (scanner);
2148 if (token != G_TOKEN_LEFT_CURLY)
2149 return G_TOKEN_LEFT_CURLY;
2153 GtkRcStyleClass *new_class;
2155 new_style = gtk_theme_engine_create_rc_style (engine);
2156 g_type_module_unuse (G_TYPE_MODULE (engine));
2158 new_class = GTK_RC_STYLE_GET_CLASS (new_style);
2160 new_class->merge (new_style, *rc_style);
2161 if ((*rc_style)->name)
2162 new_style->name = g_strdup ((*rc_style)->name);
2164 if (new_class->parse)
2166 parsed_curlies = TRUE;
2167 result = new_class->parse (new_style, scanner);
2169 if (result != G_TOKEN_NONE)
2171 g_object_unref (G_OBJECT (new_style));
2177 if (!parsed_curlies)
2179 /* Skip over remainder, looking for nested {}'s
2183 result = G_TOKEN_RIGHT_CURLY;
2184 while ((token = g_scanner_get_next_token (scanner)) != G_TOKEN_EOF)
2186 if (token == G_TOKEN_LEFT_CURLY)
2188 else if (token == G_TOKEN_RIGHT_CURLY)
2193 result = G_TOKEN_NONE;
2201 g_object_unref (G_OBJECT (*rc_style));
2202 *rc_style = new_style;
2209 gtk_rc_parse_state (GScanner *scanner,
2210 GtkStateType *state)
2215 g_return_val_if_fail (scanner != NULL, G_TOKEN_ERROR);
2216 g_return_val_if_fail (state != NULL, G_TOKEN_ERROR);
2218 /* we don't know where we got called from, so we reset the scope here.
2219 * if we bail out due to errors, we *don't* reset the scope, so the
2220 * error messaging code can make sense of our tokens.
2222 old_scope = g_scanner_set_scope (scanner, 0);
2224 token = g_scanner_get_next_token (scanner);
2225 if (token != G_TOKEN_LEFT_BRACE)
2226 return G_TOKEN_LEFT_BRACE;
2228 token = g_scanner_get_next_token (scanner);
2231 case GTK_RC_TOKEN_ACTIVE:
2232 *state = GTK_STATE_ACTIVE;
2234 case GTK_RC_TOKEN_INSENSITIVE:
2235 *state = GTK_STATE_INSENSITIVE;
2237 case GTK_RC_TOKEN_NORMAL:
2238 *state = GTK_STATE_NORMAL;
2240 case GTK_RC_TOKEN_PRELIGHT:
2241 *state = GTK_STATE_PRELIGHT;
2243 case GTK_RC_TOKEN_SELECTED:
2244 *state = GTK_STATE_SELECTED;
2247 return /* G_TOKEN_SYMBOL */ GTK_RC_TOKEN_NORMAL;
2250 token = g_scanner_get_next_token (scanner);
2251 if (token != G_TOKEN_RIGHT_BRACE)
2252 return G_TOKEN_RIGHT_BRACE;
2254 g_scanner_set_scope (scanner, old_scope);
2256 return G_TOKEN_NONE;
2260 gtk_rc_parse_priority (GScanner *scanner,
2261 GtkPathPriorityType *priority)
2266 g_return_val_if_fail (scanner != NULL, G_TOKEN_ERROR);
2267 g_return_val_if_fail (priority != NULL, G_TOKEN_ERROR);
2269 /* we don't know where we got called from, so we reset the scope here.
2270 * if we bail out due to errors, we *don't* reset the scope, so the
2271 * error messaging code can make sense of our tokens.
2273 old_scope = g_scanner_set_scope (scanner, 0);
2275 token = g_scanner_get_next_token (scanner);
2279 token = g_scanner_get_next_token (scanner);
2282 case GTK_RC_TOKEN_LOWEST:
2283 *priority = GTK_PATH_PRIO_LOWEST;
2285 case GTK_RC_TOKEN_GTK:
2286 *priority = GTK_PATH_PRIO_GTK;
2288 case GTK_RC_TOKEN_APPLICATION:
2289 *priority = GTK_PATH_PRIO_APPLICATION;
2291 case GTK_RC_TOKEN_RC:
2292 *priority = GTK_PATH_PRIO_RC;
2294 case GTK_RC_TOKEN_HIGHEST:
2295 *priority = GTK_PATH_PRIO_HIGHEST;
2298 return /* G_TOKEN_SYMBOL */ GTK_RC_TOKEN_APPLICATION;
2301 g_scanner_set_scope (scanner, old_scope);
2303 return G_TOKEN_NONE;
2307 gtk_rc_parse_color (GScanner *scanner,
2312 g_return_val_if_fail (scanner != NULL, G_TOKEN_ERROR);
2314 /* we don't need to set our own scop here, because
2315 * we don't need own symbols
2318 token = g_scanner_get_next_token (scanner);
2327 case G_TOKEN_LEFT_CURLY:
2328 token = g_scanner_get_next_token (scanner);
2329 if (token == G_TOKEN_INT)
2330 token_int = scanner->value.v_int;
2331 else if (token == G_TOKEN_FLOAT)
2332 token_int = scanner->value.v_float * 65535.0;
2334 return G_TOKEN_FLOAT;
2335 color->red = CLAMP (token_int, 0, 65535);
2337 token = g_scanner_get_next_token (scanner);
2338 if (token != G_TOKEN_COMMA)
2339 return G_TOKEN_COMMA;
2341 token = g_scanner_get_next_token (scanner);
2342 if (token == G_TOKEN_INT)
2343 token_int = scanner->value.v_int;
2344 else if (token == G_TOKEN_FLOAT)
2345 token_int = scanner->value.v_float * 65535.0;
2347 return G_TOKEN_FLOAT;
2348 color->green = CLAMP (token_int, 0, 65535);
2350 token = g_scanner_get_next_token (scanner);
2351 if (token != G_TOKEN_COMMA)
2352 return G_TOKEN_COMMA;
2354 token = g_scanner_get_next_token (scanner);
2355 if (token == G_TOKEN_INT)
2356 token_int = scanner->value.v_int;
2357 else if (token == G_TOKEN_FLOAT)
2358 token_int = scanner->value.v_float * 65535.0;
2360 return G_TOKEN_FLOAT;
2361 color->blue = CLAMP (token_int, 0, 65535);
2363 token = g_scanner_get_next_token (scanner);
2364 if (token != G_TOKEN_RIGHT_CURLY)
2365 return G_TOKEN_RIGHT_CURLY;
2366 return G_TOKEN_NONE;
2368 case G_TOKEN_STRING:
2369 if (scanner->value.v_string[0] != '#')
2370 return G_TOKEN_STRING;
2372 length = strlen (scanner->value.v_string) - 1;
2373 if (((length % 3) != 0) || (length > 12))
2374 return G_TOKEN_STRING;
2377 for (i = 0, j = 1; i < length; i++, j++)
2378 buf[i] = scanner->value.v_string[j];
2381 sscanf (buf, "%x", &temp);
2384 for (i = 0; i < length; i++, j++)
2385 buf[i] = scanner->value.v_string[j];
2388 sscanf (buf, "%x", &temp);
2389 color->green = temp;
2391 for (i = 0; i < length; i++, j++)
2392 buf[i] = scanner->value.v_string[j];
2395 sscanf (buf, "%x", &temp);
2401 color->green *= 4369;
2402 color->blue *= 4369;
2404 else if (length == 2)
2407 color->green *= 257;
2410 else if (length == 3)
2416 return G_TOKEN_NONE;
2419 return G_TOKEN_STRING;
2424 gtk_rc_parse_pixmap_path (GScanner *scanner)
2428 token = g_scanner_get_next_token (scanner);
2429 if (token != GTK_RC_TOKEN_PIXMAP_PATH)
2430 return GTK_RC_TOKEN_PIXMAP_PATH;
2432 token = g_scanner_get_next_token (scanner);
2433 if (token != G_TOKEN_STRING)
2434 return G_TOKEN_STRING;
2436 gtk_rc_parse_pixmap_path_string (scanner->value.v_string);
2438 return G_TOKEN_NONE;
2442 gtk_rc_parse_pixmap_path_string (gchar *pix_path)
2446 gint start_offset = 0;
2450 /* free the old one, or just add to the old one ? */
2451 for (path_num=0; pixmap_path[path_num]; path_num++)
2453 g_free (pixmap_path[path_num]);
2454 pixmap_path[path_num] = NULL;
2459 path_len = strlen (pix_path);
2461 buf = g_strdup (pix_path);
2463 for (end_offset = 0; end_offset <= path_len; end_offset++)
2465 if ((buf[end_offset] == G_SEARCHPATH_SEPARATOR) ||
2466 (end_offset == path_len))
2468 buf[end_offset] = '\0';
2469 pixmap_path[path_num] = g_strdup (buf + start_offset);
2471 pixmap_path[path_num] = NULL;
2472 start_offset = end_offset + 1;
2479 gtk_rc_parse_module_path (GScanner *scanner)
2483 token = g_scanner_get_next_token (scanner);
2484 if (token != GTK_RC_TOKEN_MODULE_PATH)
2485 return GTK_RC_TOKEN_MODULE_PATH;
2487 token = g_scanner_get_next_token (scanner);
2488 if (token != G_TOKEN_STRING)
2489 return G_TOKEN_STRING;
2491 gtk_rc_parse_module_path_string (scanner->value.v_string);
2493 return G_TOKEN_NONE;
2497 gtk_rc_parse_im_module_path (GScanner *scanner)
2501 token = g_scanner_get_next_token (scanner);
2502 if (token != GTK_RC_TOKEN_IM_MODULE_FILE)
2503 return GTK_RC_TOKEN_IM_MODULE_FILE;
2505 token = g_scanner_get_next_token (scanner);
2506 if (token != G_TOKEN_STRING)
2507 return G_TOKEN_STRING;
2510 g_free (im_module_path);
2512 im_module_path = g_strdup (scanner->value.v_string);
2514 return G_TOKEN_NONE;
2518 gtk_rc_parse_im_module_file (GScanner *scanner)
2522 token = g_scanner_get_next_token (scanner);
2523 if (token != GTK_RC_TOKEN_IM_MODULE_FILE)
2524 return GTK_RC_TOKEN_IM_MODULE_FILE;
2526 token = g_scanner_get_next_token (scanner);
2527 if (token != G_TOKEN_STRING)
2528 return G_TOKEN_STRING;
2531 g_free (im_module_file);
2533 im_module_file = g_strdup (scanner->value.v_string);
2535 return G_TOKEN_NONE;
2539 gtk_rc_parse_module_path_string (gchar *mod_path)
2543 gint start_offset = 0;
2547 /* free the old one, or just add to the old one ? */
2548 for (path_num=0; module_path[path_num]; path_num++)
2550 g_free (module_path[path_num]);
2551 module_path[path_num] = NULL;
2556 path_len = strlen (mod_path);
2558 buf = g_strdup (mod_path);
2560 for (end_offset = 0; end_offset <= path_len; end_offset++)
2562 if ((buf[end_offset] == G_SEARCHPATH_SEPARATOR) ||
2563 (end_offset == path_len))
2565 buf[end_offset] = '\0';
2566 module_path[path_num] = g_strdup (buf + start_offset);
2568 module_path[path_num] = NULL;
2569 start_offset = end_offset + 1;
2573 gtk_rc_append_default_module_path();
2577 gtk_rc_parse_path_pattern (GScanner *scanner)
2580 GtkPathType path_type;
2582 gboolean is_binding;
2583 GtkPathPriorityType priority = GTK_PATH_PRIO_RC;
2585 token = g_scanner_get_next_token (scanner);
2588 case GTK_RC_TOKEN_WIDGET:
2589 path_type = GTK_PATH_WIDGET;
2591 case GTK_RC_TOKEN_WIDGET_CLASS:
2592 path_type = GTK_PATH_WIDGET_CLASS;
2594 case GTK_RC_TOKEN_CLASS:
2595 path_type = GTK_PATH_CLASS;
2598 return GTK_RC_TOKEN_WIDGET_CLASS;
2601 token = g_scanner_get_next_token (scanner);
2602 if (token != G_TOKEN_STRING)
2603 return G_TOKEN_STRING;
2605 pattern = g_strdup (scanner->value.v_string);
2607 token = g_scanner_get_next_token (scanner);
2608 if (token == GTK_RC_TOKEN_STYLE)
2610 else if (token == GTK_RC_TOKEN_BINDING)
2613 if (g_scanner_peek_next_token (scanner) == ':')
2615 token = gtk_rc_parse_priority (scanner, &priority);
2616 if (token != G_TOKEN_NONE)
2626 return GTK_RC_TOKEN_STYLE;
2629 token = g_scanner_get_next_token (scanner);
2630 if (token != G_TOKEN_STRING)
2633 return G_TOKEN_STRING;
2638 GtkBindingSet *binding;
2640 binding = gtk_binding_set_find (scanner->value.v_string);
2644 return G_TOKEN_STRING;
2646 gtk_binding_set_add_path (binding, path_type, pattern, priority);
2650 GtkRcStyle *rc_style;
2653 rc_style = gtk_rc_style_find (scanner->value.v_string);
2658 return G_TOKEN_STRING;
2661 rc_set = g_new (GtkRcSet, 1);
2662 gtk_pattern_spec_init (&rc_set->pspec, pattern);
2663 rc_set->rc_style = rc_style;
2665 if (path_type == GTK_PATH_WIDGET)
2666 gtk_rc_sets_widget = g_slist_prepend (gtk_rc_sets_widget, rc_set);
2667 else if (path_type == GTK_PATH_WIDGET_CLASS)
2668 gtk_rc_sets_widget_class = g_slist_prepend (gtk_rc_sets_widget_class, rc_set);
2670 gtk_rc_sets_class = g_slist_prepend (gtk_rc_sets_class, rc_set);
2674 return G_TOKEN_NONE;
2678 gtk_rc_parse_stock_id (GScanner *scanner,
2683 token = g_scanner_get_next_token (scanner);
2684 if (token != G_TOKEN_LEFT_BRACE)
2685 return G_TOKEN_LEFT_BRACE;
2687 token = g_scanner_get_next_token (scanner);
2689 if (token != G_TOKEN_STRING)
2690 return G_TOKEN_STRING;
2692 *stock_id = g_strdup (scanner->value.v_string);
2694 token = g_scanner_get_next_token (scanner);
2695 if (token != G_TOKEN_RIGHT_BRACE)
2698 return G_TOKEN_RIGHT_BRACE;
2701 return G_TOKEN_NONE;
2705 cleanup_source (GtkIconSource *source)
2707 g_free (source->filename);
2708 g_free (source->size);
2712 gtk_rc_parse_icon_source (GScanner *scanner,
2713 GtkIconSet *icon_set)
2716 GtkIconSource source = { NULL, NULL,
2720 token = g_scanner_get_next_token (scanner);
2721 if (token != G_TOKEN_LEFT_CURLY)
2722 return G_TOKEN_LEFT_CURLY;
2724 token = g_scanner_get_next_token (scanner);
2726 if (token != G_TOKEN_STRING)
2727 return G_TOKEN_STRING;
2729 source.filename = g_strdup (scanner->value.v_string);
2731 token = g_scanner_get_next_token (scanner);
2733 if (token == G_TOKEN_RIGHT_CURLY)
2735 gtk_icon_set_add_source (icon_set, &source);
2736 cleanup_source (&source);
2737 return G_TOKEN_NONE;
2739 else if (token != G_TOKEN_COMMA)
2741 cleanup_source (&source);
2742 return G_TOKEN_COMMA;
2745 /* Get the direction */
2747 token = g_scanner_get_next_token (scanner);
2751 case GTK_RC_TOKEN_RTL:
2752 source.any_direction = FALSE;
2753 source.direction = GTK_TEXT_DIR_RTL;
2756 case GTK_RC_TOKEN_LTR:
2757 source.any_direction = FALSE;
2758 source.direction = GTK_TEXT_DIR_LTR;
2765 cleanup_source (&source);
2766 return GTK_RC_TOKEN_RTL;
2770 token = g_scanner_get_next_token (scanner);
2772 if (token == G_TOKEN_RIGHT_CURLY)
2774 gtk_icon_set_add_source (icon_set, &source);
2775 cleanup_source (&source);
2776 return G_TOKEN_NONE;
2778 else if (token != G_TOKEN_COMMA)
2780 cleanup_source (&source);
2781 return G_TOKEN_COMMA;
2786 token = g_scanner_get_next_token (scanner);
2790 case GTK_RC_TOKEN_NORMAL:
2791 source.any_state = FALSE;
2792 source.state = GTK_STATE_NORMAL;
2795 case GTK_RC_TOKEN_PRELIGHT:
2796 source.any_state = FALSE;
2797 source.state = GTK_STATE_PRELIGHT;
2801 case GTK_RC_TOKEN_INSENSITIVE:
2802 source.any_state = FALSE;
2803 source.state = GTK_STATE_INSENSITIVE;
2806 case GTK_RC_TOKEN_ACTIVE:
2807 source.any_state = FALSE;
2808 source.state = GTK_STATE_ACTIVE;
2811 case GTK_RC_TOKEN_SELECTED:
2812 source.any_state = FALSE;
2813 source.state = GTK_STATE_SELECTED;
2820 cleanup_source (&source);
2821 return GTK_RC_TOKEN_PRELIGHT;
2825 token = g_scanner_get_next_token (scanner);
2827 if (token == G_TOKEN_RIGHT_CURLY)
2829 gtk_icon_set_add_source (icon_set, &source);
2830 cleanup_source (&source);
2831 return G_TOKEN_NONE;
2833 else if (token != G_TOKEN_COMMA)
2835 cleanup_source (&source);
2836 return G_TOKEN_COMMA;
2841 token = g_scanner_get_next_token (scanner);
2845 if (token != G_TOKEN_STRING)
2847 cleanup_source (&source);
2848 return G_TOKEN_STRING;
2851 source.size = g_strdup (scanner->value.v_string);
2852 source.any_size = FALSE;
2855 /* Check the close brace */
2857 token = g_scanner_get_next_token (scanner);
2858 if (token != G_TOKEN_RIGHT_CURLY)
2860 cleanup_source (&source);
2861 return G_TOKEN_RIGHT_CURLY;
2864 gtk_icon_set_add_source (icon_set, &source);
2866 cleanup_source (&source);
2868 return G_TOKEN_NONE;
2872 gtk_rc_parse_stock (GScanner *scanner,
2873 GtkRcStyle *rc_style,
2874 GtkIconFactory *factory)
2876 GtkIconSet *icon_set = NULL;
2877 gchar *stock_id = NULL;
2880 token = g_scanner_get_next_token (scanner);
2881 if (token != GTK_RC_TOKEN_STOCK)
2882 return GTK_RC_TOKEN_STOCK;
2884 token = gtk_rc_parse_stock_id (scanner, &stock_id);
2885 if (token != G_TOKEN_NONE)
2888 token = g_scanner_get_next_token (scanner);
2889 if (token != G_TOKEN_EQUAL_SIGN)
2892 return G_TOKEN_EQUAL_SIGN;
2895 token = g_scanner_get_next_token (scanner);
2896 if (token != G_TOKEN_LEFT_CURLY)
2899 return G_TOKEN_LEFT_CURLY;
2902 token = g_scanner_peek_next_token (scanner);
2903 while (token != G_TOKEN_RIGHT_CURLY)
2905 if (icon_set == NULL)
2906 icon_set = gtk_icon_set_new ();
2908 token = gtk_rc_parse_icon_source (scanner, icon_set);
2909 if (token != G_TOKEN_NONE)
2912 gtk_icon_set_unref (icon_set);
2916 token = g_scanner_get_next_token (scanner);
2918 if (token != G_TOKEN_COMMA &&
2919 token != G_TOKEN_RIGHT_CURLY)
2922 gtk_icon_set_unref (icon_set);
2923 return G_TOKEN_RIGHT_CURLY;
2929 gtk_icon_factory_add (factory,
2933 gtk_icon_set_unref (icon_set);
2938 return G_TOKEN_NONE;
2942 typedef GdkPixmap * (*GtkImageLoader) (GdkWindow *window,
2943 GdkColormap *colormap,
2945 GdkColor *transparent_color,
2946 const gchar *filename);
2950 gtk_rc_set_image_loader(GtkImageLoader loader)
2952 image_loader = loader;
2956 gtk_rc_load_image (GdkColormap *colormap,
2957 GdkColor *transparent_color,
2958 const gchar *filename)
2960 if (strcmp (filename, "<parent>") == 0)
2961 return (GdkPixmap*) GDK_PARENT_RELATIVE;
2965 return image_loader(NULL, colormap, NULL,
2969 return gdk_pixmap_colormap_create_from_xpm (NULL, colormap, NULL,