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;
67 typedef struct _GtkRcStylePrivate GtkRcStylePrivate;
79 gchar *canonical_name;
83 struct _GtkRcStylePrivate
88 /* list of RC style lists including this RC style */
89 GSList *rc_style_lists;
92 static guint gtk_rc_style_hash (const char *name);
93 static gint gtk_rc_style_compare (const char *a,
95 static guint gtk_rc_styles_hash (const GSList *rc_styles);
96 static gint gtk_rc_styles_compare (const GSList *a,
98 static GtkRcStyle* gtk_rc_style_find (const char *name);
99 static GSList * gtk_rc_styles_match (GSList *rc_styles,
103 gchar *path_reversed);
104 static GtkStyle * gtk_rc_style_to_style (GtkRcStyle *rc_style);
105 static GtkStyle* gtk_rc_style_init (GSList *rc_styles);
106 static void gtk_rc_parse_file (const gchar *filename,
109 static void gtk_rc_parse_any (const gchar *input_name,
111 const gchar *input_string);
112 static guint gtk_rc_parse_statement (GScanner *scanner);
113 static guint gtk_rc_parse_style (GScanner *scanner);
114 static guint gtk_rc_parse_base (GScanner *scanner,
116 static guint gtk_rc_parse_bg (GScanner *scanner,
118 static guint gtk_rc_parse_fg (GScanner *scanner,
120 static guint gtk_rc_parse_text (GScanner *scanner,
122 static guint gtk_rc_parse_bg_pixmap (GScanner *scanner,
123 GtkRcStyle *rc_style);
124 static guint gtk_rc_parse_font (GScanner *scanner,
125 GtkRcStyle *rc_style);
126 static guint gtk_rc_parse_fontset (GScanner *scanner,
127 GtkRcStyle *rc_style);
128 static guint gtk_rc_parse_font_name (GScanner *scanner,
129 GtkRcStyle *rc_style);
130 static guint gtk_rc_parse_engine (GScanner *scanner,
131 GtkRcStyle *rc_style);
132 static guint gtk_rc_parse_pixmap_path (GScanner *scanner);
133 static void gtk_rc_parse_pixmap_path_string (gchar *pix_path);
134 static guint gtk_rc_parse_module_path (GScanner *scanner);
135 static void gtk_rc_parse_module_path_string (gchar *mod_path);
136 static guint gtk_rc_parse_path_pattern (GScanner *scanner);
137 static void gtk_rc_clear_hash_node (gpointer key,
140 static void gtk_rc_clear_styles (void);
141 static void gtk_rc_append_default_pixmap_path (void);
142 static void gtk_rc_append_default_module_path (void);
143 static void gtk_rc_add_initial_default_files (void);
146 static const GScannerConfig gtk_rc_scanner_config =
150 ) /* cset_skip_characters */,
155 ) /* cset_identifier_first */,
160 ) /* cset_identifier_nth */,
161 ( "#\n" ) /* cpair_comment_single */,
163 TRUE /* case_sensitive */,
165 TRUE /* skip_comment_multi */,
166 TRUE /* skip_comment_single */,
167 TRUE /* scan_comment_multi */,
168 TRUE /* scan_identifier */,
169 FALSE /* scan_identifier_1char */,
170 FALSE /* scan_identifier_NULL */,
171 TRUE /* scan_symbols */,
172 TRUE /* scan_binary */,
173 TRUE /* scan_octal */,
174 TRUE /* scan_float */,
176 TRUE /* scan_hex_dollar */,
177 TRUE /* scan_string_sq */,
178 TRUE /* scan_string_dq */,
179 TRUE /* numbers_2_int */,
180 FALSE /* int_2_float */,
181 FALSE /* identifier_2_string */,
182 TRUE /* char_2_token */,
183 TRUE /* symbol_2_token */,
184 FALSE /* scope_0_fallback */,
192 { "include", GTK_RC_TOKEN_INCLUDE },
193 { "NORMAL", GTK_RC_TOKEN_NORMAL },
194 { "ACTIVE", GTK_RC_TOKEN_ACTIVE },
195 { "PRELIGHT", GTK_RC_TOKEN_PRELIGHT },
196 { "SELECTED", GTK_RC_TOKEN_SELECTED },
197 { "INSENSITIVE", GTK_RC_TOKEN_INSENSITIVE },
198 { "fg", GTK_RC_TOKEN_FG },
199 { "bg", GTK_RC_TOKEN_BG },
200 { "base", GTK_RC_TOKEN_BASE },
201 { "text", GTK_RC_TOKEN_TEXT },
202 { "font", GTK_RC_TOKEN_FONT },
203 { "fontset", GTK_RC_TOKEN_FONTSET },
204 { "font_name", GTK_RC_TOKEN_FONT_NAME },
205 { "bg_pixmap", GTK_RC_TOKEN_BG_PIXMAP },
206 { "pixmap_path", GTK_RC_TOKEN_PIXMAP_PATH },
207 { "style", GTK_RC_TOKEN_STYLE },
208 { "binding", GTK_RC_TOKEN_BINDING },
209 { "bind", GTK_RC_TOKEN_BIND },
210 { "widget", GTK_RC_TOKEN_WIDGET },
211 { "widget_class", GTK_RC_TOKEN_WIDGET_CLASS },
212 { "class", GTK_RC_TOKEN_CLASS },
213 { "lowest", GTK_RC_TOKEN_LOWEST },
214 { "gtk", GTK_RC_TOKEN_GTK },
215 { "application", GTK_RC_TOKEN_APPLICATION },
216 { "rc", GTK_RC_TOKEN_RC },
217 { "highest", GTK_RC_TOKEN_HIGHEST },
218 { "engine", GTK_RC_TOKEN_ENGINE },
219 { "module_path", GTK_RC_TOKEN_MODULE_PATH },
222 static const guint n_symbols = sizeof (symbols) / sizeof (symbols[0]);
224 static GHashTable *rc_style_ht = NULL;
225 static GHashTable *realized_style_ht = NULL;
226 static GSList *gtk_rc_sets_widget = NULL;
227 static GSList *gtk_rc_sets_widget_class = NULL;
228 static GSList *gtk_rc_sets_class = NULL;
230 #define GTK_RC_MAX_DEFAULT_FILES 128
231 static gchar *gtk_rc_default_files[GTK_RC_MAX_DEFAULT_FILES];
232 static gboolean gtk_rc_auto_parse = TRUE;
234 #define GTK_RC_MAX_PIXMAP_PATHS 128
235 static gchar *pixmap_path[GTK_RC_MAX_PIXMAP_PATHS];
236 #define GTK_RC_MAX_MODULE_PATHS 128
237 static gchar *module_path[GTK_RC_MAX_MODULE_PATHS];
239 /* A stack of directories for RC files we are parsing currently.
240 * these are implicitely added to the end of PIXMAP_PATHS
242 GSList *rc_dir_stack = NULL;
244 /* The files we have parsed, to reread later if necessary */
245 GSList *rc_files = NULL;
247 static GtkImageLoader image_loader = NULL;
249 /* RC file handling */
255 get_gtk_sysconf_directory (void)
257 static gboolean been_here = FALSE;
258 static gchar gtk_sysconf_dir[200];
262 DWORD nbytes = sizeof (gtk_sysconf_dir);
265 return gtk_sysconf_dir;
269 if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, "Software\\GNU\\GTk+", 0,
270 KEY_QUERY_VALUE, ®_key) != ERROR_SUCCESS
271 || RegQueryValueEx (reg_key, "InstallationDirectory", 0,
272 &type, gtk_sysconf_dir, &nbytes) != ERROR_SUCCESS
275 /* Uh oh. Use the old hard-coded %WinDir%\GTk+ value */
276 GetWindowsDirectory (win_dir, sizeof (win_dir));
277 sprintf (gtk_sysconf_dir, "%s\\gtk+", win_dir);
281 RegCloseKey (reg_key);
283 return gtk_sysconf_dir;
287 get_themes_directory (void)
289 static gchar themes_dir[200];
291 sprintf (themes_dir, "%s\\themes", get_gtk_sysconf_directory ());
298 gtk_rc_get_theme_dir(void)
303 var = getenv("GTK_DATA_PREFIX");
305 path = g_strdup_printf("%s%s", var, "/share/themes");
307 path = g_strdup_printf("%s%s", GTK_DATA_PREFIX, "/share/themes");
309 path = g_strdup (get_themes_directory ());
316 gtk_rc_get_module_dir(void)
321 var = getenv("GTK_EXE_PREFIX");
323 path = g_strdup_printf("%s%s", var, "/lib/gtk/themes/engines");
325 path = g_strdup_printf("%s%s", GTK_EXE_PREFIX, "/lib/gtk/themes/engines");
327 path = g_strdup_printf ("%s%s", get_themes_directory (), "\\engines");
334 gtk_rc_append_default_pixmap_path(void)
340 var = getenv("GTK_DATA_PREFIX");
342 path = g_strdup_printf("%s%s", var, "/share/gtk/themes");
344 path = g_strdup_printf("%s%s", GTK_DATA_PREFIX, "/share/gtk/themes");
346 path = g_strdup (get_themes_directory ());
349 for (n = 0; pixmap_path[n]; n++) ;
350 if (n >= GTK_RC_MAX_PIXMAP_PATHS - 1)
355 pixmap_path[n++] = path;
356 pixmap_path[n] = NULL;
360 gtk_rc_append_default_module_path(void)
365 for (n = 0; module_path[n]; n++) ;
366 if (n >= GTK_RC_MAX_MODULE_PATHS - 1)
370 var = getenv("GTK_EXE_PREFIX");
372 path = g_strdup_printf("%s%s", var, "/lib/gtk/themes/engines");
374 path = g_strdup_printf("%s%s", GTK_EXE_PREFIX, "/lib/gtk/themes/engines");
376 path = g_strdup_printf ("%s%s", get_themes_directory (), "\\engines");
378 module_path[n++] = path;
380 var = g_get_home_dir ();
384 path = g_strdup_printf ("%s%s", var, "/.gtk/lib/themes/engines");
386 path = g_strdup_printf ("%s%s", var, "\\_gtk\\themes\\engines");
388 module_path[n++] = path;
390 module_path[n] = NULL;
394 gtk_rc_add_initial_default_files (void)
396 static gint init = FALSE;
404 gtk_rc_default_files[0] = NULL;
407 var = g_getenv("GTK_RC_FILES");
410 files = g_strsplit (var, G_SEARCHPATH_SEPARATOR_S, 128);
414 gtk_rc_add_default_file (files[i]);
422 str = g_strdup (GTK_SYSCONFDIR G_DIR_SEPARATOR_S "gtk" G_DIR_SEPARATOR_S "gtkrc");
424 str = g_strdup_printf ("%s\\gtkrc", get_gtk_sysconf_directory ());
426 gtk_rc_add_default_file (str);
429 var = g_get_home_dir ();
432 str = g_strdup_printf ("%s" G_DIR_SEPARATOR_S ".gtkrc", var);
433 gtk_rc_add_default_file (str);
440 gtk_rc_add_default_file (const gchar *file)
444 gtk_rc_add_initial_default_files ();
446 for (n = 0; gtk_rc_default_files[n]; n++) ;
447 if (n >= GTK_RC_MAX_DEFAULT_FILES - 1)
450 gtk_rc_default_files[n++] = g_strdup (file);
451 gtk_rc_default_files[n] = NULL;
455 gtk_rc_set_default_files (gchar **files)
459 gtk_rc_add_initial_default_files ();
462 while (gtk_rc_default_files[i])
464 g_free (gtk_rc_default_files[i]);
468 gtk_rc_default_files[0] = NULL;
469 gtk_rc_auto_parse = FALSE;
472 while (files[i] != NULL)
474 gtk_rc_add_default_file (files[i]);
480 gtk_rc_get_default_files (void)
482 gtk_rc_add_initial_default_files ();
484 return gtk_rc_default_files;
487 /* The following routine is based on _nl_normalize_codeset from
488 * the GNU C library. Contributed by
490 * Contributed by Ulrich Drepper <drepper@gnu.ai.mit.edu>, 1995.
491 * Copyright (C) 1995, 1996, 1997, 1998, 1999 Free Software Foundation, Inc.
493 * Normalize codeset name. There is no standard for the codeset
494 * names. Normalization allows the user to use any of the common
498 _gtk_normalize_codeset (const char *codeset, int name_len)
506 for (cnt = 0; cnt < name_len; ++cnt)
507 if (isalnum (codeset[cnt]))
511 if (isalpha (codeset[cnt]))
515 retval = g_malloc ((only_digit ? 3 : 0) + len + 1);
519 strcpy (retval, "iso");
525 for (cnt = 0; cnt < name_len; ++cnt)
526 if (isalpha (codeset[cnt]))
527 *wp++ = isupper(codeset[cnt]) ? tolower (codeset[cnt]) : codeset[cnt];
528 else if (isdigit (codeset[cnt]))
529 *wp++ = codeset[cnt];
539 static gchar *locale_suffixes[3];
540 static gint n_locale_suffixes = 0;
544 static gboolean initted = FALSE;
553 locale = g_win32_getlocale ();
555 locale = setlocale (LC_CTYPE, NULL);
560 pixmap_path[0] = NULL;
561 module_path[0] = NULL;
562 gtk_rc_append_default_pixmap_path();
563 gtk_rc_append_default_module_path();
565 gtk_rc_add_initial_default_files ();
567 if (strcmp (locale, "C") && strcmp (locale, "POSIX"))
569 /* Determine locale-specific suffixes for RC files
571 * We normalize the charset into a standard form,
572 * which has all '-' and '_' characters removed,
575 gchar *normalized_locale;
577 p = strchr (locale, '@');
578 length = p ? (p -locale) : strlen (locale);
580 p = strchr (locale, '.');
583 gchar *tmp1 = g_strndup (locale, p - locale + 1);
584 gchar *tmp2 = _gtk_normalize_codeset (p + 1, length - (p - locale + 1));
586 normalized_locale = g_strconcat (tmp1, tmp2, NULL);
590 locale_suffixes[n_locale_suffixes++] = g_strdup (normalized_locale);
594 normalized_locale = g_strndup (locale, length);
596 p = strchr (normalized_locale, '_');
599 locale_suffixes[n_locale_suffixes++] = g_strndup (normalized_locale, length);
600 length = p - normalized_locale;
603 locale_suffixes[n_locale_suffixes++] = g_strndup (normalized_locale, length);
605 g_free (normalized_locale);
610 while (gtk_rc_default_files[i] != NULL)
612 /* Try to find a locale specific RC file corresponding to
613 * to parse before the default file.
615 for (j=n_locale_suffixes-1; j>=0; j--)
617 gchar *name = g_strconcat (gtk_rc_default_files[i],
625 gtk_rc_parse (gtk_rc_default_files[i]);
631 gtk_rc_parse_string (const gchar *rc_string)
633 g_return_if_fail (rc_string != NULL);
635 gtk_rc_parse_any ("-", -1, rc_string);
639 gtk_rc_parse_file (const gchar *filename, gboolean reload)
641 GtkRcFile *rc_file = NULL;
645 g_return_if_fail (filename != NULL);
650 rc_file = tmp_list->data;
651 if (!strcmp (rc_file->name, filename))
654 tmp_list = tmp_list->next;
659 rc_file = g_new (GtkRcFile, 1);
660 rc_file->name = g_strdup (filename);
661 rc_file->canonical_name = NULL;
663 rc_file->reload = reload;
665 rc_files = g_slist_append (rc_files, rc_file);
668 if (!rc_file->canonical_name)
670 /* Get the absolute pathname */
672 if (g_path_is_absolute (rc_file->name))
673 rc_file->canonical_name = rc_file->name;
679 cwd = g_get_current_dir ();
681 str = g_string_new (cwd);
683 g_string_append_c (str, G_DIR_SEPARATOR);
684 g_string_append (str, rc_file->name);
686 rc_file->canonical_name = str->str;
687 g_string_free (str, FALSE);
691 if (!lstat (rc_file->canonical_name, &statbuf))
696 rc_file->mtime = statbuf.st_mtime;
698 fd = open (rc_file->canonical_name, O_RDONLY);
702 /* Temporarily push directory name for this file on
703 * a stack of directory names while parsing it
705 rc_dir_stack = g_slist_prepend (rc_dir_stack,
706 g_dirname (rc_file->canonical_name));
707 gtk_rc_parse_any (filename, fd, NULL);
709 tmp_list = rc_dir_stack;
710 rc_dir_stack = rc_dir_stack->next;
712 g_free (tmp_list->data);
713 g_slist_free_1 (tmp_list);
720 gtk_rc_parse (const gchar *filename)
722 g_return_if_fail (filename != NULL);
724 gtk_rc_parse_file (filename, TRUE);
727 /* Handling of RC styles */
730 gtk_rc_style_new (void)
732 GtkRcStylePrivate *new_style;
734 new_style = g_new0 (GtkRcStylePrivate, 1);
735 new_style->ref_count = 1;
737 return (GtkRcStyle *)new_style;
741 gtk_rc_style_ref (GtkRcStyle *rc_style)
743 g_return_if_fail (rc_style != NULL);
745 ((GtkRcStylePrivate *)rc_style)->ref_count++;
748 /* Like g_slist_remove, but remove all copies of data */
750 gtk_rc_slist_remove_all (GSList *list,
761 if (tmp->data == data)
767 prev->next = tmp->next;
769 g_slist_free_1 (tmp);
787 gtk_rc_style_unref (GtkRcStyle *rc_style)
789 GtkRcStylePrivate *private = (GtkRcStylePrivate *)rc_style;
792 g_return_if_fail (rc_style != NULL);
793 g_return_if_fail (private->ref_count > 0);
795 private->ref_count--;
797 if (private->ref_count == 0)
799 GSList *tmp_list1, *tmp_list2;
801 if (rc_style->engine)
803 rc_style->engine->destroy_rc_style (rc_style);
804 gtk_theme_engine_unref (rc_style->engine);
808 g_free (rc_style->name);
809 if (rc_style->font_desc)
810 pango_font_description_free (rc_style->font_desc);
812 for (i=0 ; i<5 ; i++)
813 if (rc_style->bg_pixmap_name[i])
814 g_free (rc_style->bg_pixmap_name[i]);
816 /* Now remove all references to this rc_style from
819 tmp_list1 = private->rc_style_lists;
822 GSList *rc_styles = tmp_list1->data;
823 GtkStyle *style = g_hash_table_lookup (realized_style_ht, rc_styles);
824 gtk_style_unref (style);
826 /* Remove the list of styles from the other rc_styles
829 tmp_list2 = rc_styles;
832 GtkRcStylePrivate *other_style = tmp_list2->data;
834 if (other_style != private)
835 other_style->rc_style_lists =
836 gtk_rc_slist_remove_all (other_style->rc_style_lists, rc_styles);
838 tmp_list2 = tmp_list2->next;
841 /* And from the hash table itself
843 g_hash_table_remove (realized_style_ht, rc_styles);
844 g_slist_free (rc_styles);
846 tmp_list1 = tmp_list1->next;
848 g_slist_free (private->rc_style_lists);
855 gtk_rc_clear_hash_node (gpointer key,
859 gtk_rc_style_unref (data);
863 gtk_rc_free_rc_sets (GSList *slist)
869 rc_set = slist->data;
870 gtk_pattern_spec_free_segs (&rc_set->pspec);
878 gtk_rc_clear_styles (void)
880 /* Clear out all old rc_styles */
884 g_hash_table_foreach (rc_style_ht, gtk_rc_clear_hash_node, NULL);
885 g_hash_table_destroy (rc_style_ht);
889 gtk_rc_free_rc_sets (gtk_rc_sets_widget);
890 g_slist_free (gtk_rc_sets_widget);
891 gtk_rc_sets_widget = NULL;
893 gtk_rc_free_rc_sets (gtk_rc_sets_widget_class);
894 g_slist_free (gtk_rc_sets_widget_class);
895 gtk_rc_sets_widget_class = NULL;
897 gtk_rc_free_rc_sets (gtk_rc_sets_class);
898 g_slist_free (gtk_rc_sets_class);
899 gtk_rc_sets_class = NULL;
903 gtk_rc_reparse_all (void)
906 gboolean mtime_modified = FALSE;
911 /* Check through and see if any of the RC's have had their
912 * mtime modified. If so, reparse everything.
917 rc_file = tmp_list->data;
919 if (!lstat (rc_file->name, &statbuf) &&
920 (statbuf.st_mtime > rc_file->mtime))
922 mtime_modified = TRUE;
926 tmp_list = tmp_list->next;
931 gtk_rc_clear_styles();
936 rc_file = tmp_list->data;
938 gtk_rc_parse_file (rc_file->name, FALSE);
940 tmp_list = tmp_list->next;
944 return mtime_modified;
948 gtk_rc_styles_match (GSList *rc_styles,
952 gchar *path_reversed)
962 if (gtk_pattern_match (&rc_set->pspec, path_length, path, path_reversed))
963 rc_styles = g_slist_append (rc_styles, rc_set->rc_style);
970 gtk_rc_get_style (GtkWidget *widget)
972 GtkRcStyle *widget_rc_style;
973 GSList *rc_styles = NULL;
975 static guint rc_style_key_id = 0;
977 /* We allow the specification of a single rc style to be bound
978 * tightly to a widget, for application modifications
980 if (!rc_style_key_id)
981 rc_style_key_id = g_quark_from_static_string ("gtk-rc-style");
983 widget_rc_style = gtk_object_get_data_by_id (GTK_OBJECT (widget),
987 rc_styles = g_slist_prepend (rc_styles, widget_rc_style);
989 if (gtk_rc_sets_widget)
991 gchar *path, *path_reversed;
994 gtk_widget_path (widget, &path_length, &path, &path_reversed);
995 rc_styles = gtk_rc_styles_match (rc_styles, gtk_rc_sets_widget, path_length, path, path_reversed);
997 g_free (path_reversed);
1001 if (gtk_rc_sets_widget_class)
1003 gchar *path, *path_reversed;
1006 gtk_widget_class_path (widget, &path_length, &path, &path_reversed);
1007 rc_styles = gtk_rc_styles_match (rc_styles, gtk_rc_sets_widget_class, path_length, path, path_reversed);
1009 g_free (path_reversed);
1012 if (gtk_rc_sets_class)
1016 type = GTK_OBJECT_TYPE (widget);
1019 gchar *path, *path_reversed;
1022 path = gtk_type_name (type);
1023 path_length = strlen (path);
1024 path_reversed = g_strdup (path);
1025 g_strreverse (path_reversed);
1027 rc_styles = gtk_rc_styles_match (rc_styles, gtk_rc_sets_class, path_length, path, path_reversed);
1028 g_free (path_reversed);
1030 type = gtk_type_parent (type);
1035 return gtk_rc_style_init (rc_styles);
1041 gtk_rc_add_rc_sets (GSList *slist,
1042 GtkRcStyle *rc_style,
1043 const char *pattern)
1045 GtkRcStyle *new_style;
1049 new_style = gtk_rc_style_new ();
1050 *new_style = *rc_style;
1051 new_style->name = g_strdup (rc_style->name);
1052 if (rc_style->font_desc)
1053 new_style->font_desc = pango_font_description_copy (rc_style->font_desc);
1055 for (i = 0; i < 5; i++)
1056 new_style->bg_pixmap_name[i] = g_strdup (rc_style->bg_pixmap_name[i]);
1058 rc_set = g_new (GtkRcSet, 1);
1059 gtk_pattern_spec_init (&rc_set->pspec, pattern);
1060 rc_set->rc_style = rc_style;
1062 return g_slist_prepend (slist, rc_set);
1066 gtk_rc_add_widget_name_style (GtkRcStyle *rc_style,
1067 const gchar *pattern)
1069 g_return_if_fail (rc_style != NULL);
1070 g_return_if_fail (pattern != NULL);
1072 gtk_rc_sets_widget = gtk_rc_add_rc_sets (gtk_rc_sets_widget, rc_style, pattern);
1076 gtk_rc_add_widget_class_style (GtkRcStyle *rc_style,
1077 const gchar *pattern)
1079 g_return_if_fail (rc_style != NULL);
1080 g_return_if_fail (pattern != NULL);
1082 gtk_rc_sets_widget_class = gtk_rc_add_rc_sets (gtk_rc_sets_widget_class, rc_style, pattern);
1086 gtk_rc_add_class_style (GtkRcStyle *rc_style,
1087 const gchar *pattern)
1089 g_return_if_fail (rc_style != NULL);
1090 g_return_if_fail (pattern != NULL);
1092 gtk_rc_sets_class = gtk_rc_add_rc_sets (gtk_rc_sets_class, rc_style, pattern);
1096 gtk_rc_parse_any (const gchar *input_name,
1098 const gchar *input_string)
1104 scanner = g_scanner_new ((GScannerConfig *) >k_rc_scanner_config);
1108 g_assert (input_string == NULL);
1110 g_scanner_input_file (scanner, input_fd);
1114 g_assert (input_string != NULL);
1116 g_scanner_input_text (scanner, input_string, strlen (input_string));
1118 scanner->input_name = input_name;
1120 g_scanner_freeze_symbol_table (scanner);
1121 for (i = 0; i < n_symbols; i++)
1122 g_scanner_add_symbol (scanner, symbols[i].name, GINT_TO_POINTER (symbols[i].token));
1123 g_scanner_thaw_symbol_table (scanner);
1128 if (g_scanner_peek_next_token (scanner) == G_TOKEN_EOF)
1132 guint expected_token;
1134 expected_token = gtk_rc_parse_statement (scanner);
1136 if (expected_token != G_TOKEN_NONE)
1143 if (scanner->scope_id == 0)
1145 /* if we are in scope 0, we know the symbol names
1146 * that are associated with certaintoken values.
1147 * so we look them up to make the error messages
1150 if (expected_token > GTK_RC_TOKEN_INVALID &&
1151 expected_token < GTK_RC_TOKEN_LAST)
1153 for (i = 0; i < n_symbols; i++)
1154 if (symbols[i].token == expected_token)
1155 msg = symbols[i].name;
1157 msg = g_strconcat ("e.g. `", msg, "'", NULL);
1159 if (scanner->token > GTK_RC_TOKEN_INVALID &&
1160 scanner->token < GTK_RC_TOKEN_LAST)
1162 symbol_name = "???";
1163 for (i = 0; i < n_symbols; i++)
1164 if (symbols[i].token == scanner->token)
1165 symbol_name = symbols[i].name;
1168 g_scanner_unexp_token (scanner,
1181 g_scanner_destroy (scanner);
1185 gtk_rc_styles_hash (const GSList *rc_styles)
1192 result += (result << 9) + GPOINTER_TO_UINT (rc_styles->data);
1193 rc_styles = rc_styles->next;
1200 gtk_rc_styles_compare (const GSList *a,
1205 if (a->data != b->data)
1215 gtk_rc_style_hash (const char *name)
1221 result += (result << 3) + *name++;
1227 gtk_rc_style_compare (const char *a,
1230 return (strcmp (a, b) == 0);
1234 gtk_rc_style_find (const char *name)
1237 return g_hash_table_lookup (rc_style_ht, (gpointer) name);
1242 /* Assumes ownership of rc_style */
1244 gtk_rc_style_to_style (GtkRcStyle *rc_style)
1250 style = gtk_style_new ();
1252 style->rc_style = rc_style;
1254 if (rc_style->font_desc)
1256 pango_font_description_free (style->font_desc);
1257 style->font_desc = pango_font_description_copy (rc_style->font_desc);
1259 old_font = style->font;
1260 style->font = gdk_font_from_description (style->font_desc);
1262 gdk_font_unref (old_font);
1264 style->font = old_font;
1267 for (i = 0; i < 5; i++)
1269 if (rc_style->color_flags[i] & GTK_RC_FG)
1270 style->fg[i] = rc_style->fg[i];
1271 if (rc_style->color_flags[i] & GTK_RC_BG)
1272 style->bg[i] = rc_style->bg[i];
1273 if (rc_style->color_flags[i] & GTK_RC_TEXT)
1274 style->text[i] = rc_style->text[i];
1275 if (rc_style->color_flags[i] & GTK_RC_BASE)
1276 style->base[i] = rc_style->base[i];
1279 if (rc_style->engine)
1281 style->engine = rc_style->engine;
1282 gtk_theme_engine_ref (style->engine);
1283 rc_style->engine->rc_style_to_style (style, rc_style);
1289 /* Reuses or frees rc_styles */
1291 gtk_rc_style_init (GSList *rc_styles)
1295 GtkStyle *style = NULL;
1297 if (!realized_style_ht)
1298 realized_style_ht = g_hash_table_new ((GHashFunc)gtk_rc_styles_hash,
1299 (GCompareFunc)gtk_rc_styles_compare);
1301 style = g_hash_table_lookup (realized_style_ht, rc_styles);
1305 GtkRcStyle *proto_style;
1308 proto_style = gtk_rc_style_new ();
1310 tmp_styles = rc_styles;
1313 GtkRcStyle *rc_style = tmp_styles->data;
1314 GtkRcStylePrivate *rc_style_private;
1318 if (!proto_style->bg_pixmap_name[i] && rc_style->bg_pixmap_name[i])
1319 proto_style->bg_pixmap_name[i] = g_strdup (rc_style->bg_pixmap_name[i]);
1321 if (!(proto_style->color_flags[i] & GTK_RC_FG) &&
1322 rc_style->color_flags[i] & GTK_RC_FG)
1324 proto_style->fg[i] = rc_style->fg[i];
1325 proto_style->color_flags[i] |= GTK_RC_FG;
1327 if (!(proto_style->color_flags[i] & GTK_RC_BG) &&
1328 rc_style->color_flags[i] & GTK_RC_BG)
1330 proto_style->bg[i] = rc_style->bg[i];
1331 proto_style->color_flags[i] |= GTK_RC_BG;
1333 if (!(proto_style->color_flags[i] & GTK_RC_TEXT) &&
1334 rc_style->color_flags[i] & GTK_RC_TEXT)
1336 proto_style->text[i] = rc_style->text[i];
1337 proto_style->color_flags[i] |= GTK_RC_TEXT;
1339 if (!(proto_style->color_flags[i] & GTK_RC_BASE) &&
1340 rc_style->color_flags[i] & GTK_RC_BASE)
1342 proto_style->base[i] = rc_style->base[i];
1343 proto_style->color_flags[i] |= GTK_RC_BASE;
1347 if (!proto_style->font_desc && rc_style->font_desc)
1348 proto_style->font_desc = pango_font_description_copy (rc_style->font_desc);
1350 if (!proto_style->engine && rc_style->engine)
1352 proto_style->engine = rc_style->engine;
1353 gtk_theme_engine_ref (proto_style->engine);
1356 if (proto_style->engine &&
1357 (proto_style->engine == rc_style->engine))
1358 proto_style->engine->merge_rc_style (proto_style, rc_style);
1360 /* Point from each rc_style to the list of styles */
1362 rc_style_private = (GtkRcStylePrivate *)rc_style;
1363 if (!g_slist_find (rc_style_private->rc_style_lists, rc_styles))
1364 rc_style_private->rc_style_lists = g_slist_prepend (rc_style_private->rc_style_lists, rc_styles);
1366 tmp_styles = tmp_styles->next;
1370 if (proto_style->bg_pixmap_name[i] &&
1371 (strcmp (proto_style->bg_pixmap_name[i], "<none>") == 0))
1373 g_free (proto_style->bg_pixmap_name[i]);
1374 proto_style->bg_pixmap_name[i] = NULL;
1377 style = gtk_rc_style_to_style (proto_style);
1379 g_hash_table_insert (realized_style_ht, rc_styles, style);
1382 g_slist_free (rc_styles);
1387 /*********************
1388 * Parsing functions *
1389 *********************/
1392 gtk_rc_parse_statement (GScanner *scanner)
1396 token = g_scanner_peek_next_token (scanner);
1400 case GTK_RC_TOKEN_INCLUDE:
1401 token = g_scanner_get_next_token (scanner);
1402 if (token != GTK_RC_TOKEN_INCLUDE)
1403 return GTK_RC_TOKEN_INCLUDE;
1405 token = g_scanner_get_next_token (scanner);
1406 if (token != G_TOKEN_STRING)
1407 return G_TOKEN_STRING;
1409 gtk_rc_parse_file (scanner->value.v_string, FALSE);
1410 return G_TOKEN_NONE;
1412 case GTK_RC_TOKEN_STYLE:
1413 return gtk_rc_parse_style (scanner);
1415 case GTK_RC_TOKEN_BINDING:
1416 return gtk_binding_parse_binding (scanner);
1418 case GTK_RC_TOKEN_PIXMAP_PATH:
1419 return gtk_rc_parse_pixmap_path (scanner);
1421 case GTK_RC_TOKEN_WIDGET:
1422 return gtk_rc_parse_path_pattern (scanner);
1424 case GTK_RC_TOKEN_WIDGET_CLASS:
1425 return gtk_rc_parse_path_pattern (scanner);
1427 case GTK_RC_TOKEN_CLASS:
1428 return gtk_rc_parse_path_pattern (scanner);
1430 case GTK_RC_TOKEN_MODULE_PATH:
1431 return gtk_rc_parse_module_path (scanner);
1434 g_scanner_get_next_token (scanner);
1435 return /* G_TOKEN_SYMBOL */ GTK_RC_TOKEN_STYLE;
1440 gtk_rc_parse_style (GScanner *scanner)
1442 GtkRcStyle *rc_style;
1443 GtkRcStyle *parent_style;
1448 token = g_scanner_get_next_token (scanner);
1449 if (token != GTK_RC_TOKEN_STYLE)
1450 return GTK_RC_TOKEN_STYLE;
1452 token = g_scanner_get_next_token (scanner);
1453 if (token != G_TOKEN_STRING)
1454 return G_TOKEN_STRING;
1457 rc_style = gtk_rc_style_find (scanner->value.v_string);
1462 rc_style = gtk_rc_style_new ();
1463 rc_style->name = g_strdup (scanner->value.v_string);
1465 for (i = 0; i < 5; i++)
1466 rc_style->bg_pixmap_name[i] = NULL;
1468 for (i = 0; i < 5; i++)
1469 rc_style->color_flags[i] = 0;
1471 rc_style->engine = NULL;
1472 rc_style->engine_data = NULL;
1475 token = g_scanner_peek_next_token (scanner);
1476 if (token == G_TOKEN_EQUAL_SIGN)
1478 token = g_scanner_get_next_token (scanner);
1480 token = g_scanner_get_next_token (scanner);
1481 if (token != G_TOKEN_STRING)
1486 return G_TOKEN_STRING;
1489 parent_style = gtk_rc_style_find (scanner->value.v_string);
1492 for (i = 0; i < 5; i++)
1494 rc_style->color_flags[i] = parent_style->color_flags[i];
1495 rc_style->fg[i] = parent_style->fg[i];
1496 rc_style->bg[i] = parent_style->bg[i];
1497 rc_style->text[i] = parent_style->text[i];
1498 rc_style->base[i] = parent_style->base[i];
1501 if (parent_style->font_desc)
1503 if (rc_style->font_desc)
1504 pango_font_description_free (rc_style->font_desc);
1505 rc_style->font_desc = pango_font_description_copy (parent_style->font_desc);
1508 for (i = 0; i < 5; i++)
1510 if (rc_style->bg_pixmap_name[i])
1511 g_free (rc_style->bg_pixmap_name[i]);
1512 rc_style->bg_pixmap_name[i] = g_strdup (parent_style->bg_pixmap_name[i]);
1517 token = g_scanner_get_next_token (scanner);
1518 if (token != G_TOKEN_LEFT_CURLY)
1523 return G_TOKEN_LEFT_CURLY;
1526 token = g_scanner_peek_next_token (scanner);
1527 while (token != G_TOKEN_RIGHT_CURLY)
1531 case GTK_RC_TOKEN_BASE:
1532 token = gtk_rc_parse_base (scanner, rc_style);
1534 case GTK_RC_TOKEN_BG:
1535 token = gtk_rc_parse_bg (scanner, rc_style);
1537 case GTK_RC_TOKEN_FG:
1538 token = gtk_rc_parse_fg (scanner, rc_style);
1540 case GTK_RC_TOKEN_TEXT:
1541 token = gtk_rc_parse_text (scanner, rc_style);
1543 case GTK_RC_TOKEN_BG_PIXMAP:
1544 token = gtk_rc_parse_bg_pixmap (scanner, rc_style);
1546 case GTK_RC_TOKEN_FONT:
1547 token = gtk_rc_parse_font (scanner, rc_style);
1549 case GTK_RC_TOKEN_FONTSET:
1550 token = gtk_rc_parse_fontset (scanner, rc_style);
1552 case GTK_RC_TOKEN_FONT_NAME:
1553 token = gtk_rc_parse_font_name (scanner, rc_style);
1555 case GTK_RC_TOKEN_ENGINE:
1556 token = gtk_rc_parse_engine (scanner, rc_style);
1559 g_scanner_get_next_token (scanner);
1560 token = G_TOKEN_RIGHT_CURLY;
1564 if (token != G_TOKEN_NONE)
1568 if (rc_style->font_desc)
1569 pango_font_description_free (rc_style->font_desc);
1571 for (i = 0; i < 5; i++)
1572 if (rc_style->bg_pixmap_name[i])
1573 g_free (rc_style->bg_pixmap_name[i]);
1578 token = g_scanner_peek_next_token (scanner);
1581 token = g_scanner_get_next_token (scanner);
1582 if (token != G_TOKEN_RIGHT_CURLY)
1586 if (rc_style->font_desc)
1587 pango_font_description_free (rc_style->font_desc);
1589 for (i = 0; i < 5; i++)
1590 if (rc_style->bg_pixmap_name[i])
1591 g_free (rc_style->bg_pixmap_name[i]);
1595 return G_TOKEN_RIGHT_CURLY;
1601 rc_style_ht = g_hash_table_new ((GHashFunc) gtk_rc_style_hash,
1602 (GCompareFunc) gtk_rc_style_compare);
1604 g_hash_table_insert (rc_style_ht, rc_style->name, rc_style);
1607 return G_TOKEN_NONE;
1611 gtk_rc_parse_base (GScanner *scanner,
1617 token = g_scanner_get_next_token (scanner);
1618 if (token != GTK_RC_TOKEN_BASE)
1619 return GTK_RC_TOKEN_BASE;
1621 token = gtk_rc_parse_state (scanner, &state);
1622 if (token != G_TOKEN_NONE)
1625 token = g_scanner_get_next_token (scanner);
1626 if (token != G_TOKEN_EQUAL_SIGN)
1627 return G_TOKEN_EQUAL_SIGN;
1629 style->color_flags[state] |= GTK_RC_BASE;
1630 return gtk_rc_parse_color (scanner, &style->base[state]);
1634 gtk_rc_parse_bg (GScanner *scanner,
1640 token = g_scanner_get_next_token (scanner);
1641 if (token != GTK_RC_TOKEN_BG)
1642 return GTK_RC_TOKEN_BG;
1644 token = gtk_rc_parse_state (scanner, &state);
1645 if (token != G_TOKEN_NONE)
1648 token = g_scanner_get_next_token (scanner);
1649 if (token != G_TOKEN_EQUAL_SIGN)
1650 return G_TOKEN_EQUAL_SIGN;
1652 style->color_flags[state] |= GTK_RC_BG;
1653 return gtk_rc_parse_color (scanner, &style->bg[state]);
1657 gtk_rc_parse_fg (GScanner *scanner,
1663 token = g_scanner_get_next_token (scanner);
1664 if (token != GTK_RC_TOKEN_FG)
1665 return GTK_RC_TOKEN_FG;
1667 token = gtk_rc_parse_state (scanner, &state);
1668 if (token != G_TOKEN_NONE)
1671 token = g_scanner_get_next_token (scanner);
1672 if (token != G_TOKEN_EQUAL_SIGN)
1673 return G_TOKEN_EQUAL_SIGN;
1675 style->color_flags[state] |= GTK_RC_FG;
1676 return gtk_rc_parse_color (scanner, &style->fg[state]);
1680 gtk_rc_parse_text (GScanner *scanner,
1686 token = g_scanner_get_next_token (scanner);
1687 if (token != GTK_RC_TOKEN_TEXT)
1688 return GTK_RC_TOKEN_TEXT;
1690 token = gtk_rc_parse_state (scanner, &state);
1691 if (token != G_TOKEN_NONE)
1694 token = g_scanner_get_next_token (scanner);
1695 if (token != G_TOKEN_EQUAL_SIGN)
1696 return G_TOKEN_EQUAL_SIGN;
1698 style->color_flags[state] |= GTK_RC_TEXT;
1699 return gtk_rc_parse_color (scanner, &style->text[state]);
1703 gtk_rc_parse_bg_pixmap (GScanner *scanner,
1704 GtkRcStyle *rc_style)
1710 token = g_scanner_get_next_token (scanner);
1711 if (token != GTK_RC_TOKEN_BG_PIXMAP)
1712 return GTK_RC_TOKEN_BG_PIXMAP;
1714 token = gtk_rc_parse_state (scanner, &state);
1715 if (token != G_TOKEN_NONE)
1718 token = g_scanner_get_next_token (scanner);
1719 if (token != G_TOKEN_EQUAL_SIGN)
1720 return G_TOKEN_EQUAL_SIGN;
1722 token = g_scanner_get_next_token (scanner);
1723 if (token != G_TOKEN_STRING)
1724 return G_TOKEN_STRING;
1726 if ((strcmp (scanner->value.v_string, "<parent>") == 0) ||
1727 (strcmp (scanner->value.v_string, "<none>") == 0))
1728 pixmap_file = g_strdup (scanner->value.v_string);
1730 pixmap_file = gtk_rc_find_pixmap_in_path (scanner, scanner->value.v_string);
1734 if (rc_style->bg_pixmap_name[state])
1735 g_free (rc_style->bg_pixmap_name[state]);
1736 rc_style->bg_pixmap_name[state] = pixmap_file;
1739 return G_TOKEN_NONE;
1743 gtk_rc_check_pixmap_dir (const gchar *dir, const gchar *pixmap_file)
1748 buf = g_strdup_printf ("%s" G_DIR_SEPARATOR_S "%s", dir, pixmap_file);
1750 fd = open (buf, O_RDONLY);
1763 gtk_rc_find_pixmap_in_path (GScanner *scanner,
1764 const gchar *pixmap_file)
1770 for (i = 0; (i < GTK_RC_MAX_PIXMAP_PATHS) && (pixmap_path[i] != NULL); i++)
1772 filename = gtk_rc_check_pixmap_dir (pixmap_path[i], pixmap_file);
1777 tmp_list = rc_dir_stack;
1780 filename = gtk_rc_check_pixmap_dir (tmp_list->data, pixmap_file);
1784 tmp_list = tmp_list->next;
1788 g_warning (_("Unable to locate image file in pixmap_path: \"%s\" line %d"),
1789 pixmap_file, scanner->line);
1791 g_warning (_("Unable to locate image file in pixmap_path: \"%s\""),
1798 gtk_rc_find_module_in_path (const gchar *module_file)
1804 for (i = 0; (i < GTK_RC_MAX_MODULE_PATHS) && (module_path[i] != NULL); i++)
1806 buf = g_strdup_printf ("%s" G_DIR_SEPARATOR_S "%s",
1807 module_path[i], module_file);
1809 fd = open (buf, O_RDONLY);
1823 gtk_rc_parse_font (GScanner *scanner,
1824 GtkRcStyle *rc_style)
1828 token = g_scanner_get_next_token (scanner);
1829 if (token != GTK_RC_TOKEN_FONT)
1830 return GTK_RC_TOKEN_FONT;
1832 token = g_scanner_get_next_token (scanner);
1833 if (token != G_TOKEN_EQUAL_SIGN)
1834 return G_TOKEN_EQUAL_SIGN;
1836 token = g_scanner_get_next_token (scanner);
1837 if (token != G_TOKEN_STRING)
1838 return G_TOKEN_STRING;
1840 /* Ignore, do nothing */
1842 return G_TOKEN_NONE;
1846 gtk_rc_parse_fontset (GScanner *scanner,
1847 GtkRcStyle *rc_style)
1851 token = g_scanner_get_next_token (scanner);
1852 if (token != GTK_RC_TOKEN_FONTSET)
1853 return GTK_RC_TOKEN_FONTSET;
1855 token = g_scanner_get_next_token (scanner);
1856 if (token != G_TOKEN_EQUAL_SIGN)
1857 return G_TOKEN_EQUAL_SIGN;
1859 token = g_scanner_get_next_token (scanner);
1860 if (token != G_TOKEN_STRING)
1861 return G_TOKEN_STRING;
1863 /* Do nothing - silently ignore */
1865 return G_TOKEN_NONE;
1869 gtk_rc_parse_font_name (GScanner *scanner,
1870 GtkRcStyle *rc_style)
1874 token = g_scanner_get_next_token (scanner);
1875 if (token != GTK_RC_TOKEN_FONT_NAME)
1876 return GTK_RC_TOKEN_FONT;
1878 token = g_scanner_get_next_token (scanner);
1879 if (token != G_TOKEN_EQUAL_SIGN)
1880 return G_TOKEN_EQUAL_SIGN;
1882 token = g_scanner_get_next_token (scanner);
1883 if (token != G_TOKEN_STRING)
1884 return G_TOKEN_STRING;
1886 rc_style->font_desc = pango_font_description_from_string (scanner->value.v_string);
1888 return G_TOKEN_NONE;
1892 gtk_rc_parse_engine (GScanner *scanner,
1893 GtkRcStyle *rc_style)
1897 token = g_scanner_get_next_token (scanner);
1898 if (token != GTK_RC_TOKEN_ENGINE)
1899 return GTK_RC_TOKEN_ENGINE;
1901 token = g_scanner_get_next_token (scanner);
1902 if (token != G_TOKEN_STRING)
1903 return G_TOKEN_STRING;
1905 rc_style->engine = gtk_theme_engine_get (scanner->value.v_string);
1907 token = g_scanner_get_next_token (scanner);
1908 if (token != G_TOKEN_LEFT_CURLY)
1909 return G_TOKEN_LEFT_CURLY;
1911 if (rc_style->engine)
1912 return rc_style->engine->parse_rc_style (scanner, rc_style);
1915 /* Skip over remainder, looking for nested {}'s */
1918 while ((token = g_scanner_get_next_token (scanner)) != G_TOKEN_EOF)
1920 if (token == G_TOKEN_LEFT_CURLY)
1922 else if (token == G_TOKEN_RIGHT_CURLY)
1926 return G_TOKEN_NONE;
1929 return G_TOKEN_RIGHT_CURLY;
1934 gtk_rc_parse_state (GScanner *scanner,
1935 GtkStateType *state)
1940 g_return_val_if_fail (scanner != NULL, G_TOKEN_ERROR);
1941 g_return_val_if_fail (state != NULL, G_TOKEN_ERROR);
1943 /* we don't know where we got called from, so we reset the scope here.
1944 * if we bail out due to errors, we *don't* reset the scope, so the
1945 * error messaging code can make sense of our tokens.
1947 old_scope = g_scanner_set_scope (scanner, 0);
1949 token = g_scanner_get_next_token (scanner);
1950 if (token != G_TOKEN_LEFT_BRACE)
1951 return G_TOKEN_LEFT_BRACE;
1953 token = g_scanner_get_next_token (scanner);
1956 case GTK_RC_TOKEN_ACTIVE:
1957 *state = GTK_STATE_ACTIVE;
1959 case GTK_RC_TOKEN_INSENSITIVE:
1960 *state = GTK_STATE_INSENSITIVE;
1962 case GTK_RC_TOKEN_NORMAL:
1963 *state = GTK_STATE_NORMAL;
1965 case GTK_RC_TOKEN_PRELIGHT:
1966 *state = GTK_STATE_PRELIGHT;
1968 case GTK_RC_TOKEN_SELECTED:
1969 *state = GTK_STATE_SELECTED;
1972 return /* G_TOKEN_SYMBOL */ GTK_RC_TOKEN_NORMAL;
1975 token = g_scanner_get_next_token (scanner);
1976 if (token != G_TOKEN_RIGHT_BRACE)
1977 return G_TOKEN_RIGHT_BRACE;
1979 g_scanner_set_scope (scanner, old_scope);
1981 return G_TOKEN_NONE;
1985 gtk_rc_parse_priority (GScanner *scanner,
1986 GtkPathPriorityType *priority)
1991 g_return_val_if_fail (scanner != NULL, G_TOKEN_ERROR);
1992 g_return_val_if_fail (priority != NULL, G_TOKEN_ERROR);
1994 /* we don't know where we got called from, so we reset the scope here.
1995 * if we bail out due to errors, we *don't* reset the scope, so the
1996 * error messaging code can make sense of our tokens.
1998 old_scope = g_scanner_set_scope (scanner, 0);
2000 token = g_scanner_get_next_token (scanner);
2004 token = g_scanner_get_next_token (scanner);
2007 case GTK_RC_TOKEN_LOWEST:
2008 *priority = GTK_PATH_PRIO_LOWEST;
2010 case GTK_RC_TOKEN_GTK:
2011 *priority = GTK_PATH_PRIO_GTK;
2013 case GTK_RC_TOKEN_APPLICATION:
2014 *priority = GTK_PATH_PRIO_APPLICATION;
2016 case GTK_RC_TOKEN_RC:
2017 *priority = GTK_PATH_PRIO_RC;
2019 case GTK_RC_TOKEN_HIGHEST:
2020 *priority = GTK_PATH_PRIO_HIGHEST;
2023 return /* G_TOKEN_SYMBOL */ GTK_RC_TOKEN_APPLICATION;
2026 g_scanner_set_scope (scanner, old_scope);
2028 return G_TOKEN_NONE;
2032 gtk_rc_parse_color (GScanner *scanner,
2037 g_return_val_if_fail (scanner != NULL, G_TOKEN_ERROR);
2039 /* we don't need to set our own scop here, because
2040 * we don't need own symbols
2043 token = g_scanner_get_next_token (scanner);
2052 case G_TOKEN_LEFT_CURLY:
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->red = CLAMP (token_int, 0, 65535);
2062 token = g_scanner_get_next_token (scanner);
2063 if (token != G_TOKEN_COMMA)
2064 return G_TOKEN_COMMA;
2066 token = g_scanner_get_next_token (scanner);
2067 if (token == G_TOKEN_INT)
2068 token_int = scanner->value.v_int;
2069 else if (token == G_TOKEN_FLOAT)
2070 token_int = scanner->value.v_float * 65535.0;
2072 return G_TOKEN_FLOAT;
2073 color->green = CLAMP (token_int, 0, 65535);
2075 token = g_scanner_get_next_token (scanner);
2076 if (token != G_TOKEN_COMMA)
2077 return G_TOKEN_COMMA;
2079 token = g_scanner_get_next_token (scanner);
2080 if (token == G_TOKEN_INT)
2081 token_int = scanner->value.v_int;
2082 else if (token == G_TOKEN_FLOAT)
2083 token_int = scanner->value.v_float * 65535.0;
2085 return G_TOKEN_FLOAT;
2086 color->blue = CLAMP (token_int, 0, 65535);
2088 token = g_scanner_get_next_token (scanner);
2089 if (token != G_TOKEN_RIGHT_CURLY)
2090 return G_TOKEN_RIGHT_CURLY;
2091 return G_TOKEN_NONE;
2093 case G_TOKEN_STRING:
2094 if (scanner->value.v_string[0] != '#')
2095 return G_TOKEN_STRING;
2097 length = strlen (scanner->value.v_string) - 1;
2098 if (((length % 3) != 0) || (length > 12))
2099 return G_TOKEN_STRING;
2102 for (i = 0, j = 1; i < length; i++, j++)
2103 buf[i] = scanner->value.v_string[j];
2106 sscanf (buf, "%x", &temp);
2109 for (i = 0; i < length; i++, j++)
2110 buf[i] = scanner->value.v_string[j];
2113 sscanf (buf, "%x", &temp);
2114 color->green = temp;
2116 for (i = 0; i < length; i++, j++)
2117 buf[i] = scanner->value.v_string[j];
2120 sscanf (buf, "%x", &temp);
2126 color->green *= 4369;
2127 color->blue *= 4369;
2129 else if (length == 2)
2132 color->green *= 257;
2135 else if (length == 3)
2141 return G_TOKEN_NONE;
2144 return G_TOKEN_STRING;
2149 gtk_rc_parse_pixmap_path (GScanner *scanner)
2153 token = g_scanner_get_next_token (scanner);
2154 if (token != GTK_RC_TOKEN_PIXMAP_PATH)
2155 return GTK_RC_TOKEN_PIXMAP_PATH;
2157 token = g_scanner_get_next_token (scanner);
2158 if (token != G_TOKEN_STRING)
2159 return G_TOKEN_STRING;
2161 gtk_rc_parse_pixmap_path_string (scanner->value.v_string);
2163 return G_TOKEN_NONE;
2167 gtk_rc_parse_pixmap_path_string (gchar *pix_path)
2171 gint start_offset = 0;
2175 /* free the old one, or just add to the old one ? */
2176 for (path_num=0; pixmap_path[path_num]; path_num++)
2178 g_free (pixmap_path[path_num]);
2179 pixmap_path[path_num] = NULL;
2184 path_len = strlen (pix_path);
2186 buf = g_strdup (pix_path);
2188 for (end_offset = 0; end_offset <= path_len; end_offset++)
2190 if ((buf[end_offset] == G_SEARCHPATH_SEPARATOR) ||
2191 (end_offset == path_len))
2193 buf[end_offset] = '\0';
2194 pixmap_path[path_num] = g_strdup (buf + start_offset);
2196 pixmap_path[path_num] = NULL;
2197 start_offset = end_offset + 1;
2201 gtk_rc_append_default_pixmap_path();
2205 gtk_rc_parse_module_path (GScanner *scanner)
2209 token = g_scanner_get_next_token (scanner);
2210 if (token != GTK_RC_TOKEN_MODULE_PATH)
2211 return GTK_RC_TOKEN_MODULE_PATH;
2213 token = g_scanner_get_next_token (scanner);
2214 if (token != G_TOKEN_STRING)
2215 return G_TOKEN_STRING;
2217 gtk_rc_parse_module_path_string (scanner->value.v_string);
2219 return G_TOKEN_NONE;
2223 gtk_rc_parse_module_path_string (gchar *mod_path)
2227 gint start_offset = 0;
2231 /* free the old one, or just add to the old one ? */
2232 for (path_num=0; module_path[path_num]; path_num++)
2234 g_free (module_path[path_num]);
2235 module_path[path_num] = NULL;
2240 path_len = strlen (mod_path);
2242 buf = g_strdup (mod_path);
2244 for (end_offset = 0; end_offset <= path_len; end_offset++)
2246 if ((buf[end_offset] == G_SEARCHPATH_SEPARATOR) ||
2247 (end_offset == path_len))
2249 buf[end_offset] = '\0';
2250 module_path[path_num] = g_strdup (buf + start_offset);
2252 module_path[path_num] = NULL;
2253 start_offset = end_offset + 1;
2257 gtk_rc_append_default_module_path();
2261 gtk_rc_parse_path_pattern (GScanner *scanner)
2264 GtkPathType path_type;
2266 gboolean is_binding;
2267 GtkPathPriorityType priority = GTK_PATH_PRIO_RC;
2269 token = g_scanner_get_next_token (scanner);
2272 case GTK_RC_TOKEN_WIDGET:
2273 path_type = GTK_PATH_WIDGET;
2275 case GTK_RC_TOKEN_WIDGET_CLASS:
2276 path_type = GTK_PATH_WIDGET_CLASS;
2278 case GTK_RC_TOKEN_CLASS:
2279 path_type = GTK_PATH_CLASS;
2282 return GTK_RC_TOKEN_WIDGET_CLASS;
2285 token = g_scanner_get_next_token (scanner);
2286 if (token != G_TOKEN_STRING)
2287 return G_TOKEN_STRING;
2289 pattern = g_strdup (scanner->value.v_string);
2291 token = g_scanner_get_next_token (scanner);
2292 if (token == GTK_RC_TOKEN_STYLE)
2294 else if (token == GTK_RC_TOKEN_BINDING)
2297 if (g_scanner_peek_next_token (scanner) == ':')
2299 token = gtk_rc_parse_priority (scanner, &priority);
2300 if (token != G_TOKEN_NONE)
2310 return GTK_RC_TOKEN_STYLE;
2313 token = g_scanner_get_next_token (scanner);
2314 if (token != G_TOKEN_STRING)
2317 return G_TOKEN_STRING;
2322 GtkBindingSet *binding;
2324 binding = gtk_binding_set_find (scanner->value.v_string);
2328 return G_TOKEN_STRING;
2330 gtk_binding_set_add_path (binding, path_type, pattern, priority);
2334 GtkRcStyle *rc_style;
2337 rc_style = gtk_rc_style_find (scanner->value.v_string);
2342 return G_TOKEN_STRING;
2345 rc_set = g_new (GtkRcSet, 1);
2346 gtk_pattern_spec_init (&rc_set->pspec, pattern);
2347 rc_set->rc_style = rc_style;
2349 if (path_type == GTK_PATH_WIDGET)
2350 gtk_rc_sets_widget = g_slist_prepend (gtk_rc_sets_widget, rc_set);
2351 else if (path_type == GTK_PATH_WIDGET_CLASS)
2352 gtk_rc_sets_widget_class = g_slist_prepend (gtk_rc_sets_widget_class, rc_set);
2354 gtk_rc_sets_class = g_slist_prepend (gtk_rc_sets_class, rc_set);
2358 return G_TOKEN_NONE;
2362 typedef GdkPixmap * (*GtkImageLoader) (GdkWindow *window,
2363 GdkColormap *colormap,
2365 GdkColor *transparent_color,
2366 const gchar *filename);
2370 gtk_rc_set_image_loader(GtkImageLoader loader)
2372 image_loader = loader;
2376 gtk_rc_load_image (GdkColormap *colormap,
2377 GdkColor *transparent_color,
2378 const gchar *filename)
2380 if (strcmp (filename, "<parent>") == 0)
2381 return (GdkPixmap*) GDK_PARENT_RELATIVE;
2385 return image_loader(NULL, colormap, NULL,
2389 return gdk_pixmap_colormap_create_from_xpm (NULL, colormap, NULL,