1 /* GTK - The GIMP Toolkit
2 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
21 * Modified by the GTK+ Team and others 1997-1999. See the AUTHORS
22 * file for a list of people on the GTK+ Team. See the ChangeLog
23 * files for a list of changes. These files are distributed with
24 * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
31 #ifdef GDK_WINDOWING_X11
32 #include <X11/Xlocale.h> /* so we get the right setlocale */
41 #ifdef HAVE_SYS_PARAM_H
42 #include <sys/param.h>
58 #include "gtkbindings.h"
59 #include "gtkthemes.h"
62 typedef struct _GtkRcSet GtkRcSet;
63 typedef struct _GtkRcNode GtkRcNode;
64 typedef struct _GtkRcFile GtkRcFile;
76 gchar *canonical_name;
80 static guint gtk_rc_style_hash (const char *name);
81 static gint gtk_rc_style_compare (const char *a,
83 static guint gtk_rc_styles_hash (const GSList *rc_styles);
84 static gint gtk_rc_styles_compare (const GSList *a,
86 static GtkRcStyle* gtk_rc_style_find (const char *name);
87 static GSList * gtk_rc_styles_match (GSList *rc_styles,
91 gchar *path_reversed);
92 static GtkStyle * gtk_rc_style_to_style (GtkRcStyle *rc_style);
93 static GtkStyle* gtk_rc_style_init (GSList *rc_styles);
94 static void gtk_rc_parse_file (const gchar *filename,
97 static void gtk_rc_parse_any (const gchar *input_name,
99 const gchar *input_string);
100 static guint gtk_rc_parse_statement (GScanner *scanner);
101 static guint gtk_rc_parse_style (GScanner *scanner);
102 static guint gtk_rc_parse_base (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_bg_pixmap (GScanner *scanner,
111 GtkRcStyle *rc_style);
112 static guint gtk_rc_parse_font (GScanner *scanner,
113 GtkRcStyle *rc_style);
114 static guint gtk_rc_parse_fontset (GScanner *scanner,
115 GtkRcStyle *rc_style);
116 static guint gtk_rc_parse_engine (GScanner *scanner,
117 GtkRcStyle *rc_style);
118 static guint gtk_rc_parse_pixmap_path (GScanner *scanner);
119 static void gtk_rc_parse_pixmap_path_string (gchar *pix_path);
120 static guint gtk_rc_parse_module_path (GScanner *scanner);
121 static void gtk_rc_parse_module_path_string (gchar *mod_path);
122 static guint gtk_rc_parse_path_pattern (GScanner *scanner);
123 static void gtk_rc_clear_hash_node (gpointer key,
126 static void gtk_rc_clear_styles (void);
127 static void gtk_rc_append_default_pixmap_path (void);
128 static void gtk_rc_append_default_module_path (void);
129 static void gtk_rc_append_pixmap_path (gchar *dir);
130 static void gtk_rc_add_initial_default_files (void);
133 static const GScannerConfig gtk_rc_scanner_config =
137 ) /* cset_skip_characters */,
142 ) /* cset_identifier_first */,
147 ) /* cset_identifier_nth */,
148 ( "#\n" ) /* cpair_comment_single */,
150 TRUE /* case_sensitive */,
152 TRUE /* skip_comment_multi */,
153 TRUE /* skip_comment_single */,
154 TRUE /* scan_comment_multi */,
155 TRUE /* scan_identifier */,
156 FALSE /* scan_identifier_1char */,
157 FALSE /* scan_identifier_NULL */,
158 TRUE /* scan_symbols */,
159 TRUE /* scan_binary */,
160 TRUE /* scan_octal */,
161 TRUE /* scan_float */,
163 TRUE /* scan_hex_dollar */,
164 TRUE /* scan_string_sq */,
165 TRUE /* scan_string_dq */,
166 TRUE /* numbers_2_int */,
167 FALSE /* int_2_float */,
168 FALSE /* identifier_2_string */,
169 TRUE /* char_2_token */,
170 TRUE /* symbol_2_token */,
171 FALSE /* scope_0_fallback */,
179 { "include", GTK_RC_TOKEN_INCLUDE },
180 { "NORMAL", GTK_RC_TOKEN_NORMAL },
181 { "ACTIVE", GTK_RC_TOKEN_ACTIVE },
182 { "PRELIGHT", GTK_RC_TOKEN_PRELIGHT },
183 { "SELECTED", GTK_RC_TOKEN_SELECTED },
184 { "INSENSITIVE", GTK_RC_TOKEN_INSENSITIVE },
185 { "fg", GTK_RC_TOKEN_FG },
186 { "bg", GTK_RC_TOKEN_BG },
187 { "base", GTK_RC_TOKEN_BASE },
188 { "text", GTK_RC_TOKEN_TEXT },
189 { "font", GTK_RC_TOKEN_FONT },
190 { "fontset", GTK_RC_TOKEN_FONTSET },
191 { "bg_pixmap", GTK_RC_TOKEN_BG_PIXMAP },
192 { "pixmap_path", GTK_RC_TOKEN_PIXMAP_PATH },
193 { "style", GTK_RC_TOKEN_STYLE },
194 { "binding", GTK_RC_TOKEN_BINDING },
195 { "bind", GTK_RC_TOKEN_BIND },
196 { "widget", GTK_RC_TOKEN_WIDGET },
197 { "widget_class", GTK_RC_TOKEN_WIDGET_CLASS },
198 { "class", GTK_RC_TOKEN_CLASS },
199 { "lowest", GTK_RC_TOKEN_LOWEST },
200 { "gtk", GTK_RC_TOKEN_GTK },
201 { "application", GTK_RC_TOKEN_APPLICATION },
202 { "rc", GTK_RC_TOKEN_RC },
203 { "highest", GTK_RC_TOKEN_HIGHEST },
204 { "engine", GTK_RC_TOKEN_ENGINE },
205 { "module_path", GTK_RC_TOKEN_MODULE_PATH },
208 static const guint n_symbols = sizeof (symbols) / sizeof (symbols[0]);
210 static GHashTable *rc_style_ht = NULL;
211 static GHashTable *realized_style_ht = NULL;
212 static GSList *gtk_rc_sets_widget = NULL;
213 static GSList *gtk_rc_sets_widget_class = NULL;
214 static GSList *gtk_rc_sets_class = NULL;
216 #define GTK_RC_MAX_DEFAULT_FILES 128
217 static gchar *gtk_rc_default_files[GTK_RC_MAX_DEFAULT_FILES];
218 static gboolean gtk_rc_auto_parse = TRUE;
220 #define GTK_RC_MAX_PIXMAP_PATHS 128
221 static gchar *pixmap_path[GTK_RC_MAX_PIXMAP_PATHS];
222 #define GTK_RC_MAX_MODULE_PATHS 128
223 static gchar *module_path[GTK_RC_MAX_MODULE_PATHS];
225 /* The files we have parsed, to reread later if necessary */
226 GSList *rc_files = NULL;
228 static GtkImageLoader image_loader = NULL;
230 /* RC file handling */
236 get_gtk_sysconf_directory (void)
238 static gchar gtk_sysconf_dir[200];
241 GetWindowsDirectory (win_dir, sizeof (win_dir));
242 sprintf (gtk_sysconf_dir, "%s\\gtk+", win_dir);
243 return gtk_sysconf_dir;
247 get_themes_directory (void)
249 /* We really should fetch this from the Registry. The GIMP
250 * installation program stores the Themes installation
251 * directory in HKLM\Software\GNU\GTk+\Themes\InstallDirectory.
254 static gchar themes_dir[200];
256 sprintf (themes_dir, "%s\\themes", get_gtk_sysconf_directory ());
263 gtk_rc_get_theme_dir(void)
268 var = getenv("GTK_DATA_PREFIX");
270 path = g_strdup_printf("%s%s", var, "/share/themes");
272 path = g_strdup_printf("%s%s", GTK_DATA_PREFIX, "/share/themes");
274 path = g_strdup (get_themes_directory ());
281 gtk_rc_get_module_dir(void)
286 var = getenv("GTK_EXE_PREFIX");
288 path = g_strdup_printf("%s%s", var, "/lib/gtk/themes/engines");
290 path = g_strdup_printf("%s%s", GTK_EXE_PREFIX, "/lib/gtk/themes/engines");
292 path = g_strdup_printf ("%s%s", get_themes_directory (), "\\engines");
299 gtk_rc_append_default_pixmap_path(void)
305 var = getenv("GTK_DATA_PREFIX");
307 path = g_strdup_printf("%s%s", var, "/share/gtk/themes");
309 path = g_strdup_printf("%s%s", GTK_DATA_PREFIX, "/share/gtk/themes");
311 path = g_strdup (get_themes_directory ());
314 for (n = 0; pixmap_path[n]; n++) ;
315 if (n >= GTK_RC_MAX_PIXMAP_PATHS - 1)
320 pixmap_path[n++] = path;
321 pixmap_path[n] = NULL;
325 gtk_rc_append_pixmap_path(gchar *dir)
329 for (n = 0; pixmap_path[n]; n++) ;
330 if (n >= GTK_RC_MAX_MODULE_PATHS - 1)
332 pixmap_path[n++] = g_strdup(dir);
333 pixmap_path[n] = NULL;
337 gtk_rc_append_default_module_path(void)
342 for (n = 0; module_path[n]; n++) ;
343 if (n >= GTK_RC_MAX_MODULE_PATHS - 1)
347 var = getenv("GTK_EXE_PREFIX");
349 path = g_strdup_printf("%s%s", var, "/lib/gtk/themes/engines");
351 path = g_strdup_printf("%s%s", GTK_EXE_PREFIX, "/lib/gtk/themes/engines");
353 path = g_strdup_printf ("%s%s", get_themes_directory (), "\\engines");
355 module_path[n++] = path;
357 var = g_get_home_dir ();
361 path = g_strdup_printf ("%s%s", var, "/.gtk/lib/themes/engines");
363 path = g_strdup_printf ("%s%s", var, "\\_gtk\\themes\\engines");
365 module_path[n++] = path;
367 module_path[n] = NULL;
371 gtk_rc_add_initial_default_files (void)
373 static gint init = FALSE;
381 gtk_rc_default_files[0] = NULL;
384 var = g_getenv("GTK_RC_FILES");
387 files = g_strsplit (var, G_SEARCHPATH_SEPARATOR_S, 128);
391 gtk_rc_add_default_file (files[i]);
399 str = g_strdup (GTK_SYSCONFDIR G_DIR_SEPARATOR_S "gtk" G_DIR_SEPARATOR_S "gtkrc");
401 str = g_strdup_printf ("%s\\gtkrc", get_gtk_sysconf_directory ());
403 gtk_rc_add_default_file (str);
406 var = g_get_home_dir ();
409 str = g_strdup_printf ("%s" G_DIR_SEPARATOR_S ".gtkrc", var);
410 gtk_rc_add_default_file (str);
417 gtk_rc_add_default_file (const gchar *file)
421 gtk_rc_add_initial_default_files ();
423 for (n = 0; gtk_rc_default_files[n]; n++) ;
424 if (n >= GTK_RC_MAX_DEFAULT_FILES - 1)
427 gtk_rc_default_files[n++] = g_strdup (file);
428 gtk_rc_default_files[n] = NULL;
432 gtk_rc_set_default_files (gchar **files)
436 gtk_rc_add_initial_default_files ();
439 while (gtk_rc_default_files[i])
441 g_free (gtk_rc_default_files[i]);
445 gtk_rc_default_files[0] = NULL;
446 gtk_rc_auto_parse = FALSE;
449 while (files[i] != NULL)
451 gtk_rc_add_default_file (files[i]);
457 gtk_rc_get_default_files (void)
459 gtk_rc_add_initial_default_files ();
461 return gtk_rc_default_files;
467 gchar *locale_suffixes[3];
468 gint n_locale_suffixes = 0;
471 char *locale = g_win32_getlocale ();
473 #ifdef HAVE_LC_MESSAGES
474 char *locale = setlocale (LC_MESSAGES, NULL);
476 char *locale = setlocale (LC_CTYPE, NULL);
482 rc_style_ht = g_hash_table_new ((GHashFunc) gtk_rc_style_hash,
483 (GCompareFunc) gtk_rc_style_compare);
484 pixmap_path[0] = NULL;
485 module_path[0] = NULL;
486 gtk_rc_append_default_pixmap_path();
487 gtk_rc_append_default_module_path();
489 gtk_rc_add_initial_default_files ();
491 if (strcmp (locale, "C") && strcmp (locale, "POSIX"))
493 /* Determine locale-specific suffixes for RC files
495 p = strchr (locale, '@');
496 length = p ? (p -locale) : strlen (locale);
498 p = strchr (locale, '.');
501 locale_suffixes[n_locale_suffixes++] = g_strndup (locale, length);
505 p = strchr (locale, '_');
508 locale_suffixes[n_locale_suffixes++] = g_strndup (locale, length);
512 locale_suffixes[n_locale_suffixes++] = g_strndup (locale, length);
516 while (gtk_rc_default_files[i] != NULL)
518 /* Try to find a locale specific RC file corresponding to
519 * to parse before the default file.
521 for (j=n_locale_suffixes-1; j>=0; j--)
523 gchar *name = g_strconcat (gtk_rc_default_files[i],
531 gtk_rc_parse (gtk_rc_default_files[i]);
537 gtk_rc_parse_string (const gchar *rc_string)
539 g_return_if_fail (rc_string != NULL);
541 gtk_rc_parse_any ("-", -1, rc_string);
545 gtk_rc_parse_file (const gchar *filename, gboolean reload)
547 GtkRcFile *rc_file = NULL;
551 g_return_if_fail (filename != NULL);
556 rc_file = tmp_list->data;
557 if (!strcmp (rc_file->name, filename))
560 tmp_list = tmp_list->next;
565 rc_file = g_new (GtkRcFile, 1);
566 rc_file->name = g_strdup (filename);
567 rc_file->canonical_name = NULL;
569 rc_file->reload = reload;
571 rc_files = g_slist_append (rc_files, rc_file);
574 if (!rc_file->canonical_name)
576 /* Get the absolute pathname */
578 if (g_path_is_absolute (rc_file->name))
579 rc_file->canonical_name = rc_file->name;
585 cwd = g_get_current_dir ();
587 str = g_string_new (cwd);
589 g_string_append_c (str, G_DIR_SEPARATOR);
590 g_string_append (str, rc_file->name);
592 rc_file->canonical_name = str->str;
593 g_string_free (str, FALSE);
597 if (!lstat (rc_file->canonical_name, &statbuf))
601 rc_file->mtime = statbuf.st_mtime;
603 fd = open (rc_file->canonical_name, O_RDONLY);
611 dir = g_strdup(rc_file->canonical_name);
612 for (i = strlen(dir) - 1; (i >= 0) && (dir[i] != G_DIR_SEPARATOR); i--)
614 if (i >= 0 && dir[i] == G_DIR_SEPARATOR)
616 gtk_rc_append_pixmap_path(dir);
619 gtk_rc_parse_any (filename, fd, NULL);
626 gtk_rc_parse (const gchar *filename)
628 g_return_if_fail (filename != NULL);
630 gtk_rc_parse_file (filename, TRUE);
633 /* Handling of RC styles */
636 gtk_rc_style_new (void)
638 GtkRcStyle *new_style;
640 new_style = g_new0 (GtkRcStyle, 1);
641 new_style->ref_count = 1;
647 gtk_rc_style_ref (GtkRcStyle *rc_style)
649 g_return_if_fail (rc_style != NULL);
651 rc_style->ref_count++;
655 gtk_rc_style_unref (GtkRcStyle *rc_style)
659 g_return_if_fail (rc_style != NULL);
660 g_return_if_fail (rc_style->ref_count > 0);
662 rc_style->ref_count--;
664 if (rc_style->ref_count == 0)
666 if (rc_style->engine)
668 rc_style->engine->destroy_rc_style (rc_style);
669 gtk_theme_engine_unref (rc_style->engine);
673 g_free (rc_style->name);
674 if (rc_style->fontset_name)
675 g_free (rc_style->fontset_name);
676 if (rc_style->font_name)
677 g_free (rc_style->font_name);
679 for (i=0 ; i<5 ; i++)
680 if (rc_style->bg_pixmap_name[i])
681 g_free (rc_style->bg_pixmap_name[i]);
688 gtk_rc_clear_realized_node (gpointer key,
692 gtk_style_unref (data);
696 gtk_rc_clear_hash_node (gpointer key,
700 gtk_rc_style_unref (data);
704 gtk_rc_free_rc_sets (GSList *slist)
710 rc_set = slist->data;
711 gtk_pattern_spec_free_segs (&rc_set->pspec);
719 gtk_rc_clear_styles (void)
721 /* Clear out all old rc_styles */
725 g_hash_table_foreach (rc_style_ht, gtk_rc_clear_hash_node, NULL);
726 g_hash_table_destroy (rc_style_ht);
730 if (realized_style_ht)
732 g_hash_table_foreach (realized_style_ht, gtk_rc_clear_realized_node, NULL);
733 g_hash_table_destroy (realized_style_ht);
734 realized_style_ht = NULL;
737 gtk_rc_free_rc_sets (gtk_rc_sets_widget);
738 g_slist_free (gtk_rc_sets_widget);
739 gtk_rc_sets_widget = NULL;
741 gtk_rc_free_rc_sets (gtk_rc_sets_widget_class);
742 g_slist_free (gtk_rc_sets_widget_class);
743 gtk_rc_sets_widget_class = NULL;
745 gtk_rc_free_rc_sets (gtk_rc_sets_class);
746 g_slist_free (gtk_rc_sets_class);
747 gtk_rc_sets_class = NULL;
753 gtk_rc_reparse_all (void)
756 gboolean mtime_modified = FALSE;
761 /* Check through and see if any of the RC's have had their
762 * mtime modified. If so, reparse everything.
767 rc_file = tmp_list->data;
769 if (!lstat (rc_file->name, &statbuf) &&
770 (statbuf.st_mtime > rc_file->mtime))
772 mtime_modified = TRUE;
776 tmp_list = tmp_list->next;
781 gtk_rc_clear_styles();
786 rc_file = tmp_list->data;
788 gtk_rc_parse_file (rc_file->name, FALSE);
790 tmp_list = tmp_list->next;
794 return mtime_modified;
798 gtk_rc_styles_match (GSList *rc_styles,
802 gchar *path_reversed)
812 if (gtk_pattern_match (&rc_set->pspec, path_length, path, path_reversed))
813 rc_styles = g_slist_append (rc_styles, rc_set->rc_style);
820 gtk_rc_get_style (GtkWidget *widget)
822 GtkRcStyle *widget_rc_style;
823 GSList *rc_styles = NULL;
825 static guint rc_style_key_id = 0;
827 /* We allow the specification of a single rc style to be bound
828 * tightly to a widget, for application modifications
830 if (!rc_style_key_id)
831 rc_style_key_id = g_quark_from_static_string ("gtk-rc-style");
833 widget_rc_style = gtk_object_get_data_by_id (GTK_OBJECT (widget),
837 rc_styles = g_slist_prepend (rc_styles, widget_rc_style);
839 if (gtk_rc_sets_widget)
841 gchar *path, *path_reversed;
844 gtk_widget_path (widget, &path_length, &path, &path_reversed);
845 rc_styles = gtk_rc_styles_match (rc_styles, gtk_rc_sets_widget, path_length, path, path_reversed);
847 g_free (path_reversed);
851 if (gtk_rc_sets_widget_class)
853 gchar *path, *path_reversed;
856 gtk_widget_class_path (widget, &path_length, &path, &path_reversed);
857 rc_styles = gtk_rc_styles_match (rc_styles, gtk_rc_sets_widget_class, path_length, path, path_reversed);
859 g_free (path_reversed);
862 if (gtk_rc_sets_class)
866 type = GTK_OBJECT_TYPE (widget);
869 gchar *path, *path_reversed;
872 path = gtk_type_name (type);
873 path_length = strlen (path);
874 path_reversed = g_strdup (path);
875 g_strreverse (path_reversed);
877 rc_styles = gtk_rc_styles_match (rc_styles, gtk_rc_sets_class, path_length, path, path_reversed);
878 g_free (path_reversed);
880 type = gtk_type_parent (type);
885 return gtk_rc_style_init (rc_styles);
891 gtk_rc_add_rc_sets (GSList *slist,
892 GtkRcStyle *rc_style,
895 GtkRcStyle *new_style;
899 new_style = gtk_rc_style_new ();
900 *new_style = *rc_style;
901 new_style->name = g_strdup (rc_style->name);
902 new_style->font_name = g_strdup (rc_style->font_name);
903 new_style->fontset_name = g_strdup (rc_style->fontset_name);
905 for (i = 0; i < 5; i++)
906 new_style->bg_pixmap_name[i] = g_strdup (rc_style->bg_pixmap_name[i]);
908 rc_set = g_new (GtkRcSet, 1);
909 gtk_pattern_spec_init (&rc_set->pspec, pattern);
910 rc_set->rc_style = rc_style;
912 return g_slist_prepend (slist, rc_set);
916 gtk_rc_add_widget_name_style (GtkRcStyle *rc_style,
917 const gchar *pattern)
919 g_return_if_fail (rc_style != NULL);
920 g_return_if_fail (pattern != NULL);
922 gtk_rc_sets_widget = gtk_rc_add_rc_sets (gtk_rc_sets_widget, rc_style, pattern);
926 gtk_rc_add_widget_class_style (GtkRcStyle *rc_style,
927 const gchar *pattern)
929 g_return_if_fail (rc_style != NULL);
930 g_return_if_fail (pattern != NULL);
932 gtk_rc_sets_widget_class = gtk_rc_add_rc_sets (gtk_rc_sets_widget_class, rc_style, pattern);
936 gtk_rc_add_class_style (GtkRcStyle *rc_style,
937 const gchar *pattern)
939 g_return_if_fail (rc_style != NULL);
940 g_return_if_fail (pattern != NULL);
942 gtk_rc_sets_class = gtk_rc_add_rc_sets (gtk_rc_sets_class, rc_style, pattern);
946 gtk_rc_parse_any (const gchar *input_name,
948 const gchar *input_string)
954 scanner = g_scanner_new ((GScannerConfig *) >k_rc_scanner_config);
958 g_assert (input_string == NULL);
960 g_scanner_input_file (scanner, input_fd);
964 g_assert (input_string != NULL);
966 g_scanner_input_text (scanner, input_string, strlen (input_string));
968 scanner->input_name = input_name;
970 g_scanner_freeze_symbol_table (scanner);
971 for (i = 0; i < n_symbols; i++)
972 g_scanner_add_symbol (scanner, symbols[i].name, GINT_TO_POINTER (symbols[i].token));
973 g_scanner_thaw_symbol_table (scanner);
978 if (g_scanner_peek_next_token (scanner) == G_TOKEN_EOF)
982 guint expected_token;
984 expected_token = gtk_rc_parse_statement (scanner);
986 if (expected_token != G_TOKEN_NONE)
993 if (scanner->scope_id == 0)
995 /* if we are in scope 0, we know the symbol names
996 * that are associated with certaintoken values.
997 * so we look them up to make the error messages
1000 if (expected_token > GTK_RC_TOKEN_INVALID &&
1001 expected_token < GTK_RC_TOKEN_LAST)
1003 for (i = 0; i < n_symbols; i++)
1004 if (symbols[i].token == expected_token)
1005 msg = symbols[i].name;
1007 msg = g_strconcat ("e.g. `", msg, "'", NULL);
1009 if (scanner->token > GTK_RC_TOKEN_INVALID &&
1010 scanner->token < GTK_RC_TOKEN_LAST)
1012 symbol_name = "???";
1013 for (i = 0; i < n_symbols; i++)
1014 if (symbols[i].token == scanner->token)
1015 symbol_name = symbols[i].name;
1018 g_scanner_unexp_token (scanner,
1031 g_scanner_destroy (scanner);
1035 gtk_rc_styles_hash (const GSList *rc_styles)
1042 result += (result << 9) + GPOINTER_TO_UINT (rc_styles->data);
1043 rc_styles = rc_styles->next;
1050 gtk_rc_styles_compare (const GSList *a,
1055 if (a->data != b->data)
1065 gtk_rc_style_hash (const char *name)
1071 result += (result << 3) + *name++;
1077 gtk_rc_style_compare (const char *a,
1080 return (strcmp (a, b) == 0);
1084 gtk_rc_style_find (const char *name)
1086 GtkRcStyle *rc_style;
1088 rc_style = g_hash_table_lookup (rc_style_ht, (gpointer) name);
1093 /* Assumes ownership of rc_style */
1095 gtk_rc_style_to_style (GtkRcStyle *rc_style)
1101 style = gtk_style_new ();
1103 style->rc_style = rc_style;
1105 if (rc_style->fontset_name)
1107 old_font = style->font;
1108 style->font = gdk_fontset_load (rc_style->fontset_name);
1110 gdk_font_unref (old_font);
1112 style->font = old_font;
1114 else if (rc_style->font_name)
1116 old_font = style->font;
1117 style->font = gdk_font_load (rc_style->font_name);
1119 gdk_font_unref (old_font);
1121 style->font = old_font;
1124 for (i = 0; i < 5; i++)
1126 if (rc_style->color_flags[i] & GTK_RC_FG)
1127 style->fg[i] = rc_style->fg[i];
1128 if (rc_style->color_flags[i] & GTK_RC_BG)
1129 style->bg[i] = rc_style->bg[i];
1130 if (rc_style->color_flags[i] & GTK_RC_TEXT)
1131 style->text[i] = rc_style->text[i];
1132 if (rc_style->color_flags[i] & GTK_RC_BASE)
1133 style->base[i] = rc_style->base[i];
1136 if (rc_style->engine)
1138 style->engine = rc_style->engine;
1139 gtk_theme_engine_ref (style->engine);
1140 rc_style->engine->rc_style_to_style (style, rc_style);
1146 /* Reuses or frees rc_styles */
1148 gtk_rc_style_init (GSList *rc_styles)
1152 GtkStyle *style = NULL;
1153 GtkRcStyle *proto_style;
1155 if (!realized_style_ht)
1156 realized_style_ht = g_hash_table_new ((GHashFunc)gtk_rc_styles_hash,
1157 (GCompareFunc)gtk_rc_styles_compare);
1159 style = g_hash_table_lookup (realized_style_ht, rc_styles);
1163 GSList *tmp_styles = rc_styles;
1165 proto_style = gtk_rc_style_new ();
1169 GtkRcStyle *rc_style = tmp_styles->data;
1173 if (!proto_style->bg_pixmap_name[i] && rc_style->bg_pixmap_name[i])
1174 proto_style->bg_pixmap_name[i] = g_strdup (rc_style->bg_pixmap_name[i]);
1176 if (!(proto_style->color_flags[i] & GTK_RC_FG) &&
1177 rc_style->color_flags[i] & GTK_RC_FG)
1179 proto_style->fg[i] = rc_style->fg[i];
1180 proto_style->color_flags[i] |= GTK_RC_FG;
1182 if (!(proto_style->color_flags[i] & GTK_RC_BG) &&
1183 rc_style->color_flags[i] & GTK_RC_BG)
1185 proto_style->bg[i] = rc_style->bg[i];
1186 proto_style->color_flags[i] |= GTK_RC_BG;
1188 if (!(proto_style->color_flags[i] & GTK_RC_TEXT) &&
1189 rc_style->color_flags[i] & GTK_RC_TEXT)
1191 proto_style->text[i] = rc_style->text[i];
1192 proto_style->color_flags[i] |= GTK_RC_TEXT;
1194 if (!(proto_style->color_flags[i] & GTK_RC_BASE) &&
1195 rc_style->color_flags[i] & GTK_RC_BASE)
1197 proto_style->base[i] = rc_style->base[i];
1198 proto_style->color_flags[i] |= GTK_RC_BASE;
1202 if (!proto_style->font_name && rc_style->font_name)
1203 proto_style->font_name = g_strdup (rc_style->font_name);
1204 if (!proto_style->fontset_name && rc_style->fontset_name)
1205 proto_style->fontset_name = g_strdup (rc_style->fontset_name);
1207 if (!proto_style->engine && rc_style->engine)
1209 proto_style->engine = rc_style->engine;
1210 gtk_theme_engine_ref (proto_style->engine);
1213 if (proto_style->engine &&
1214 (proto_style->engine == rc_style->engine))
1215 proto_style->engine->merge_rc_style (proto_style, rc_style);
1217 tmp_styles = tmp_styles->next;
1221 if (proto_style->bg_pixmap_name[i] &&
1222 (strcmp (proto_style->bg_pixmap_name[i], "<none>") == 0))
1224 g_free (proto_style->bg_pixmap_name[i]);
1225 proto_style->bg_pixmap_name[i] = NULL;
1228 style = gtk_rc_style_to_style (proto_style);
1230 g_hash_table_insert (realized_style_ht, rc_styles, style);
1236 /*********************
1237 * Parsing functions *
1238 *********************/
1241 gtk_rc_parse_statement (GScanner *scanner)
1245 token = g_scanner_peek_next_token (scanner);
1249 case GTK_RC_TOKEN_INCLUDE:
1250 token = g_scanner_get_next_token (scanner);
1251 if (token != GTK_RC_TOKEN_INCLUDE)
1252 return GTK_RC_TOKEN_INCLUDE;
1254 token = g_scanner_get_next_token (scanner);
1255 if (token != G_TOKEN_STRING)
1256 return G_TOKEN_STRING;
1258 gtk_rc_parse_file (scanner->value.v_string, FALSE);
1259 return G_TOKEN_NONE;
1261 case GTK_RC_TOKEN_STYLE:
1262 return gtk_rc_parse_style (scanner);
1264 case GTK_RC_TOKEN_BINDING:
1265 return gtk_binding_parse_binding (scanner);
1267 case GTK_RC_TOKEN_PIXMAP_PATH:
1268 return gtk_rc_parse_pixmap_path (scanner);
1270 case GTK_RC_TOKEN_WIDGET:
1271 return gtk_rc_parse_path_pattern (scanner);
1273 case GTK_RC_TOKEN_WIDGET_CLASS:
1274 return gtk_rc_parse_path_pattern (scanner);
1276 case GTK_RC_TOKEN_CLASS:
1277 return gtk_rc_parse_path_pattern (scanner);
1279 case GTK_RC_TOKEN_MODULE_PATH:
1280 return gtk_rc_parse_module_path (scanner);
1283 g_scanner_get_next_token (scanner);
1284 return /* G_TOKEN_SYMBOL */ GTK_RC_TOKEN_STYLE;
1289 gtk_rc_parse_style (GScanner *scanner)
1291 GtkRcStyle *rc_style;
1292 GtkRcStyle *parent_style;
1297 token = g_scanner_get_next_token (scanner);
1298 if (token != GTK_RC_TOKEN_STYLE)
1299 return GTK_RC_TOKEN_STYLE;
1301 token = g_scanner_get_next_token (scanner);
1302 if (token != G_TOKEN_STRING)
1303 return G_TOKEN_STRING;
1306 rc_style = g_hash_table_lookup (rc_style_ht, scanner->value.v_string);
1311 rc_style = gtk_rc_style_new ();
1312 rc_style->name = g_strdup (scanner->value.v_string);
1314 for (i = 0; i < 5; i++)
1315 rc_style->bg_pixmap_name[i] = NULL;
1317 for (i = 0; i < 5; i++)
1318 rc_style->color_flags[i] = 0;
1320 rc_style->engine = NULL;
1321 rc_style->engine_data = NULL;
1324 token = g_scanner_peek_next_token (scanner);
1325 if (token == G_TOKEN_EQUAL_SIGN)
1327 token = g_scanner_get_next_token (scanner);
1329 token = g_scanner_get_next_token (scanner);
1330 if (token != G_TOKEN_STRING)
1335 return G_TOKEN_STRING;
1338 parent_style = g_hash_table_lookup (rc_style_ht, scanner->value.v_string);
1341 for (i = 0; i < 5; i++)
1343 rc_style->color_flags[i] = parent_style->color_flags[i];
1344 rc_style->fg[i] = parent_style->fg[i];
1345 rc_style->bg[i] = parent_style->bg[i];
1346 rc_style->text[i] = parent_style->text[i];
1347 rc_style->base[i] = parent_style->base[i];
1350 if (parent_style->fontset_name)
1352 if (rc_style->fontset_name)
1353 g_free (rc_style->fontset_name);
1354 rc_style->fontset_name = g_strdup (parent_style->fontset_name);
1356 else if (parent_style->font_name)
1358 if (rc_style->font_name)
1359 g_free (rc_style->font_name);
1360 rc_style->font_name = g_strdup (parent_style->font_name);
1363 for (i = 0; i < 5; i++)
1365 if (rc_style->bg_pixmap_name[i])
1366 g_free (rc_style->bg_pixmap_name[i]);
1367 rc_style->bg_pixmap_name[i] = g_strdup (parent_style->bg_pixmap_name[i]);
1372 token = g_scanner_get_next_token (scanner);
1373 if (token != G_TOKEN_LEFT_CURLY)
1378 return G_TOKEN_LEFT_CURLY;
1381 token = g_scanner_peek_next_token (scanner);
1382 while (token != G_TOKEN_RIGHT_CURLY)
1386 case GTK_RC_TOKEN_BASE:
1387 token = gtk_rc_parse_base (scanner, rc_style);
1389 case GTK_RC_TOKEN_BG:
1390 token = gtk_rc_parse_bg (scanner, rc_style);
1392 case GTK_RC_TOKEN_FG:
1393 token = gtk_rc_parse_fg (scanner, rc_style);
1395 case GTK_RC_TOKEN_TEXT:
1396 token = gtk_rc_parse_text (scanner, rc_style);
1398 case GTK_RC_TOKEN_BG_PIXMAP:
1399 token = gtk_rc_parse_bg_pixmap (scanner, rc_style);
1401 case GTK_RC_TOKEN_FONT:
1402 token = gtk_rc_parse_font (scanner, rc_style);
1404 case GTK_RC_TOKEN_FONTSET:
1405 token = gtk_rc_parse_fontset (scanner, rc_style);
1407 case GTK_RC_TOKEN_ENGINE:
1408 token = gtk_rc_parse_engine (scanner, rc_style);
1411 g_scanner_get_next_token (scanner);
1412 token = G_TOKEN_RIGHT_CURLY;
1416 if (token != G_TOKEN_NONE)
1420 if (rc_style->fontset_name)
1421 g_free (rc_style->fontset_name);
1422 if (rc_style->font_name)
1423 g_free (rc_style->font_name);
1424 for (i = 0; i < 5; i++)
1425 if (rc_style->bg_pixmap_name[i])
1426 g_free (rc_style->bg_pixmap_name[i]);
1431 token = g_scanner_peek_next_token (scanner);
1434 token = g_scanner_get_next_token (scanner);
1435 if (token != G_TOKEN_RIGHT_CURLY)
1439 if (rc_style->fontset_name)
1440 g_free (rc_style->fontset_name);
1441 if (rc_style->font_name)
1442 g_free (rc_style->font_name);
1444 for (i = 0; i < 5; i++)
1445 if (rc_style->bg_pixmap_name[i])
1446 g_free (rc_style->bg_pixmap_name[i]);
1450 return G_TOKEN_RIGHT_CURLY;
1454 g_hash_table_insert (rc_style_ht, rc_style->name, rc_style);
1456 return G_TOKEN_NONE;
1460 gtk_rc_parse_base (GScanner *scanner,
1466 token = g_scanner_get_next_token (scanner);
1467 if (token != GTK_RC_TOKEN_BASE)
1468 return GTK_RC_TOKEN_BASE;
1470 token = gtk_rc_parse_state (scanner, &state);
1471 if (token != G_TOKEN_NONE)
1474 token = g_scanner_get_next_token (scanner);
1475 if (token != G_TOKEN_EQUAL_SIGN)
1476 return G_TOKEN_EQUAL_SIGN;
1478 style->color_flags[state] |= GTK_RC_BASE;
1479 return gtk_rc_parse_color (scanner, &style->base[state]);
1483 gtk_rc_parse_bg (GScanner *scanner,
1489 token = g_scanner_get_next_token (scanner);
1490 if (token != GTK_RC_TOKEN_BG)
1491 return GTK_RC_TOKEN_BG;
1493 token = gtk_rc_parse_state (scanner, &state);
1494 if (token != G_TOKEN_NONE)
1497 token = g_scanner_get_next_token (scanner);
1498 if (token != G_TOKEN_EQUAL_SIGN)
1499 return G_TOKEN_EQUAL_SIGN;
1501 style->color_flags[state] |= GTK_RC_BG;
1502 return gtk_rc_parse_color (scanner, &style->bg[state]);
1506 gtk_rc_parse_fg (GScanner *scanner,
1512 token = g_scanner_get_next_token (scanner);
1513 if (token != GTK_RC_TOKEN_FG)
1514 return GTK_RC_TOKEN_FG;
1516 token = gtk_rc_parse_state (scanner, &state);
1517 if (token != G_TOKEN_NONE)
1520 token = g_scanner_get_next_token (scanner);
1521 if (token != G_TOKEN_EQUAL_SIGN)
1522 return G_TOKEN_EQUAL_SIGN;
1524 style->color_flags[state] |= GTK_RC_FG;
1525 return gtk_rc_parse_color (scanner, &style->fg[state]);
1529 gtk_rc_parse_text (GScanner *scanner,
1535 token = g_scanner_get_next_token (scanner);
1536 if (token != GTK_RC_TOKEN_TEXT)
1537 return GTK_RC_TOKEN_TEXT;
1539 token = gtk_rc_parse_state (scanner, &state);
1540 if (token != G_TOKEN_NONE)
1543 token = g_scanner_get_next_token (scanner);
1544 if (token != G_TOKEN_EQUAL_SIGN)
1545 return G_TOKEN_EQUAL_SIGN;
1547 style->color_flags[state] |= GTK_RC_TEXT;
1548 return gtk_rc_parse_color (scanner, &style->text[state]);
1552 gtk_rc_parse_bg_pixmap (GScanner *scanner,
1553 GtkRcStyle *rc_style)
1559 token = g_scanner_get_next_token (scanner);
1560 if (token != GTK_RC_TOKEN_BG_PIXMAP)
1561 return GTK_RC_TOKEN_BG_PIXMAP;
1563 token = gtk_rc_parse_state (scanner, &state);
1564 if (token != G_TOKEN_NONE)
1567 token = g_scanner_get_next_token (scanner);
1568 if (token != G_TOKEN_EQUAL_SIGN)
1569 return G_TOKEN_EQUAL_SIGN;
1571 token = g_scanner_get_next_token (scanner);
1572 if (token != G_TOKEN_STRING)
1573 return G_TOKEN_STRING;
1575 if ((strcmp (scanner->value.v_string, "<parent>") == 0) ||
1576 (strcmp (scanner->value.v_string, "<none>") == 0))
1577 pixmap_file = g_strdup (scanner->value.v_string);
1579 pixmap_file = gtk_rc_find_pixmap_in_path (scanner, scanner->value.v_string);
1583 if (rc_style->bg_pixmap_name[state])
1584 g_free (rc_style->bg_pixmap_name[state]);
1585 rc_style->bg_pixmap_name[state] = pixmap_file;
1588 return G_TOKEN_NONE;
1592 gtk_rc_find_pixmap_in_path (GScanner *scanner,
1593 const gchar *pixmap_file)
1599 for (i = 0; (i < GTK_RC_MAX_PIXMAP_PATHS) && (pixmap_path[i] != NULL); i++)
1601 buf = g_strdup_printf ("%s" G_DIR_SEPARATOR_S "%s",
1602 pixmap_path[i], pixmap_file);
1604 fd = open (buf, O_RDONLY);
1615 g_warning (_("Unable to locate image file in pixmap_path: \"%s\" line %d"),
1616 pixmap_file, scanner->line);
1618 g_warning (_("Unable to locate image file in pixmap_path: \"%s\""),
1625 gtk_rc_find_module_in_path (const gchar *module_file)
1631 for (i = 0; (i < GTK_RC_MAX_MODULE_PATHS) && (module_path[i] != NULL); i++)
1633 buf = g_strdup_printf ("%s" G_DIR_SEPARATOR_S "%s",
1634 module_path[i], module_file);
1636 fd = open (buf, O_RDONLY);
1650 gtk_rc_parse_font (GScanner *scanner,
1651 GtkRcStyle *rc_style)
1655 token = g_scanner_get_next_token (scanner);
1656 if (token != GTK_RC_TOKEN_FONT)
1657 return GTK_RC_TOKEN_FONT;
1659 token = g_scanner_get_next_token (scanner);
1660 if (token != G_TOKEN_EQUAL_SIGN)
1661 return G_TOKEN_EQUAL_SIGN;
1663 token = g_scanner_get_next_token (scanner);
1664 if (token != G_TOKEN_STRING)
1665 return G_TOKEN_STRING;
1667 if (rc_style->font_name)
1668 g_free (rc_style->font_name);
1669 rc_style->font_name = g_strdup (scanner->value.v_string);
1671 return G_TOKEN_NONE;
1675 gtk_rc_parse_fontset (GScanner *scanner,
1676 GtkRcStyle *rc_style)
1680 token = g_scanner_get_next_token (scanner);
1681 if (token != GTK_RC_TOKEN_FONTSET)
1682 return GTK_RC_TOKEN_FONTSET;
1684 token = g_scanner_get_next_token (scanner);
1685 if (token != G_TOKEN_EQUAL_SIGN)
1686 return G_TOKEN_EQUAL_SIGN;
1688 token = g_scanner_get_next_token (scanner);
1689 if (token != G_TOKEN_STRING)
1690 return G_TOKEN_STRING;
1692 if (rc_style->fontset_name)
1693 g_free (rc_style->fontset_name);
1694 rc_style->fontset_name = g_strdup (scanner->value.v_string);
1696 return G_TOKEN_NONE;
1700 gtk_rc_parse_engine (GScanner *scanner,
1701 GtkRcStyle *rc_style)
1705 token = g_scanner_get_next_token (scanner);
1706 if (token != GTK_RC_TOKEN_ENGINE)
1707 return GTK_RC_TOKEN_ENGINE;
1709 token = g_scanner_get_next_token (scanner);
1710 if (token != G_TOKEN_STRING)
1711 return G_TOKEN_STRING;
1713 rc_style->engine = gtk_theme_engine_get (scanner->value.v_string);
1715 token = g_scanner_get_next_token (scanner);
1716 if (token != G_TOKEN_LEFT_CURLY)
1717 return G_TOKEN_LEFT_CURLY;
1719 if (rc_style->engine)
1720 return rc_style->engine->parse_rc_style (scanner, rc_style);
1723 /* Skip over remainder, looking for nested {}'s */
1726 while ((token = g_scanner_get_next_token (scanner)) != G_TOKEN_EOF)
1728 if (token == G_TOKEN_LEFT_CURLY)
1730 else if (token == G_TOKEN_RIGHT_CURLY)
1734 return G_TOKEN_NONE;
1737 return G_TOKEN_RIGHT_CURLY;
1742 gtk_rc_parse_state (GScanner *scanner,
1743 GtkStateType *state)
1748 g_return_val_if_fail (scanner != NULL, G_TOKEN_ERROR);
1749 g_return_val_if_fail (state != NULL, G_TOKEN_ERROR);
1751 /* we don't know where we got called from, so we reset the scope here.
1752 * if we bail out due to errors, we *don't* reset the scope, so the
1753 * error messaging code can make sense of our tokens.
1755 old_scope = g_scanner_set_scope (scanner, 0);
1757 token = g_scanner_get_next_token (scanner);
1758 if (token != G_TOKEN_LEFT_BRACE)
1759 return G_TOKEN_LEFT_BRACE;
1761 token = g_scanner_get_next_token (scanner);
1764 case GTK_RC_TOKEN_ACTIVE:
1765 *state = GTK_STATE_ACTIVE;
1767 case GTK_RC_TOKEN_INSENSITIVE:
1768 *state = GTK_STATE_INSENSITIVE;
1770 case GTK_RC_TOKEN_NORMAL:
1771 *state = GTK_STATE_NORMAL;
1773 case GTK_RC_TOKEN_PRELIGHT:
1774 *state = GTK_STATE_PRELIGHT;
1776 case GTK_RC_TOKEN_SELECTED:
1777 *state = GTK_STATE_SELECTED;
1780 return /* G_TOKEN_SYMBOL */ GTK_RC_TOKEN_NORMAL;
1783 token = g_scanner_get_next_token (scanner);
1784 if (token != G_TOKEN_RIGHT_BRACE)
1785 return G_TOKEN_RIGHT_BRACE;
1787 g_scanner_set_scope (scanner, old_scope);
1789 return G_TOKEN_NONE;
1793 gtk_rc_parse_priority (GScanner *scanner,
1794 GtkPathPriorityType *priority)
1799 g_return_val_if_fail (scanner != NULL, G_TOKEN_ERROR);
1800 g_return_val_if_fail (priority != NULL, G_TOKEN_ERROR);
1802 /* we don't know where we got called from, so we reset the scope here.
1803 * if we bail out due to errors, we *don't* reset the scope, so the
1804 * error messaging code can make sense of our tokens.
1806 old_scope = g_scanner_set_scope (scanner, 0);
1808 token = g_scanner_get_next_token (scanner);
1812 token = g_scanner_get_next_token (scanner);
1815 case GTK_RC_TOKEN_LOWEST:
1816 *priority = GTK_PATH_PRIO_LOWEST;
1818 case GTK_RC_TOKEN_GTK:
1819 *priority = GTK_PATH_PRIO_GTK;
1821 case GTK_RC_TOKEN_APPLICATION:
1822 *priority = GTK_PATH_PRIO_APPLICATION;
1824 case GTK_RC_TOKEN_RC:
1825 *priority = GTK_PATH_PRIO_RC;
1827 case GTK_RC_TOKEN_HIGHEST:
1828 *priority = GTK_PATH_PRIO_HIGHEST;
1831 return /* G_TOKEN_SYMBOL */ GTK_RC_TOKEN_APPLICATION;
1834 g_scanner_set_scope (scanner, old_scope);
1836 return G_TOKEN_NONE;
1840 gtk_rc_parse_color (GScanner *scanner,
1845 g_return_val_if_fail (scanner != NULL, G_TOKEN_ERROR);
1847 /* we don't need to set our own scop here, because
1848 * we don't need own symbols
1851 token = g_scanner_get_next_token (scanner);
1860 case G_TOKEN_LEFT_CURLY:
1861 token = g_scanner_get_next_token (scanner);
1862 if (token == G_TOKEN_INT)
1863 token_int = scanner->value.v_int;
1864 else if (token == G_TOKEN_FLOAT)
1865 token_int = scanner->value.v_float * 65535.0;
1867 return G_TOKEN_FLOAT;
1868 color->red = CLAMP (token_int, 0, 65535);
1870 token = g_scanner_get_next_token (scanner);
1871 if (token != G_TOKEN_COMMA)
1872 return G_TOKEN_COMMA;
1874 token = g_scanner_get_next_token (scanner);
1875 if (token == G_TOKEN_INT)
1876 token_int = scanner->value.v_int;
1877 else if (token == G_TOKEN_FLOAT)
1878 token_int = scanner->value.v_float * 65535.0;
1880 return G_TOKEN_FLOAT;
1881 color->green = CLAMP (token_int, 0, 65535);
1883 token = g_scanner_get_next_token (scanner);
1884 if (token != G_TOKEN_COMMA)
1885 return G_TOKEN_COMMA;
1887 token = g_scanner_get_next_token (scanner);
1888 if (token == G_TOKEN_INT)
1889 token_int = scanner->value.v_int;
1890 else if (token == G_TOKEN_FLOAT)
1891 token_int = scanner->value.v_float * 65535.0;
1893 return G_TOKEN_FLOAT;
1894 color->blue = CLAMP (token_int, 0, 65535);
1896 token = g_scanner_get_next_token (scanner);
1897 if (token != G_TOKEN_RIGHT_CURLY)
1898 return G_TOKEN_RIGHT_CURLY;
1899 return G_TOKEN_NONE;
1901 case G_TOKEN_STRING:
1902 if (scanner->value.v_string[0] != '#')
1903 return G_TOKEN_STRING;
1905 length = strlen (scanner->value.v_string) - 1;
1906 if (((length % 3) != 0) || (length > 12))
1907 return G_TOKEN_STRING;
1910 for (i = 0, j = 1; i < length; i++, j++)
1911 buf[i] = scanner->value.v_string[j];
1914 sscanf (buf, "%x", &temp);
1917 for (i = 0; i < length; i++, j++)
1918 buf[i] = scanner->value.v_string[j];
1921 sscanf (buf, "%x", &temp);
1922 color->green = temp;
1924 for (i = 0; i < length; i++, j++)
1925 buf[i] = scanner->value.v_string[j];
1928 sscanf (buf, "%x", &temp);
1934 color->green *= 4369;
1935 color->blue *= 4369;
1937 else if (length == 2)
1940 color->green *= 257;
1943 else if (length == 3)
1949 return G_TOKEN_NONE;
1952 return G_TOKEN_STRING;
1957 gtk_rc_parse_pixmap_path (GScanner *scanner)
1961 token = g_scanner_get_next_token (scanner);
1962 if (token != GTK_RC_TOKEN_PIXMAP_PATH)
1963 return GTK_RC_TOKEN_PIXMAP_PATH;
1965 token = g_scanner_get_next_token (scanner);
1966 if (token != G_TOKEN_STRING)
1967 return G_TOKEN_STRING;
1969 gtk_rc_parse_pixmap_path_string (scanner->value.v_string);
1971 return G_TOKEN_NONE;
1975 gtk_rc_parse_pixmap_path_string (gchar *pix_path)
1979 gint start_offset = 0;
1983 /* free the old one, or just add to the old one ? */
1984 for (path_num=0; pixmap_path[path_num]; path_num++)
1986 g_free (pixmap_path[path_num]);
1987 pixmap_path[path_num] = NULL;
1992 path_len = strlen (pix_path);
1994 buf = g_strdup (pix_path);
1996 for (end_offset = 0; end_offset <= path_len; end_offset++)
1998 if ((buf[end_offset] == G_SEARCHPATH_SEPARATOR) ||
1999 (end_offset == path_len))
2001 buf[end_offset] = '\0';
2002 pixmap_path[path_num] = g_strdup (buf + start_offset);
2004 pixmap_path[path_num] = NULL;
2005 start_offset = end_offset + 1;
2009 gtk_rc_append_default_pixmap_path();
2013 gtk_rc_parse_module_path (GScanner *scanner)
2017 token = g_scanner_get_next_token (scanner);
2018 if (token != GTK_RC_TOKEN_MODULE_PATH)
2019 return GTK_RC_TOKEN_MODULE_PATH;
2021 token = g_scanner_get_next_token (scanner);
2022 if (token != G_TOKEN_STRING)
2023 return G_TOKEN_STRING;
2025 gtk_rc_parse_module_path_string (scanner->value.v_string);
2027 return G_TOKEN_NONE;
2031 gtk_rc_parse_module_path_string (gchar *mod_path)
2035 gint start_offset = 0;
2039 /* free the old one, or just add to the old one ? */
2040 for (path_num=0; module_path[path_num]; path_num++)
2042 g_free (module_path[path_num]);
2043 module_path[path_num] = NULL;
2048 path_len = strlen (mod_path);
2050 buf = g_strdup (mod_path);
2052 for (end_offset = 0; end_offset <= path_len; end_offset++)
2054 if ((buf[end_offset] == G_SEARCHPATH_SEPARATOR) ||
2055 (end_offset == path_len))
2057 buf[end_offset] = '\0';
2058 module_path[path_num] = g_strdup (buf + start_offset);
2060 module_path[path_num] = NULL;
2061 start_offset = end_offset + 1;
2065 gtk_rc_append_default_module_path();
2069 gtk_rc_parse_path_pattern (GScanner *scanner)
2072 GtkPathType path_type;
2074 gboolean is_binding;
2075 GtkPathPriorityType priority = GTK_PATH_PRIO_RC;
2077 token = g_scanner_get_next_token (scanner);
2080 case GTK_RC_TOKEN_WIDGET:
2081 path_type = GTK_PATH_WIDGET;
2083 case GTK_RC_TOKEN_WIDGET_CLASS:
2084 path_type = GTK_PATH_WIDGET_CLASS;
2086 case GTK_RC_TOKEN_CLASS:
2087 path_type = GTK_PATH_CLASS;
2090 return GTK_RC_TOKEN_WIDGET_CLASS;
2093 token = g_scanner_get_next_token (scanner);
2094 if (token != G_TOKEN_STRING)
2095 return G_TOKEN_STRING;
2097 pattern = g_strdup (scanner->value.v_string);
2099 token = g_scanner_get_next_token (scanner);
2100 if (token == GTK_RC_TOKEN_STYLE)
2102 else if (token == GTK_RC_TOKEN_BINDING)
2105 if (g_scanner_peek_next_token (scanner) == ':')
2107 token = gtk_rc_parse_priority (scanner, &priority);
2108 if (token != G_TOKEN_NONE)
2118 return GTK_RC_TOKEN_STYLE;
2121 token = g_scanner_get_next_token (scanner);
2122 if (token != G_TOKEN_STRING)
2125 return G_TOKEN_STRING;
2130 GtkBindingSet *binding;
2132 binding = gtk_binding_set_find (scanner->value.v_string);
2136 return G_TOKEN_STRING;
2138 gtk_binding_set_add_path (binding, path_type, pattern, priority);
2142 GtkRcStyle *rc_style;
2145 rc_style = gtk_rc_style_find (scanner->value.v_string);
2150 return G_TOKEN_STRING;
2153 rc_set = g_new (GtkRcSet, 1);
2154 gtk_pattern_spec_init (&rc_set->pspec, pattern);
2155 rc_set->rc_style = rc_style;
2157 if (path_type == GTK_PATH_WIDGET)
2158 gtk_rc_sets_widget = g_slist_prepend (gtk_rc_sets_widget, rc_set);
2159 else if (path_type == GTK_PATH_WIDGET_CLASS)
2160 gtk_rc_sets_widget_class = g_slist_prepend (gtk_rc_sets_widget_class, rc_set);
2162 gtk_rc_sets_class = g_slist_prepend (gtk_rc_sets_class, rc_set);
2166 return G_TOKEN_NONE;
2170 typedef GdkPixmap * (*GtkImageLoader) (GdkWindow *window,
2171 GdkColormap *colormap,
2173 GdkColor *transparent_color,
2174 const gchar *filename);
2178 gtk_rc_set_image_loader(GtkImageLoader loader)
2180 image_loader = loader;
2184 gtk_rc_load_image (GdkColormap *colormap,
2185 GdkColor *transparent_color,
2186 const gchar *filename)
2188 if (strcmp (filename, "<parent>") == 0)
2189 return (GdkPixmap*) GDK_PARENT_RELATIVE;
2193 return image_loader(NULL, colormap, NULL,
2197 return gdk_pixmap_colormap_create_from_xpm (NULL, colormap, NULL,