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/.
30 #include "gdkconfig.h"
32 #ifdef GDK_WINDOWING_X11
33 #include <X11/Xlocale.h> /* so we get the right setlocale */
42 #ifdef HAVE_SYS_PARAM_H
43 #include <sys/param.h>
55 #include <windows.h> /* For GetWindowsDirectory */
60 #include "gtkbindings.h"
61 #include "gtkthemes.h"
64 typedef struct _GtkRcSet GtkRcSet;
65 typedef struct _GtkRcNode GtkRcNode;
66 typedef struct _GtkRcFile GtkRcFile;
78 gchar *canonical_name;
82 static guint gtk_rc_style_hash (const char *name);
83 static gint gtk_rc_style_compare (const char *a,
85 static guint gtk_rc_styles_hash (const GSList *rc_styles);
86 static gint gtk_rc_styles_compare (const GSList *a,
88 static GtkRcStyle* gtk_rc_style_find (const char *name);
89 static GSList * gtk_rc_styles_match (GSList *rc_styles,
93 gchar *path_reversed);
94 static GtkStyle * gtk_rc_style_to_style (GtkRcStyle *rc_style);
95 static GtkStyle* gtk_rc_init_style (GSList *rc_styles);
96 static void gtk_rc_parse_file (const gchar *filename,
98 static void gtk_rc_parse_any (const gchar *input_name,
100 const gchar *input_string);
101 static guint gtk_rc_parse_statement (GScanner *scanner);
102 static guint gtk_rc_parse_style (GScanner *scanner);
103 static guint gtk_rc_parse_base (GScanner *scanner,
105 static guint gtk_rc_parse_bg (GScanner *scanner,
107 static guint gtk_rc_parse_fg (GScanner *scanner,
109 static guint gtk_rc_parse_text (GScanner *scanner,
111 static guint gtk_rc_parse_bg_pixmap (GScanner *scanner,
112 GtkRcStyle *rc_style);
113 static guint gtk_rc_parse_font (GScanner *scanner,
114 GtkRcStyle *rc_style);
115 static guint gtk_rc_parse_fontset (GScanner *scanner,
116 GtkRcStyle *rc_style);
117 static guint gtk_rc_parse_font_name (GScanner *scanner,
118 GtkRcStyle *rc_style);
119 static guint gtk_rc_parse_engine (GScanner *scanner,
120 GtkRcStyle *rc_style);
121 static guint gtk_rc_parse_pixmap_path (GScanner *scanner);
122 static void gtk_rc_parse_pixmap_path_string (gchar *pix_path);
123 static guint gtk_rc_parse_module_path (GScanner *scanner);
124 static void gtk_rc_parse_module_path_string (gchar *mod_path);
125 static guint gtk_rc_parse_path_pattern (GScanner *scanner);
126 static void gtk_rc_clear_hash_node (gpointer key,
129 static void gtk_rc_clear_styles (void);
130 static void gtk_rc_append_default_pixmap_path (void);
131 static void gtk_rc_append_default_module_path (void);
132 static void gtk_rc_add_initial_default_files (void);
134 static void gtk_rc_style_init (GtkRcStyle *style);
135 static void gtk_rc_style_class_init (GtkRcStyleClass *klass);
136 static void gtk_rc_style_finalize (GObject *object);
138 static gpointer parent_class = NULL;
140 static const GScannerConfig gtk_rc_scanner_config =
144 ) /* cset_skip_characters */,
149 ) /* cset_identifier_first */,
154 ) /* cset_identifier_nth */,
155 ( "#\n" ) /* cpair_comment_single */,
157 TRUE /* case_sensitive */,
159 TRUE /* skip_comment_multi */,
160 TRUE /* skip_comment_single */,
161 TRUE /* scan_comment_multi */,
162 TRUE /* scan_identifier */,
163 FALSE /* scan_identifier_1char */,
164 FALSE /* scan_identifier_NULL */,
165 TRUE /* scan_symbols */,
166 TRUE /* scan_binary */,
167 TRUE /* scan_octal */,
168 TRUE /* scan_float */,
170 TRUE /* scan_hex_dollar */,
171 TRUE /* scan_string_sq */,
172 TRUE /* scan_string_dq */,
173 TRUE /* numbers_2_int */,
174 FALSE /* int_2_float */,
175 FALSE /* identifier_2_string */,
176 TRUE /* char_2_token */,
177 TRUE /* symbol_2_token */,
178 FALSE /* scope_0_fallback */,
186 { "include", GTK_RC_TOKEN_INCLUDE },
187 { "NORMAL", GTK_RC_TOKEN_NORMAL },
188 { "ACTIVE", GTK_RC_TOKEN_ACTIVE },
189 { "PRELIGHT", GTK_RC_TOKEN_PRELIGHT },
190 { "SELECTED", GTK_RC_TOKEN_SELECTED },
191 { "INSENSITIVE", GTK_RC_TOKEN_INSENSITIVE },
192 { "fg", GTK_RC_TOKEN_FG },
193 { "bg", GTK_RC_TOKEN_BG },
194 { "base", GTK_RC_TOKEN_BASE },
195 { "text", GTK_RC_TOKEN_TEXT },
196 { "font", GTK_RC_TOKEN_FONT },
197 { "fontset", GTK_RC_TOKEN_FONTSET },
198 { "font_name", GTK_RC_TOKEN_FONT_NAME },
199 { "bg_pixmap", GTK_RC_TOKEN_BG_PIXMAP },
200 { "pixmap_path", GTK_RC_TOKEN_PIXMAP_PATH },
201 { "style", GTK_RC_TOKEN_STYLE },
202 { "binding", GTK_RC_TOKEN_BINDING },
203 { "bind", GTK_RC_TOKEN_BIND },
204 { "widget", GTK_RC_TOKEN_WIDGET },
205 { "widget_class", GTK_RC_TOKEN_WIDGET_CLASS },
206 { "class", GTK_RC_TOKEN_CLASS },
207 { "lowest", GTK_RC_TOKEN_LOWEST },
208 { "gtk", GTK_RC_TOKEN_GTK },
209 { "application", GTK_RC_TOKEN_APPLICATION },
210 { "rc", GTK_RC_TOKEN_RC },
211 { "highest", GTK_RC_TOKEN_HIGHEST },
212 { "engine", GTK_RC_TOKEN_ENGINE },
213 { "module_path", GTK_RC_TOKEN_MODULE_PATH },
216 static const guint n_symbols = sizeof (symbols) / sizeof (symbols[0]);
218 static GHashTable *rc_style_ht = NULL;
219 static GHashTable *realized_style_ht = NULL;
220 static GSList *gtk_rc_sets_widget = NULL;
221 static GSList *gtk_rc_sets_widget_class = NULL;
222 static GSList *gtk_rc_sets_class = NULL;
224 #define GTK_RC_MAX_DEFAULT_FILES 128
225 static gchar *gtk_rc_default_files[GTK_RC_MAX_DEFAULT_FILES];
226 static gboolean gtk_rc_auto_parse = TRUE;
228 #define GTK_RC_MAX_PIXMAP_PATHS 128
229 static gchar *pixmap_path[GTK_RC_MAX_PIXMAP_PATHS];
230 #define GTK_RC_MAX_MODULE_PATHS 128
231 static gchar *module_path[GTK_RC_MAX_MODULE_PATHS];
233 /* A stack of directories for RC files we are parsing currently.
234 * these are implicitely added to the end of PIXMAP_PATHS
236 GSList *rc_dir_stack = NULL;
238 /* The files we have parsed, to reread later if necessary */
239 GSList *rc_files = NULL;
241 static GtkImageLoader image_loader = NULL;
243 /* RC file handling */
249 get_gtk_sysconf_directory (void)
251 static gboolean been_here = FALSE;
252 static gchar gtk_sysconf_dir[200];
256 DWORD nbytes = sizeof (gtk_sysconf_dir);
259 return gtk_sysconf_dir;
263 if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, "Software\\GNU\\GTk+", 0,
264 KEY_QUERY_VALUE, ®_key) != ERROR_SUCCESS
265 || RegQueryValueEx (reg_key, "InstallationDirectory", 0,
266 &type, gtk_sysconf_dir, &nbytes) != ERROR_SUCCESS
269 /* Uh oh. Use the old hard-coded %WinDir%\GTk+ value */
270 GetWindowsDirectory (win_dir, sizeof (win_dir));
271 sprintf (gtk_sysconf_dir, "%s\\gtk+", win_dir);
275 RegCloseKey (reg_key);
277 return gtk_sysconf_dir;
281 get_themes_directory (void)
283 static gchar themes_dir[200];
285 sprintf (themes_dir, "%s\\themes", get_gtk_sysconf_directory ());
292 gtk_rc_get_theme_dir(void)
297 var = getenv("GTK_DATA_PREFIX");
299 path = g_strdup_printf("%s%s", var, "/share/themes");
301 path = g_strdup_printf("%s%s", GTK_DATA_PREFIX, "/share/themes");
303 path = g_strdup (get_themes_directory ());
310 gtk_rc_get_module_dir(void)
315 var = getenv("GTK_EXE_PREFIX");
317 path = g_strdup_printf("%s%s", var, "/lib/gtk/themes/engines");
319 path = g_strdup_printf("%s%s", GTK_EXE_PREFIX, "/lib/gtk/themes/engines");
321 path = g_strdup_printf ("%s%s", get_themes_directory (), "\\engines");
328 gtk_rc_append_default_pixmap_path(void)
334 var = getenv("GTK_DATA_PREFIX");
336 path = g_strdup_printf("%s%s", var, "/share/gtk/themes");
338 path = g_strdup_printf("%s%s", GTK_DATA_PREFIX, "/share/gtk/themes");
340 path = g_strdup (get_themes_directory ());
343 for (n = 0; pixmap_path[n]; n++) ;
344 if (n >= GTK_RC_MAX_PIXMAP_PATHS - 1)
349 pixmap_path[n++] = path;
350 pixmap_path[n] = NULL;
354 gtk_rc_append_default_module_path(void)
359 for (n = 0; module_path[n]; n++) ;
360 if (n >= GTK_RC_MAX_MODULE_PATHS - 1)
364 var = getenv("GTK_EXE_PREFIX");
366 path = g_strdup_printf("%s%s", var, "/lib/gtk/themes/engines");
368 path = g_strdup_printf("%s%s", GTK_EXE_PREFIX, "/lib/gtk/themes/engines");
370 path = g_strdup_printf ("%s%s", get_themes_directory (), "\\engines");
372 module_path[n++] = path;
374 var = g_get_home_dir ();
378 path = g_strdup_printf ("%s%s", var, "/.gtk/lib/themes/engines");
380 path = g_strdup_printf ("%s%s", var, "\\_gtk\\themes\\engines");
382 module_path[n++] = path;
384 module_path[n] = NULL;
388 gtk_rc_add_initial_default_files (void)
390 static gint init = FALSE;
398 gtk_rc_default_files[0] = NULL;
401 var = g_getenv("GTK_RC_FILES");
404 files = g_strsplit (var, G_SEARCHPATH_SEPARATOR_S, 128);
408 gtk_rc_add_default_file (files[i]);
416 str = g_strdup (GTK_SYSCONFDIR G_DIR_SEPARATOR_S "gtk" G_DIR_SEPARATOR_S "gtkrc");
418 str = g_strdup_printf ("%s\\gtkrc", get_gtk_sysconf_directory ());
420 gtk_rc_add_default_file (str);
423 var = g_get_home_dir ();
426 str = g_strdup_printf ("%s" G_DIR_SEPARATOR_S ".gtkrc", var);
427 gtk_rc_add_default_file (str);
434 gtk_rc_add_default_file (const gchar *file)
438 gtk_rc_add_initial_default_files ();
440 for (n = 0; gtk_rc_default_files[n]; n++) ;
441 if (n >= GTK_RC_MAX_DEFAULT_FILES - 1)
444 gtk_rc_default_files[n++] = g_strdup (file);
445 gtk_rc_default_files[n] = NULL;
449 gtk_rc_set_default_files (gchar **files)
453 gtk_rc_add_initial_default_files ();
456 while (gtk_rc_default_files[i])
458 g_free (gtk_rc_default_files[i]);
462 gtk_rc_default_files[0] = NULL;
463 gtk_rc_auto_parse = FALSE;
466 while (files[i] != NULL)
468 gtk_rc_add_default_file (files[i]);
474 gtk_rc_get_default_files (void)
476 gtk_rc_add_initial_default_files ();
478 return gtk_rc_default_files;
481 /* The following routine is based on _nl_normalize_codeset from
482 * the GNU C library. Contributed by
484 * Contributed by Ulrich Drepper <drepper@gnu.ai.mit.edu>, 1995.
485 * Copyright (C) 1995, 1996, 1997, 1998, 1999 Free Software Foundation, Inc.
487 * Normalize codeset name. There is no standard for the codeset
488 * names. Normalization allows the user to use any of the common
492 _gtk_normalize_codeset (const char *codeset, int name_len)
500 for (cnt = 0; cnt < name_len; ++cnt)
501 if (isalnum (codeset[cnt]))
505 if (isalpha (codeset[cnt]))
509 retval = g_malloc ((only_digit ? 3 : 0) + len + 1);
513 strcpy (retval, "iso");
519 for (cnt = 0; cnt < name_len; ++cnt)
520 if (isalpha (codeset[cnt]))
521 *wp++ = isupper(codeset[cnt]) ? tolower (codeset[cnt]) : codeset[cnt];
522 else if (isdigit (codeset[cnt]))
523 *wp++ = codeset[cnt];
533 static gchar *locale_suffixes[3];
534 static gint n_locale_suffixes = 0;
538 static gboolean initted = FALSE;
547 locale = g_win32_getlocale ();
549 locale = setlocale (LC_CTYPE, NULL);
554 pixmap_path[0] = NULL;
555 module_path[0] = NULL;
556 gtk_rc_append_default_pixmap_path();
557 gtk_rc_append_default_module_path();
559 gtk_rc_add_initial_default_files ();
561 if (strcmp (locale, "C") && strcmp (locale, "POSIX"))
563 /* Determine locale-specific suffixes for RC files
565 * We normalize the charset into a standard form,
566 * which has all '-' and '_' characters removed,
569 gchar *normalized_locale;
571 p = strchr (locale, '@');
572 length = p ? (p -locale) : strlen (locale);
574 p = strchr (locale, '.');
577 gchar *tmp1 = g_strndup (locale, p - locale + 1);
578 gchar *tmp2 = _gtk_normalize_codeset (p + 1, length - (p - locale + 1));
580 normalized_locale = g_strconcat (tmp1, tmp2, NULL);
584 locale_suffixes[n_locale_suffixes++] = g_strdup (normalized_locale);
588 normalized_locale = g_strndup (locale, length);
590 p = strchr (normalized_locale, '_');
593 locale_suffixes[n_locale_suffixes++] = g_strndup (normalized_locale, length);
594 length = p - normalized_locale;
597 locale_suffixes[n_locale_suffixes++] = g_strndup (normalized_locale, length);
599 g_free (normalized_locale);
604 while (gtk_rc_default_files[i] != NULL)
606 /* Try to find a locale specific RC file corresponding to
607 * to parse before the default file.
609 for (j=n_locale_suffixes-1; j>=0; j--)
611 gchar *name = g_strconcat (gtk_rc_default_files[i],
619 gtk_rc_parse (gtk_rc_default_files[i]);
625 gtk_rc_parse_string (const gchar *rc_string)
627 g_return_if_fail (rc_string != NULL);
629 gtk_rc_parse_any ("-", -1, rc_string);
633 gtk_rc_parse_file (const gchar *filename, gboolean reload)
635 GtkRcFile *rc_file = NULL;
639 g_return_if_fail (filename != NULL);
644 rc_file = tmp_list->data;
645 if (!strcmp (rc_file->name, filename))
648 tmp_list = tmp_list->next;
653 rc_file = g_new (GtkRcFile, 1);
654 rc_file->name = g_strdup (filename);
655 rc_file->canonical_name = NULL;
657 rc_file->reload = reload;
659 rc_files = g_slist_append (rc_files, rc_file);
662 if (!rc_file->canonical_name)
664 /* Get the absolute pathname */
666 if (g_path_is_absolute (rc_file->name))
667 rc_file->canonical_name = rc_file->name;
673 cwd = g_get_current_dir ();
675 str = g_string_new (cwd);
677 g_string_append_c (str, G_DIR_SEPARATOR);
678 g_string_append (str, rc_file->name);
680 rc_file->canonical_name = str->str;
681 g_string_free (str, FALSE);
685 if (!lstat (rc_file->canonical_name, &statbuf))
690 rc_file->mtime = statbuf.st_mtime;
692 fd = open (rc_file->canonical_name, O_RDONLY);
696 /* Temporarily push directory name for this file on
697 * a stack of directory names while parsing it
699 rc_dir_stack = g_slist_prepend (rc_dir_stack,
700 g_dirname (rc_file->canonical_name));
701 gtk_rc_parse_any (filename, fd, NULL);
703 tmp_list = rc_dir_stack;
704 rc_dir_stack = rc_dir_stack->next;
706 g_free (tmp_list->data);
707 g_slist_free_1 (tmp_list);
714 gtk_rc_parse (const gchar *filename)
716 g_return_if_fail (filename != NULL);
718 gtk_rc_parse_file (filename, TRUE);
721 /* Handling of RC styles */
724 gtk_rc_style_get_type (void)
726 static GType object_type = 0;
730 static const GTypeInfo object_info =
732 sizeof (GtkRcStyleClass),
733 (GBaseInitFunc) NULL,
734 (GBaseFinalizeFunc) NULL,
735 (GClassInitFunc) gtk_rc_style_class_init,
736 NULL, /* class_finalize */
737 NULL, /* class_data */
740 (GInstanceInitFunc) gtk_rc_style_init,
743 object_type = g_type_register_static (G_TYPE_OBJECT,
752 gtk_rc_style_init (GtkRcStyle *style)
758 gtk_rc_style_class_init (GtkRcStyleClass *klass)
760 GObjectClass *object_class = G_OBJECT_CLASS (klass);
762 parent_class = g_type_class_peek_parent (klass);
764 object_class->finalize = gtk_rc_style_finalize;
767 /* Like g_slist_remove, but remove all copies of data */
769 gtk_rc_slist_remove_all (GSList *list,
780 if (tmp->data == data)
786 prev->next = tmp->next;
788 g_slist_free_1 (tmp);
806 gtk_rc_style_finalize (GObject *object)
809 GSList *tmp_list1, *tmp_list2;
810 GtkRcStyle *rc_style;
812 rc_style = GTK_RC_STYLE (object);
814 if (rc_style->engine)
816 rc_style->engine->destroy_rc_style (rc_style);
817 gtk_theme_engine_unref (rc_style->engine);
821 g_free (rc_style->name);
822 if (rc_style->font_desc)
823 pango_font_description_free (rc_style->font_desc);
825 for (i=0 ; i<5 ; i++)
826 if (rc_style->bg_pixmap_name[i])
827 g_free (rc_style->bg_pixmap_name[i]);
829 /* Now remove all references to this rc_style from
832 tmp_list1 = rc_style->rc_style_lists;
835 GSList *rc_styles = tmp_list1->data;
836 GtkStyle *style = g_hash_table_lookup (realized_style_ht, rc_styles);
837 gtk_style_unref (style);
839 /* Remove the list of styles from the other rc_styles
842 tmp_list2 = rc_styles;
845 GtkRcStyle *other_style = tmp_list2->data;
847 if (other_style != rc_style)
848 other_style->rc_style_lists =
849 gtk_rc_slist_remove_all (other_style->rc_style_lists, rc_styles);
851 tmp_list2 = tmp_list2->next;
854 /* And from the hash table itself
856 g_hash_table_remove (realized_style_ht, rc_styles);
857 g_slist_free (rc_styles);
859 tmp_list1 = tmp_list1->next;
861 g_slist_free (rc_style->rc_style_lists);
863 G_OBJECT_CLASS (parent_class)->finalize (object);
867 gtk_rc_style_new (void)
871 style = GTK_RC_STYLE (g_type_create_instance (gtk_rc_style_get_type ()));
877 gtk_rc_style_ref (GtkRcStyle *rc_style)
879 g_return_if_fail (GTK_IS_RC_STYLE (rc_style));
881 g_object_ref (G_OBJECT (rc_style));
885 gtk_rc_style_unref (GtkRcStyle *rc_style)
887 g_return_if_fail (GTK_IS_RC_STYLE (rc_style));
889 g_object_unref (G_OBJECT (rc_style));
893 gtk_rc_clear_hash_node (gpointer key,
897 gtk_rc_style_unref (data);
901 gtk_rc_free_rc_sets (GSList *slist)
907 rc_set = slist->data;
908 gtk_pattern_spec_free_segs (&rc_set->pspec);
916 gtk_rc_clear_styles (void)
918 /* Clear out all old rc_styles */
922 g_hash_table_foreach (rc_style_ht, gtk_rc_clear_hash_node, NULL);
923 g_hash_table_destroy (rc_style_ht);
927 gtk_rc_free_rc_sets (gtk_rc_sets_widget);
928 g_slist_free (gtk_rc_sets_widget);
929 gtk_rc_sets_widget = NULL;
931 gtk_rc_free_rc_sets (gtk_rc_sets_widget_class);
932 g_slist_free (gtk_rc_sets_widget_class);
933 gtk_rc_sets_widget_class = NULL;
935 gtk_rc_free_rc_sets (gtk_rc_sets_class);
936 g_slist_free (gtk_rc_sets_class);
937 gtk_rc_sets_class = NULL;
941 gtk_rc_reparse_all (void)
944 gboolean mtime_modified = FALSE;
949 /* Check through and see if any of the RC's have had their
950 * mtime modified. If so, reparse everything.
955 rc_file = tmp_list->data;
957 if (!lstat (rc_file->name, &statbuf) &&
958 (statbuf.st_mtime > rc_file->mtime))
960 mtime_modified = TRUE;
964 tmp_list = tmp_list->next;
969 gtk_rc_clear_styles();
974 rc_file = tmp_list->data;
976 gtk_rc_parse_file (rc_file->name, FALSE);
978 tmp_list = tmp_list->next;
982 return mtime_modified;
986 gtk_rc_styles_match (GSList *rc_styles,
990 gchar *path_reversed)
1000 if (gtk_pattern_match (&rc_set->pspec, path_length, path, path_reversed))
1001 rc_styles = g_slist_append (rc_styles, rc_set->rc_style);
1008 gtk_rc_get_style (GtkWidget *widget)
1010 GtkRcStyle *widget_rc_style;
1011 GSList *rc_styles = NULL;
1013 static guint rc_style_key_id = 0;
1015 /* We allow the specification of a single rc style to be bound
1016 * tightly to a widget, for application modifications
1018 if (!rc_style_key_id)
1019 rc_style_key_id = g_quark_from_static_string ("gtk-rc-style");
1021 widget_rc_style = gtk_object_get_data_by_id (GTK_OBJECT (widget),
1024 if (widget_rc_style)
1025 rc_styles = g_slist_prepend (rc_styles, widget_rc_style);
1027 if (gtk_rc_sets_widget)
1029 gchar *path, *path_reversed;
1032 gtk_widget_path (widget, &path_length, &path, &path_reversed);
1033 rc_styles = gtk_rc_styles_match (rc_styles, gtk_rc_sets_widget, path_length, path, path_reversed);
1035 g_free (path_reversed);
1039 if (gtk_rc_sets_widget_class)
1041 gchar *path, *path_reversed;
1044 gtk_widget_class_path (widget, &path_length, &path, &path_reversed);
1045 rc_styles = gtk_rc_styles_match (rc_styles, gtk_rc_sets_widget_class, path_length, path, path_reversed);
1047 g_free (path_reversed);
1050 if (gtk_rc_sets_class)
1054 type = GTK_OBJECT_TYPE (widget);
1057 gchar *path, *path_reversed;
1060 path = gtk_type_name (type);
1061 path_length = strlen (path);
1062 path_reversed = g_strdup (path);
1063 g_strreverse (path_reversed);
1065 rc_styles = gtk_rc_styles_match (rc_styles, gtk_rc_sets_class, path_length, path, path_reversed);
1066 g_free (path_reversed);
1068 type = gtk_type_parent (type);
1073 return gtk_rc_init_style (rc_styles);
1079 gtk_rc_add_rc_sets (GSList *slist,
1080 GtkRcStyle *rc_style,
1081 const char *pattern)
1083 GtkRcStyle *new_style;
1087 new_style = gtk_rc_style_new ();
1088 *new_style = *rc_style;
1089 new_style->name = g_strdup (rc_style->name);
1090 if (rc_style->font_desc)
1091 new_style->font_desc = pango_font_description_copy (rc_style->font_desc);
1093 for (i = 0; i < 5; i++)
1094 new_style->bg_pixmap_name[i] = g_strdup (rc_style->bg_pixmap_name[i]);
1096 rc_set = g_new (GtkRcSet, 1);
1097 gtk_pattern_spec_init (&rc_set->pspec, pattern);
1098 rc_set->rc_style = rc_style;
1100 return g_slist_prepend (slist, rc_set);
1104 gtk_rc_add_widget_name_style (GtkRcStyle *rc_style,
1105 const gchar *pattern)
1107 g_return_if_fail (rc_style != NULL);
1108 g_return_if_fail (pattern != NULL);
1110 gtk_rc_sets_widget = gtk_rc_add_rc_sets (gtk_rc_sets_widget, rc_style, pattern);
1114 gtk_rc_add_widget_class_style (GtkRcStyle *rc_style,
1115 const gchar *pattern)
1117 g_return_if_fail (rc_style != NULL);
1118 g_return_if_fail (pattern != NULL);
1120 gtk_rc_sets_widget_class = gtk_rc_add_rc_sets (gtk_rc_sets_widget_class, rc_style, pattern);
1124 gtk_rc_add_class_style (GtkRcStyle *rc_style,
1125 const gchar *pattern)
1127 g_return_if_fail (rc_style != NULL);
1128 g_return_if_fail (pattern != NULL);
1130 gtk_rc_sets_class = gtk_rc_add_rc_sets (gtk_rc_sets_class, rc_style, pattern);
1134 gtk_rc_parse_any (const gchar *input_name,
1136 const gchar *input_string)
1142 scanner = g_scanner_new ((GScannerConfig *) >k_rc_scanner_config);
1146 g_assert (input_string == NULL);
1148 g_scanner_input_file (scanner, input_fd);
1152 g_assert (input_string != NULL);
1154 g_scanner_input_text (scanner, input_string, strlen (input_string));
1156 scanner->input_name = input_name;
1158 g_scanner_freeze_symbol_table (scanner);
1159 for (i = 0; i < n_symbols; i++)
1160 g_scanner_add_symbol (scanner, symbols[i].name, GINT_TO_POINTER (symbols[i].token));
1161 g_scanner_thaw_symbol_table (scanner);
1166 if (g_scanner_peek_next_token (scanner) == G_TOKEN_EOF)
1170 guint expected_token;
1172 expected_token = gtk_rc_parse_statement (scanner);
1174 if (expected_token != G_TOKEN_NONE)
1181 if (scanner->scope_id == 0)
1183 /* if we are in scope 0, we know the symbol names
1184 * that are associated with certaintoken values.
1185 * so we look them up to make the error messages
1188 if (expected_token > GTK_RC_TOKEN_INVALID &&
1189 expected_token < GTK_RC_TOKEN_LAST)
1191 for (i = 0; i < n_symbols; i++)
1192 if (symbols[i].token == expected_token)
1193 msg = symbols[i].name;
1195 msg = g_strconcat ("e.g. `", msg, "'", NULL);
1197 if (scanner->token > GTK_RC_TOKEN_INVALID &&
1198 scanner->token < GTK_RC_TOKEN_LAST)
1200 symbol_name = "???";
1201 for (i = 0; i < n_symbols; i++)
1202 if (symbols[i].token == scanner->token)
1203 symbol_name = symbols[i].name;
1206 g_scanner_unexp_token (scanner,
1219 g_scanner_destroy (scanner);
1223 gtk_rc_styles_hash (const GSList *rc_styles)
1230 result += (result << 9) + GPOINTER_TO_UINT (rc_styles->data);
1231 rc_styles = rc_styles->next;
1238 gtk_rc_styles_compare (const GSList *a,
1243 if (a->data != b->data)
1253 gtk_rc_style_hash (const char *name)
1259 result += (result << 3) + *name++;
1265 gtk_rc_style_compare (const char *a,
1268 return (strcmp (a, b) == 0);
1272 gtk_rc_style_find (const char *name)
1275 return g_hash_table_lookup (rc_style_ht, (gpointer) name);
1280 /* Assumes ownership of rc_style */
1282 gtk_rc_style_to_style (GtkRcStyle *rc_style)
1288 style = gtk_style_new ();
1290 style->rc_style = rc_style;
1292 if (rc_style->font_desc)
1294 pango_font_description_free (style->font_desc);
1295 style->font_desc = pango_font_description_copy (rc_style->font_desc);
1297 old_font = style->font;
1298 style->font = gdk_font_from_description (style->font_desc);
1300 gdk_font_unref (old_font);
1302 style->font = old_font;
1305 for (i = 0; i < 5; i++)
1307 if (rc_style->color_flags[i] & GTK_RC_FG)
1308 style->fg[i] = rc_style->fg[i];
1309 if (rc_style->color_flags[i] & GTK_RC_BG)
1310 style->bg[i] = rc_style->bg[i];
1311 if (rc_style->color_flags[i] & GTK_RC_TEXT)
1312 style->text[i] = rc_style->text[i];
1313 if (rc_style->color_flags[i] & GTK_RC_BASE)
1314 style->base[i] = rc_style->base[i];
1317 if (rc_style->engine)
1319 style->engine = rc_style->engine;
1320 gtk_theme_engine_ref (style->engine);
1321 rc_style->engine->rc_style_to_style (style, rc_style);
1327 /* Reuses or frees rc_styles */
1329 gtk_rc_init_style (GSList *rc_styles)
1333 GtkStyle *style = NULL;
1335 if (!realized_style_ht)
1336 realized_style_ht = g_hash_table_new ((GHashFunc)gtk_rc_styles_hash,
1337 (GCompareFunc)gtk_rc_styles_compare);
1339 style = g_hash_table_lookup (realized_style_ht, rc_styles);
1343 GtkRcStyle *proto_style;
1346 proto_style = gtk_rc_style_new ();
1348 tmp_styles = rc_styles;
1351 GtkRcStyle *rc_style = tmp_styles->data;
1355 if (!proto_style->bg_pixmap_name[i] && rc_style->bg_pixmap_name[i])
1356 proto_style->bg_pixmap_name[i] = g_strdup (rc_style->bg_pixmap_name[i]);
1358 if (!(proto_style->color_flags[i] & GTK_RC_FG) &&
1359 rc_style->color_flags[i] & GTK_RC_FG)
1361 proto_style->fg[i] = rc_style->fg[i];
1362 proto_style->color_flags[i] |= GTK_RC_FG;
1364 if (!(proto_style->color_flags[i] & GTK_RC_BG) &&
1365 rc_style->color_flags[i] & GTK_RC_BG)
1367 proto_style->bg[i] = rc_style->bg[i];
1368 proto_style->color_flags[i] |= GTK_RC_BG;
1370 if (!(proto_style->color_flags[i] & GTK_RC_TEXT) &&
1371 rc_style->color_flags[i] & GTK_RC_TEXT)
1373 proto_style->text[i] = rc_style->text[i];
1374 proto_style->color_flags[i] |= GTK_RC_TEXT;
1376 if (!(proto_style->color_flags[i] & GTK_RC_BASE) &&
1377 rc_style->color_flags[i] & GTK_RC_BASE)
1379 proto_style->base[i] = rc_style->base[i];
1380 proto_style->color_flags[i] |= GTK_RC_BASE;
1384 if (!proto_style->font_desc && rc_style->font_desc)
1385 proto_style->font_desc = pango_font_description_copy (rc_style->font_desc);
1387 if (!proto_style->engine && rc_style->engine)
1389 proto_style->engine = rc_style->engine;
1390 gtk_theme_engine_ref (proto_style->engine);
1393 if (proto_style->engine &&
1394 (proto_style->engine == rc_style->engine))
1395 proto_style->engine->merge_rc_style (proto_style, rc_style);
1397 /* Point from each rc_style to the list of styles */
1399 if (!g_slist_find (rc_style->rc_style_lists, rc_styles))
1400 rc_style->rc_style_lists = g_slist_prepend (rc_style->rc_style_lists, rc_styles);
1402 tmp_styles = tmp_styles->next;
1406 if (proto_style->bg_pixmap_name[i] &&
1407 (strcmp (proto_style->bg_pixmap_name[i], "<none>") == 0))
1409 g_free (proto_style->bg_pixmap_name[i]);
1410 proto_style->bg_pixmap_name[i] = NULL;
1413 style = gtk_rc_style_to_style (proto_style);
1415 g_hash_table_insert (realized_style_ht, rc_styles, style);
1418 g_slist_free (rc_styles);
1423 /*********************
1424 * Parsing functions *
1425 *********************/
1428 gtk_rc_parse_statement (GScanner *scanner)
1432 token = g_scanner_peek_next_token (scanner);
1436 case GTK_RC_TOKEN_INCLUDE:
1437 token = g_scanner_get_next_token (scanner);
1438 if (token != GTK_RC_TOKEN_INCLUDE)
1439 return GTK_RC_TOKEN_INCLUDE;
1441 token = g_scanner_get_next_token (scanner);
1442 if (token != G_TOKEN_STRING)
1443 return G_TOKEN_STRING;
1445 gtk_rc_parse_file (scanner->value.v_string, FALSE);
1446 return G_TOKEN_NONE;
1448 case GTK_RC_TOKEN_STYLE:
1449 return gtk_rc_parse_style (scanner);
1451 case GTK_RC_TOKEN_BINDING:
1452 return gtk_binding_parse_binding (scanner);
1454 case GTK_RC_TOKEN_PIXMAP_PATH:
1455 return gtk_rc_parse_pixmap_path (scanner);
1457 case GTK_RC_TOKEN_WIDGET:
1458 return gtk_rc_parse_path_pattern (scanner);
1460 case GTK_RC_TOKEN_WIDGET_CLASS:
1461 return gtk_rc_parse_path_pattern (scanner);
1463 case GTK_RC_TOKEN_CLASS:
1464 return gtk_rc_parse_path_pattern (scanner);
1466 case GTK_RC_TOKEN_MODULE_PATH:
1467 return gtk_rc_parse_module_path (scanner);
1470 g_scanner_get_next_token (scanner);
1471 return /* G_TOKEN_SYMBOL */ GTK_RC_TOKEN_STYLE;
1476 gtk_rc_parse_style (GScanner *scanner)
1478 GtkRcStyle *rc_style;
1479 GtkRcStyle *parent_style;
1484 token = g_scanner_get_next_token (scanner);
1485 if (token != GTK_RC_TOKEN_STYLE)
1486 return GTK_RC_TOKEN_STYLE;
1488 token = g_scanner_get_next_token (scanner);
1489 if (token != G_TOKEN_STRING)
1490 return G_TOKEN_STRING;
1493 rc_style = gtk_rc_style_find (scanner->value.v_string);
1498 rc_style = gtk_rc_style_new ();
1499 rc_style->name = g_strdup (scanner->value.v_string);
1501 for (i = 0; i < 5; i++)
1502 rc_style->bg_pixmap_name[i] = NULL;
1504 for (i = 0; i < 5; i++)
1505 rc_style->color_flags[i] = 0;
1507 rc_style->engine = NULL;
1508 rc_style->engine_data = NULL;
1511 token = g_scanner_peek_next_token (scanner);
1512 if (token == G_TOKEN_EQUAL_SIGN)
1514 token = g_scanner_get_next_token (scanner);
1516 token = g_scanner_get_next_token (scanner);
1517 if (token != G_TOKEN_STRING)
1522 return G_TOKEN_STRING;
1525 parent_style = gtk_rc_style_find (scanner->value.v_string);
1528 for (i = 0; i < 5; i++)
1530 rc_style->color_flags[i] = parent_style->color_flags[i];
1531 rc_style->fg[i] = parent_style->fg[i];
1532 rc_style->bg[i] = parent_style->bg[i];
1533 rc_style->text[i] = parent_style->text[i];
1534 rc_style->base[i] = parent_style->base[i];
1537 if (parent_style->font_desc)
1539 if (rc_style->font_desc)
1540 pango_font_description_free (rc_style->font_desc);
1541 rc_style->font_desc = pango_font_description_copy (parent_style->font_desc);
1544 for (i = 0; i < 5; i++)
1546 if (rc_style->bg_pixmap_name[i])
1547 g_free (rc_style->bg_pixmap_name[i]);
1548 rc_style->bg_pixmap_name[i] = g_strdup (parent_style->bg_pixmap_name[i]);
1553 token = g_scanner_get_next_token (scanner);
1554 if (token != G_TOKEN_LEFT_CURLY)
1559 return G_TOKEN_LEFT_CURLY;
1562 token = g_scanner_peek_next_token (scanner);
1563 while (token != G_TOKEN_RIGHT_CURLY)
1567 case GTK_RC_TOKEN_BASE:
1568 token = gtk_rc_parse_base (scanner, rc_style);
1570 case GTK_RC_TOKEN_BG:
1571 token = gtk_rc_parse_bg (scanner, rc_style);
1573 case GTK_RC_TOKEN_FG:
1574 token = gtk_rc_parse_fg (scanner, rc_style);
1576 case GTK_RC_TOKEN_TEXT:
1577 token = gtk_rc_parse_text (scanner, rc_style);
1579 case GTK_RC_TOKEN_BG_PIXMAP:
1580 token = gtk_rc_parse_bg_pixmap (scanner, rc_style);
1582 case GTK_RC_TOKEN_FONT:
1583 token = gtk_rc_parse_font (scanner, rc_style);
1585 case GTK_RC_TOKEN_FONTSET:
1586 token = gtk_rc_parse_fontset (scanner, rc_style);
1588 case GTK_RC_TOKEN_FONT_NAME:
1589 token = gtk_rc_parse_font_name (scanner, rc_style);
1591 case GTK_RC_TOKEN_ENGINE:
1592 token = gtk_rc_parse_engine (scanner, rc_style);
1595 g_scanner_get_next_token (scanner);
1596 token = G_TOKEN_RIGHT_CURLY;
1600 if (token != G_TOKEN_NONE)
1604 if (rc_style->font_desc)
1605 pango_font_description_free (rc_style->font_desc);
1607 for (i = 0; i < 5; i++)
1608 if (rc_style->bg_pixmap_name[i])
1609 g_free (rc_style->bg_pixmap_name[i]);
1614 token = g_scanner_peek_next_token (scanner);
1617 token = g_scanner_get_next_token (scanner);
1618 if (token != G_TOKEN_RIGHT_CURLY)
1622 if (rc_style->font_desc)
1623 pango_font_description_free (rc_style->font_desc);
1625 for (i = 0; i < 5; i++)
1626 if (rc_style->bg_pixmap_name[i])
1627 g_free (rc_style->bg_pixmap_name[i]);
1631 return G_TOKEN_RIGHT_CURLY;
1637 rc_style_ht = g_hash_table_new ((GHashFunc) gtk_rc_style_hash,
1638 (GCompareFunc) gtk_rc_style_compare);
1640 g_hash_table_insert (rc_style_ht, rc_style->name, rc_style);
1643 return G_TOKEN_NONE;
1647 gtk_rc_parse_base (GScanner *scanner,
1653 token = g_scanner_get_next_token (scanner);
1654 if (token != GTK_RC_TOKEN_BASE)
1655 return GTK_RC_TOKEN_BASE;
1657 token = gtk_rc_parse_state (scanner, &state);
1658 if (token != G_TOKEN_NONE)
1661 token = g_scanner_get_next_token (scanner);
1662 if (token != G_TOKEN_EQUAL_SIGN)
1663 return G_TOKEN_EQUAL_SIGN;
1665 style->color_flags[state] |= GTK_RC_BASE;
1666 return gtk_rc_parse_color (scanner, &style->base[state]);
1670 gtk_rc_parse_bg (GScanner *scanner,
1676 token = g_scanner_get_next_token (scanner);
1677 if (token != GTK_RC_TOKEN_BG)
1678 return GTK_RC_TOKEN_BG;
1680 token = gtk_rc_parse_state (scanner, &state);
1681 if (token != G_TOKEN_NONE)
1684 token = g_scanner_get_next_token (scanner);
1685 if (token != G_TOKEN_EQUAL_SIGN)
1686 return G_TOKEN_EQUAL_SIGN;
1688 style->color_flags[state] |= GTK_RC_BG;
1689 return gtk_rc_parse_color (scanner, &style->bg[state]);
1693 gtk_rc_parse_fg (GScanner *scanner,
1699 token = g_scanner_get_next_token (scanner);
1700 if (token != GTK_RC_TOKEN_FG)
1701 return GTK_RC_TOKEN_FG;
1703 token = gtk_rc_parse_state (scanner, &state);
1704 if (token != G_TOKEN_NONE)
1707 token = g_scanner_get_next_token (scanner);
1708 if (token != G_TOKEN_EQUAL_SIGN)
1709 return G_TOKEN_EQUAL_SIGN;
1711 style->color_flags[state] |= GTK_RC_FG;
1712 return gtk_rc_parse_color (scanner, &style->fg[state]);
1716 gtk_rc_parse_text (GScanner *scanner,
1722 token = g_scanner_get_next_token (scanner);
1723 if (token != GTK_RC_TOKEN_TEXT)
1724 return GTK_RC_TOKEN_TEXT;
1726 token = gtk_rc_parse_state (scanner, &state);
1727 if (token != G_TOKEN_NONE)
1730 token = g_scanner_get_next_token (scanner);
1731 if (token != G_TOKEN_EQUAL_SIGN)
1732 return G_TOKEN_EQUAL_SIGN;
1734 style->color_flags[state] |= GTK_RC_TEXT;
1735 return gtk_rc_parse_color (scanner, &style->text[state]);
1739 gtk_rc_parse_bg_pixmap (GScanner *scanner,
1740 GtkRcStyle *rc_style)
1746 token = g_scanner_get_next_token (scanner);
1747 if (token != GTK_RC_TOKEN_BG_PIXMAP)
1748 return GTK_RC_TOKEN_BG_PIXMAP;
1750 token = gtk_rc_parse_state (scanner, &state);
1751 if (token != G_TOKEN_NONE)
1754 token = g_scanner_get_next_token (scanner);
1755 if (token != G_TOKEN_EQUAL_SIGN)
1756 return G_TOKEN_EQUAL_SIGN;
1758 token = g_scanner_get_next_token (scanner);
1759 if (token != G_TOKEN_STRING)
1760 return G_TOKEN_STRING;
1762 if ((strcmp (scanner->value.v_string, "<parent>") == 0) ||
1763 (strcmp (scanner->value.v_string, "<none>") == 0))
1764 pixmap_file = g_strdup (scanner->value.v_string);
1766 pixmap_file = gtk_rc_find_pixmap_in_path (scanner, scanner->value.v_string);
1770 if (rc_style->bg_pixmap_name[state])
1771 g_free (rc_style->bg_pixmap_name[state]);
1772 rc_style->bg_pixmap_name[state] = pixmap_file;
1775 return G_TOKEN_NONE;
1779 gtk_rc_check_pixmap_dir (const gchar *dir, const gchar *pixmap_file)
1784 buf = g_strdup_printf ("%s" G_DIR_SEPARATOR_S "%s", dir, pixmap_file);
1786 fd = open (buf, O_RDONLY);
1799 gtk_rc_find_pixmap_in_path (GScanner *scanner,
1800 const gchar *pixmap_file)
1806 for (i = 0; (i < GTK_RC_MAX_PIXMAP_PATHS) && (pixmap_path[i] != NULL); i++)
1808 filename = gtk_rc_check_pixmap_dir (pixmap_path[i], pixmap_file);
1813 tmp_list = rc_dir_stack;
1816 filename = gtk_rc_check_pixmap_dir (tmp_list->data, pixmap_file);
1820 tmp_list = tmp_list->next;
1824 g_warning (_("Unable to locate image file in pixmap_path: \"%s\" line %d"),
1825 pixmap_file, scanner->line);
1827 g_warning (_("Unable to locate image file in pixmap_path: \"%s\""),
1834 gtk_rc_find_module_in_path (const gchar *module_file)
1840 for (i = 0; (i < GTK_RC_MAX_MODULE_PATHS) && (module_path[i] != NULL); i++)
1842 buf = g_strdup_printf ("%s" G_DIR_SEPARATOR_S "%s",
1843 module_path[i], module_file);
1845 fd = open (buf, O_RDONLY);
1859 gtk_rc_parse_font (GScanner *scanner,
1860 GtkRcStyle *rc_style)
1864 token = g_scanner_get_next_token (scanner);
1865 if (token != GTK_RC_TOKEN_FONT)
1866 return GTK_RC_TOKEN_FONT;
1868 token = g_scanner_get_next_token (scanner);
1869 if (token != G_TOKEN_EQUAL_SIGN)
1870 return G_TOKEN_EQUAL_SIGN;
1872 token = g_scanner_get_next_token (scanner);
1873 if (token != G_TOKEN_STRING)
1874 return G_TOKEN_STRING;
1876 /* Ignore, do nothing */
1878 return G_TOKEN_NONE;
1882 gtk_rc_parse_fontset (GScanner *scanner,
1883 GtkRcStyle *rc_style)
1887 token = g_scanner_get_next_token (scanner);
1888 if (token != GTK_RC_TOKEN_FONTSET)
1889 return GTK_RC_TOKEN_FONTSET;
1891 token = g_scanner_get_next_token (scanner);
1892 if (token != G_TOKEN_EQUAL_SIGN)
1893 return G_TOKEN_EQUAL_SIGN;
1895 token = g_scanner_get_next_token (scanner);
1896 if (token != G_TOKEN_STRING)
1897 return G_TOKEN_STRING;
1899 /* Do nothing - silently ignore */
1901 return G_TOKEN_NONE;
1905 gtk_rc_parse_font_name (GScanner *scanner,
1906 GtkRcStyle *rc_style)
1910 token = g_scanner_get_next_token (scanner);
1911 if (token != GTK_RC_TOKEN_FONT_NAME)
1912 return GTK_RC_TOKEN_FONT;
1914 token = g_scanner_get_next_token (scanner);
1915 if (token != G_TOKEN_EQUAL_SIGN)
1916 return G_TOKEN_EQUAL_SIGN;
1918 token = g_scanner_get_next_token (scanner);
1919 if (token != G_TOKEN_STRING)
1920 return G_TOKEN_STRING;
1922 rc_style->font_desc = pango_font_description_from_string (scanner->value.v_string);
1924 return G_TOKEN_NONE;
1928 gtk_rc_parse_engine (GScanner *scanner,
1929 GtkRcStyle *rc_style)
1933 token = g_scanner_get_next_token (scanner);
1934 if (token != GTK_RC_TOKEN_ENGINE)
1935 return GTK_RC_TOKEN_ENGINE;
1937 token = g_scanner_get_next_token (scanner);
1938 if (token != G_TOKEN_STRING)
1939 return G_TOKEN_STRING;
1941 rc_style->engine = gtk_theme_engine_get (scanner->value.v_string);
1943 token = g_scanner_get_next_token (scanner);
1944 if (token != G_TOKEN_LEFT_CURLY)
1945 return G_TOKEN_LEFT_CURLY;
1947 if (rc_style->engine)
1948 return rc_style->engine->parse_rc_style (scanner, rc_style);
1951 /* Skip over remainder, looking for nested {}'s */
1954 while ((token = g_scanner_get_next_token (scanner)) != G_TOKEN_EOF)
1956 if (token == G_TOKEN_LEFT_CURLY)
1958 else if (token == G_TOKEN_RIGHT_CURLY)
1962 return G_TOKEN_NONE;
1965 return G_TOKEN_RIGHT_CURLY;
1970 gtk_rc_parse_state (GScanner *scanner,
1971 GtkStateType *state)
1976 g_return_val_if_fail (scanner != NULL, G_TOKEN_ERROR);
1977 g_return_val_if_fail (state != NULL, G_TOKEN_ERROR);
1979 /* we don't know where we got called from, so we reset the scope here.
1980 * if we bail out due to errors, we *don't* reset the scope, so the
1981 * error messaging code can make sense of our tokens.
1983 old_scope = g_scanner_set_scope (scanner, 0);
1985 token = g_scanner_get_next_token (scanner);
1986 if (token != G_TOKEN_LEFT_BRACE)
1987 return G_TOKEN_LEFT_BRACE;
1989 token = g_scanner_get_next_token (scanner);
1992 case GTK_RC_TOKEN_ACTIVE:
1993 *state = GTK_STATE_ACTIVE;
1995 case GTK_RC_TOKEN_INSENSITIVE:
1996 *state = GTK_STATE_INSENSITIVE;
1998 case GTK_RC_TOKEN_NORMAL:
1999 *state = GTK_STATE_NORMAL;
2001 case GTK_RC_TOKEN_PRELIGHT:
2002 *state = GTK_STATE_PRELIGHT;
2004 case GTK_RC_TOKEN_SELECTED:
2005 *state = GTK_STATE_SELECTED;
2008 return /* G_TOKEN_SYMBOL */ GTK_RC_TOKEN_NORMAL;
2011 token = g_scanner_get_next_token (scanner);
2012 if (token != G_TOKEN_RIGHT_BRACE)
2013 return G_TOKEN_RIGHT_BRACE;
2015 g_scanner_set_scope (scanner, old_scope);
2017 return G_TOKEN_NONE;
2021 gtk_rc_parse_priority (GScanner *scanner,
2022 GtkPathPriorityType *priority)
2027 g_return_val_if_fail (scanner != NULL, G_TOKEN_ERROR);
2028 g_return_val_if_fail (priority != NULL, G_TOKEN_ERROR);
2030 /* we don't know where we got called from, so we reset the scope here.
2031 * if we bail out due to errors, we *don't* reset the scope, so the
2032 * error messaging code can make sense of our tokens.
2034 old_scope = g_scanner_set_scope (scanner, 0);
2036 token = g_scanner_get_next_token (scanner);
2040 token = g_scanner_get_next_token (scanner);
2043 case GTK_RC_TOKEN_LOWEST:
2044 *priority = GTK_PATH_PRIO_LOWEST;
2046 case GTK_RC_TOKEN_GTK:
2047 *priority = GTK_PATH_PRIO_GTK;
2049 case GTK_RC_TOKEN_APPLICATION:
2050 *priority = GTK_PATH_PRIO_APPLICATION;
2052 case GTK_RC_TOKEN_RC:
2053 *priority = GTK_PATH_PRIO_RC;
2055 case GTK_RC_TOKEN_HIGHEST:
2056 *priority = GTK_PATH_PRIO_HIGHEST;
2059 return /* G_TOKEN_SYMBOL */ GTK_RC_TOKEN_APPLICATION;
2062 g_scanner_set_scope (scanner, old_scope);
2064 return G_TOKEN_NONE;
2068 gtk_rc_parse_color (GScanner *scanner,
2073 g_return_val_if_fail (scanner != NULL, G_TOKEN_ERROR);
2075 /* we don't need to set our own scop here, because
2076 * we don't need own symbols
2079 token = g_scanner_get_next_token (scanner);
2088 case G_TOKEN_LEFT_CURLY:
2089 token = g_scanner_get_next_token (scanner);
2090 if (token == G_TOKEN_INT)
2091 token_int = scanner->value.v_int;
2092 else if (token == G_TOKEN_FLOAT)
2093 token_int = scanner->value.v_float * 65535.0;
2095 return G_TOKEN_FLOAT;
2096 color->red = CLAMP (token_int, 0, 65535);
2098 token = g_scanner_get_next_token (scanner);
2099 if (token != G_TOKEN_COMMA)
2100 return G_TOKEN_COMMA;
2102 token = g_scanner_get_next_token (scanner);
2103 if (token == G_TOKEN_INT)
2104 token_int = scanner->value.v_int;
2105 else if (token == G_TOKEN_FLOAT)
2106 token_int = scanner->value.v_float * 65535.0;
2108 return G_TOKEN_FLOAT;
2109 color->green = CLAMP (token_int, 0, 65535);
2111 token = g_scanner_get_next_token (scanner);
2112 if (token != G_TOKEN_COMMA)
2113 return G_TOKEN_COMMA;
2115 token = g_scanner_get_next_token (scanner);
2116 if (token == G_TOKEN_INT)
2117 token_int = scanner->value.v_int;
2118 else if (token == G_TOKEN_FLOAT)
2119 token_int = scanner->value.v_float * 65535.0;
2121 return G_TOKEN_FLOAT;
2122 color->blue = CLAMP (token_int, 0, 65535);
2124 token = g_scanner_get_next_token (scanner);
2125 if (token != G_TOKEN_RIGHT_CURLY)
2126 return G_TOKEN_RIGHT_CURLY;
2127 return G_TOKEN_NONE;
2129 case G_TOKEN_STRING:
2130 if (scanner->value.v_string[0] != '#')
2131 return G_TOKEN_STRING;
2133 length = strlen (scanner->value.v_string) - 1;
2134 if (((length % 3) != 0) || (length > 12))
2135 return G_TOKEN_STRING;
2138 for (i = 0, j = 1; i < length; i++, j++)
2139 buf[i] = scanner->value.v_string[j];
2142 sscanf (buf, "%x", &temp);
2145 for (i = 0; i < length; i++, j++)
2146 buf[i] = scanner->value.v_string[j];
2149 sscanf (buf, "%x", &temp);
2150 color->green = temp;
2152 for (i = 0; i < length; i++, j++)
2153 buf[i] = scanner->value.v_string[j];
2156 sscanf (buf, "%x", &temp);
2162 color->green *= 4369;
2163 color->blue *= 4369;
2165 else if (length == 2)
2168 color->green *= 257;
2171 else if (length == 3)
2177 return G_TOKEN_NONE;
2180 return G_TOKEN_STRING;
2185 gtk_rc_parse_pixmap_path (GScanner *scanner)
2189 token = g_scanner_get_next_token (scanner);
2190 if (token != GTK_RC_TOKEN_PIXMAP_PATH)
2191 return GTK_RC_TOKEN_PIXMAP_PATH;
2193 token = g_scanner_get_next_token (scanner);
2194 if (token != G_TOKEN_STRING)
2195 return G_TOKEN_STRING;
2197 gtk_rc_parse_pixmap_path_string (scanner->value.v_string);
2199 return G_TOKEN_NONE;
2203 gtk_rc_parse_pixmap_path_string (gchar *pix_path)
2207 gint start_offset = 0;
2211 /* free the old one, or just add to the old one ? */
2212 for (path_num=0; pixmap_path[path_num]; path_num++)
2214 g_free (pixmap_path[path_num]);
2215 pixmap_path[path_num] = NULL;
2220 path_len = strlen (pix_path);
2222 buf = g_strdup (pix_path);
2224 for (end_offset = 0; end_offset <= path_len; end_offset++)
2226 if ((buf[end_offset] == G_SEARCHPATH_SEPARATOR) ||
2227 (end_offset == path_len))
2229 buf[end_offset] = '\0';
2230 pixmap_path[path_num] = g_strdup (buf + start_offset);
2232 pixmap_path[path_num] = NULL;
2233 start_offset = end_offset + 1;
2237 gtk_rc_append_default_pixmap_path();
2241 gtk_rc_parse_module_path (GScanner *scanner)
2245 token = g_scanner_get_next_token (scanner);
2246 if (token != GTK_RC_TOKEN_MODULE_PATH)
2247 return GTK_RC_TOKEN_MODULE_PATH;
2249 token = g_scanner_get_next_token (scanner);
2250 if (token != G_TOKEN_STRING)
2251 return G_TOKEN_STRING;
2253 gtk_rc_parse_module_path_string (scanner->value.v_string);
2255 return G_TOKEN_NONE;
2259 gtk_rc_parse_module_path_string (gchar *mod_path)
2263 gint start_offset = 0;
2267 /* free the old one, or just add to the old one ? */
2268 for (path_num=0; module_path[path_num]; path_num++)
2270 g_free (module_path[path_num]);
2271 module_path[path_num] = NULL;
2276 path_len = strlen (mod_path);
2278 buf = g_strdup (mod_path);
2280 for (end_offset = 0; end_offset <= path_len; end_offset++)
2282 if ((buf[end_offset] == G_SEARCHPATH_SEPARATOR) ||
2283 (end_offset == path_len))
2285 buf[end_offset] = '\0';
2286 module_path[path_num] = g_strdup (buf + start_offset);
2288 module_path[path_num] = NULL;
2289 start_offset = end_offset + 1;
2293 gtk_rc_append_default_module_path();
2297 gtk_rc_parse_path_pattern (GScanner *scanner)
2300 GtkPathType path_type;
2302 gboolean is_binding;
2303 GtkPathPriorityType priority = GTK_PATH_PRIO_RC;
2305 token = g_scanner_get_next_token (scanner);
2308 case GTK_RC_TOKEN_WIDGET:
2309 path_type = GTK_PATH_WIDGET;
2311 case GTK_RC_TOKEN_WIDGET_CLASS:
2312 path_type = GTK_PATH_WIDGET_CLASS;
2314 case GTK_RC_TOKEN_CLASS:
2315 path_type = GTK_PATH_CLASS;
2318 return GTK_RC_TOKEN_WIDGET_CLASS;
2321 token = g_scanner_get_next_token (scanner);
2322 if (token != G_TOKEN_STRING)
2323 return G_TOKEN_STRING;
2325 pattern = g_strdup (scanner->value.v_string);
2327 token = g_scanner_get_next_token (scanner);
2328 if (token == GTK_RC_TOKEN_STYLE)
2330 else if (token == GTK_RC_TOKEN_BINDING)
2333 if (g_scanner_peek_next_token (scanner) == ':')
2335 token = gtk_rc_parse_priority (scanner, &priority);
2336 if (token != G_TOKEN_NONE)
2346 return GTK_RC_TOKEN_STYLE;
2349 token = g_scanner_get_next_token (scanner);
2350 if (token != G_TOKEN_STRING)
2353 return G_TOKEN_STRING;
2358 GtkBindingSet *binding;
2360 binding = gtk_binding_set_find (scanner->value.v_string);
2364 return G_TOKEN_STRING;
2366 gtk_binding_set_add_path (binding, path_type, pattern, priority);
2370 GtkRcStyle *rc_style;
2373 rc_style = gtk_rc_style_find (scanner->value.v_string);
2378 return G_TOKEN_STRING;
2381 rc_set = g_new (GtkRcSet, 1);
2382 gtk_pattern_spec_init (&rc_set->pspec, pattern);
2383 rc_set->rc_style = rc_style;
2385 if (path_type == GTK_PATH_WIDGET)
2386 gtk_rc_sets_widget = g_slist_prepend (gtk_rc_sets_widget, rc_set);
2387 else if (path_type == GTK_PATH_WIDGET_CLASS)
2388 gtk_rc_sets_widget_class = g_slist_prepend (gtk_rc_sets_widget_class, rc_set);
2390 gtk_rc_sets_class = g_slist_prepend (gtk_rc_sets_class, rc_set);
2394 return G_TOKEN_NONE;
2398 typedef GdkPixmap * (*GtkImageLoader) (GdkWindow *window,
2399 GdkColormap *colormap,
2401 GdkColor *transparent_color,
2402 const gchar *filename);
2406 gtk_rc_set_image_loader(GtkImageLoader loader)
2408 image_loader = loader;
2412 gtk_rc_load_image (GdkColormap *colormap,
2413 GdkColor *transparent_color,
2414 const gchar *filename)
2416 if (strcmp (filename, "<parent>") == 0)
2417 return (GdkPixmap*) GDK_PARENT_RELATIVE;
2421 return image_loader(NULL, colormap, NULL,
2425 return gdk_pixmap_colormap_create_from_xpm (NULL, colormap, NULL,