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;
470 #ifdef HAVE_LC_MESSAGES
471 char *locale = setlocale (LC_MESSAGES, NULL);
473 char *locale = setlocale (LC_CTYPE, NULL);
478 rc_style_ht = g_hash_table_new ((GHashFunc) gtk_rc_style_hash,
479 (GCompareFunc) gtk_rc_style_compare);
480 pixmap_path[0] = NULL;
481 module_path[0] = NULL;
482 gtk_rc_append_default_pixmap_path();
483 gtk_rc_append_default_module_path();
485 gtk_rc_add_initial_default_files ();
487 if (strcmp (locale, "C") && strcmp (locale, "POSIX"))
489 /* Determine locale-specific suffixes for RC files
491 p = strchr (locale, '@');
492 length = p ? (p -locale) : strlen (locale);
494 p = strchr (locale, '.');
497 locale_suffixes[n_locale_suffixes++] = g_strndup (locale, length);
501 p = strchr (locale, '_');
504 locale_suffixes[n_locale_suffixes++] = g_strndup (locale, length);
508 locale_suffixes[n_locale_suffixes++] = g_strndup (locale, length);
512 while (gtk_rc_default_files[i] != NULL)
514 /* Try to find a locale specific RC file corresponding to
515 * to parse before the default file.
517 for (j=n_locale_suffixes-1; j>=0; j--)
519 gchar *name = g_strconcat (gtk_rc_default_files[i],
527 gtk_rc_parse (gtk_rc_default_files[i]);
533 gtk_rc_parse_string (const gchar *rc_string)
535 g_return_if_fail (rc_string != NULL);
537 gtk_rc_parse_any ("-", -1, rc_string);
541 gtk_rc_parse_file (const gchar *filename, gboolean reload)
543 GtkRcFile *rc_file = NULL;
547 g_return_if_fail (filename != NULL);
552 rc_file = tmp_list->data;
553 if (!strcmp (rc_file->name, filename))
556 tmp_list = tmp_list->next;
561 rc_file = g_new (GtkRcFile, 1);
562 rc_file->name = g_strdup (filename);
563 rc_file->canonical_name = NULL;
565 rc_file->reload = reload;
567 rc_files = g_slist_append (rc_files, rc_file);
570 if (!rc_file->canonical_name)
572 /* Get the absolute pathname */
574 if (g_path_is_absolute (rc_file->name))
575 rc_file->canonical_name = rc_file->name;
581 cwd = g_get_current_dir ();
583 str = g_string_new (cwd);
585 g_string_append_c (str, G_DIR_SEPARATOR);
586 g_string_append (str, rc_file->name);
588 rc_file->canonical_name = str->str;
589 g_string_free (str, FALSE);
593 if (!lstat (rc_file->canonical_name, &statbuf))
597 rc_file->mtime = statbuf.st_mtime;
599 fd = open (rc_file->canonical_name, O_RDONLY);
607 dir = g_strdup(rc_file->canonical_name);
608 for (i = strlen(dir) - 1; (i >= 0) && (dir[i] != G_DIR_SEPARATOR); i--)
610 if (i >= 0 && dir[i] == G_DIR_SEPARATOR)
612 gtk_rc_append_pixmap_path(dir);
615 gtk_rc_parse_any (filename, fd, NULL);
622 gtk_rc_parse (const gchar *filename)
624 g_return_if_fail (filename != NULL);
626 gtk_rc_parse_file (filename, TRUE);
629 /* Handling of RC styles */
632 gtk_rc_style_new (void)
634 GtkRcStyle *new_style;
636 new_style = g_new0 (GtkRcStyle, 1);
637 new_style->ref_count = 1;
643 gtk_rc_style_ref (GtkRcStyle *rc_style)
645 g_return_if_fail (rc_style != NULL);
647 rc_style->ref_count++;
651 gtk_rc_style_unref (GtkRcStyle *rc_style)
655 g_return_if_fail (rc_style != NULL);
656 g_return_if_fail (rc_style->ref_count > 0);
658 rc_style->ref_count--;
660 if (rc_style->ref_count == 0)
662 if (rc_style->engine)
664 rc_style->engine->destroy_rc_style (rc_style);
665 gtk_theme_engine_unref (rc_style->engine);
669 g_free (rc_style->name);
670 if (rc_style->fontset_name)
671 g_free (rc_style->fontset_name);
672 if (rc_style->font_name)
673 g_free (rc_style->font_name);
675 for (i=0 ; i<5 ; i++)
676 if (rc_style->bg_pixmap_name[i])
677 g_free (rc_style->bg_pixmap_name[i]);
684 gtk_rc_clear_realized_node (gpointer key,
688 gtk_style_unref (data);
692 gtk_rc_clear_hash_node (gpointer key,
696 gtk_rc_style_unref (data);
700 gtk_rc_free_rc_sets (GSList *slist)
706 rc_set = slist->data;
707 gtk_pattern_spec_free_segs (&rc_set->pspec);
715 gtk_rc_clear_styles (void)
717 /* Clear out all old rc_styles */
721 g_hash_table_foreach (rc_style_ht, gtk_rc_clear_hash_node, NULL);
722 g_hash_table_destroy (rc_style_ht);
726 if (realized_style_ht)
728 g_hash_table_foreach (realized_style_ht, gtk_rc_clear_realized_node, NULL);
729 g_hash_table_destroy (realized_style_ht);
730 realized_style_ht = NULL;
733 gtk_rc_free_rc_sets (gtk_rc_sets_widget);
734 g_slist_free (gtk_rc_sets_widget);
735 gtk_rc_sets_widget = NULL;
737 gtk_rc_free_rc_sets (gtk_rc_sets_widget_class);
738 g_slist_free (gtk_rc_sets_widget_class);
739 gtk_rc_sets_widget_class = NULL;
741 gtk_rc_free_rc_sets (gtk_rc_sets_class);
742 g_slist_free (gtk_rc_sets_class);
743 gtk_rc_sets_class = NULL;
749 gtk_rc_reparse_all (void)
752 gboolean mtime_modified = FALSE;
757 /* Check through and see if any of the RC's have had their
758 * mtime modified. If so, reparse everything.
763 rc_file = tmp_list->data;
765 if (!lstat (rc_file->name, &statbuf) &&
766 (statbuf.st_mtime > rc_file->mtime))
768 mtime_modified = TRUE;
772 tmp_list = tmp_list->next;
777 gtk_rc_clear_styles();
782 rc_file = tmp_list->data;
784 gtk_rc_parse_file (rc_file->name, FALSE);
786 tmp_list = tmp_list->next;
790 return mtime_modified;
794 gtk_rc_styles_match (GSList *rc_styles,
798 gchar *path_reversed)
808 if (gtk_pattern_match (&rc_set->pspec, path_length, path, path_reversed))
809 rc_styles = g_slist_append (rc_styles, rc_set->rc_style);
816 gtk_rc_get_style (GtkWidget *widget)
818 GtkRcStyle *widget_rc_style;
819 GSList *rc_styles = NULL;
821 static guint rc_style_key_id = 0;
823 /* We allow the specification of a single rc style to be bound
824 * tightly to a widget, for application modifications
826 if (!rc_style_key_id)
827 rc_style_key_id = g_quark_from_static_string ("gtk-rc-style");
829 widget_rc_style = gtk_object_get_data_by_id (GTK_OBJECT (widget),
833 rc_styles = g_slist_prepend (rc_styles, widget_rc_style);
835 if (gtk_rc_sets_widget)
837 gchar *path, *path_reversed;
840 gtk_widget_path (widget, &path_length, &path, &path_reversed);
841 rc_styles = gtk_rc_styles_match (rc_styles, gtk_rc_sets_widget, path_length, path, path_reversed);
843 g_free (path_reversed);
847 if (gtk_rc_sets_widget_class)
849 gchar *path, *path_reversed;
852 gtk_widget_class_path (widget, &path_length, &path, &path_reversed);
853 rc_styles = gtk_rc_styles_match (rc_styles, gtk_rc_sets_widget_class, path_length, path, path_reversed);
855 g_free (path_reversed);
858 if (gtk_rc_sets_class)
862 type = GTK_OBJECT_TYPE (widget);
865 gchar *path, *path_reversed;
868 path = gtk_type_name (type);
869 path_length = strlen (path);
870 path_reversed = g_strdup (path);
871 g_strreverse (path_reversed);
873 rc_styles = gtk_rc_styles_match (rc_styles, gtk_rc_sets_class, path_length, path, path_reversed);
874 g_free (path_reversed);
876 type = gtk_type_parent (type);
881 return gtk_rc_style_init (rc_styles);
887 gtk_rc_add_rc_sets (GSList *slist,
888 GtkRcStyle *rc_style,
891 GtkRcStyle *new_style;
895 new_style = gtk_rc_style_new ();
896 *new_style = *rc_style;
897 new_style->name = g_strdup (rc_style->name);
898 new_style->font_name = g_strdup (rc_style->font_name);
899 new_style->fontset_name = g_strdup (rc_style->fontset_name);
901 for (i = 0; i < 5; i++)
902 new_style->bg_pixmap_name[i] = g_strdup (rc_style->bg_pixmap_name[i]);
904 rc_set = g_new (GtkRcSet, 1);
905 gtk_pattern_spec_init (&rc_set->pspec, pattern);
906 rc_set->rc_style = rc_style;
908 return g_slist_prepend (slist, rc_set);
912 gtk_rc_add_widget_name_style (GtkRcStyle *rc_style,
913 const gchar *pattern)
915 g_return_if_fail (rc_style != NULL);
916 g_return_if_fail (pattern != NULL);
918 gtk_rc_sets_widget = gtk_rc_add_rc_sets (gtk_rc_sets_widget, rc_style, pattern);
922 gtk_rc_add_widget_class_style (GtkRcStyle *rc_style,
923 const gchar *pattern)
925 g_return_if_fail (rc_style != NULL);
926 g_return_if_fail (pattern != NULL);
928 gtk_rc_sets_widget_class = gtk_rc_add_rc_sets (gtk_rc_sets_widget_class, rc_style, pattern);
932 gtk_rc_add_class_style (GtkRcStyle *rc_style,
933 const gchar *pattern)
935 g_return_if_fail (rc_style != NULL);
936 g_return_if_fail (pattern != NULL);
938 gtk_rc_sets_class = gtk_rc_add_rc_sets (gtk_rc_sets_class, rc_style, pattern);
942 gtk_rc_parse_any (const gchar *input_name,
944 const gchar *input_string)
950 scanner = g_scanner_new ((GScannerConfig *) >k_rc_scanner_config);
954 g_assert (input_string == NULL);
956 g_scanner_input_file (scanner, input_fd);
960 g_assert (input_string != NULL);
962 g_scanner_input_text (scanner, input_string, strlen (input_string));
964 scanner->input_name = input_name;
966 g_scanner_freeze_symbol_table (scanner);
967 for (i = 0; i < n_symbols; i++)
968 g_scanner_add_symbol (scanner, symbols[i].name, GINT_TO_POINTER (symbols[i].token));
969 g_scanner_thaw_symbol_table (scanner);
974 if (g_scanner_peek_next_token (scanner) == G_TOKEN_EOF)
978 guint expected_token;
980 expected_token = gtk_rc_parse_statement (scanner);
982 if (expected_token != G_TOKEN_NONE)
989 if (scanner->scope_id == 0)
991 /* if we are in scope 0, we know the symbol names
992 * that are associated with certaintoken values.
993 * so we look them up to make the error messages
996 if (expected_token > GTK_RC_TOKEN_INVALID &&
997 expected_token < GTK_RC_TOKEN_LAST)
999 for (i = 0; i < n_symbols; i++)
1000 if (symbols[i].token == expected_token)
1001 msg = symbols[i].name;
1003 msg = g_strconcat ("e.g. `", msg, "'", NULL);
1005 if (scanner->token > GTK_RC_TOKEN_INVALID &&
1006 scanner->token < GTK_RC_TOKEN_LAST)
1008 symbol_name = "???";
1009 for (i = 0; i < n_symbols; i++)
1010 if (symbols[i].token == scanner->token)
1011 symbol_name = symbols[i].name;
1014 g_scanner_unexp_token (scanner,
1027 g_scanner_destroy (scanner);
1031 gtk_rc_styles_hash (const GSList *rc_styles)
1038 result += (result << 9) + GPOINTER_TO_UINT (rc_styles->data);
1039 rc_styles = rc_styles->next;
1046 gtk_rc_styles_compare (const GSList *a,
1051 if (a->data != b->data)
1061 gtk_rc_style_hash (const char *name)
1067 result += (result << 3) + *name++;
1073 gtk_rc_style_compare (const char *a,
1076 return (strcmp (a, b) == 0);
1080 gtk_rc_style_find (const char *name)
1082 GtkRcStyle *rc_style;
1084 rc_style = g_hash_table_lookup (rc_style_ht, (gpointer) name);
1089 /* Assumes ownership of rc_style */
1091 gtk_rc_style_to_style (GtkRcStyle *rc_style)
1097 style = gtk_style_new ();
1099 style->rc_style = rc_style;
1101 if (rc_style->fontset_name)
1103 old_font = style->font;
1104 style->font = gdk_fontset_load (rc_style->fontset_name);
1106 gdk_font_unref (old_font);
1108 style->font = old_font;
1110 else if (rc_style->font_name)
1112 old_font = style->font;
1113 style->font = gdk_font_load (rc_style->font_name);
1115 gdk_font_unref (old_font);
1117 style->font = old_font;
1120 for (i = 0; i < 5; i++)
1122 if (rc_style->color_flags[i] & GTK_RC_FG)
1123 style->fg[i] = rc_style->fg[i];
1124 if (rc_style->color_flags[i] & GTK_RC_BG)
1125 style->bg[i] = rc_style->bg[i];
1126 if (rc_style->color_flags[i] & GTK_RC_TEXT)
1127 style->text[i] = rc_style->text[i];
1128 if (rc_style->color_flags[i] & GTK_RC_BASE)
1129 style->base[i] = rc_style->base[i];
1132 if (rc_style->engine)
1134 style->engine = rc_style->engine;
1135 gtk_theme_engine_ref (style->engine);
1136 rc_style->engine->rc_style_to_style (style, rc_style);
1142 /* Reuses or frees rc_styles */
1144 gtk_rc_style_init (GSList *rc_styles)
1148 GtkStyle *style = NULL;
1149 GtkRcStyle *proto_style;
1151 if (!realized_style_ht)
1152 realized_style_ht = g_hash_table_new ((GHashFunc)gtk_rc_styles_hash,
1153 (GCompareFunc)gtk_rc_styles_compare);
1155 style = g_hash_table_lookup (realized_style_ht, rc_styles);
1159 GSList *tmp_styles = rc_styles;
1161 proto_style = gtk_rc_style_new ();
1165 GtkRcStyle *rc_style = tmp_styles->data;
1169 if (!proto_style->bg_pixmap_name[i] && rc_style->bg_pixmap_name[i])
1170 proto_style->bg_pixmap_name[i] = g_strdup (rc_style->bg_pixmap_name[i]);
1172 if (!(proto_style->color_flags[i] & GTK_RC_FG) &&
1173 rc_style->color_flags[i] & GTK_RC_FG)
1175 proto_style->fg[i] = rc_style->fg[i];
1176 proto_style->color_flags[i] |= GTK_RC_FG;
1178 if (!(proto_style->color_flags[i] & GTK_RC_BG) &&
1179 rc_style->color_flags[i] & GTK_RC_BG)
1181 proto_style->bg[i] = rc_style->bg[i];
1182 proto_style->color_flags[i] |= GTK_RC_BG;
1184 if (!(proto_style->color_flags[i] & GTK_RC_TEXT) &&
1185 rc_style->color_flags[i] & GTK_RC_TEXT)
1187 proto_style->text[i] = rc_style->text[i];
1188 proto_style->color_flags[i] |= GTK_RC_TEXT;
1190 if (!(proto_style->color_flags[i] & GTK_RC_BASE) &&
1191 rc_style->color_flags[i] & GTK_RC_BASE)
1193 proto_style->base[i] = rc_style->base[i];
1194 proto_style->color_flags[i] |= GTK_RC_BASE;
1198 if (!proto_style->font_name && rc_style->font_name)
1199 proto_style->font_name = g_strdup (rc_style->font_name);
1200 if (!proto_style->fontset_name && rc_style->fontset_name)
1201 proto_style->fontset_name = g_strdup (rc_style->fontset_name);
1203 if (!proto_style->engine && rc_style->engine)
1205 proto_style->engine = rc_style->engine;
1206 gtk_theme_engine_ref (proto_style->engine);
1209 if (proto_style->engine &&
1210 (proto_style->engine == rc_style->engine))
1211 proto_style->engine->merge_rc_style (proto_style, rc_style);
1213 tmp_styles = tmp_styles->next;
1217 if (proto_style->bg_pixmap_name[i] &&
1218 (strcmp (proto_style->bg_pixmap_name[i], "<none>") == 0))
1220 g_free (proto_style->bg_pixmap_name[i]);
1221 proto_style->bg_pixmap_name[i] = NULL;
1224 style = gtk_rc_style_to_style (proto_style);
1226 g_hash_table_insert (realized_style_ht, rc_styles, style);
1232 /*********************
1233 * Parsing functions *
1234 *********************/
1237 gtk_rc_parse_statement (GScanner *scanner)
1241 token = g_scanner_peek_next_token (scanner);
1245 case GTK_RC_TOKEN_INCLUDE:
1246 token = g_scanner_get_next_token (scanner);
1247 if (token != GTK_RC_TOKEN_INCLUDE)
1248 return GTK_RC_TOKEN_INCLUDE;
1250 token = g_scanner_get_next_token (scanner);
1251 if (token != G_TOKEN_STRING)
1252 return G_TOKEN_STRING;
1254 gtk_rc_parse_file (scanner->value.v_string, FALSE);
1255 return G_TOKEN_NONE;
1257 case GTK_RC_TOKEN_STYLE:
1258 return gtk_rc_parse_style (scanner);
1260 case GTK_RC_TOKEN_BINDING:
1261 return gtk_binding_parse_binding (scanner);
1263 case GTK_RC_TOKEN_PIXMAP_PATH:
1264 return gtk_rc_parse_pixmap_path (scanner);
1266 case GTK_RC_TOKEN_WIDGET:
1267 return gtk_rc_parse_path_pattern (scanner);
1269 case GTK_RC_TOKEN_WIDGET_CLASS:
1270 return gtk_rc_parse_path_pattern (scanner);
1272 case GTK_RC_TOKEN_CLASS:
1273 return gtk_rc_parse_path_pattern (scanner);
1275 case GTK_RC_TOKEN_MODULE_PATH:
1276 return gtk_rc_parse_module_path (scanner);
1279 g_scanner_get_next_token (scanner);
1280 return /* G_TOKEN_SYMBOL */ GTK_RC_TOKEN_STYLE;
1285 gtk_rc_parse_style (GScanner *scanner)
1287 GtkRcStyle *rc_style;
1288 GtkRcStyle *parent_style;
1293 token = g_scanner_get_next_token (scanner);
1294 if (token != GTK_RC_TOKEN_STYLE)
1295 return GTK_RC_TOKEN_STYLE;
1297 token = g_scanner_get_next_token (scanner);
1298 if (token != G_TOKEN_STRING)
1299 return G_TOKEN_STRING;
1302 rc_style = g_hash_table_lookup (rc_style_ht, scanner->value.v_string);
1307 rc_style = gtk_rc_style_new ();
1308 rc_style->name = g_strdup (scanner->value.v_string);
1310 for (i = 0; i < 5; i++)
1311 rc_style->bg_pixmap_name[i] = NULL;
1313 for (i = 0; i < 5; i++)
1314 rc_style->color_flags[i] = 0;
1316 rc_style->engine = NULL;
1317 rc_style->engine_data = NULL;
1320 token = g_scanner_peek_next_token (scanner);
1321 if (token == G_TOKEN_EQUAL_SIGN)
1323 token = g_scanner_get_next_token (scanner);
1325 token = g_scanner_get_next_token (scanner);
1326 if (token != G_TOKEN_STRING)
1331 return G_TOKEN_STRING;
1334 parent_style = g_hash_table_lookup (rc_style_ht, scanner->value.v_string);
1337 for (i = 0; i < 5; i++)
1339 rc_style->color_flags[i] = parent_style->color_flags[i];
1340 rc_style->fg[i] = parent_style->fg[i];
1341 rc_style->bg[i] = parent_style->bg[i];
1342 rc_style->text[i] = parent_style->text[i];
1343 rc_style->base[i] = parent_style->base[i];
1346 if (parent_style->fontset_name)
1348 if (rc_style->fontset_name)
1349 g_free (rc_style->fontset_name);
1350 rc_style->fontset_name = g_strdup (parent_style->fontset_name);
1352 else if (parent_style->font_name)
1354 if (rc_style->font_name)
1355 g_free (rc_style->font_name);
1356 rc_style->font_name = g_strdup (parent_style->font_name);
1359 for (i = 0; i < 5; i++)
1361 if (rc_style->bg_pixmap_name[i])
1362 g_free (rc_style->bg_pixmap_name[i]);
1363 rc_style->bg_pixmap_name[i] = g_strdup (parent_style->bg_pixmap_name[i]);
1368 token = g_scanner_get_next_token (scanner);
1369 if (token != G_TOKEN_LEFT_CURLY)
1374 return G_TOKEN_LEFT_CURLY;
1377 token = g_scanner_peek_next_token (scanner);
1378 while (token != G_TOKEN_RIGHT_CURLY)
1382 case GTK_RC_TOKEN_BASE:
1383 token = gtk_rc_parse_base (scanner, rc_style);
1385 case GTK_RC_TOKEN_BG:
1386 token = gtk_rc_parse_bg (scanner, rc_style);
1388 case GTK_RC_TOKEN_FG:
1389 token = gtk_rc_parse_fg (scanner, rc_style);
1391 case GTK_RC_TOKEN_TEXT:
1392 token = gtk_rc_parse_text (scanner, rc_style);
1394 case GTK_RC_TOKEN_BG_PIXMAP:
1395 token = gtk_rc_parse_bg_pixmap (scanner, rc_style);
1397 case GTK_RC_TOKEN_FONT:
1398 token = gtk_rc_parse_font (scanner, rc_style);
1400 case GTK_RC_TOKEN_FONTSET:
1401 token = gtk_rc_parse_fontset (scanner, rc_style);
1403 case GTK_RC_TOKEN_ENGINE:
1404 token = gtk_rc_parse_engine (scanner, rc_style);
1407 g_scanner_get_next_token (scanner);
1408 token = G_TOKEN_RIGHT_CURLY;
1412 if (token != G_TOKEN_NONE)
1416 if (rc_style->fontset_name)
1417 g_free (rc_style->fontset_name);
1418 if (rc_style->font_name)
1419 g_free (rc_style->font_name);
1420 for (i = 0; i < 5; i++)
1421 if (rc_style->bg_pixmap_name[i])
1422 g_free (rc_style->bg_pixmap_name[i]);
1427 token = g_scanner_peek_next_token (scanner);
1430 token = g_scanner_get_next_token (scanner);
1431 if (token != G_TOKEN_RIGHT_CURLY)
1435 if (rc_style->fontset_name)
1436 g_free (rc_style->fontset_name);
1437 if (rc_style->font_name)
1438 g_free (rc_style->font_name);
1440 for (i = 0; i < 5; i++)
1441 if (rc_style->bg_pixmap_name[i])
1442 g_free (rc_style->bg_pixmap_name[i]);
1446 return G_TOKEN_RIGHT_CURLY;
1450 g_hash_table_insert (rc_style_ht, rc_style->name, rc_style);
1452 return G_TOKEN_NONE;
1456 gtk_rc_parse_base (GScanner *scanner,
1462 token = g_scanner_get_next_token (scanner);
1463 if (token != GTK_RC_TOKEN_BASE)
1464 return GTK_RC_TOKEN_BASE;
1466 token = gtk_rc_parse_state (scanner, &state);
1467 if (token != G_TOKEN_NONE)
1470 token = g_scanner_get_next_token (scanner);
1471 if (token != G_TOKEN_EQUAL_SIGN)
1472 return G_TOKEN_EQUAL_SIGN;
1474 style->color_flags[state] |= GTK_RC_BASE;
1475 return gtk_rc_parse_color (scanner, &style->base[state]);
1479 gtk_rc_parse_bg (GScanner *scanner,
1485 token = g_scanner_get_next_token (scanner);
1486 if (token != GTK_RC_TOKEN_BG)
1487 return GTK_RC_TOKEN_BG;
1489 token = gtk_rc_parse_state (scanner, &state);
1490 if (token != G_TOKEN_NONE)
1493 token = g_scanner_get_next_token (scanner);
1494 if (token != G_TOKEN_EQUAL_SIGN)
1495 return G_TOKEN_EQUAL_SIGN;
1497 style->color_flags[state] |= GTK_RC_BG;
1498 return gtk_rc_parse_color (scanner, &style->bg[state]);
1502 gtk_rc_parse_fg (GScanner *scanner,
1508 token = g_scanner_get_next_token (scanner);
1509 if (token != GTK_RC_TOKEN_FG)
1510 return GTK_RC_TOKEN_FG;
1512 token = gtk_rc_parse_state (scanner, &state);
1513 if (token != G_TOKEN_NONE)
1516 token = g_scanner_get_next_token (scanner);
1517 if (token != G_TOKEN_EQUAL_SIGN)
1518 return G_TOKEN_EQUAL_SIGN;
1520 style->color_flags[state] |= GTK_RC_FG;
1521 return gtk_rc_parse_color (scanner, &style->fg[state]);
1525 gtk_rc_parse_text (GScanner *scanner,
1531 token = g_scanner_get_next_token (scanner);
1532 if (token != GTK_RC_TOKEN_TEXT)
1533 return GTK_RC_TOKEN_TEXT;
1535 token = gtk_rc_parse_state (scanner, &state);
1536 if (token != G_TOKEN_NONE)
1539 token = g_scanner_get_next_token (scanner);
1540 if (token != G_TOKEN_EQUAL_SIGN)
1541 return G_TOKEN_EQUAL_SIGN;
1543 style->color_flags[state] |= GTK_RC_TEXT;
1544 return gtk_rc_parse_color (scanner, &style->text[state]);
1548 gtk_rc_parse_bg_pixmap (GScanner *scanner,
1549 GtkRcStyle *rc_style)
1555 token = g_scanner_get_next_token (scanner);
1556 if (token != GTK_RC_TOKEN_BG_PIXMAP)
1557 return GTK_RC_TOKEN_BG_PIXMAP;
1559 token = gtk_rc_parse_state (scanner, &state);
1560 if (token != G_TOKEN_NONE)
1563 token = g_scanner_get_next_token (scanner);
1564 if (token != G_TOKEN_EQUAL_SIGN)
1565 return G_TOKEN_EQUAL_SIGN;
1567 token = g_scanner_get_next_token (scanner);
1568 if (token != G_TOKEN_STRING)
1569 return G_TOKEN_STRING;
1571 if ((strcmp (scanner->value.v_string, "<parent>") == 0) ||
1572 (strcmp (scanner->value.v_string, "<none>") == 0))
1573 pixmap_file = g_strdup (scanner->value.v_string);
1575 pixmap_file = gtk_rc_find_pixmap_in_path (scanner, scanner->value.v_string);
1579 if (rc_style->bg_pixmap_name[state])
1580 g_free (rc_style->bg_pixmap_name[state]);
1581 rc_style->bg_pixmap_name[state] = pixmap_file;
1584 return G_TOKEN_NONE;
1588 gtk_rc_find_pixmap_in_path (GScanner *scanner,
1589 const gchar *pixmap_file)
1595 for (i = 0; (i < GTK_RC_MAX_PIXMAP_PATHS) && (pixmap_path[i] != NULL); i++)
1597 buf = g_strdup_printf ("%s" G_DIR_SEPARATOR_S "%s",
1598 pixmap_path[i], pixmap_file);
1600 fd = open (buf, O_RDONLY);
1611 g_warning (_("Unable to locate image file in pixmap_path: \"%s\" line %d"),
1612 pixmap_file, scanner->line);
1614 g_warning (_("Unable to locate image file in pixmap_path: \"%s\""),
1621 gtk_rc_find_module_in_path (const gchar *module_file)
1627 for (i = 0; (i < GTK_RC_MAX_MODULE_PATHS) && (module_path[i] != NULL); i++)
1629 buf = g_strdup_printf ("%s" G_DIR_SEPARATOR_S "%s",
1630 module_path[i], module_file);
1632 fd = open (buf, O_RDONLY);
1646 gtk_rc_parse_font (GScanner *scanner,
1647 GtkRcStyle *rc_style)
1651 token = g_scanner_get_next_token (scanner);
1652 if (token != GTK_RC_TOKEN_FONT)
1653 return GTK_RC_TOKEN_FONT;
1655 token = g_scanner_get_next_token (scanner);
1656 if (token != G_TOKEN_EQUAL_SIGN)
1657 return G_TOKEN_EQUAL_SIGN;
1659 token = g_scanner_get_next_token (scanner);
1660 if (token != G_TOKEN_STRING)
1661 return G_TOKEN_STRING;
1663 if (rc_style->font_name)
1664 g_free (rc_style->font_name);
1665 rc_style->font_name = g_strdup (scanner->value.v_string);
1667 return G_TOKEN_NONE;
1671 gtk_rc_parse_fontset (GScanner *scanner,
1672 GtkRcStyle *rc_style)
1676 token = g_scanner_get_next_token (scanner);
1677 if (token != GTK_RC_TOKEN_FONTSET)
1678 return GTK_RC_TOKEN_FONTSET;
1680 token = g_scanner_get_next_token (scanner);
1681 if (token != G_TOKEN_EQUAL_SIGN)
1682 return G_TOKEN_EQUAL_SIGN;
1684 token = g_scanner_get_next_token (scanner);
1685 if (token != G_TOKEN_STRING)
1686 return G_TOKEN_STRING;
1688 if (rc_style->fontset_name)
1689 g_free (rc_style->fontset_name);
1690 rc_style->fontset_name = g_strdup (scanner->value.v_string);
1692 return G_TOKEN_NONE;
1696 gtk_rc_parse_engine (GScanner *scanner,
1697 GtkRcStyle *rc_style)
1701 token = g_scanner_get_next_token (scanner);
1702 if (token != GTK_RC_TOKEN_ENGINE)
1703 return GTK_RC_TOKEN_ENGINE;
1705 token = g_scanner_get_next_token (scanner);
1706 if (token != G_TOKEN_STRING)
1707 return G_TOKEN_STRING;
1709 rc_style->engine = gtk_theme_engine_get (scanner->value.v_string);
1711 token = g_scanner_get_next_token (scanner);
1712 if (token != G_TOKEN_LEFT_CURLY)
1713 return G_TOKEN_LEFT_CURLY;
1715 if (rc_style->engine)
1716 return rc_style->engine->parse_rc_style (scanner, rc_style);
1719 /* Skip over remainder, looking for nested {}'s */
1722 while ((token = g_scanner_get_next_token (scanner)) != G_TOKEN_EOF)
1724 if (token == G_TOKEN_LEFT_CURLY)
1726 else if (token == G_TOKEN_RIGHT_CURLY)
1730 return G_TOKEN_NONE;
1733 return G_TOKEN_RIGHT_CURLY;
1738 gtk_rc_parse_state (GScanner *scanner,
1739 GtkStateType *state)
1744 g_return_val_if_fail (scanner != NULL, G_TOKEN_ERROR);
1745 g_return_val_if_fail (state != NULL, G_TOKEN_ERROR);
1747 /* we don't know where we got called from, so we reset the scope here.
1748 * if we bail out due to errors, we *don't* reset the scope, so the
1749 * error messaging code can make sense of our tokens.
1751 old_scope = g_scanner_set_scope (scanner, 0);
1753 token = g_scanner_get_next_token (scanner);
1754 if (token != G_TOKEN_LEFT_BRACE)
1755 return G_TOKEN_LEFT_BRACE;
1757 token = g_scanner_get_next_token (scanner);
1760 case GTK_RC_TOKEN_ACTIVE:
1761 *state = GTK_STATE_ACTIVE;
1763 case GTK_RC_TOKEN_INSENSITIVE:
1764 *state = GTK_STATE_INSENSITIVE;
1766 case GTK_RC_TOKEN_NORMAL:
1767 *state = GTK_STATE_NORMAL;
1769 case GTK_RC_TOKEN_PRELIGHT:
1770 *state = GTK_STATE_PRELIGHT;
1772 case GTK_RC_TOKEN_SELECTED:
1773 *state = GTK_STATE_SELECTED;
1776 return /* G_TOKEN_SYMBOL */ GTK_RC_TOKEN_NORMAL;
1779 token = g_scanner_get_next_token (scanner);
1780 if (token != G_TOKEN_RIGHT_BRACE)
1781 return G_TOKEN_RIGHT_BRACE;
1783 g_scanner_set_scope (scanner, old_scope);
1785 return G_TOKEN_NONE;
1789 gtk_rc_parse_priority (GScanner *scanner,
1790 GtkPathPriorityType *priority)
1795 g_return_val_if_fail (scanner != NULL, G_TOKEN_ERROR);
1796 g_return_val_if_fail (priority != NULL, G_TOKEN_ERROR);
1798 /* we don't know where we got called from, so we reset the scope here.
1799 * if we bail out due to errors, we *don't* reset the scope, so the
1800 * error messaging code can make sense of our tokens.
1802 old_scope = g_scanner_set_scope (scanner, 0);
1804 token = g_scanner_get_next_token (scanner);
1808 token = g_scanner_get_next_token (scanner);
1811 case GTK_RC_TOKEN_LOWEST:
1812 *priority = GTK_PATH_PRIO_LOWEST;
1814 case GTK_RC_TOKEN_GTK:
1815 *priority = GTK_PATH_PRIO_GTK;
1817 case GTK_RC_TOKEN_APPLICATION:
1818 *priority = GTK_PATH_PRIO_APPLICATION;
1820 case GTK_RC_TOKEN_RC:
1821 *priority = GTK_PATH_PRIO_RC;
1823 case GTK_RC_TOKEN_HIGHEST:
1824 *priority = GTK_PATH_PRIO_HIGHEST;
1827 return /* G_TOKEN_SYMBOL */ GTK_RC_TOKEN_APPLICATION;
1830 g_scanner_set_scope (scanner, old_scope);
1832 return G_TOKEN_NONE;
1836 gtk_rc_parse_color (GScanner *scanner,
1841 g_return_val_if_fail (scanner != NULL, G_TOKEN_ERROR);
1843 /* we don't need to set our own scop here, because
1844 * we don't need own symbols
1847 token = g_scanner_get_next_token (scanner);
1856 case G_TOKEN_LEFT_CURLY:
1857 token = g_scanner_get_next_token (scanner);
1858 if (token == G_TOKEN_INT)
1859 token_int = scanner->value.v_int;
1860 else if (token == G_TOKEN_FLOAT)
1861 token_int = scanner->value.v_float * 65535.0;
1863 return G_TOKEN_FLOAT;
1864 color->red = CLAMP (token_int, 0, 65535);
1866 token = g_scanner_get_next_token (scanner);
1867 if (token != G_TOKEN_COMMA)
1868 return G_TOKEN_COMMA;
1870 token = g_scanner_get_next_token (scanner);
1871 if (token == G_TOKEN_INT)
1872 token_int = scanner->value.v_int;
1873 else if (token == G_TOKEN_FLOAT)
1874 token_int = scanner->value.v_float * 65535.0;
1876 return G_TOKEN_FLOAT;
1877 color->green = CLAMP (token_int, 0, 65535);
1879 token = g_scanner_get_next_token (scanner);
1880 if (token != G_TOKEN_COMMA)
1881 return G_TOKEN_COMMA;
1883 token = g_scanner_get_next_token (scanner);
1884 if (token == G_TOKEN_INT)
1885 token_int = scanner->value.v_int;
1886 else if (token == G_TOKEN_FLOAT)
1887 token_int = scanner->value.v_float * 65535.0;
1889 return G_TOKEN_FLOAT;
1890 color->blue = CLAMP (token_int, 0, 65535);
1892 token = g_scanner_get_next_token (scanner);
1893 if (token != G_TOKEN_RIGHT_CURLY)
1894 return G_TOKEN_RIGHT_CURLY;
1895 return G_TOKEN_NONE;
1897 case G_TOKEN_STRING:
1898 if (scanner->value.v_string[0] != '#')
1899 return G_TOKEN_STRING;
1901 length = strlen (scanner->value.v_string) - 1;
1902 if (((length % 3) != 0) || (length > 12))
1903 return G_TOKEN_STRING;
1906 for (i = 0, j = 1; i < length; i++, j++)
1907 buf[i] = scanner->value.v_string[j];
1910 sscanf (buf, "%x", &temp);
1913 for (i = 0; i < length; i++, j++)
1914 buf[i] = scanner->value.v_string[j];
1917 sscanf (buf, "%x", &temp);
1918 color->green = temp;
1920 for (i = 0; i < length; i++, j++)
1921 buf[i] = scanner->value.v_string[j];
1924 sscanf (buf, "%x", &temp);
1930 color->green *= 4369;
1931 color->blue *= 4369;
1933 else if (length == 2)
1936 color->green *= 257;
1939 else if (length == 3)
1945 return G_TOKEN_NONE;
1948 return G_TOKEN_STRING;
1953 gtk_rc_parse_pixmap_path (GScanner *scanner)
1957 token = g_scanner_get_next_token (scanner);
1958 if (token != GTK_RC_TOKEN_PIXMAP_PATH)
1959 return GTK_RC_TOKEN_PIXMAP_PATH;
1961 token = g_scanner_get_next_token (scanner);
1962 if (token != G_TOKEN_STRING)
1963 return G_TOKEN_STRING;
1965 gtk_rc_parse_pixmap_path_string (scanner->value.v_string);
1967 return G_TOKEN_NONE;
1971 gtk_rc_parse_pixmap_path_string (gchar *pix_path)
1975 gint start_offset = 0;
1979 /* free the old one, or just add to the old one ? */
1980 for (path_num=0; pixmap_path[path_num]; path_num++)
1982 g_free (pixmap_path[path_num]);
1983 pixmap_path[path_num] = NULL;
1988 path_len = strlen (pix_path);
1990 buf = g_strdup (pix_path);
1992 for (end_offset = 0; end_offset <= path_len; end_offset++)
1994 if ((buf[end_offset] == G_SEARCHPATH_SEPARATOR) ||
1995 (end_offset == path_len))
1997 buf[end_offset] = '\0';
1998 pixmap_path[path_num] = g_strdup (buf + start_offset);
2000 pixmap_path[path_num] = NULL;
2001 start_offset = end_offset + 1;
2005 gtk_rc_append_default_pixmap_path();
2009 gtk_rc_parse_module_path (GScanner *scanner)
2013 token = g_scanner_get_next_token (scanner);
2014 if (token != GTK_RC_TOKEN_MODULE_PATH)
2015 return GTK_RC_TOKEN_MODULE_PATH;
2017 token = g_scanner_get_next_token (scanner);
2018 if (token != G_TOKEN_STRING)
2019 return G_TOKEN_STRING;
2021 gtk_rc_parse_module_path_string (scanner->value.v_string);
2023 return G_TOKEN_NONE;
2027 gtk_rc_parse_module_path_string (gchar *mod_path)
2031 gint start_offset = 0;
2035 /* free the old one, or just add to the old one ? */
2036 for (path_num=0; module_path[path_num]; path_num++)
2038 g_free (module_path[path_num]);
2039 module_path[path_num] = NULL;
2044 path_len = strlen (mod_path);
2046 buf = g_strdup (mod_path);
2048 for (end_offset = 0; end_offset <= path_len; end_offset++)
2050 if ((buf[end_offset] == G_SEARCHPATH_SEPARATOR) ||
2051 (end_offset == path_len))
2053 buf[end_offset] = '\0';
2054 module_path[path_num] = g_strdup (buf + start_offset);
2056 module_path[path_num] = NULL;
2057 start_offset = end_offset + 1;
2061 gtk_rc_append_default_module_path();
2065 gtk_rc_parse_path_pattern (GScanner *scanner)
2068 GtkPathType path_type;
2070 gboolean is_binding;
2071 GtkPathPriorityType priority = GTK_PATH_PRIO_RC;
2073 token = g_scanner_get_next_token (scanner);
2076 case GTK_RC_TOKEN_WIDGET:
2077 path_type = GTK_PATH_WIDGET;
2079 case GTK_RC_TOKEN_WIDGET_CLASS:
2080 path_type = GTK_PATH_WIDGET_CLASS;
2082 case GTK_RC_TOKEN_CLASS:
2083 path_type = GTK_PATH_CLASS;
2086 return GTK_RC_TOKEN_WIDGET_CLASS;
2089 token = g_scanner_get_next_token (scanner);
2090 if (token != G_TOKEN_STRING)
2091 return G_TOKEN_STRING;
2093 pattern = g_strdup (scanner->value.v_string);
2095 token = g_scanner_get_next_token (scanner);
2096 if (token == GTK_RC_TOKEN_STYLE)
2098 else if (token == GTK_RC_TOKEN_BINDING)
2101 if (g_scanner_peek_next_token (scanner) == ':')
2103 token = gtk_rc_parse_priority (scanner, &priority);
2104 if (token != G_TOKEN_NONE)
2114 return GTK_RC_TOKEN_STYLE;
2117 token = g_scanner_get_next_token (scanner);
2118 if (token != G_TOKEN_STRING)
2121 return G_TOKEN_STRING;
2126 GtkBindingSet *binding;
2128 binding = gtk_binding_set_find (scanner->value.v_string);
2132 return G_TOKEN_STRING;
2134 gtk_binding_set_add_path (binding, path_type, pattern, priority);
2138 GtkRcStyle *rc_style;
2141 rc_style = gtk_rc_style_find (scanner->value.v_string);
2146 return G_TOKEN_STRING;
2149 rc_set = g_new (GtkRcSet, 1);
2150 gtk_pattern_spec_init (&rc_set->pspec, pattern);
2151 rc_set->rc_style = rc_style;
2153 if (path_type == GTK_PATH_WIDGET)
2154 gtk_rc_sets_widget = g_slist_prepend (gtk_rc_sets_widget, rc_set);
2155 else if (path_type == GTK_PATH_WIDGET_CLASS)
2156 gtk_rc_sets_widget_class = g_slist_prepend (gtk_rc_sets_widget_class, rc_set);
2158 gtk_rc_sets_class = g_slist_prepend (gtk_rc_sets_class, rc_set);
2162 return G_TOKEN_NONE;
2166 typedef GdkPixmap * (*GtkImageLoader) (GdkWindow *window,
2167 GdkColormap *colormap,
2169 GdkColor *transparent_color,
2170 const gchar *filename);
2174 gtk_rc_set_image_loader(GtkImageLoader loader)
2176 image_loader = loader;
2180 gtk_rc_load_image (GdkColormap *colormap,
2181 GdkColor *transparent_color,
2182 const gchar *filename)
2184 if (strcmp (filename, "<parent>") == 0)
2185 return (GdkPixmap*) GDK_PARENT_RELATIVE;
2189 return image_loader(NULL, colormap, NULL,
2193 return gdk_pixmap_colormap_create_from_xpm (NULL, colormap, NULL,