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;
63 typedef struct _GtkRcStylePrivate GtkRcStylePrivate;
75 gchar *canonical_name;
79 struct _GtkRcStylePrivate
84 /* list of RC style lists including this RC style */
85 GSList *rc_style_lists;
88 static guint gtk_rc_style_hash (const char *name);
89 static gint gtk_rc_style_compare (const char *a,
91 static guint gtk_rc_styles_hash (const GSList *rc_styles);
92 static gint gtk_rc_styles_compare (const GSList *a,
94 static GtkRcStyle* gtk_rc_style_find (const char *name);
95 static GSList * gtk_rc_styles_match (GSList *rc_styles,
99 gchar *path_reversed);
100 static GtkStyle * gtk_rc_style_to_style (GtkRcStyle *rc_style);
101 static GtkStyle* gtk_rc_style_init (GSList *rc_styles);
102 static void gtk_rc_parse_file (const gchar *filename,
105 static void gtk_rc_parse_any (const gchar *input_name,
107 const gchar *input_string);
108 static guint gtk_rc_parse_statement (GScanner *scanner);
109 static guint gtk_rc_parse_style (GScanner *scanner);
110 static guint gtk_rc_parse_base (GScanner *scanner,
112 static guint gtk_rc_parse_bg (GScanner *scanner,
114 static guint gtk_rc_parse_fg (GScanner *scanner,
116 static guint gtk_rc_parse_text (GScanner *scanner,
118 static guint gtk_rc_parse_bg_pixmap (GScanner *scanner,
119 GtkRcStyle *rc_style);
120 static guint gtk_rc_parse_font (GScanner *scanner,
121 GtkRcStyle *rc_style);
122 static guint gtk_rc_parse_fontset (GScanner *scanner,
123 GtkRcStyle *rc_style);
124 static guint gtk_rc_parse_engine (GScanner *scanner,
125 GtkRcStyle *rc_style);
126 static guint gtk_rc_parse_pixmap_path (GScanner *scanner);
127 static void gtk_rc_parse_pixmap_path_string (gchar *pix_path);
128 static guint gtk_rc_parse_module_path (GScanner *scanner);
129 static void gtk_rc_parse_module_path_string (gchar *mod_path);
130 static guint gtk_rc_parse_path_pattern (GScanner *scanner);
131 static void gtk_rc_clear_hash_node (gpointer key,
134 static void gtk_rc_clear_styles (void);
135 static void gtk_rc_append_default_pixmap_path (void);
136 static void gtk_rc_append_default_module_path (void);
137 static void gtk_rc_add_initial_default_files (void);
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 { "bg_pixmap", GTK_RC_TOKEN_BG_PIXMAP },
199 { "pixmap_path", GTK_RC_TOKEN_PIXMAP_PATH },
200 { "style", GTK_RC_TOKEN_STYLE },
201 { "binding", GTK_RC_TOKEN_BINDING },
202 { "bind", GTK_RC_TOKEN_BIND },
203 { "widget", GTK_RC_TOKEN_WIDGET },
204 { "widget_class", GTK_RC_TOKEN_WIDGET_CLASS },
205 { "class", GTK_RC_TOKEN_CLASS },
206 { "lowest", GTK_RC_TOKEN_LOWEST },
207 { "gtk", GTK_RC_TOKEN_GTK },
208 { "application", GTK_RC_TOKEN_APPLICATION },
209 { "rc", GTK_RC_TOKEN_RC },
210 { "highest", GTK_RC_TOKEN_HIGHEST },
211 { "engine", GTK_RC_TOKEN_ENGINE },
212 { "module_path", GTK_RC_TOKEN_MODULE_PATH },
215 static const guint n_symbols = sizeof (symbols) / sizeof (symbols[0]);
217 static GHashTable *rc_style_ht = NULL;
218 static GHashTable *realized_style_ht = NULL;
219 static GSList *gtk_rc_sets_widget = NULL;
220 static GSList *gtk_rc_sets_widget_class = NULL;
221 static GSList *gtk_rc_sets_class = NULL;
223 #define GTK_RC_MAX_DEFAULT_FILES 128
224 static gchar *gtk_rc_default_files[GTK_RC_MAX_DEFAULT_FILES];
225 static gboolean gtk_rc_auto_parse = TRUE;
227 #define GTK_RC_MAX_PIXMAP_PATHS 128
228 static gchar *pixmap_path[GTK_RC_MAX_PIXMAP_PATHS];
229 #define GTK_RC_MAX_MODULE_PATHS 128
230 static gchar *module_path[GTK_RC_MAX_MODULE_PATHS];
232 /* A stack of directories for RC files we are parsing currently.
233 * these are implicitely added to the end of PIXMAP_PATHS
235 GSList *rc_dir_stack = NULL;
237 /* The files we have parsed, to reread later if necessary */
238 GSList *rc_files = NULL;
240 static GtkImageLoader image_loader = NULL;
242 /* RC file handling */
248 get_gtk_sysconf_directory (void)
250 static gchar gtk_sysconf_dir[200];
253 GetWindowsDirectory (win_dir, sizeof (win_dir));
254 sprintf (gtk_sysconf_dir, "%s\\gtk+", win_dir);
255 return gtk_sysconf_dir;
259 get_themes_directory (void)
261 /* We really should fetch this from the Registry. The GIMP
262 * installation program stores the Themes installation
263 * directory in HKLM\Software\GNU\GTk+\Themes\InstallDirectory.
266 static gchar themes_dir[200];
268 sprintf (themes_dir, "%s\\themes", get_gtk_sysconf_directory ());
275 gtk_rc_get_theme_dir(void)
280 var = getenv("GTK_DATA_PREFIX");
282 path = g_strdup_printf("%s%s", var, "/share/themes");
284 path = g_strdup_printf("%s%s", GTK_DATA_PREFIX, "/share/themes");
286 path = g_strdup (get_themes_directory ());
293 gtk_rc_get_module_dir(void)
298 var = getenv("GTK_EXE_PREFIX");
300 path = g_strdup_printf("%s%s", var, "/lib/gtk/themes/engines");
302 path = g_strdup_printf("%s%s", GTK_EXE_PREFIX, "/lib/gtk/themes/engines");
304 path = g_strdup_printf ("%s%s", get_themes_directory (), "\\engines");
311 gtk_rc_append_default_pixmap_path(void)
317 var = getenv("GTK_DATA_PREFIX");
319 path = g_strdup_printf("%s%s", var, "/share/gtk/themes");
321 path = g_strdup_printf("%s%s", GTK_DATA_PREFIX, "/share/gtk/themes");
323 path = g_strdup (get_themes_directory ());
326 for (n = 0; pixmap_path[n]; n++) ;
327 if (n >= GTK_RC_MAX_PIXMAP_PATHS - 1)
332 pixmap_path[n++] = path;
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;
464 /* The following routine is based on _nl_normalize_codeset from
465 * the GNU C library. Contributed by
467 * Contributed by Ulrich Drepper <drepper@gnu.ai.mit.edu>, 1995.
468 * Copyright (C) 1995, 1996, 1997, 1998, 1999 Free Software Foundation, Inc.
470 * Normalize codeset name. There is no standard for the codeset
471 * names. Normalization allows the user to use any of the common
475 _gtk_normalize_codeset (const char *codeset, int name_len)
483 for (cnt = 0; cnt < name_len; ++cnt)
484 if (isalnum (codeset[cnt]))
488 if (isalpha (codeset[cnt]))
492 retval = g_malloc ((only_digit ? 3 : 0) + len + 1);
496 strcpy (retval, "iso");
502 for (cnt = 0; cnt < name_len; ++cnt)
503 if (isalpha (codeset[cnt]))
504 *wp++ = isupper(codeset[cnt]) ? tolower (codeset[cnt]) : codeset[cnt];
505 else if (isdigit (codeset[cnt]))
506 *wp++ = codeset[cnt];
516 static gchar *locale_suffixes[3];
517 static gint n_locale_suffixes = 0;
521 static gboolean initted = FALSE;
530 locale = g_win32_getlocale ();
532 locale = setlocale (LC_CTYPE, NULL);
537 pixmap_path[0] = NULL;
538 module_path[0] = NULL;
539 gtk_rc_append_default_pixmap_path();
540 gtk_rc_append_default_module_path();
542 gtk_rc_add_initial_default_files ();
544 if (strcmp (locale, "C") && strcmp (locale, "POSIX"))
546 /* Determine locale-specific suffixes for RC files
548 * We normalize the charset into a standard form,
549 * which has all '-' and '_' characters removed,
552 gchar *normalized_locale;
554 p = strchr (locale, '@');
555 length = p ? (p -locale) : strlen (locale);
557 p = strchr (locale, '.');
560 gchar *tmp1 = g_strndup (locale, p - locale + 1);
561 gchar *tmp2 = _gtk_normalize_codeset (p + 1, length - (p - locale + 1));
563 normalized_locale = g_strconcat (tmp1, tmp2, NULL);
567 locale_suffixes[n_locale_suffixes++] = g_strdup (normalized_locale);
571 normalized_locale = g_strndup (locale, length);
573 p = strchr (normalized_locale, '_');
576 locale_suffixes[n_locale_suffixes++] = g_strndup (normalized_locale, length);
577 length = p - normalized_locale;
580 locale_suffixes[n_locale_suffixes++] = g_strndup (normalized_locale, length);
582 g_free (normalized_locale);
587 while (gtk_rc_default_files[i] != NULL)
589 /* Try to find a locale specific RC file corresponding to
590 * to parse before the default file.
592 for (j=n_locale_suffixes-1; j>=0; j--)
594 gchar *name = g_strconcat (gtk_rc_default_files[i],
602 gtk_rc_parse (gtk_rc_default_files[i]);
608 gtk_rc_parse_string (const gchar *rc_string)
610 g_return_if_fail (rc_string != NULL);
612 gtk_rc_parse_any ("-", -1, rc_string);
616 gtk_rc_parse_file (const gchar *filename, gboolean reload)
618 GtkRcFile *rc_file = NULL;
622 g_return_if_fail (filename != NULL);
627 rc_file = tmp_list->data;
628 if (!strcmp (rc_file->name, filename))
631 tmp_list = tmp_list->next;
636 rc_file = g_new (GtkRcFile, 1);
637 rc_file->name = g_strdup (filename);
638 rc_file->canonical_name = NULL;
640 rc_file->reload = reload;
642 rc_files = g_slist_append (rc_files, rc_file);
645 if (!rc_file->canonical_name)
647 /* Get the absolute pathname */
649 if (g_path_is_absolute (rc_file->name))
650 rc_file->canonical_name = rc_file->name;
656 cwd = g_get_current_dir ();
658 str = g_string_new (cwd);
660 g_string_append_c (str, G_DIR_SEPARATOR);
661 g_string_append (str, rc_file->name);
663 rc_file->canonical_name = str->str;
664 g_string_free (str, FALSE);
668 if (!lstat (rc_file->canonical_name, &statbuf))
673 rc_file->mtime = statbuf.st_mtime;
675 fd = open (rc_file->canonical_name, O_RDONLY);
679 /* Temporarily push directory name for this file on
680 * a stack of directory names while parsing it
682 rc_dir_stack = g_slist_prepend (rc_dir_stack,
683 g_dirname (rc_file->canonical_name));
684 gtk_rc_parse_any (filename, fd, NULL);
686 tmp_list = rc_dir_stack;
687 rc_dir_stack = rc_dir_stack->next;
689 g_free (tmp_list->data);
690 g_slist_free_1 (tmp_list);
697 gtk_rc_parse (const gchar *filename)
699 g_return_if_fail (filename != NULL);
701 gtk_rc_parse_file (filename, TRUE);
704 /* Handling of RC styles */
707 gtk_rc_style_new (void)
709 GtkRcStylePrivate *new_style;
711 new_style = g_new0 (GtkRcStylePrivate, 1);
712 new_style->ref_count = 1;
714 return (GtkRcStyle *)new_style;
718 gtk_rc_style_ref (GtkRcStyle *rc_style)
720 g_return_if_fail (rc_style != NULL);
722 ((GtkRcStylePrivate *)rc_style)->ref_count++;
725 /* Like g_slist_remove, but remove all copies of data */
727 gtk_rc_slist_remove_all (GSList *list,
738 if (tmp->data == data)
744 prev->next = tmp->next;
746 g_slist_free_1 (tmp);
764 gtk_rc_style_unref (GtkRcStyle *rc_style)
766 GtkRcStylePrivate *private = (GtkRcStylePrivate *)rc_style;
769 g_return_if_fail (rc_style != NULL);
770 g_return_if_fail (private->ref_count > 0);
772 private->ref_count--;
774 if (private->ref_count == 0)
776 GSList *tmp_list1, *tmp_list2;
778 if (rc_style->engine)
780 rc_style->engine->destroy_rc_style (rc_style);
781 gtk_theme_engine_unref (rc_style->engine);
785 g_free (rc_style->name);
786 if (rc_style->fontset_name)
787 g_free (rc_style->fontset_name);
788 if (rc_style->font_name)
789 g_free (rc_style->font_name);
791 for (i=0 ; i<5 ; i++)
792 if (rc_style->bg_pixmap_name[i])
793 g_free (rc_style->bg_pixmap_name[i]);
795 /* Now remove all references to this rc_style from
798 tmp_list1 = private->rc_style_lists;
801 GSList *rc_styles = tmp_list1->data;
802 GtkStyle *style = g_hash_table_lookup (realized_style_ht, rc_styles);
803 gtk_style_unref (style);
805 /* Remove the list of styles from the other rc_styles
808 tmp_list2 = rc_styles;
811 GtkRcStylePrivate *other_style = tmp_list2->data;
813 if (other_style != private)
814 other_style->rc_style_lists =
815 gtk_rc_slist_remove_all (other_style->rc_style_lists, rc_styles);
817 tmp_list2 = tmp_list2->next;
820 /* And from the hash table itself
822 g_hash_table_remove (realized_style_ht, rc_styles);
823 g_slist_free (rc_styles);
825 tmp_list1 = tmp_list1->next;
827 g_slist_free (private->rc_style_lists);
834 gtk_rc_clear_hash_node (gpointer key,
838 gtk_rc_style_unref (data);
842 gtk_rc_free_rc_sets (GSList *slist)
848 rc_set = slist->data;
849 gtk_pattern_spec_free_segs (&rc_set->pspec);
857 gtk_rc_clear_styles (void)
859 /* Clear out all old rc_styles */
863 g_hash_table_foreach (rc_style_ht, gtk_rc_clear_hash_node, NULL);
864 g_hash_table_destroy (rc_style_ht);
868 gtk_rc_free_rc_sets (gtk_rc_sets_widget);
869 g_slist_free (gtk_rc_sets_widget);
870 gtk_rc_sets_widget = NULL;
872 gtk_rc_free_rc_sets (gtk_rc_sets_widget_class);
873 g_slist_free (gtk_rc_sets_widget_class);
874 gtk_rc_sets_widget_class = NULL;
876 gtk_rc_free_rc_sets (gtk_rc_sets_class);
877 g_slist_free (gtk_rc_sets_class);
878 gtk_rc_sets_class = NULL;
882 gtk_rc_reparse_all (void)
885 gboolean mtime_modified = FALSE;
890 /* Check through and see if any of the RC's have had their
891 * mtime modified. If so, reparse everything.
896 rc_file = tmp_list->data;
898 if (!lstat (rc_file->name, &statbuf) &&
899 (statbuf.st_mtime > rc_file->mtime))
901 mtime_modified = TRUE;
905 tmp_list = tmp_list->next;
910 gtk_rc_clear_styles();
915 rc_file = tmp_list->data;
917 gtk_rc_parse_file (rc_file->name, FALSE);
919 tmp_list = tmp_list->next;
923 return mtime_modified;
927 gtk_rc_styles_match (GSList *rc_styles,
931 gchar *path_reversed)
941 if (gtk_pattern_match (&rc_set->pspec, path_length, path, path_reversed))
942 rc_styles = g_slist_append (rc_styles, rc_set->rc_style);
949 gtk_rc_get_style (GtkWidget *widget)
951 GtkRcStyle *widget_rc_style;
952 GSList *rc_styles = NULL;
954 static guint rc_style_key_id = 0;
956 /* We allow the specification of a single rc style to be bound
957 * tightly to a widget, for application modifications
959 if (!rc_style_key_id)
960 rc_style_key_id = g_quark_from_static_string ("gtk-rc-style");
962 widget_rc_style = gtk_object_get_data_by_id (GTK_OBJECT (widget),
966 rc_styles = g_slist_prepend (rc_styles, widget_rc_style);
968 if (gtk_rc_sets_widget)
970 gchar *path, *path_reversed;
973 gtk_widget_path (widget, &path_length, &path, &path_reversed);
974 rc_styles = gtk_rc_styles_match (rc_styles, gtk_rc_sets_widget, path_length, path, path_reversed);
976 g_free (path_reversed);
980 if (gtk_rc_sets_widget_class)
982 gchar *path, *path_reversed;
985 gtk_widget_class_path (widget, &path_length, &path, &path_reversed);
986 rc_styles = gtk_rc_styles_match (rc_styles, gtk_rc_sets_widget_class, path_length, path, path_reversed);
988 g_free (path_reversed);
991 if (gtk_rc_sets_class)
995 type = GTK_OBJECT_TYPE (widget);
998 gchar *path, *path_reversed;
1001 path = gtk_type_name (type);
1002 path_length = strlen (path);
1003 path_reversed = g_strdup (path);
1004 g_strreverse (path_reversed);
1006 rc_styles = gtk_rc_styles_match (rc_styles, gtk_rc_sets_class, path_length, path, path_reversed);
1007 g_free (path_reversed);
1009 type = gtk_type_parent (type);
1014 return gtk_rc_style_init (rc_styles);
1020 gtk_rc_add_rc_sets (GSList *slist,
1021 GtkRcStyle *rc_style,
1022 const char *pattern)
1024 GtkRcStyle *new_style;
1028 new_style = gtk_rc_style_new ();
1029 *new_style = *rc_style;
1030 new_style->name = g_strdup (rc_style->name);
1031 new_style->font_name = g_strdup (rc_style->font_name);
1032 new_style->fontset_name = g_strdup (rc_style->fontset_name);
1034 for (i = 0; i < 5; i++)
1035 new_style->bg_pixmap_name[i] = g_strdup (rc_style->bg_pixmap_name[i]);
1037 rc_set = g_new (GtkRcSet, 1);
1038 gtk_pattern_spec_init (&rc_set->pspec, pattern);
1039 rc_set->rc_style = rc_style;
1041 return g_slist_prepend (slist, rc_set);
1045 gtk_rc_add_widget_name_style (GtkRcStyle *rc_style,
1046 const gchar *pattern)
1048 g_return_if_fail (rc_style != NULL);
1049 g_return_if_fail (pattern != NULL);
1051 gtk_rc_sets_widget = gtk_rc_add_rc_sets (gtk_rc_sets_widget, rc_style, pattern);
1055 gtk_rc_add_widget_class_style (GtkRcStyle *rc_style,
1056 const gchar *pattern)
1058 g_return_if_fail (rc_style != NULL);
1059 g_return_if_fail (pattern != NULL);
1061 gtk_rc_sets_widget_class = gtk_rc_add_rc_sets (gtk_rc_sets_widget_class, rc_style, pattern);
1065 gtk_rc_add_class_style (GtkRcStyle *rc_style,
1066 const gchar *pattern)
1068 g_return_if_fail (rc_style != NULL);
1069 g_return_if_fail (pattern != NULL);
1071 gtk_rc_sets_class = gtk_rc_add_rc_sets (gtk_rc_sets_class, rc_style, pattern);
1075 gtk_rc_parse_any (const gchar *input_name,
1077 const gchar *input_string)
1083 scanner = g_scanner_new ((GScannerConfig *) >k_rc_scanner_config);
1087 g_assert (input_string == NULL);
1089 g_scanner_input_file (scanner, input_fd);
1093 g_assert (input_string != NULL);
1095 g_scanner_input_text (scanner, input_string, strlen (input_string));
1097 scanner->input_name = input_name;
1099 g_scanner_freeze_symbol_table (scanner);
1100 for (i = 0; i < n_symbols; i++)
1101 g_scanner_add_symbol (scanner, symbols[i].name, GINT_TO_POINTER (symbols[i].token));
1102 g_scanner_thaw_symbol_table (scanner);
1107 if (g_scanner_peek_next_token (scanner) == G_TOKEN_EOF)
1111 guint expected_token;
1113 expected_token = gtk_rc_parse_statement (scanner);
1115 if (expected_token != G_TOKEN_NONE)
1122 if (scanner->scope_id == 0)
1124 /* if we are in scope 0, we know the symbol names
1125 * that are associated with certaintoken values.
1126 * so we look them up to make the error messages
1129 if (expected_token > GTK_RC_TOKEN_INVALID &&
1130 expected_token < GTK_RC_TOKEN_LAST)
1132 for (i = 0; i < n_symbols; i++)
1133 if (symbols[i].token == expected_token)
1134 msg = symbols[i].name;
1136 msg = g_strconcat ("e.g. `", msg, "'", NULL);
1138 if (scanner->token > GTK_RC_TOKEN_INVALID &&
1139 scanner->token < GTK_RC_TOKEN_LAST)
1141 symbol_name = "???";
1142 for (i = 0; i < n_symbols; i++)
1143 if (symbols[i].token == scanner->token)
1144 symbol_name = symbols[i].name;
1147 g_scanner_unexp_token (scanner,
1160 g_scanner_destroy (scanner);
1164 gtk_rc_styles_hash (const GSList *rc_styles)
1171 result += (result << 9) + GPOINTER_TO_UINT (rc_styles->data);
1172 rc_styles = rc_styles->next;
1179 gtk_rc_styles_compare (const GSList *a,
1184 if (a->data != b->data)
1194 gtk_rc_style_hash (const char *name)
1200 result += (result << 3) + *name++;
1206 gtk_rc_style_compare (const char *a,
1209 return (strcmp (a, b) == 0);
1213 gtk_rc_style_find (const char *name)
1216 return g_hash_table_lookup (rc_style_ht, (gpointer) name);
1221 /* Assumes ownership of rc_style */
1223 gtk_rc_style_to_style (GtkRcStyle *rc_style)
1229 style = gtk_style_new ();
1231 style->rc_style = rc_style;
1233 if (rc_style->fontset_name)
1235 old_font = style->font;
1236 style->font = gdk_fontset_load (rc_style->fontset_name);
1238 gdk_font_unref (old_font);
1240 style->font = old_font;
1242 else if (rc_style->font_name)
1244 old_font = style->font;
1245 style->font = gdk_font_load (rc_style->font_name);
1247 gdk_font_unref (old_font);
1249 style->font = old_font;
1252 for (i = 0; i < 5; i++)
1254 if (rc_style->color_flags[i] & GTK_RC_FG)
1255 style->fg[i] = rc_style->fg[i];
1256 if (rc_style->color_flags[i] & GTK_RC_BG)
1257 style->bg[i] = rc_style->bg[i];
1258 if (rc_style->color_flags[i] & GTK_RC_TEXT)
1259 style->text[i] = rc_style->text[i];
1260 if (rc_style->color_flags[i] & GTK_RC_BASE)
1261 style->base[i] = rc_style->base[i];
1264 if (rc_style->engine)
1266 style->engine = rc_style->engine;
1267 gtk_theme_engine_ref (style->engine);
1268 rc_style->engine->rc_style_to_style (style, rc_style);
1274 /* Reuses or frees rc_styles */
1276 gtk_rc_style_init (GSList *rc_styles)
1280 GtkStyle *style = NULL;
1282 if (!realized_style_ht)
1283 realized_style_ht = g_hash_table_new ((GHashFunc)gtk_rc_styles_hash,
1284 (GCompareFunc)gtk_rc_styles_compare);
1286 style = g_hash_table_lookup (realized_style_ht, rc_styles);
1290 GtkRcStyle *proto_style;
1293 proto_style = gtk_rc_style_new ();
1295 tmp_styles = rc_styles;
1298 GtkRcStyle *rc_style = tmp_styles->data;
1299 GtkRcStylePrivate *rc_style_private;
1303 if (!proto_style->bg_pixmap_name[i] && rc_style->bg_pixmap_name[i])
1304 proto_style->bg_pixmap_name[i] = g_strdup (rc_style->bg_pixmap_name[i]);
1306 if (!(proto_style->color_flags[i] & GTK_RC_FG) &&
1307 rc_style->color_flags[i] & GTK_RC_FG)
1309 proto_style->fg[i] = rc_style->fg[i];
1310 proto_style->color_flags[i] |= GTK_RC_FG;
1312 if (!(proto_style->color_flags[i] & GTK_RC_BG) &&
1313 rc_style->color_flags[i] & GTK_RC_BG)
1315 proto_style->bg[i] = rc_style->bg[i];
1316 proto_style->color_flags[i] |= GTK_RC_BG;
1318 if (!(proto_style->color_flags[i] & GTK_RC_TEXT) &&
1319 rc_style->color_flags[i] & GTK_RC_TEXT)
1321 proto_style->text[i] = rc_style->text[i];
1322 proto_style->color_flags[i] |= GTK_RC_TEXT;
1324 if (!(proto_style->color_flags[i] & GTK_RC_BASE) &&
1325 rc_style->color_flags[i] & GTK_RC_BASE)
1327 proto_style->base[i] = rc_style->base[i];
1328 proto_style->color_flags[i] |= GTK_RC_BASE;
1332 if (!proto_style->font_name && rc_style->font_name)
1333 proto_style->font_name = g_strdup (rc_style->font_name);
1334 if (!proto_style->fontset_name && rc_style->fontset_name)
1335 proto_style->fontset_name = g_strdup (rc_style->fontset_name);
1337 if (!proto_style->engine && rc_style->engine)
1339 proto_style->engine = rc_style->engine;
1340 gtk_theme_engine_ref (proto_style->engine);
1343 if (proto_style->engine &&
1344 (proto_style->engine == rc_style->engine))
1345 proto_style->engine->merge_rc_style (proto_style, rc_style);
1347 /* Point from each rc_style to the list of styles */
1349 rc_style_private = (GtkRcStylePrivate *)rc_style;
1350 if (!g_slist_find (rc_style_private->rc_style_lists, rc_styles))
1351 rc_style_private->rc_style_lists = g_slist_prepend (rc_style_private->rc_style_lists, rc_styles);
1353 tmp_styles = tmp_styles->next;
1357 if (proto_style->bg_pixmap_name[i] &&
1358 (strcmp (proto_style->bg_pixmap_name[i], "<none>") == 0))
1360 g_free (proto_style->bg_pixmap_name[i]);
1361 proto_style->bg_pixmap_name[i] = NULL;
1364 style = gtk_rc_style_to_style (proto_style);
1366 g_hash_table_insert (realized_style_ht, rc_styles, style);
1369 g_slist_free (rc_styles);
1374 /*********************
1375 * Parsing functions *
1376 *********************/
1379 gtk_rc_parse_statement (GScanner *scanner)
1383 token = g_scanner_peek_next_token (scanner);
1387 case GTK_RC_TOKEN_INCLUDE:
1388 token = g_scanner_get_next_token (scanner);
1389 if (token != GTK_RC_TOKEN_INCLUDE)
1390 return GTK_RC_TOKEN_INCLUDE;
1392 token = g_scanner_get_next_token (scanner);
1393 if (token != G_TOKEN_STRING)
1394 return G_TOKEN_STRING;
1396 gtk_rc_parse_file (scanner->value.v_string, FALSE);
1397 return G_TOKEN_NONE;
1399 case GTK_RC_TOKEN_STYLE:
1400 return gtk_rc_parse_style (scanner);
1402 case GTK_RC_TOKEN_BINDING:
1403 return gtk_binding_parse_binding (scanner);
1405 case GTK_RC_TOKEN_PIXMAP_PATH:
1406 return gtk_rc_parse_pixmap_path (scanner);
1408 case GTK_RC_TOKEN_WIDGET:
1409 return gtk_rc_parse_path_pattern (scanner);
1411 case GTK_RC_TOKEN_WIDGET_CLASS:
1412 return gtk_rc_parse_path_pattern (scanner);
1414 case GTK_RC_TOKEN_CLASS:
1415 return gtk_rc_parse_path_pattern (scanner);
1417 case GTK_RC_TOKEN_MODULE_PATH:
1418 return gtk_rc_parse_module_path (scanner);
1421 g_scanner_get_next_token (scanner);
1422 return /* G_TOKEN_SYMBOL */ GTK_RC_TOKEN_STYLE;
1427 gtk_rc_parse_style (GScanner *scanner)
1429 GtkRcStyle *rc_style;
1430 GtkRcStyle *parent_style;
1435 token = g_scanner_get_next_token (scanner);
1436 if (token != GTK_RC_TOKEN_STYLE)
1437 return GTK_RC_TOKEN_STYLE;
1439 token = g_scanner_get_next_token (scanner);
1440 if (token != G_TOKEN_STRING)
1441 return G_TOKEN_STRING;
1444 rc_style = gtk_rc_style_find (scanner->value.v_string);
1449 rc_style = gtk_rc_style_new ();
1450 rc_style->name = g_strdup (scanner->value.v_string);
1452 for (i = 0; i < 5; i++)
1453 rc_style->bg_pixmap_name[i] = NULL;
1455 for (i = 0; i < 5; i++)
1456 rc_style->color_flags[i] = 0;
1458 rc_style->engine = NULL;
1459 rc_style->engine_data = NULL;
1462 token = g_scanner_peek_next_token (scanner);
1463 if (token == G_TOKEN_EQUAL_SIGN)
1465 token = g_scanner_get_next_token (scanner);
1467 token = g_scanner_get_next_token (scanner);
1468 if (token != G_TOKEN_STRING)
1473 return G_TOKEN_STRING;
1476 parent_style = gtk_rc_style_find (scanner->value.v_string);
1479 for (i = 0; i < 5; i++)
1481 rc_style->color_flags[i] = parent_style->color_flags[i];
1482 rc_style->fg[i] = parent_style->fg[i];
1483 rc_style->bg[i] = parent_style->bg[i];
1484 rc_style->text[i] = parent_style->text[i];
1485 rc_style->base[i] = parent_style->base[i];
1488 if (parent_style->fontset_name)
1490 if (rc_style->fontset_name)
1491 g_free (rc_style->fontset_name);
1492 rc_style->fontset_name = g_strdup (parent_style->fontset_name);
1494 else if (parent_style->font_name)
1496 if (rc_style->font_name)
1497 g_free (rc_style->font_name);
1498 rc_style->font_name = g_strdup (parent_style->font_name);
1501 for (i = 0; i < 5; i++)
1503 if (rc_style->bg_pixmap_name[i])
1504 g_free (rc_style->bg_pixmap_name[i]);
1505 rc_style->bg_pixmap_name[i] = g_strdup (parent_style->bg_pixmap_name[i]);
1510 token = g_scanner_get_next_token (scanner);
1511 if (token != G_TOKEN_LEFT_CURLY)
1516 return G_TOKEN_LEFT_CURLY;
1519 token = g_scanner_peek_next_token (scanner);
1520 while (token != G_TOKEN_RIGHT_CURLY)
1524 case GTK_RC_TOKEN_BASE:
1525 token = gtk_rc_parse_base (scanner, rc_style);
1527 case GTK_RC_TOKEN_BG:
1528 token = gtk_rc_parse_bg (scanner, rc_style);
1530 case GTK_RC_TOKEN_FG:
1531 token = gtk_rc_parse_fg (scanner, rc_style);
1533 case GTK_RC_TOKEN_TEXT:
1534 token = gtk_rc_parse_text (scanner, rc_style);
1536 case GTK_RC_TOKEN_BG_PIXMAP:
1537 token = gtk_rc_parse_bg_pixmap (scanner, rc_style);
1539 case GTK_RC_TOKEN_FONT:
1540 token = gtk_rc_parse_font (scanner, rc_style);
1542 case GTK_RC_TOKEN_FONTSET:
1543 token = gtk_rc_parse_fontset (scanner, rc_style);
1545 case GTK_RC_TOKEN_ENGINE:
1546 token = gtk_rc_parse_engine (scanner, rc_style);
1549 g_scanner_get_next_token (scanner);
1550 token = G_TOKEN_RIGHT_CURLY;
1554 if (token != G_TOKEN_NONE)
1558 if (rc_style->fontset_name)
1559 g_free (rc_style->fontset_name);
1560 if (rc_style->font_name)
1561 g_free (rc_style->font_name);
1562 for (i = 0; i < 5; i++)
1563 if (rc_style->bg_pixmap_name[i])
1564 g_free (rc_style->bg_pixmap_name[i]);
1569 token = g_scanner_peek_next_token (scanner);
1572 token = g_scanner_get_next_token (scanner);
1573 if (token != G_TOKEN_RIGHT_CURLY)
1577 if (rc_style->fontset_name)
1578 g_free (rc_style->fontset_name);
1579 if (rc_style->font_name)
1580 g_free (rc_style->font_name);
1582 for (i = 0; i < 5; i++)
1583 if (rc_style->bg_pixmap_name[i])
1584 g_free (rc_style->bg_pixmap_name[i]);
1588 return G_TOKEN_RIGHT_CURLY;
1594 rc_style_ht = g_hash_table_new ((GHashFunc) gtk_rc_style_hash,
1595 (GCompareFunc) gtk_rc_style_compare);
1597 g_hash_table_insert (rc_style_ht, rc_style->name, rc_style);
1600 return G_TOKEN_NONE;
1604 gtk_rc_parse_base (GScanner *scanner,
1610 token = g_scanner_get_next_token (scanner);
1611 if (token != GTK_RC_TOKEN_BASE)
1612 return GTK_RC_TOKEN_BASE;
1614 token = gtk_rc_parse_state (scanner, &state);
1615 if (token != G_TOKEN_NONE)
1618 token = g_scanner_get_next_token (scanner);
1619 if (token != G_TOKEN_EQUAL_SIGN)
1620 return G_TOKEN_EQUAL_SIGN;
1622 style->color_flags[state] |= GTK_RC_BASE;
1623 return gtk_rc_parse_color (scanner, &style->base[state]);
1627 gtk_rc_parse_bg (GScanner *scanner,
1633 token = g_scanner_get_next_token (scanner);
1634 if (token != GTK_RC_TOKEN_BG)
1635 return GTK_RC_TOKEN_BG;
1637 token = gtk_rc_parse_state (scanner, &state);
1638 if (token != G_TOKEN_NONE)
1641 token = g_scanner_get_next_token (scanner);
1642 if (token != G_TOKEN_EQUAL_SIGN)
1643 return G_TOKEN_EQUAL_SIGN;
1645 style->color_flags[state] |= GTK_RC_BG;
1646 return gtk_rc_parse_color (scanner, &style->bg[state]);
1650 gtk_rc_parse_fg (GScanner *scanner,
1656 token = g_scanner_get_next_token (scanner);
1657 if (token != GTK_RC_TOKEN_FG)
1658 return GTK_RC_TOKEN_FG;
1660 token = gtk_rc_parse_state (scanner, &state);
1661 if (token != G_TOKEN_NONE)
1664 token = g_scanner_get_next_token (scanner);
1665 if (token != G_TOKEN_EQUAL_SIGN)
1666 return G_TOKEN_EQUAL_SIGN;
1668 style->color_flags[state] |= GTK_RC_FG;
1669 return gtk_rc_parse_color (scanner, &style->fg[state]);
1673 gtk_rc_parse_text (GScanner *scanner,
1679 token = g_scanner_get_next_token (scanner);
1680 if (token != GTK_RC_TOKEN_TEXT)
1681 return GTK_RC_TOKEN_TEXT;
1683 token = gtk_rc_parse_state (scanner, &state);
1684 if (token != G_TOKEN_NONE)
1687 token = g_scanner_get_next_token (scanner);
1688 if (token != G_TOKEN_EQUAL_SIGN)
1689 return G_TOKEN_EQUAL_SIGN;
1691 style->color_flags[state] |= GTK_RC_TEXT;
1692 return gtk_rc_parse_color (scanner, &style->text[state]);
1696 gtk_rc_parse_bg_pixmap (GScanner *scanner,
1697 GtkRcStyle *rc_style)
1703 token = g_scanner_get_next_token (scanner);
1704 if (token != GTK_RC_TOKEN_BG_PIXMAP)
1705 return GTK_RC_TOKEN_BG_PIXMAP;
1707 token = gtk_rc_parse_state (scanner, &state);
1708 if (token != G_TOKEN_NONE)
1711 token = g_scanner_get_next_token (scanner);
1712 if (token != G_TOKEN_EQUAL_SIGN)
1713 return G_TOKEN_EQUAL_SIGN;
1715 token = g_scanner_get_next_token (scanner);
1716 if (token != G_TOKEN_STRING)
1717 return G_TOKEN_STRING;
1719 if ((strcmp (scanner->value.v_string, "<parent>") == 0) ||
1720 (strcmp (scanner->value.v_string, "<none>") == 0))
1721 pixmap_file = g_strdup (scanner->value.v_string);
1723 pixmap_file = gtk_rc_find_pixmap_in_path (scanner, scanner->value.v_string);
1727 if (rc_style->bg_pixmap_name[state])
1728 g_free (rc_style->bg_pixmap_name[state]);
1729 rc_style->bg_pixmap_name[state] = pixmap_file;
1732 return G_TOKEN_NONE;
1736 gtk_rc_check_pixmap_dir (const gchar *dir, const gchar *pixmap_file)
1741 buf = g_strdup_printf ("%s" G_DIR_SEPARATOR_S "%s", dir, pixmap_file);
1743 fd = open (buf, O_RDONLY);
1756 gtk_rc_find_pixmap_in_path (GScanner *scanner,
1757 const gchar *pixmap_file)
1763 for (i = 0; (i < GTK_RC_MAX_PIXMAP_PATHS) && (pixmap_path[i] != NULL); i++)
1765 filename = gtk_rc_check_pixmap_dir (pixmap_path[i], pixmap_file);
1770 tmp_list = rc_dir_stack;
1773 filename = gtk_rc_check_pixmap_dir (tmp_list->data, pixmap_file);
1777 tmp_list = tmp_list->next;
1781 g_warning (_("Unable to locate image file in pixmap_path: \"%s\" line %d"),
1782 pixmap_file, scanner->line);
1784 g_warning (_("Unable to locate image file in pixmap_path: \"%s\""),
1791 gtk_rc_find_module_in_path (const gchar *module_file)
1797 for (i = 0; (i < GTK_RC_MAX_MODULE_PATHS) && (module_path[i] != NULL); i++)
1799 buf = g_strdup_printf ("%s" G_DIR_SEPARATOR_S "%s",
1800 module_path[i], module_file);
1802 fd = open (buf, O_RDONLY);
1816 gtk_rc_parse_font (GScanner *scanner,
1817 GtkRcStyle *rc_style)
1821 token = g_scanner_get_next_token (scanner);
1822 if (token != GTK_RC_TOKEN_FONT)
1823 return GTK_RC_TOKEN_FONT;
1825 token = g_scanner_get_next_token (scanner);
1826 if (token != G_TOKEN_EQUAL_SIGN)
1827 return G_TOKEN_EQUAL_SIGN;
1829 token = g_scanner_get_next_token (scanner);
1830 if (token != G_TOKEN_STRING)
1831 return G_TOKEN_STRING;
1833 if (rc_style->font_name)
1834 g_free (rc_style->font_name);
1835 rc_style->font_name = g_strdup (scanner->value.v_string);
1837 return G_TOKEN_NONE;
1841 gtk_rc_parse_fontset (GScanner *scanner,
1842 GtkRcStyle *rc_style)
1846 token = g_scanner_get_next_token (scanner);
1847 if (token != GTK_RC_TOKEN_FONTSET)
1848 return GTK_RC_TOKEN_FONTSET;
1850 token = g_scanner_get_next_token (scanner);
1851 if (token != G_TOKEN_EQUAL_SIGN)
1852 return G_TOKEN_EQUAL_SIGN;
1854 token = g_scanner_get_next_token (scanner);
1855 if (token != G_TOKEN_STRING)
1856 return G_TOKEN_STRING;
1858 if (rc_style->fontset_name)
1859 g_free (rc_style->fontset_name);
1860 rc_style->fontset_name = g_strdup (scanner->value.v_string);
1862 return G_TOKEN_NONE;
1866 gtk_rc_parse_engine (GScanner *scanner,
1867 GtkRcStyle *rc_style)
1871 token = g_scanner_get_next_token (scanner);
1872 if (token != GTK_RC_TOKEN_ENGINE)
1873 return GTK_RC_TOKEN_ENGINE;
1875 token = g_scanner_get_next_token (scanner);
1876 if (token != G_TOKEN_STRING)
1877 return G_TOKEN_STRING;
1879 rc_style->engine = gtk_theme_engine_get (scanner->value.v_string);
1881 token = g_scanner_get_next_token (scanner);
1882 if (token != G_TOKEN_LEFT_CURLY)
1883 return G_TOKEN_LEFT_CURLY;
1885 if (rc_style->engine)
1886 return rc_style->engine->parse_rc_style (scanner, rc_style);
1889 /* Skip over remainder, looking for nested {}'s */
1892 while ((token = g_scanner_get_next_token (scanner)) != G_TOKEN_EOF)
1894 if (token == G_TOKEN_LEFT_CURLY)
1896 else if (token == G_TOKEN_RIGHT_CURLY)
1900 return G_TOKEN_NONE;
1903 return G_TOKEN_RIGHT_CURLY;
1908 gtk_rc_parse_state (GScanner *scanner,
1909 GtkStateType *state)
1914 g_return_val_if_fail (scanner != NULL, G_TOKEN_ERROR);
1915 g_return_val_if_fail (state != NULL, G_TOKEN_ERROR);
1917 /* we don't know where we got called from, so we reset the scope here.
1918 * if we bail out due to errors, we *don't* reset the scope, so the
1919 * error messaging code can make sense of our tokens.
1921 old_scope = g_scanner_set_scope (scanner, 0);
1923 token = g_scanner_get_next_token (scanner);
1924 if (token != G_TOKEN_LEFT_BRACE)
1925 return G_TOKEN_LEFT_BRACE;
1927 token = g_scanner_get_next_token (scanner);
1930 case GTK_RC_TOKEN_ACTIVE:
1931 *state = GTK_STATE_ACTIVE;
1933 case GTK_RC_TOKEN_INSENSITIVE:
1934 *state = GTK_STATE_INSENSITIVE;
1936 case GTK_RC_TOKEN_NORMAL:
1937 *state = GTK_STATE_NORMAL;
1939 case GTK_RC_TOKEN_PRELIGHT:
1940 *state = GTK_STATE_PRELIGHT;
1942 case GTK_RC_TOKEN_SELECTED:
1943 *state = GTK_STATE_SELECTED;
1946 return /* G_TOKEN_SYMBOL */ GTK_RC_TOKEN_NORMAL;
1949 token = g_scanner_get_next_token (scanner);
1950 if (token != G_TOKEN_RIGHT_BRACE)
1951 return G_TOKEN_RIGHT_BRACE;
1953 g_scanner_set_scope (scanner, old_scope);
1955 return G_TOKEN_NONE;
1959 gtk_rc_parse_priority (GScanner *scanner,
1960 GtkPathPriorityType *priority)
1965 g_return_val_if_fail (scanner != NULL, G_TOKEN_ERROR);
1966 g_return_val_if_fail (priority != NULL, G_TOKEN_ERROR);
1968 /* we don't know where we got called from, so we reset the scope here.
1969 * if we bail out due to errors, we *don't* reset the scope, so the
1970 * error messaging code can make sense of our tokens.
1972 old_scope = g_scanner_set_scope (scanner, 0);
1974 token = g_scanner_get_next_token (scanner);
1978 token = g_scanner_get_next_token (scanner);
1981 case GTK_RC_TOKEN_LOWEST:
1982 *priority = GTK_PATH_PRIO_LOWEST;
1984 case GTK_RC_TOKEN_GTK:
1985 *priority = GTK_PATH_PRIO_GTK;
1987 case GTK_RC_TOKEN_APPLICATION:
1988 *priority = GTK_PATH_PRIO_APPLICATION;
1990 case GTK_RC_TOKEN_RC:
1991 *priority = GTK_PATH_PRIO_RC;
1993 case GTK_RC_TOKEN_HIGHEST:
1994 *priority = GTK_PATH_PRIO_HIGHEST;
1997 return /* G_TOKEN_SYMBOL */ GTK_RC_TOKEN_APPLICATION;
2000 g_scanner_set_scope (scanner, old_scope);
2002 return G_TOKEN_NONE;
2006 gtk_rc_parse_color (GScanner *scanner,
2011 g_return_val_if_fail (scanner != NULL, G_TOKEN_ERROR);
2013 /* we don't need to set our own scop here, because
2014 * we don't need own symbols
2017 token = g_scanner_get_next_token (scanner);
2026 case G_TOKEN_LEFT_CURLY:
2027 token = g_scanner_get_next_token (scanner);
2028 if (token == G_TOKEN_INT)
2029 token_int = scanner->value.v_int;
2030 else if (token == G_TOKEN_FLOAT)
2031 token_int = scanner->value.v_float * 65535.0;
2033 return G_TOKEN_FLOAT;
2034 color->red = CLAMP (token_int, 0, 65535);
2036 token = g_scanner_get_next_token (scanner);
2037 if (token != G_TOKEN_COMMA)
2038 return G_TOKEN_COMMA;
2040 token = g_scanner_get_next_token (scanner);
2041 if (token == G_TOKEN_INT)
2042 token_int = scanner->value.v_int;
2043 else if (token == G_TOKEN_FLOAT)
2044 token_int = scanner->value.v_float * 65535.0;
2046 return G_TOKEN_FLOAT;
2047 color->green = CLAMP (token_int, 0, 65535);
2049 token = g_scanner_get_next_token (scanner);
2050 if (token != G_TOKEN_COMMA)
2051 return G_TOKEN_COMMA;
2053 token = g_scanner_get_next_token (scanner);
2054 if (token == G_TOKEN_INT)
2055 token_int = scanner->value.v_int;
2056 else if (token == G_TOKEN_FLOAT)
2057 token_int = scanner->value.v_float * 65535.0;
2059 return G_TOKEN_FLOAT;
2060 color->blue = CLAMP (token_int, 0, 65535);
2062 token = g_scanner_get_next_token (scanner);
2063 if (token != G_TOKEN_RIGHT_CURLY)
2064 return G_TOKEN_RIGHT_CURLY;
2065 return G_TOKEN_NONE;
2067 case G_TOKEN_STRING:
2068 if (scanner->value.v_string[0] != '#')
2069 return G_TOKEN_STRING;
2071 length = strlen (scanner->value.v_string) - 1;
2072 if (((length % 3) != 0) || (length > 12))
2073 return G_TOKEN_STRING;
2076 for (i = 0, j = 1; i < length; i++, j++)
2077 buf[i] = scanner->value.v_string[j];
2080 sscanf (buf, "%x", &temp);
2083 for (i = 0; i < length; i++, j++)
2084 buf[i] = scanner->value.v_string[j];
2087 sscanf (buf, "%x", &temp);
2088 color->green = temp;
2090 for (i = 0; i < length; i++, j++)
2091 buf[i] = scanner->value.v_string[j];
2094 sscanf (buf, "%x", &temp);
2100 color->green *= 4369;
2101 color->blue *= 4369;
2103 else if (length == 2)
2106 color->green *= 257;
2109 else if (length == 3)
2115 return G_TOKEN_NONE;
2118 return G_TOKEN_STRING;
2123 gtk_rc_parse_pixmap_path (GScanner *scanner)
2127 token = g_scanner_get_next_token (scanner);
2128 if (token != GTK_RC_TOKEN_PIXMAP_PATH)
2129 return GTK_RC_TOKEN_PIXMAP_PATH;
2131 token = g_scanner_get_next_token (scanner);
2132 if (token != G_TOKEN_STRING)
2133 return G_TOKEN_STRING;
2135 gtk_rc_parse_pixmap_path_string (scanner->value.v_string);
2137 return G_TOKEN_NONE;
2141 gtk_rc_parse_pixmap_path_string (gchar *pix_path)
2145 gint start_offset = 0;
2149 /* free the old one, or just add to the old one ? */
2150 for (path_num=0; pixmap_path[path_num]; path_num++)
2152 g_free (pixmap_path[path_num]);
2153 pixmap_path[path_num] = NULL;
2158 path_len = strlen (pix_path);
2160 buf = g_strdup (pix_path);
2162 for (end_offset = 0; end_offset <= path_len; end_offset++)
2164 if ((buf[end_offset] == G_SEARCHPATH_SEPARATOR) ||
2165 (end_offset == path_len))
2167 buf[end_offset] = '\0';
2168 pixmap_path[path_num] = g_strdup (buf + start_offset);
2170 pixmap_path[path_num] = NULL;
2171 start_offset = end_offset + 1;
2175 gtk_rc_append_default_pixmap_path();
2179 gtk_rc_parse_module_path (GScanner *scanner)
2183 token = g_scanner_get_next_token (scanner);
2184 if (token != GTK_RC_TOKEN_MODULE_PATH)
2185 return GTK_RC_TOKEN_MODULE_PATH;
2187 token = g_scanner_get_next_token (scanner);
2188 if (token != G_TOKEN_STRING)
2189 return G_TOKEN_STRING;
2191 gtk_rc_parse_module_path_string (scanner->value.v_string);
2193 return G_TOKEN_NONE;
2197 gtk_rc_parse_module_path_string (gchar *mod_path)
2201 gint start_offset = 0;
2205 /* free the old one, or just add to the old one ? */
2206 for (path_num=0; module_path[path_num]; path_num++)
2208 g_free (module_path[path_num]);
2209 module_path[path_num] = NULL;
2214 path_len = strlen (mod_path);
2216 buf = g_strdup (mod_path);
2218 for (end_offset = 0; end_offset <= path_len; end_offset++)
2220 if ((buf[end_offset] == G_SEARCHPATH_SEPARATOR) ||
2221 (end_offset == path_len))
2223 buf[end_offset] = '\0';
2224 module_path[path_num] = g_strdup (buf + start_offset);
2226 module_path[path_num] = NULL;
2227 start_offset = end_offset + 1;
2231 gtk_rc_append_default_module_path();
2235 gtk_rc_parse_path_pattern (GScanner *scanner)
2238 GtkPathType path_type;
2240 gboolean is_binding;
2241 GtkPathPriorityType priority = GTK_PATH_PRIO_RC;
2243 token = g_scanner_get_next_token (scanner);
2246 case GTK_RC_TOKEN_WIDGET:
2247 path_type = GTK_PATH_WIDGET;
2249 case GTK_RC_TOKEN_WIDGET_CLASS:
2250 path_type = GTK_PATH_WIDGET_CLASS;
2252 case GTK_RC_TOKEN_CLASS:
2253 path_type = GTK_PATH_CLASS;
2256 return GTK_RC_TOKEN_WIDGET_CLASS;
2259 token = g_scanner_get_next_token (scanner);
2260 if (token != G_TOKEN_STRING)
2261 return G_TOKEN_STRING;
2263 pattern = g_strdup (scanner->value.v_string);
2265 token = g_scanner_get_next_token (scanner);
2266 if (token == GTK_RC_TOKEN_STYLE)
2268 else if (token == GTK_RC_TOKEN_BINDING)
2271 if (g_scanner_peek_next_token (scanner) == ':')
2273 token = gtk_rc_parse_priority (scanner, &priority);
2274 if (token != G_TOKEN_NONE)
2284 return GTK_RC_TOKEN_STYLE;
2287 token = g_scanner_get_next_token (scanner);
2288 if (token != G_TOKEN_STRING)
2291 return G_TOKEN_STRING;
2296 GtkBindingSet *binding;
2298 binding = gtk_binding_set_find (scanner->value.v_string);
2302 return G_TOKEN_STRING;
2304 gtk_binding_set_add_path (binding, path_type, pattern, priority);
2308 GtkRcStyle *rc_style;
2311 rc_style = gtk_rc_style_find (scanner->value.v_string);
2316 return G_TOKEN_STRING;
2319 rc_set = g_new (GtkRcSet, 1);
2320 gtk_pattern_spec_init (&rc_set->pspec, pattern);
2321 rc_set->rc_style = rc_style;
2323 if (path_type == GTK_PATH_WIDGET)
2324 gtk_rc_sets_widget = g_slist_prepend (gtk_rc_sets_widget, rc_set);
2325 else if (path_type == GTK_PATH_WIDGET_CLASS)
2326 gtk_rc_sets_widget_class = g_slist_prepend (gtk_rc_sets_widget_class, rc_set);
2328 gtk_rc_sets_class = g_slist_prepend (gtk_rc_sets_class, rc_set);
2332 return G_TOKEN_NONE;
2336 typedef GdkPixmap * (*GtkImageLoader) (GdkWindow *window,
2337 GdkColormap *colormap,
2339 GdkColor *transparent_color,
2340 const gchar *filename);
2344 gtk_rc_set_image_loader(GtkImageLoader loader)
2346 image_loader = loader;
2350 gtk_rc_load_image (GdkColormap *colormap,
2351 GdkColor *transparent_color,
2352 const gchar *filename)
2354 if (strcmp (filename, "<parent>") == 0)
2355 return (GdkPixmap*) GDK_PARENT_RELATIVE;
2359 return image_loader(NULL, colormap, NULL,
2363 return gdk_pixmap_colormap_create_from_xpm (NULL, colormap, NULL,