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/.
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>
56 #include "gtkbindings.h"
57 #include "gtkthemes.h"
60 typedef struct _GtkRcSet GtkRcSet;
61 typedef struct _GtkRcNode GtkRcNode;
62 typedef struct _GtkRcFile GtkRcFile;
74 gchar *canonical_name;
78 static guint gtk_rc_style_hash (const char *name);
79 static gint gtk_rc_style_compare (const char *a,
81 static guint gtk_rc_styles_hash (const GSList *rc_styles);
82 static gint gtk_rc_styles_compare (const GSList *a,
84 static GtkRcStyle* gtk_rc_style_find (const char *name);
85 static GSList * gtk_rc_styles_match (GSList *rc_styles,
89 gchar *path_reversed);
90 static GtkStyle * gtk_rc_style_to_style (GtkRcStyle *rc_style);
91 static GtkStyle* gtk_rc_style_init (GSList *rc_styles);
92 static void gtk_rc_parse_file (const gchar *filename,
95 static void gtk_rc_parse_any (const gchar *input_name,
97 const gchar *input_string);
98 static guint gtk_rc_parse_statement (GScanner *scanner);
99 static guint gtk_rc_parse_style (GScanner *scanner);
100 static guint gtk_rc_parse_base (GScanner *scanner,
102 static guint gtk_rc_parse_bg (GScanner *scanner,
104 static guint gtk_rc_parse_fg (GScanner *scanner,
106 static guint gtk_rc_parse_text (GScanner *scanner,
108 static guint gtk_rc_parse_bg_pixmap (GScanner *scanner,
109 GtkRcStyle *rc_style);
110 static guint gtk_rc_parse_font (GScanner *scanner,
111 GtkRcStyle *rc_style);
112 static guint gtk_rc_parse_fontset (GScanner *scanner,
113 GtkRcStyle *rc_style);
114 static guint gtk_rc_parse_engine (GScanner *scanner,
115 GtkRcStyle *rc_style);
116 static guint gtk_rc_parse_pixmap_path (GScanner *scanner);
117 static void gtk_rc_parse_pixmap_path_string (gchar *pix_path);
118 static guint gtk_rc_parse_module_path (GScanner *scanner);
119 static void gtk_rc_parse_module_path_string (gchar *mod_path);
120 static guint gtk_rc_parse_path_pattern (GScanner *scanner);
121 static void gtk_rc_clear_hash_node (gpointer key,
124 static void gtk_rc_clear_styles (void);
125 static void gtk_rc_append_default_pixmap_path (void);
126 static void gtk_rc_append_default_module_path (void);
127 static void gtk_rc_append_pixmap_path (gchar *dir);
128 static void gtk_rc_add_initial_default_files (void);
131 static const GScannerConfig gtk_rc_scanner_config =
135 ) /* cset_skip_characters */,
140 ) /* cset_identifier_first */,
145 ) /* cset_identifier_nth */,
146 ( "#\n" ) /* cpair_comment_single */,
148 TRUE /* case_sensitive */,
150 TRUE /* skip_comment_multi */,
151 TRUE /* skip_comment_single */,
152 TRUE /* scan_comment_multi */,
153 TRUE /* scan_identifier */,
154 FALSE /* scan_identifier_1char */,
155 FALSE /* scan_identifier_NULL */,
156 TRUE /* scan_symbols */,
157 TRUE /* scan_binary */,
158 TRUE /* scan_octal */,
159 TRUE /* scan_float */,
161 TRUE /* scan_hex_dollar */,
162 TRUE /* scan_string_sq */,
163 TRUE /* scan_string_dq */,
164 TRUE /* numbers_2_int */,
165 FALSE /* int_2_float */,
166 FALSE /* identifier_2_string */,
167 TRUE /* char_2_token */,
168 TRUE /* symbol_2_token */,
169 FALSE /* scope_0_fallback */,
177 { "include", GTK_RC_TOKEN_INCLUDE },
178 { "NORMAL", GTK_RC_TOKEN_NORMAL },
179 { "ACTIVE", GTK_RC_TOKEN_ACTIVE },
180 { "PRELIGHT", GTK_RC_TOKEN_PRELIGHT },
181 { "SELECTED", GTK_RC_TOKEN_SELECTED },
182 { "INSENSITIVE", GTK_RC_TOKEN_INSENSITIVE },
183 { "fg", GTK_RC_TOKEN_FG },
184 { "bg", GTK_RC_TOKEN_BG },
185 { "base", GTK_RC_TOKEN_BASE },
186 { "text", GTK_RC_TOKEN_TEXT },
187 { "font", GTK_RC_TOKEN_FONT },
188 { "fontset", GTK_RC_TOKEN_FONTSET },
189 { "bg_pixmap", GTK_RC_TOKEN_BG_PIXMAP },
190 { "pixmap_path", GTK_RC_TOKEN_PIXMAP_PATH },
191 { "style", GTK_RC_TOKEN_STYLE },
192 { "binding", GTK_RC_TOKEN_BINDING },
193 { "bind", GTK_RC_TOKEN_BIND },
194 { "widget", GTK_RC_TOKEN_WIDGET },
195 { "widget_class", GTK_RC_TOKEN_WIDGET_CLASS },
196 { "class", GTK_RC_TOKEN_CLASS },
197 { "lowest", GTK_RC_TOKEN_LOWEST },
198 { "gtk", GTK_RC_TOKEN_GTK },
199 { "application", GTK_RC_TOKEN_APPLICATION },
200 { "rc", GTK_RC_TOKEN_RC },
201 { "highest", GTK_RC_TOKEN_HIGHEST },
202 { "engine", GTK_RC_TOKEN_ENGINE },
203 { "module_path", GTK_RC_TOKEN_MODULE_PATH },
206 static const guint n_symbols = sizeof (symbols) / sizeof (symbols[0]);
208 static GHashTable *rc_style_ht = NULL;
209 static GHashTable *realized_style_ht = NULL;
210 static GSList *gtk_rc_sets_widget = NULL;
211 static GSList *gtk_rc_sets_widget_class = NULL;
212 static GSList *gtk_rc_sets_class = NULL;
214 #define GTK_RC_MAX_DEFAULT_FILES 128
215 static gchar *gtk_rc_default_files[GTK_RC_MAX_DEFAULT_FILES];
216 static gboolean gtk_rc_auto_parse = TRUE;
218 #define GTK_RC_MAX_PIXMAP_PATHS 128
219 static gchar *pixmap_path[GTK_RC_MAX_PIXMAP_PATHS];
220 #define GTK_RC_MAX_MODULE_PATHS 128
221 static gchar *module_path[GTK_RC_MAX_MODULE_PATHS];
223 /* The files we have parsed, to reread later if necessary */
224 GSList *rc_files = NULL;
226 static GtkImageLoader image_loader = NULL;
228 /* RC file handling */
234 get_gtk_sysconf_directory (void)
236 static gchar gtk_sysconf_dir[200];
239 GetWindowsDirectory (win_dir, sizeof (win_dir));
240 sprintf (gtk_sysconf_dir, "%s\\gtk+", win_dir);
241 return gtk_sysconf_dir;
245 get_themes_directory (void)
247 /* We really should fetch this from the Registry. The GIMP
248 * installation program stores the Themes installation
249 * directory in HKLM\Software\GNU\GTk+\Themes\InstallDirectory.
252 static gchar themes_dir[200];
254 sprintf (themes_dir, "%s\\themes", get_gtk_sysconf_directory ());
261 gtk_rc_get_theme_dir(void)
266 var = getenv("GTK_DATA_PREFIX");
268 path = g_strdup_printf("%s%s", var, "/share/themes");
270 path = g_strdup_printf("%s%s", GTK_DATA_PREFIX, "/share/themes");
272 path = g_strdup (get_themes_directory ());
279 gtk_rc_get_module_dir(void)
284 var = getenv("GTK_EXE_PREFIX");
286 path = g_strdup_printf("%s%s", var, "/lib/gtk/themes/engines");
288 path = g_strdup_printf("%s%s", GTK_EXE_PREFIX, "/lib/gtk/themes/engines");
290 path = g_strdup_printf ("%s%s", get_themes_directory (), "\\engines");
297 gtk_rc_append_default_pixmap_path(void)
303 var = getenv("GTK_DATA_PREFIX");
305 path = g_strdup_printf("%s%s", var, "/share/gtk/themes");
307 path = g_strdup_printf("%s%s", GTK_DATA_PREFIX, "/share/gtk/themes");
309 path = g_strdup (get_themes_directory ());
312 for (n = 0; pixmap_path[n]; n++) ;
313 if (n >= GTK_RC_MAX_PIXMAP_PATHS - 1)
318 pixmap_path[n++] = path;
319 pixmap_path[n] = NULL;
323 gtk_rc_append_pixmap_path(gchar *dir)
327 for (n = 0; pixmap_path[n]; n++) ;
328 if (n >= GTK_RC_MAX_MODULE_PATHS - 1)
330 pixmap_path[n++] = g_strdup(dir);
331 pixmap_path[n] = NULL;
335 gtk_rc_append_default_module_path(void)
340 for (n = 0; module_path[n]; n++) ;
341 if (n >= GTK_RC_MAX_MODULE_PATHS - 1)
345 var = getenv("GTK_EXE_PREFIX");
347 path = g_strdup_printf("%s%s", var, "/lib/gtk/themes/engines");
349 path = g_strdup_printf("%s%s", GTK_EXE_PREFIX, "/lib/gtk/themes/engines");
351 path = g_strdup_printf ("%s%s", get_themes_directory (), "\\engines");
353 module_path[n++] = path;
355 var = g_get_home_dir ();
359 path = g_strdup_printf ("%s%s", var, "/.gtk/lib/themes/engines");
361 path = g_strdup_printf ("%s%s", var, "\\_gtk\\themes\\engines");
363 module_path[n++] = path;
365 module_path[n] = NULL;
369 gtk_rc_add_initial_default_files (void)
371 static gint init = FALSE;
379 gtk_rc_default_files[0] = NULL;
382 var = g_getenv("GTK_RC_FILES");
385 files = g_strsplit (var, G_SEARCHPATH_SEPARATOR_S, 128);
389 gtk_rc_add_default_file (files[i]);
397 str = g_strdup (GTK_SYSCONFDIR G_DIR_SEPARATOR_S "gtk" G_DIR_SEPARATOR_S "gtkrc");
399 str = g_strdup_printf ("%s\\gtkrc", get_gtk_sysconf_directory ());
401 gtk_rc_add_default_file (str);
404 var = g_get_home_dir ();
407 str = g_strdup_printf ("%s" G_DIR_SEPARATOR_S ".gtkrc", var);
408 gtk_rc_add_default_file (str);
415 gtk_rc_add_default_file (const gchar *file)
419 gtk_rc_add_initial_default_files ();
421 for (n = 0; gtk_rc_default_files[n]; n++) ;
422 if (n >= GTK_RC_MAX_DEFAULT_FILES - 1)
425 gtk_rc_default_files[n++] = g_strdup (file);
426 gtk_rc_default_files[n] = NULL;
430 gtk_rc_set_default_files (gchar **files)
434 gtk_rc_add_initial_default_files ();
437 while (gtk_rc_default_files[i])
439 g_free (gtk_rc_default_files[i]);
443 gtk_rc_default_files[0] = NULL;
444 gtk_rc_auto_parse = FALSE;
447 while (files[i] != NULL)
449 gtk_rc_add_default_file (files[i]);
455 gtk_rc_get_default_files (void)
457 gtk_rc_add_initial_default_files ();
459 return gtk_rc_default_files;
465 gchar *locale_suffixes[3];
466 gint n_locale_suffixes = 0;
469 char *locale = g_win32_getlocale ();
471 #ifdef HAVE_LC_MESSAGES
472 char *locale = setlocale (LC_MESSAGES, NULL);
474 char *locale = setlocale (LC_CTYPE, NULL);
480 rc_style_ht = g_hash_table_new ((GHashFunc) gtk_rc_style_hash,
481 (GCompareFunc) gtk_rc_style_compare);
482 pixmap_path[0] = NULL;
483 module_path[0] = NULL;
484 gtk_rc_append_default_pixmap_path();
485 gtk_rc_append_default_module_path();
487 gtk_rc_add_initial_default_files ();
489 if (strcmp (locale, "C") && strcmp (locale, "POSIX"))
491 /* Determine locale-specific suffixes for RC files
493 p = strchr (locale, '@');
494 length = p ? (p -locale) : strlen (locale);
496 p = strchr (locale, '.');
499 locale_suffixes[n_locale_suffixes++] = g_strndup (locale, length);
503 p = strchr (locale, '_');
506 locale_suffixes[n_locale_suffixes++] = g_strndup (locale, length);
510 locale_suffixes[n_locale_suffixes++] = g_strndup (locale, length);
514 while (gtk_rc_default_files[i] != NULL)
516 /* Try to find a locale specific RC file corresponding to
517 * to parse before the default file.
519 for (j=n_locale_suffixes-1; j>=0; j--)
521 gchar *name = g_strconcat (gtk_rc_default_files[i],
529 gtk_rc_parse (gtk_rc_default_files[i]);
535 gtk_rc_parse_string (const gchar *rc_string)
537 g_return_if_fail (rc_string != NULL);
539 gtk_rc_parse_any ("-", -1, rc_string);
543 gtk_rc_parse_file (const gchar *filename, gboolean reload)
545 GtkRcFile *rc_file = NULL;
549 g_return_if_fail (filename != NULL);
554 rc_file = tmp_list->data;
555 if (!strcmp (rc_file->name, filename))
558 tmp_list = tmp_list->next;
563 rc_file = g_new (GtkRcFile, 1);
564 rc_file->name = g_strdup (filename);
565 rc_file->canonical_name = NULL;
567 rc_file->reload = reload;
569 rc_files = g_slist_append (rc_files, rc_file);
572 if (!rc_file->canonical_name)
574 /* Get the absolute pathname */
576 if (g_path_is_absolute (rc_file->name))
577 rc_file->canonical_name = rc_file->name;
583 cwd = g_get_current_dir ();
585 str = g_string_new (cwd);
587 g_string_append_c (str, G_DIR_SEPARATOR);
588 g_string_append (str, rc_file->name);
590 rc_file->canonical_name = str->str;
591 g_string_free (str, FALSE);
595 if (!lstat (rc_file->canonical_name, &statbuf))
599 rc_file->mtime = statbuf.st_mtime;
601 fd = open (rc_file->canonical_name, O_RDONLY);
609 dir = g_strdup(rc_file->canonical_name);
610 for (i = strlen(dir) - 1; (i >= 0) && (dir[i] != G_DIR_SEPARATOR); i--)
612 if (i >= 0 && dir[i] == G_DIR_SEPARATOR)
614 gtk_rc_append_pixmap_path(dir);
617 gtk_rc_parse_any (filename, fd, NULL);
624 gtk_rc_parse (const gchar *filename)
626 g_return_if_fail (filename != NULL);
628 gtk_rc_parse_file (filename, TRUE);
631 /* Handling of RC styles */
634 gtk_rc_style_new (void)
636 GtkRcStyle *new_style;
638 new_style = g_new0 (GtkRcStyle, 1);
639 new_style->ref_count = 1;
645 gtk_rc_style_ref (GtkRcStyle *rc_style)
647 g_return_if_fail (rc_style != NULL);
649 rc_style->ref_count++;
653 gtk_rc_style_unref (GtkRcStyle *rc_style)
657 g_return_if_fail (rc_style != NULL);
658 g_return_if_fail (rc_style->ref_count > 0);
660 rc_style->ref_count--;
662 if (rc_style->ref_count == 0)
664 if (rc_style->engine)
666 rc_style->engine->destroy_rc_style (rc_style);
667 gtk_theme_engine_unref (rc_style->engine);
671 g_free (rc_style->name);
672 if (rc_style->fontset_name)
673 g_free (rc_style->fontset_name);
674 if (rc_style->font_name)
675 g_free (rc_style->font_name);
677 for (i=0 ; i<5 ; i++)
678 if (rc_style->bg_pixmap_name[i])
679 g_free (rc_style->bg_pixmap_name[i]);
686 gtk_rc_clear_realized_node (gpointer key,
690 gtk_style_unref (data);
694 gtk_rc_clear_hash_node (gpointer key,
698 gtk_rc_style_unref (data);
702 gtk_rc_free_rc_sets (GSList *slist)
708 rc_set = slist->data;
709 gtk_pattern_spec_free_segs (&rc_set->pspec);
717 gtk_rc_clear_styles (void)
719 /* Clear out all old rc_styles */
723 g_hash_table_foreach (rc_style_ht, gtk_rc_clear_hash_node, NULL);
724 g_hash_table_destroy (rc_style_ht);
728 if (realized_style_ht)
730 g_hash_table_foreach (realized_style_ht, gtk_rc_clear_realized_node, NULL);
731 g_hash_table_destroy (realized_style_ht);
732 realized_style_ht = NULL;
735 gtk_rc_free_rc_sets (gtk_rc_sets_widget);
736 g_slist_free (gtk_rc_sets_widget);
737 gtk_rc_sets_widget = NULL;
739 gtk_rc_free_rc_sets (gtk_rc_sets_widget_class);
740 g_slist_free (gtk_rc_sets_widget_class);
741 gtk_rc_sets_widget_class = NULL;
743 gtk_rc_free_rc_sets (gtk_rc_sets_class);
744 g_slist_free (gtk_rc_sets_class);
745 gtk_rc_sets_class = NULL;
751 gtk_rc_reparse_all (void)
754 gboolean mtime_modified = FALSE;
759 /* Check through and see if any of the RC's have had their
760 * mtime modified. If so, reparse everything.
765 rc_file = tmp_list->data;
767 if (!lstat (rc_file->name, &statbuf) &&
768 (statbuf.st_mtime > rc_file->mtime))
770 mtime_modified = TRUE;
774 tmp_list = tmp_list->next;
779 gtk_rc_clear_styles();
784 rc_file = tmp_list->data;
786 gtk_rc_parse_file (rc_file->name, FALSE);
788 tmp_list = tmp_list->next;
792 return mtime_modified;
796 gtk_rc_styles_match (GSList *rc_styles,
800 gchar *path_reversed)
810 if (gtk_pattern_match (&rc_set->pspec, path_length, path, path_reversed))
811 rc_styles = g_slist_append (rc_styles, rc_set->rc_style);
818 gtk_rc_get_style (GtkWidget *widget)
820 GtkRcStyle *widget_rc_style;
821 GSList *rc_styles = NULL;
823 static guint rc_style_key_id = 0;
825 /* We allow the specification of a single rc style to be bound
826 * tightly to a widget, for application modifications
828 if (!rc_style_key_id)
829 rc_style_key_id = g_quark_from_static_string ("gtk-rc-style");
831 widget_rc_style = gtk_object_get_data_by_id (GTK_OBJECT (widget),
835 rc_styles = g_slist_prepend (rc_styles, widget_rc_style);
837 if (gtk_rc_sets_widget)
839 gchar *path, *path_reversed;
842 gtk_widget_path (widget, &path_length, &path, &path_reversed);
843 rc_styles = gtk_rc_styles_match (rc_styles, gtk_rc_sets_widget, path_length, path, path_reversed);
845 g_free (path_reversed);
849 if (gtk_rc_sets_widget_class)
851 gchar *path, *path_reversed;
854 gtk_widget_class_path (widget, &path_length, &path, &path_reversed);
855 rc_styles = gtk_rc_styles_match (rc_styles, gtk_rc_sets_widget_class, path_length, path, path_reversed);
857 g_free (path_reversed);
860 if (gtk_rc_sets_class)
864 type = GTK_OBJECT_TYPE (widget);
867 gchar *path, *path_reversed;
870 path = gtk_type_name (type);
871 path_length = strlen (path);
872 path_reversed = g_strdup (path);
873 g_strreverse (path_reversed);
875 rc_styles = gtk_rc_styles_match (rc_styles, gtk_rc_sets_class, path_length, path, path_reversed);
876 g_free (path_reversed);
878 type = gtk_type_parent (type);
883 return gtk_rc_style_init (rc_styles);
889 gtk_rc_add_rc_sets (GSList *slist,
890 GtkRcStyle *rc_style,
893 GtkRcStyle *new_style;
897 new_style = gtk_rc_style_new ();
898 *new_style = *rc_style;
899 new_style->name = g_strdup (rc_style->name);
900 new_style->font_name = g_strdup (rc_style->font_name);
901 new_style->fontset_name = g_strdup (rc_style->fontset_name);
903 for (i = 0; i < 5; i++)
904 new_style->bg_pixmap_name[i] = g_strdup (rc_style->bg_pixmap_name[i]);
906 rc_set = g_new (GtkRcSet, 1);
907 gtk_pattern_spec_init (&rc_set->pspec, pattern);
908 rc_set->rc_style = rc_style;
910 return g_slist_prepend (slist, rc_set);
914 gtk_rc_add_widget_name_style (GtkRcStyle *rc_style,
915 const gchar *pattern)
917 g_return_if_fail (rc_style != NULL);
918 g_return_if_fail (pattern != NULL);
920 gtk_rc_sets_widget = gtk_rc_add_rc_sets (gtk_rc_sets_widget, rc_style, pattern);
924 gtk_rc_add_widget_class_style (GtkRcStyle *rc_style,
925 const gchar *pattern)
927 g_return_if_fail (rc_style != NULL);
928 g_return_if_fail (pattern != NULL);
930 gtk_rc_sets_widget_class = gtk_rc_add_rc_sets (gtk_rc_sets_widget_class, rc_style, pattern);
934 gtk_rc_add_class_style (GtkRcStyle *rc_style,
935 const gchar *pattern)
937 g_return_if_fail (rc_style != NULL);
938 g_return_if_fail (pattern != NULL);
940 gtk_rc_sets_class = gtk_rc_add_rc_sets (gtk_rc_sets_class, rc_style, pattern);
944 gtk_rc_parse_any (const gchar *input_name,
946 const gchar *input_string)
952 scanner = g_scanner_new ((GScannerConfig *) >k_rc_scanner_config);
956 g_assert (input_string == NULL);
958 g_scanner_input_file (scanner, input_fd);
962 g_assert (input_string != NULL);
964 g_scanner_input_text (scanner, input_string, strlen (input_string));
966 scanner->input_name = input_name;
968 g_scanner_freeze_symbol_table (scanner);
969 for (i = 0; i < n_symbols; i++)
970 g_scanner_add_symbol (scanner, symbols[i].name, GINT_TO_POINTER (symbols[i].token));
971 g_scanner_thaw_symbol_table (scanner);
976 if (g_scanner_peek_next_token (scanner) == G_TOKEN_EOF)
980 guint expected_token;
982 expected_token = gtk_rc_parse_statement (scanner);
984 if (expected_token != G_TOKEN_NONE)
991 if (scanner->scope_id == 0)
993 /* if we are in scope 0, we know the symbol names
994 * that are associated with certaintoken values.
995 * so we look them up to make the error messages
998 if (expected_token > GTK_RC_TOKEN_INVALID &&
999 expected_token < GTK_RC_TOKEN_LAST)
1001 for (i = 0; i < n_symbols; i++)
1002 if (symbols[i].token == expected_token)
1003 msg = symbols[i].name;
1005 msg = g_strconcat ("e.g. `", msg, "'", NULL);
1007 if (scanner->token > GTK_RC_TOKEN_INVALID &&
1008 scanner->token < GTK_RC_TOKEN_LAST)
1010 symbol_name = "???";
1011 for (i = 0; i < n_symbols; i++)
1012 if (symbols[i].token == scanner->token)
1013 symbol_name = symbols[i].name;
1016 g_scanner_unexp_token (scanner,
1029 g_scanner_destroy (scanner);
1033 gtk_rc_styles_hash (const GSList *rc_styles)
1040 result += (result << 9) + GPOINTER_TO_UINT (rc_styles->data);
1041 rc_styles = rc_styles->next;
1048 gtk_rc_styles_compare (const GSList *a,
1053 if (a->data != b->data)
1063 gtk_rc_style_hash (const char *name)
1069 result += (result << 3) + *name++;
1075 gtk_rc_style_compare (const char *a,
1078 return (strcmp (a, b) == 0);
1082 gtk_rc_style_find (const char *name)
1084 GtkRcStyle *rc_style;
1086 rc_style = g_hash_table_lookup (rc_style_ht, (gpointer) name);
1091 /* Assumes ownership of rc_style */
1093 gtk_rc_style_to_style (GtkRcStyle *rc_style)
1099 style = gtk_style_new ();
1101 style->rc_style = rc_style;
1103 if (rc_style->fontset_name)
1105 old_font = style->font;
1106 style->font = gdk_fontset_load (rc_style->fontset_name);
1108 gdk_font_unref (old_font);
1110 style->font = old_font;
1112 else if (rc_style->font_name)
1114 old_font = style->font;
1115 style->font = gdk_font_load (rc_style->font_name);
1117 gdk_font_unref (old_font);
1119 style->font = old_font;
1122 for (i = 0; i < 5; i++)
1124 if (rc_style->color_flags[i] & GTK_RC_FG)
1125 style->fg[i] = rc_style->fg[i];
1126 if (rc_style->color_flags[i] & GTK_RC_BG)
1127 style->bg[i] = rc_style->bg[i];
1128 if (rc_style->color_flags[i] & GTK_RC_TEXT)
1129 style->text[i] = rc_style->text[i];
1130 if (rc_style->color_flags[i] & GTK_RC_BASE)
1131 style->base[i] = rc_style->base[i];
1134 if (rc_style->engine)
1136 style->engine = rc_style->engine;
1137 gtk_theme_engine_ref (style->engine);
1138 rc_style->engine->rc_style_to_style (style, rc_style);
1144 /* Reuses or frees rc_styles */
1146 gtk_rc_style_init (GSList *rc_styles)
1150 GtkStyle *style = NULL;
1151 GtkRcStyle *proto_style;
1153 if (!realized_style_ht)
1154 realized_style_ht = g_hash_table_new ((GHashFunc)gtk_rc_styles_hash,
1155 (GCompareFunc)gtk_rc_styles_compare);
1157 style = g_hash_table_lookup (realized_style_ht, rc_styles);
1161 GSList *tmp_styles = rc_styles;
1163 proto_style = gtk_rc_style_new ();
1167 GtkRcStyle *rc_style = tmp_styles->data;
1171 if (!proto_style->bg_pixmap_name[i] && rc_style->bg_pixmap_name[i])
1172 proto_style->bg_pixmap_name[i] = g_strdup (rc_style->bg_pixmap_name[i]);
1174 if (!(proto_style->color_flags[i] & GTK_RC_FG) &&
1175 rc_style->color_flags[i] & GTK_RC_FG)
1177 proto_style->fg[i] = rc_style->fg[i];
1178 proto_style->color_flags[i] |= GTK_RC_FG;
1180 if (!(proto_style->color_flags[i] & GTK_RC_BG) &&
1181 rc_style->color_flags[i] & GTK_RC_BG)
1183 proto_style->bg[i] = rc_style->bg[i];
1184 proto_style->color_flags[i] |= GTK_RC_BG;
1186 if (!(proto_style->color_flags[i] & GTK_RC_TEXT) &&
1187 rc_style->color_flags[i] & GTK_RC_TEXT)
1189 proto_style->text[i] = rc_style->text[i];
1190 proto_style->color_flags[i] |= GTK_RC_TEXT;
1192 if (!(proto_style->color_flags[i] & GTK_RC_BASE) &&
1193 rc_style->color_flags[i] & GTK_RC_BASE)
1195 proto_style->base[i] = rc_style->base[i];
1196 proto_style->color_flags[i] |= GTK_RC_BASE;
1200 if (!proto_style->font_name && rc_style->font_name)
1201 proto_style->font_name = g_strdup (rc_style->font_name);
1202 if (!proto_style->fontset_name && rc_style->fontset_name)
1203 proto_style->fontset_name = g_strdup (rc_style->fontset_name);
1205 if (!proto_style->engine && rc_style->engine)
1207 proto_style->engine = rc_style->engine;
1208 gtk_theme_engine_ref (proto_style->engine);
1211 if (proto_style->engine &&
1212 (proto_style->engine == rc_style->engine))
1213 proto_style->engine->merge_rc_style (proto_style, rc_style);
1215 tmp_styles = tmp_styles->next;
1219 if (proto_style->bg_pixmap_name[i] &&
1220 (strcmp (proto_style->bg_pixmap_name[i], "<none>") == 0))
1222 g_free (proto_style->bg_pixmap_name[i]);
1223 proto_style->bg_pixmap_name[i] = NULL;
1226 style = gtk_rc_style_to_style (proto_style);
1228 g_hash_table_insert (realized_style_ht, rc_styles, style);
1234 /*********************
1235 * Parsing functions *
1236 *********************/
1239 gtk_rc_parse_statement (GScanner *scanner)
1243 token = g_scanner_peek_next_token (scanner);
1247 case GTK_RC_TOKEN_INCLUDE:
1248 token = g_scanner_get_next_token (scanner);
1249 if (token != GTK_RC_TOKEN_INCLUDE)
1250 return GTK_RC_TOKEN_INCLUDE;
1252 token = g_scanner_get_next_token (scanner);
1253 if (token != G_TOKEN_STRING)
1254 return G_TOKEN_STRING;
1256 gtk_rc_parse_file (scanner->value.v_string, FALSE);
1257 return G_TOKEN_NONE;
1259 case GTK_RC_TOKEN_STYLE:
1260 return gtk_rc_parse_style (scanner);
1262 case GTK_RC_TOKEN_BINDING:
1263 return gtk_binding_parse_binding (scanner);
1265 case GTK_RC_TOKEN_PIXMAP_PATH:
1266 return gtk_rc_parse_pixmap_path (scanner);
1268 case GTK_RC_TOKEN_WIDGET:
1269 return gtk_rc_parse_path_pattern (scanner);
1271 case GTK_RC_TOKEN_WIDGET_CLASS:
1272 return gtk_rc_parse_path_pattern (scanner);
1274 case GTK_RC_TOKEN_CLASS:
1275 return gtk_rc_parse_path_pattern (scanner);
1277 case GTK_RC_TOKEN_MODULE_PATH:
1278 return gtk_rc_parse_module_path (scanner);
1281 g_scanner_get_next_token (scanner);
1282 return /* G_TOKEN_SYMBOL */ GTK_RC_TOKEN_STYLE;
1287 gtk_rc_parse_style (GScanner *scanner)
1289 GtkRcStyle *rc_style;
1290 GtkRcStyle *parent_style;
1295 token = g_scanner_get_next_token (scanner);
1296 if (token != GTK_RC_TOKEN_STYLE)
1297 return GTK_RC_TOKEN_STYLE;
1299 token = g_scanner_get_next_token (scanner);
1300 if (token != G_TOKEN_STRING)
1301 return G_TOKEN_STRING;
1304 rc_style = g_hash_table_lookup (rc_style_ht, scanner->value.v_string);
1309 rc_style = gtk_rc_style_new ();
1310 rc_style->name = g_strdup (scanner->value.v_string);
1312 for (i = 0; i < 5; i++)
1313 rc_style->bg_pixmap_name[i] = NULL;
1315 for (i = 0; i < 5; i++)
1316 rc_style->color_flags[i] = 0;
1318 rc_style->engine = NULL;
1319 rc_style->engine_data = NULL;
1322 token = g_scanner_peek_next_token (scanner);
1323 if (token == G_TOKEN_EQUAL_SIGN)
1325 token = g_scanner_get_next_token (scanner);
1327 token = g_scanner_get_next_token (scanner);
1328 if (token != G_TOKEN_STRING)
1333 return G_TOKEN_STRING;
1336 parent_style = g_hash_table_lookup (rc_style_ht, scanner->value.v_string);
1339 for (i = 0; i < 5; i++)
1341 rc_style->color_flags[i] = parent_style->color_flags[i];
1342 rc_style->fg[i] = parent_style->fg[i];
1343 rc_style->bg[i] = parent_style->bg[i];
1344 rc_style->text[i] = parent_style->text[i];
1345 rc_style->base[i] = parent_style->base[i];
1348 if (parent_style->fontset_name)
1350 if (rc_style->fontset_name)
1351 g_free (rc_style->fontset_name);
1352 rc_style->fontset_name = g_strdup (parent_style->fontset_name);
1354 else if (parent_style->font_name)
1356 if (rc_style->font_name)
1357 g_free (rc_style->font_name);
1358 rc_style->font_name = g_strdup (parent_style->font_name);
1361 for (i = 0; i < 5; i++)
1363 if (rc_style->bg_pixmap_name[i])
1364 g_free (rc_style->bg_pixmap_name[i]);
1365 rc_style->bg_pixmap_name[i] = g_strdup (parent_style->bg_pixmap_name[i]);
1370 token = g_scanner_get_next_token (scanner);
1371 if (token != G_TOKEN_LEFT_CURLY)
1376 return G_TOKEN_LEFT_CURLY;
1379 token = g_scanner_peek_next_token (scanner);
1380 while (token != G_TOKEN_RIGHT_CURLY)
1384 case GTK_RC_TOKEN_BASE:
1385 token = gtk_rc_parse_base (scanner, rc_style);
1387 case GTK_RC_TOKEN_BG:
1388 token = gtk_rc_parse_bg (scanner, rc_style);
1390 case GTK_RC_TOKEN_FG:
1391 token = gtk_rc_parse_fg (scanner, rc_style);
1393 case GTK_RC_TOKEN_TEXT:
1394 token = gtk_rc_parse_text (scanner, rc_style);
1396 case GTK_RC_TOKEN_BG_PIXMAP:
1397 token = gtk_rc_parse_bg_pixmap (scanner, rc_style);
1399 case GTK_RC_TOKEN_FONT:
1400 token = gtk_rc_parse_font (scanner, rc_style);
1402 case GTK_RC_TOKEN_FONTSET:
1403 token = gtk_rc_parse_fontset (scanner, rc_style);
1405 case GTK_RC_TOKEN_ENGINE:
1406 token = gtk_rc_parse_engine (scanner, rc_style);
1409 g_scanner_get_next_token (scanner);
1410 token = G_TOKEN_RIGHT_CURLY;
1414 if (token != G_TOKEN_NONE)
1418 if (rc_style->fontset_name)
1419 g_free (rc_style->fontset_name);
1420 if (rc_style->font_name)
1421 g_free (rc_style->font_name);
1422 for (i = 0; i < 5; i++)
1423 if (rc_style->bg_pixmap_name[i])
1424 g_free (rc_style->bg_pixmap_name[i]);
1429 token = g_scanner_peek_next_token (scanner);
1432 token = g_scanner_get_next_token (scanner);
1433 if (token != G_TOKEN_RIGHT_CURLY)
1437 if (rc_style->fontset_name)
1438 g_free (rc_style->fontset_name);
1439 if (rc_style->font_name)
1440 g_free (rc_style->font_name);
1442 for (i = 0; i < 5; i++)
1443 if (rc_style->bg_pixmap_name[i])
1444 g_free (rc_style->bg_pixmap_name[i]);
1448 return G_TOKEN_RIGHT_CURLY;
1452 g_hash_table_insert (rc_style_ht, rc_style->name, rc_style);
1454 return G_TOKEN_NONE;
1458 gtk_rc_parse_base (GScanner *scanner,
1464 token = g_scanner_get_next_token (scanner);
1465 if (token != GTK_RC_TOKEN_BASE)
1466 return GTK_RC_TOKEN_BASE;
1468 token = gtk_rc_parse_state (scanner, &state);
1469 if (token != G_TOKEN_NONE)
1472 token = g_scanner_get_next_token (scanner);
1473 if (token != G_TOKEN_EQUAL_SIGN)
1474 return G_TOKEN_EQUAL_SIGN;
1476 style->color_flags[state] |= GTK_RC_BASE;
1477 return gtk_rc_parse_color (scanner, &style->base[state]);
1481 gtk_rc_parse_bg (GScanner *scanner,
1487 token = g_scanner_get_next_token (scanner);
1488 if (token != GTK_RC_TOKEN_BG)
1489 return GTK_RC_TOKEN_BG;
1491 token = gtk_rc_parse_state (scanner, &state);
1492 if (token != G_TOKEN_NONE)
1495 token = g_scanner_get_next_token (scanner);
1496 if (token != G_TOKEN_EQUAL_SIGN)
1497 return G_TOKEN_EQUAL_SIGN;
1499 style->color_flags[state] |= GTK_RC_BG;
1500 return gtk_rc_parse_color (scanner, &style->bg[state]);
1504 gtk_rc_parse_fg (GScanner *scanner,
1510 token = g_scanner_get_next_token (scanner);
1511 if (token != GTK_RC_TOKEN_FG)
1512 return GTK_RC_TOKEN_FG;
1514 token = gtk_rc_parse_state (scanner, &state);
1515 if (token != G_TOKEN_NONE)
1518 token = g_scanner_get_next_token (scanner);
1519 if (token != G_TOKEN_EQUAL_SIGN)
1520 return G_TOKEN_EQUAL_SIGN;
1522 style->color_flags[state] |= GTK_RC_FG;
1523 return gtk_rc_parse_color (scanner, &style->fg[state]);
1527 gtk_rc_parse_text (GScanner *scanner,
1533 token = g_scanner_get_next_token (scanner);
1534 if (token != GTK_RC_TOKEN_TEXT)
1535 return GTK_RC_TOKEN_TEXT;
1537 token = gtk_rc_parse_state (scanner, &state);
1538 if (token != G_TOKEN_NONE)
1541 token = g_scanner_get_next_token (scanner);
1542 if (token != G_TOKEN_EQUAL_SIGN)
1543 return G_TOKEN_EQUAL_SIGN;
1545 style->color_flags[state] |= GTK_RC_TEXT;
1546 return gtk_rc_parse_color (scanner, &style->text[state]);
1550 gtk_rc_parse_bg_pixmap (GScanner *scanner,
1551 GtkRcStyle *rc_style)
1557 token = g_scanner_get_next_token (scanner);
1558 if (token != GTK_RC_TOKEN_BG_PIXMAP)
1559 return GTK_RC_TOKEN_BG_PIXMAP;
1561 token = gtk_rc_parse_state (scanner, &state);
1562 if (token != G_TOKEN_NONE)
1565 token = g_scanner_get_next_token (scanner);
1566 if (token != G_TOKEN_EQUAL_SIGN)
1567 return G_TOKEN_EQUAL_SIGN;
1569 token = g_scanner_get_next_token (scanner);
1570 if (token != G_TOKEN_STRING)
1571 return G_TOKEN_STRING;
1573 if ((strcmp (scanner->value.v_string, "<parent>") == 0) ||
1574 (strcmp (scanner->value.v_string, "<none>") == 0))
1575 pixmap_file = g_strdup (scanner->value.v_string);
1577 pixmap_file = gtk_rc_find_pixmap_in_path (scanner, scanner->value.v_string);
1581 if (rc_style->bg_pixmap_name[state])
1582 g_free (rc_style->bg_pixmap_name[state]);
1583 rc_style->bg_pixmap_name[state] = pixmap_file;
1586 return G_TOKEN_NONE;
1590 gtk_rc_find_pixmap_in_path (GScanner *scanner,
1591 const gchar *pixmap_file)
1597 for (i = 0; (i < GTK_RC_MAX_PIXMAP_PATHS) && (pixmap_path[i] != NULL); i++)
1599 buf = g_strdup_printf ("%s" G_DIR_SEPARATOR_S "%s",
1600 pixmap_path[i], pixmap_file);
1602 fd = open (buf, O_RDONLY);
1613 g_warning (_("Unable to locate image file in pixmap_path: \"%s\" line %d"),
1614 pixmap_file, scanner->line);
1616 g_warning (_("Unable to locate image file in pixmap_path: \"%s\""),
1623 gtk_rc_find_module_in_path (const gchar *module_file)
1629 for (i = 0; (i < GTK_RC_MAX_MODULE_PATHS) && (module_path[i] != NULL); i++)
1631 buf = g_strdup_printf ("%s" G_DIR_SEPARATOR_S "%s",
1632 module_path[i], module_file);
1634 fd = open (buf, O_RDONLY);
1648 gtk_rc_parse_font (GScanner *scanner,
1649 GtkRcStyle *rc_style)
1653 token = g_scanner_get_next_token (scanner);
1654 if (token != GTK_RC_TOKEN_FONT)
1655 return GTK_RC_TOKEN_FONT;
1657 token = g_scanner_get_next_token (scanner);
1658 if (token != G_TOKEN_EQUAL_SIGN)
1659 return G_TOKEN_EQUAL_SIGN;
1661 token = g_scanner_get_next_token (scanner);
1662 if (token != G_TOKEN_STRING)
1663 return G_TOKEN_STRING;
1665 if (rc_style->font_name)
1666 g_free (rc_style->font_name);
1667 rc_style->font_name = g_strdup (scanner->value.v_string);
1669 return G_TOKEN_NONE;
1673 gtk_rc_parse_fontset (GScanner *scanner,
1674 GtkRcStyle *rc_style)
1678 token = g_scanner_get_next_token (scanner);
1679 if (token != GTK_RC_TOKEN_FONTSET)
1680 return GTK_RC_TOKEN_FONTSET;
1682 token = g_scanner_get_next_token (scanner);
1683 if (token != G_TOKEN_EQUAL_SIGN)
1684 return G_TOKEN_EQUAL_SIGN;
1686 token = g_scanner_get_next_token (scanner);
1687 if (token != G_TOKEN_STRING)
1688 return G_TOKEN_STRING;
1690 if (rc_style->fontset_name)
1691 g_free (rc_style->fontset_name);
1692 rc_style->fontset_name = g_strdup (scanner->value.v_string);
1694 return G_TOKEN_NONE;
1698 gtk_rc_parse_engine (GScanner *scanner,
1699 GtkRcStyle *rc_style)
1703 token = g_scanner_get_next_token (scanner);
1704 if (token != GTK_RC_TOKEN_ENGINE)
1705 return GTK_RC_TOKEN_ENGINE;
1707 token = g_scanner_get_next_token (scanner);
1708 if (token != G_TOKEN_STRING)
1709 return G_TOKEN_STRING;
1711 rc_style->engine = gtk_theme_engine_get (scanner->value.v_string);
1713 token = g_scanner_get_next_token (scanner);
1714 if (token != G_TOKEN_LEFT_CURLY)
1715 return G_TOKEN_LEFT_CURLY;
1717 if (rc_style->engine)
1718 return rc_style->engine->parse_rc_style (scanner, rc_style);
1721 /* Skip over remainder, looking for nested {}'s */
1724 while ((token = g_scanner_get_next_token (scanner)) != G_TOKEN_EOF)
1726 if (token == G_TOKEN_LEFT_CURLY)
1728 else if (token == G_TOKEN_RIGHT_CURLY)
1732 return G_TOKEN_NONE;
1735 return G_TOKEN_RIGHT_CURLY;
1740 gtk_rc_parse_state (GScanner *scanner,
1741 GtkStateType *state)
1746 g_return_val_if_fail (scanner != NULL, G_TOKEN_ERROR);
1747 g_return_val_if_fail (state != NULL, G_TOKEN_ERROR);
1749 /* we don't know where we got called from, so we reset the scope here.
1750 * if we bail out due to errors, we *don't* reset the scope, so the
1751 * error messaging code can make sense of our tokens.
1753 old_scope = g_scanner_set_scope (scanner, 0);
1755 token = g_scanner_get_next_token (scanner);
1756 if (token != G_TOKEN_LEFT_BRACE)
1757 return G_TOKEN_LEFT_BRACE;
1759 token = g_scanner_get_next_token (scanner);
1762 case GTK_RC_TOKEN_ACTIVE:
1763 *state = GTK_STATE_ACTIVE;
1765 case GTK_RC_TOKEN_INSENSITIVE:
1766 *state = GTK_STATE_INSENSITIVE;
1768 case GTK_RC_TOKEN_NORMAL:
1769 *state = GTK_STATE_NORMAL;
1771 case GTK_RC_TOKEN_PRELIGHT:
1772 *state = GTK_STATE_PRELIGHT;
1774 case GTK_RC_TOKEN_SELECTED:
1775 *state = GTK_STATE_SELECTED;
1778 return /* G_TOKEN_SYMBOL */ GTK_RC_TOKEN_NORMAL;
1781 token = g_scanner_get_next_token (scanner);
1782 if (token != G_TOKEN_RIGHT_BRACE)
1783 return G_TOKEN_RIGHT_BRACE;
1785 g_scanner_set_scope (scanner, old_scope);
1787 return G_TOKEN_NONE;
1791 gtk_rc_parse_priority (GScanner *scanner,
1792 GtkPathPriorityType *priority)
1797 g_return_val_if_fail (scanner != NULL, G_TOKEN_ERROR);
1798 g_return_val_if_fail (priority != NULL, G_TOKEN_ERROR);
1800 /* we don't know where we got called from, so we reset the scope here.
1801 * if we bail out due to errors, we *don't* reset the scope, so the
1802 * error messaging code can make sense of our tokens.
1804 old_scope = g_scanner_set_scope (scanner, 0);
1806 token = g_scanner_get_next_token (scanner);
1810 token = g_scanner_get_next_token (scanner);
1813 case GTK_RC_TOKEN_LOWEST:
1814 *priority = GTK_PATH_PRIO_LOWEST;
1816 case GTK_RC_TOKEN_GTK:
1817 *priority = GTK_PATH_PRIO_GTK;
1819 case GTK_RC_TOKEN_APPLICATION:
1820 *priority = GTK_PATH_PRIO_APPLICATION;
1822 case GTK_RC_TOKEN_RC:
1823 *priority = GTK_PATH_PRIO_RC;
1825 case GTK_RC_TOKEN_HIGHEST:
1826 *priority = GTK_PATH_PRIO_HIGHEST;
1829 return /* G_TOKEN_SYMBOL */ GTK_RC_TOKEN_APPLICATION;
1832 g_scanner_set_scope (scanner, old_scope);
1834 return G_TOKEN_NONE;
1838 gtk_rc_parse_color (GScanner *scanner,
1843 g_return_val_if_fail (scanner != NULL, G_TOKEN_ERROR);
1845 /* we don't need to set our own scop here, because
1846 * we don't need own symbols
1849 token = g_scanner_get_next_token (scanner);
1858 case G_TOKEN_LEFT_CURLY:
1859 token = g_scanner_get_next_token (scanner);
1860 if (token == G_TOKEN_INT)
1861 token_int = scanner->value.v_int;
1862 else if (token == G_TOKEN_FLOAT)
1863 token_int = scanner->value.v_float * 65535.0;
1865 return G_TOKEN_FLOAT;
1866 color->red = CLAMP (token_int, 0, 65535);
1868 token = g_scanner_get_next_token (scanner);
1869 if (token != G_TOKEN_COMMA)
1870 return G_TOKEN_COMMA;
1872 token = g_scanner_get_next_token (scanner);
1873 if (token == G_TOKEN_INT)
1874 token_int = scanner->value.v_int;
1875 else if (token == G_TOKEN_FLOAT)
1876 token_int = scanner->value.v_float * 65535.0;
1878 return G_TOKEN_FLOAT;
1879 color->green = CLAMP (token_int, 0, 65535);
1881 token = g_scanner_get_next_token (scanner);
1882 if (token != G_TOKEN_COMMA)
1883 return G_TOKEN_COMMA;
1885 token = g_scanner_get_next_token (scanner);
1886 if (token == G_TOKEN_INT)
1887 token_int = scanner->value.v_int;
1888 else if (token == G_TOKEN_FLOAT)
1889 token_int = scanner->value.v_float * 65535.0;
1891 return G_TOKEN_FLOAT;
1892 color->blue = CLAMP (token_int, 0, 65535);
1894 token = g_scanner_get_next_token (scanner);
1895 if (token != G_TOKEN_RIGHT_CURLY)
1896 return G_TOKEN_RIGHT_CURLY;
1897 return G_TOKEN_NONE;
1899 case G_TOKEN_STRING:
1900 if (scanner->value.v_string[0] != '#')
1901 return G_TOKEN_STRING;
1903 length = strlen (scanner->value.v_string) - 1;
1904 if (((length % 3) != 0) || (length > 12))
1905 return G_TOKEN_STRING;
1908 for (i = 0, j = 1; i < length; i++, j++)
1909 buf[i] = scanner->value.v_string[j];
1912 sscanf (buf, "%x", &temp);
1915 for (i = 0; i < length; i++, j++)
1916 buf[i] = scanner->value.v_string[j];
1919 sscanf (buf, "%x", &temp);
1920 color->green = temp;
1922 for (i = 0; i < length; i++, j++)
1923 buf[i] = scanner->value.v_string[j];
1926 sscanf (buf, "%x", &temp);
1932 color->green *= 4369;
1933 color->blue *= 4369;
1935 else if (length == 2)
1938 color->green *= 257;
1941 else if (length == 3)
1947 return G_TOKEN_NONE;
1950 return G_TOKEN_STRING;
1955 gtk_rc_parse_pixmap_path (GScanner *scanner)
1959 token = g_scanner_get_next_token (scanner);
1960 if (token != GTK_RC_TOKEN_PIXMAP_PATH)
1961 return GTK_RC_TOKEN_PIXMAP_PATH;
1963 token = g_scanner_get_next_token (scanner);
1964 if (token != G_TOKEN_STRING)
1965 return G_TOKEN_STRING;
1967 gtk_rc_parse_pixmap_path_string (scanner->value.v_string);
1969 return G_TOKEN_NONE;
1973 gtk_rc_parse_pixmap_path_string (gchar *pix_path)
1977 gint start_offset = 0;
1981 /* free the old one, or just add to the old one ? */
1982 for (path_num=0; pixmap_path[path_num]; path_num++)
1984 g_free (pixmap_path[path_num]);
1985 pixmap_path[path_num] = NULL;
1990 path_len = strlen (pix_path);
1992 buf = g_strdup (pix_path);
1994 for (end_offset = 0; end_offset <= path_len; end_offset++)
1996 if ((buf[end_offset] == G_SEARCHPATH_SEPARATOR) ||
1997 (end_offset == path_len))
1999 buf[end_offset] = '\0';
2000 pixmap_path[path_num] = g_strdup (buf + start_offset);
2002 pixmap_path[path_num] = NULL;
2003 start_offset = end_offset + 1;
2007 gtk_rc_append_default_pixmap_path();
2011 gtk_rc_parse_module_path (GScanner *scanner)
2015 token = g_scanner_get_next_token (scanner);
2016 if (token != GTK_RC_TOKEN_MODULE_PATH)
2017 return GTK_RC_TOKEN_MODULE_PATH;
2019 token = g_scanner_get_next_token (scanner);
2020 if (token != G_TOKEN_STRING)
2021 return G_TOKEN_STRING;
2023 gtk_rc_parse_module_path_string (scanner->value.v_string);
2025 return G_TOKEN_NONE;
2029 gtk_rc_parse_module_path_string (gchar *mod_path)
2033 gint start_offset = 0;
2037 /* free the old one, or just add to the old one ? */
2038 for (path_num=0; module_path[path_num]; path_num++)
2040 g_free (module_path[path_num]);
2041 module_path[path_num] = NULL;
2046 path_len = strlen (mod_path);
2048 buf = g_strdup (mod_path);
2050 for (end_offset = 0; end_offset <= path_len; end_offset++)
2052 if ((buf[end_offset] == G_SEARCHPATH_SEPARATOR) ||
2053 (end_offset == path_len))
2055 buf[end_offset] = '\0';
2056 module_path[path_num] = g_strdup (buf + start_offset);
2058 module_path[path_num] = NULL;
2059 start_offset = end_offset + 1;
2063 gtk_rc_append_default_module_path();
2067 gtk_rc_parse_path_pattern (GScanner *scanner)
2070 GtkPathType path_type;
2072 gboolean is_binding;
2073 GtkPathPriorityType priority = GTK_PATH_PRIO_RC;
2075 token = g_scanner_get_next_token (scanner);
2078 case GTK_RC_TOKEN_WIDGET:
2079 path_type = GTK_PATH_WIDGET;
2081 case GTK_RC_TOKEN_WIDGET_CLASS:
2082 path_type = GTK_PATH_WIDGET_CLASS;
2084 case GTK_RC_TOKEN_CLASS:
2085 path_type = GTK_PATH_CLASS;
2088 return GTK_RC_TOKEN_WIDGET_CLASS;
2091 token = g_scanner_get_next_token (scanner);
2092 if (token != G_TOKEN_STRING)
2093 return G_TOKEN_STRING;
2095 pattern = g_strdup (scanner->value.v_string);
2097 token = g_scanner_get_next_token (scanner);
2098 if (token == GTK_RC_TOKEN_STYLE)
2100 else if (token == GTK_RC_TOKEN_BINDING)
2103 if (g_scanner_peek_next_token (scanner) == ':')
2105 token = gtk_rc_parse_priority (scanner, &priority);
2106 if (token != G_TOKEN_NONE)
2116 return GTK_RC_TOKEN_STYLE;
2119 token = g_scanner_get_next_token (scanner);
2120 if (token != G_TOKEN_STRING)
2123 return G_TOKEN_STRING;
2128 GtkBindingSet *binding;
2130 binding = gtk_binding_set_find (scanner->value.v_string);
2134 return G_TOKEN_STRING;
2136 gtk_binding_set_add_path (binding, path_type, pattern, priority);
2140 GtkRcStyle *rc_style;
2143 rc_style = gtk_rc_style_find (scanner->value.v_string);
2148 return G_TOKEN_STRING;
2151 rc_set = g_new (GtkRcSet, 1);
2152 gtk_pattern_spec_init (&rc_set->pspec, pattern);
2153 rc_set->rc_style = rc_style;
2155 if (path_type == GTK_PATH_WIDGET)
2156 gtk_rc_sets_widget = g_slist_prepend (gtk_rc_sets_widget, rc_set);
2157 else if (path_type == GTK_PATH_WIDGET_CLASS)
2158 gtk_rc_sets_widget_class = g_slist_prepend (gtk_rc_sets_widget_class, rc_set);
2160 gtk_rc_sets_class = g_slist_prepend (gtk_rc_sets_class, rc_set);
2164 return G_TOKEN_NONE;
2168 typedef GdkPixmap * (*GtkImageLoader) (GdkWindow *window,
2169 GdkColormap *colormap,
2171 GdkColor *transparent_color,
2172 const gchar *filename);
2176 gtk_rc_set_image_loader(GtkImageLoader loader)
2178 image_loader = loader;
2182 gtk_rc_load_image (GdkColormap *colormap,
2183 GdkColor *transparent_color,
2184 const gchar *filename)
2186 if (strcmp (filename, "<parent>") == 0)
2187 return (GdkPixmap*) GDK_PARENT_RELATIVE;
2191 return image_loader(NULL, colormap, NULL,
2195 return gdk_pixmap_colormap_create_from_xpm (NULL, colormap, NULL,