]> Pileus Git - ~andy/gtk/blob - gtk/gtkrc.c
gtk/gtkmain.c Use the new
[~andy/gtk] / gtk / gtkrc.c
1 /* GTK - The GIMP Toolkit
2  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser 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.
8  *
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  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser 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.
18  */
19
20 /*
21  * Modified by the GTK+ Team and others 1997-2000.  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/. 
25  */
26
27 #include "config.h"
28
29 #ifdef GDK_WINDOWING_X11
30 #include <X11/Xlocale.h>        /* so we get the right setlocale */
31 #else
32 #include <locale.h>
33 #endif
34 #include <ctype.h>
35 #ifdef HAVE_UNISTD_H
36 #include <unistd.h>
37 #endif
38 #include <sys/stat.h>
39 #ifdef HAVE_SYS_PARAM_H
40 #include <sys/param.h>
41 #endif
42 #include <fcntl.h>
43 #include <string.h>
44 #include <stdio.h>
45 #include <stdlib.h>
46
47 #ifndef HAVE_LSTAT
48 #define lstat stat
49 #endif
50
51 #include <glib.h>
52 #include "gdkconfig.h"
53
54 #include "gtkcompat.h"
55 #include "gtkrc.h"
56 #include "gtkbindings.h"
57 #include "gtkthemes.h"
58 #include "gtkintl.h"
59 #include "gtkiconfactory.h"
60
61 #ifdef G_OS_WIN32
62 #include <io.h>
63 #endif
64
65 typedef struct _GtkRcSet    GtkRcSet;
66 typedef struct _GtkRcNode   GtkRcNode;
67 typedef struct _GtkRcFile   GtkRcFile;
68
69 struct _GtkRcSet
70 {
71   GtkPatternSpec pspec;
72   GtkRcStyle    *rc_style;
73 };
74
75 struct _GtkRcFile
76 {
77   time_t mtime;
78   gchar *name;
79   gchar *canonical_name;
80   gboolean reload;
81 };
82
83 static guint       gtk_rc_style_hash                 (const char      *name);
84 static gboolean    gtk_rc_style_equal                (const char      *a,
85                                                       const char      *b);
86 static guint       gtk_rc_styles_hash                (const GSList    *rc_styles);
87 static gboolean    gtk_rc_styles_equal                (const GSList    *a,
88                                                       const GSList    *b);
89 static GtkRcStyle* gtk_rc_style_find                 (const char      *name);
90 static GSList *    gtk_rc_styles_match               (GSList          *rc_styles,
91                                                       GSList          *sets,
92                                                       guint            path_length,
93                                                       gchar           *path,
94                                                       gchar           *path_reversed);
95 static GtkStyle *  gtk_rc_style_to_style             (GtkRcStyle      *rc_style);
96 static GtkStyle*   gtk_rc_init_style                 (GSList          *rc_styles);
97 static void        gtk_rc_parse_file                 (const gchar     *filename,
98                                                       gboolean         reload);
99 static void        gtk_rc_parse_any                  (const gchar     *input_name,
100                                                       gint             input_fd,
101                                                       const gchar     *input_string);
102 static guint       gtk_rc_parse_statement            (GScanner        *scanner);
103 static guint       gtk_rc_parse_style                (GScanner        *scanner);
104 static guint       gtk_rc_parse_bg                   (GScanner        *scanner,
105                                                       GtkRcStyle      *style);
106 static guint       gtk_rc_parse_fg                   (GScanner        *scanner,
107                                                       GtkRcStyle      *style);
108 static guint       gtk_rc_parse_text                 (GScanner        *scanner,
109                                                       GtkRcStyle      *style);
110 static guint       gtk_rc_parse_base                 (GScanner        *scanner,
111                                                       GtkRcStyle      *style);
112 static guint       gtk_rc_parse_xthickness           (GScanner        *scanner,
113                                                       GtkRcStyle      *style);
114 static guint       gtk_rc_parse_ythickness           (GScanner        *scanner,
115                                                       GtkRcStyle      *style);
116 static guint       gtk_rc_parse_bg_pixmap            (GScanner        *scanner,
117                                                       GtkRcStyle      *rc_style);
118 static guint       gtk_rc_parse_font                 (GScanner        *scanner,
119                                                       GtkRcStyle      *rc_style);
120 static guint       gtk_rc_parse_fontset              (GScanner        *scanner,
121                                                       GtkRcStyle      *rc_style);
122 static guint       gtk_rc_parse_font_name            (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_im_module_path       (GScanner        *scanner);
131 static guint       gtk_rc_parse_im_module_file       (GScanner        *scanner);
132 static guint       gtk_rc_parse_path_pattern         (GScanner        *scanner);
133 static guint       gtk_rc_parse_stock                (GScanner        *scanner,
134                                                       GtkRcStyle      *rc_style,
135                                                       GtkIconFactory  *factory);
136 static void        gtk_rc_clear_hash_node            (gpointer         key,
137                                                       gpointer         data,
138                                                       gpointer         user_data);
139 static void        gtk_rc_clear_styles               (void);
140 static void        gtk_rc_append_default_module_path (void);
141 static void        gtk_rc_add_initial_default_files  (void);
142
143 static void        gtk_rc_style_init              (GtkRcStyle      *style);
144 static void        gtk_rc_style_class_init        (GtkRcStyleClass *klass);
145 static void        gtk_rc_style_finalize          (GObject         *object);
146 static void        gtk_rc_style_real_merge        (GtkRcStyle      *dest,
147                                                    GtkRcStyle      *src);
148 static GtkRcStyle *gtk_rc_style_real_clone        (GtkRcStyle      *rc_style);
149 static GtkStyle *  gtk_rc_style_real_create_style (GtkRcStyle      *rc_style);
150
151 static gpointer parent_class = NULL;
152
153 static const GScannerConfig     gtk_rc_scanner_config =
154 {
155   (
156    " \t\r\n"
157    )                    /* cset_skip_characters */,
158   (
159    G_CSET_a_2_z
160    "_"
161    G_CSET_A_2_Z
162    )                    /* cset_identifier_first */,
163   (
164    G_CSET_a_2_z
165    "_-0123456789"
166    G_CSET_A_2_Z
167    )                    /* cset_identifier_nth */,
168   ( "#\n" )             /* cpair_comment_single */,
169   
170   TRUE                  /* case_sensitive */,
171   
172   TRUE                  /* skip_comment_multi */,
173   TRUE                  /* skip_comment_single */,
174   TRUE                  /* scan_comment_multi */,
175   TRUE                  /* scan_identifier */,
176   FALSE                 /* scan_identifier_1char */,
177   FALSE                 /* scan_identifier_NULL */,
178   TRUE                  /* scan_symbols */,
179   TRUE                  /* scan_binary */,
180   TRUE                  /* scan_octal */,
181   TRUE                  /* scan_float */,
182   TRUE                  /* scan_hex */,
183   TRUE                  /* scan_hex_dollar */,
184   TRUE                  /* scan_string_sq */,
185   TRUE                  /* scan_string_dq */,
186   TRUE                  /* numbers_2_int */,
187   FALSE                 /* int_2_float */,
188   FALSE                 /* identifier_2_string */,
189   TRUE                  /* char_2_token */,
190   TRUE                  /* symbol_2_token */,
191   FALSE                 /* scope_0_fallback */,
192 };
193
194 static const struct
195 {
196   gchar *name;
197   guint token;
198 } symbols[] = {
199   { "include", GTK_RC_TOKEN_INCLUDE },
200   { "NORMAL", GTK_RC_TOKEN_NORMAL },
201   { "ACTIVE", GTK_RC_TOKEN_ACTIVE },
202   { "PRELIGHT", GTK_RC_TOKEN_PRELIGHT },
203   { "SELECTED", GTK_RC_TOKEN_SELECTED },
204   { "INSENSITIVE", GTK_RC_TOKEN_INSENSITIVE },
205   { "fg", GTK_RC_TOKEN_FG },
206   { "bg", GTK_RC_TOKEN_BG },
207   { "text", GTK_RC_TOKEN_TEXT },
208   { "base", GTK_RC_TOKEN_BASE },
209   { "xthickness", GTK_RC_TOKEN_XTHICKNESS },
210   { "ythickness", GTK_RC_TOKEN_YTHICKNESS },
211   { "font", GTK_RC_TOKEN_FONT },
212   { "fontset", GTK_RC_TOKEN_FONTSET },
213   { "font_name", GTK_RC_TOKEN_FONT_NAME },
214   { "bg_pixmap", GTK_RC_TOKEN_BG_PIXMAP },
215   { "pixmap_path", GTK_RC_TOKEN_PIXMAP_PATH },
216   { "style", GTK_RC_TOKEN_STYLE },
217   { "binding", GTK_RC_TOKEN_BINDING },
218   { "bind", GTK_RC_TOKEN_BIND },
219   { "widget", GTK_RC_TOKEN_WIDGET },
220   { "widget_class", GTK_RC_TOKEN_WIDGET_CLASS },
221   { "class", GTK_RC_TOKEN_CLASS },
222   { "lowest", GTK_RC_TOKEN_LOWEST },
223   { "gtk", GTK_RC_TOKEN_GTK },
224   { "application", GTK_RC_TOKEN_APPLICATION },
225   { "rc", GTK_RC_TOKEN_RC },
226   { "highest", GTK_RC_TOKEN_HIGHEST },
227   { "engine", GTK_RC_TOKEN_ENGINE },
228   { "module_path", GTK_RC_TOKEN_MODULE_PATH },
229   { "stock", GTK_RC_TOKEN_STOCK },
230   { "im_module_path", GTK_RC_TOKEN_IM_MODULE_PATH },
231   { "im_module_file", GTK_RC_TOKEN_IM_MODULE_FILE },
232   { "LTR", GTK_RC_TOKEN_LTR },
233   { "RTL", GTK_RC_TOKEN_RTL }
234 };
235
236 static const guint n_symbols = sizeof (symbols) / sizeof (symbols[0]);
237
238 static gchar *im_module_path = NULL;
239 static gchar *im_module_file = NULL;
240
241 static GHashTable *rc_style_ht = NULL;
242 static GHashTable *realized_style_ht = NULL;
243 static GSList *gtk_rc_sets_widget = NULL;
244 static GSList *gtk_rc_sets_widget_class = NULL;
245 static GSList *gtk_rc_sets_class = NULL;
246
247 #define GTK_RC_MAX_DEFAULT_FILES 128
248 static gchar *gtk_rc_default_files[GTK_RC_MAX_DEFAULT_FILES];
249 static gboolean gtk_rc_auto_parse = TRUE;
250
251 #define GTK_RC_MAX_PIXMAP_PATHS 128
252 static gchar *pixmap_path[GTK_RC_MAX_PIXMAP_PATHS];
253 #define GTK_RC_MAX_MODULE_PATHS 128
254 static gchar *module_path[GTK_RC_MAX_MODULE_PATHS];
255
256 /* A stack of directories for RC files we are parsing currently.
257  * these are implicitely added to the end of PIXMAP_PATHS
258  */
259 GSList *rc_dir_stack = NULL;
260
261 /* The files we have parsed, to reread later if necessary */
262 GSList *rc_files = NULL;
263
264 static GtkImageLoader image_loader = NULL;
265
266 /* RC file handling */
267
268
269 #ifdef G_OS_WIN32
270
271 static gchar *
272 get_gtk_dll_name (void)
273 {
274   static gchar *gtk_dll = NULL;
275
276   if (!gtk_dll)
277     gtk_dll = g_strdup_printf ("gtk-%d.%d.dll", GTK_MAJOR_VERSION, GTK_MINOR_VERSION);
278
279   return gtk_dll;
280 }
281
282 static gchar *
283 get_themes_directory (void)
284 {
285   return g_win32_get_package_installation_subdirectory (GETTEXT_PACKAGE,
286                                                         get_gtk_dll_name (),
287                                                         "themes");
288 }
289
290 #endif
291  
292 static gchar *
293 gtk_rc_make_default_dir (const gchar *type)
294 {
295   gchar *var, *path;
296
297 #ifndef G_OS_WIN32
298   var = getenv("GTK_EXE_PREFIX");
299   if (var)
300     path = g_strdup_printf("%s%s%s", var, "/lib/gtk-2.0/" GTK_VERSION "/", type);
301   else
302     path = g_strdup_printf("%s%s%s", GTK_EXE_PREFIX, "/lib/gtk-2.0/" GTK_VERSION "/", type);
303 #else
304   path = g_strdup_printf ("%s\\%s", get_themes_directory (), type);
305 #endif
306
307   return path;
308 }
309
310 gchar *
311 gtk_rc_get_im_module_path (void)
312 {
313   gchar *result = g_getenv ("GTK_IM_MODULE_PATH");
314
315   if (!result)
316     {
317       if (im_module_path)
318         result = im_module_path;
319       else
320         return gtk_rc_make_default_dir ("immodules");
321     }
322
323   return g_strdup (result);
324 }
325
326 gchar *
327 gtk_rc_get_im_module_file (void)
328 {
329   gchar *result = g_strdup (g_getenv ("GTK_IM_MODULE_FILE"));
330
331   if (!result)
332     {
333       if (im_module_file)
334         result = g_strdup (im_module_file);
335       else
336 #ifndef G_OS_WIN32
337         result = g_strdup (GTK_SYSCONFDIR G_DIR_SEPARATOR_S "gtk-2.0" G_DIR_SEPARATOR_S "gtk.immodules");
338 #else
339         result = g_strdup_printf ("%s\\gtk.immodules", g_win32_get_package_installation_directory (GETTEXT_PACKAGE, get_gtk_dll_name ()));
340 #endif
341     }
342
343   return result;
344 }
345
346 gchar *
347 gtk_rc_get_theme_dir(void)
348 {
349   gchar *var, *path;
350
351 #ifndef G_OS_WIN32
352   var = getenv("GTK_DATA_PREFIX");
353   if (var)
354     path = g_strdup_printf("%s%s", var, "/share/themes");
355   else
356     path = g_strdup_printf("%s%s", GTK_DATA_PREFIX, "/share/themes");
357 #else
358   path = g_strdup (get_themes_directory ());
359 #endif
360
361   return path;
362 }
363
364 gchar *
365 gtk_rc_get_module_dir(void)
366 {
367   return gtk_rc_make_default_dir ("engines");
368 }
369
370 static void
371 gtk_rc_append_default_module_path(void)
372 {
373   gchar *var, *path;
374   gint n;
375
376   for (n = 0; module_path[n]; n++) ;
377   if (n >= GTK_RC_MAX_MODULE_PATHS - 1)
378     return;
379   
380 #ifndef G_OS_WIN32
381   var = getenv("GTK_EXE_PREFIX");
382   if (var)
383     path = g_strdup_printf("%s%s", var, "/lib/gtk-2.0/" GTK_VERSION "/engines");
384   else
385     path = g_strdup_printf("%s%s", GTK_EXE_PREFIX, "/lib/gtk-2.0/" GTK_VERSION "/engines");
386 #else
387   path = g_strdup_printf ("%s%s", get_themes_directory (), "\\engines");
388 #endif
389   module_path[n++] = path;
390
391   var = g_get_home_dir ();
392   if (var)
393     {
394       gchar *sep;
395       /* Don't duplicate the directory separator, causes trouble at
396        * least on Windows.
397        */
398       if (var[strlen (var) -1] != G_DIR_SEPARATOR)
399         sep = G_DIR_SEPARATOR_S;
400       else
401         sep = "";
402       /* This produces something like ~/.gtk-2.0/2.0/engines */
403       path = g_strdup_printf ("%s%s%s", var, sep,
404                               ".gtk-2.0" G_DIR_SEPARATOR_S
405                               GTK_VERSION G_DIR_SEPARATOR_S
406                               "engines");
407       module_path[n++] = path;
408     }
409   module_path[n] = NULL;
410 }
411
412 static void
413 gtk_rc_add_initial_default_files (void)
414 {
415   static gint init = FALSE;
416   gchar *var, *str;
417   gchar **files;
418   gint i;
419
420   if (init)
421     return;
422   
423   gtk_rc_default_files[0] = NULL;
424   init = TRUE;
425
426   var = g_getenv("GTK_RC_FILES");
427   if (var)
428     {
429       files = g_strsplit (var, G_SEARCHPATH_SEPARATOR_S, 128);
430       i=0;
431       while (files[i])
432         {
433           gtk_rc_add_default_file (files[i]);
434           i++;
435         }
436       g_strfreev (files);
437     }
438   else
439     {
440 #ifndef G_OS_WIN32
441       str = g_strdup (GTK_SYSCONFDIR G_DIR_SEPARATOR_S "gtk-2.0" G_DIR_SEPARATOR_S "gtkrc");
442 #else
443       str = g_strdup_printf ("%s\\gtkrc", g_win32_get_package_installation_directory (GETTEXT_PACKAGE, get_gtk_dll_name ()));
444 #endif
445
446       gtk_rc_add_default_file (str);
447       g_free (str);
448
449       var = g_get_home_dir ();
450       if (var)
451         {
452           gchar *sep;
453           if (var[strlen (var) -1] != G_DIR_SEPARATOR)
454             sep = G_DIR_SEPARATOR_S;
455           else
456             sep = "";
457           str = g_strdup_printf ("%s%s.gtkrc-2.0", var, sep);
458           gtk_rc_add_default_file (str);
459           g_free (str);
460         }
461     }
462 }
463
464 void
465 gtk_rc_add_default_file (const gchar *file)
466 {
467   guint n;
468   
469   gtk_rc_add_initial_default_files ();
470
471   for (n = 0; gtk_rc_default_files[n]; n++) ;
472   if (n >= GTK_RC_MAX_DEFAULT_FILES - 1)
473     return;
474   
475   gtk_rc_default_files[n++] = g_strdup (file);
476   gtk_rc_default_files[n] = NULL;
477 }
478
479 void
480 gtk_rc_set_default_files (gchar **files)
481 {
482   gint i;
483
484   gtk_rc_add_initial_default_files ();
485
486   i = 0;
487   while (gtk_rc_default_files[i])
488     {
489       g_free (gtk_rc_default_files[i]);
490       i++;
491     }
492     
493   gtk_rc_default_files[0] = NULL;
494   gtk_rc_auto_parse = FALSE;
495
496   i = 0;
497   while (files[i] != NULL)
498     {
499       gtk_rc_add_default_file (files[i]);
500       i++;
501     }
502 }
503
504 gchar **
505 gtk_rc_get_default_files (void)
506 {
507   gtk_rc_add_initial_default_files ();
508
509   return gtk_rc_default_files;
510 }
511
512  /* The following routine is based on _nl_normalize_codeset from
513   * the GNU C library. Contributed by
514   *
515   * Contributed by Ulrich Drepper <drepper@gnu.ai.mit.edu>, 1995.
516   * Copyright (C) 1995, 1996, 1997, 1998, 1999 Free Software Foundation, Inc.
517   * 
518   * Normalize codeset name.  There is no standard for the codeset
519   * names.  Normalization allows the user to use any of the common
520   * names.
521   */
522  static char *
523  _gtk_normalize_codeset (const char *codeset, int name_len)
524  {
525    int len = 0;
526    int only_digit = 1;
527    char *retval;
528    char *wp;
529    int cnt;
530  
531    for (cnt = 0; cnt < name_len; ++cnt)
532      if (isalnum (codeset[cnt]))
533        {
534         ++len;
535  
536         if (isalpha (codeset[cnt]))
537           only_digit = 0;
538        }
539  
540    retval = g_malloc ((only_digit ? 3 : 0) + len + 1);
541  
542    if (only_digit)
543      {
544        memcpy (retval, "iso", 4);
545        wp = retval + 3;
546      }
547    else
548      wp = retval;
549    
550    for (cnt = 0; cnt < name_len; ++cnt)
551      if (isalpha (codeset[cnt]))
552        *wp++ = isupper(codeset[cnt]) ? tolower (codeset[cnt]) : codeset[cnt];
553      else if (isdigit (codeset[cnt]))
554        *wp++ = codeset[cnt];
555    
556    *wp = '\0';
557  
558    return retval;
559  }
560  
561 void
562 gtk_rc_init (void)
563 {
564   static gchar *locale_suffixes[3];
565   static gint n_locale_suffixes = 0;
566
567   gint i, j;
568
569   static gboolean initted = FALSE;
570
571   if (!initted)
572     {
573       gint length;
574       gchar *locale;
575       gchar *p;
576
577 #ifdef G_OS_WIN32      
578       locale = g_win32_getlocale ();
579 #else      
580       locale = setlocale (LC_CTYPE, NULL);
581 #endif      
582       
583       initted = TRUE;
584
585       pixmap_path[0] = NULL;
586       module_path[0] = NULL;
587       gtk_rc_append_default_module_path();
588       
589       gtk_rc_add_initial_default_files ();
590
591       if (strcmp (locale, "C") && strcmp (locale, "POSIX"))
592         {
593           /* Determine locale-specific suffixes for RC files
594            *
595            * We normalize the charset into a standard form,
596            * which has all '-' and '_' characters removed,
597            * and is lowercase.
598            */
599           gchar *normalized_locale;
600
601           p = strchr (locale, '@');
602           length = p ? (p -locale) : strlen (locale);
603
604           p = strchr (locale, '.');
605           if (p)
606             {
607               gchar *tmp1 = g_strndup (locale, p - locale + 1);
608               gchar *tmp2 = _gtk_normalize_codeset (p + 1, length - (p - locale + 1));
609               
610               normalized_locale = g_strconcat (tmp1, tmp2, NULL);
611               g_free (tmp1);
612               g_free (tmp2);
613                                                  
614               locale_suffixes[n_locale_suffixes++] = g_strdup (normalized_locale);
615               length = p - locale;
616             }
617           else
618             normalized_locale = g_strndup (locale, length);
619           
620           p = strchr (normalized_locale, '_');
621           if (p)
622             {
623               locale_suffixes[n_locale_suffixes++] = g_strndup (normalized_locale, length);
624               length = p - normalized_locale;
625             }
626           
627           locale_suffixes[n_locale_suffixes++] = g_strndup (normalized_locale, length);
628
629           g_free (normalized_locale);
630         }
631     }
632   
633   i = 0;
634   while (gtk_rc_default_files[i] != NULL)
635     {
636       /* Try to find a locale specific RC file corresponding to
637        * to parse before the default file.
638        */
639       for (j=n_locale_suffixes-1; j>=0; j--)
640         {
641           gchar *name = g_strconcat (gtk_rc_default_files[i],
642                                      ".",
643                                      locale_suffixes[j],
644                                      NULL);
645           gtk_rc_parse (name);
646           g_free (name);
647         }
648
649       gtk_rc_parse (gtk_rc_default_files[i]);
650       i++;
651     }
652 }
653
654 void
655 gtk_rc_parse_string (const gchar *rc_string)
656 {
657   g_return_if_fail (rc_string != NULL);
658
659   gtk_rc_parse_any ("-", -1, rc_string);
660 }
661
662 static void
663 gtk_rc_parse_file (const gchar *filename, gboolean reload)
664 {
665   GtkRcFile *rc_file = NULL;
666   struct stat statbuf;
667   GSList *tmp_list;
668
669   g_return_if_fail (filename != NULL);
670
671   tmp_list = rc_files;
672   while (tmp_list)
673     {
674       rc_file = tmp_list->data;
675       if (!strcmp (rc_file->name, filename))
676         break;
677       
678       tmp_list = tmp_list->next;
679     }
680
681   if (!tmp_list)
682     {
683       rc_file = g_new (GtkRcFile, 1);
684       rc_file->name = g_strdup (filename);
685       rc_file->canonical_name = NULL;
686       rc_file->mtime = 0;
687       rc_file->reload = reload;
688
689       rc_files = g_slist_append (rc_files, rc_file);
690     }
691
692   if (!rc_file->canonical_name)
693     {
694       /* Get the absolute pathname */
695
696       if (g_path_is_absolute (rc_file->name))
697         rc_file->canonical_name = rc_file->name;
698       else
699         {
700           GString *str;
701           gchar *cwd;
702
703           cwd = g_get_current_dir ();
704
705           str = g_string_new (cwd);
706           g_free (cwd);
707           g_string_append_c (str, G_DIR_SEPARATOR);
708           g_string_append (str, rc_file->name);
709           
710           rc_file->canonical_name = str->str;
711           g_string_free (str, FALSE);
712         }
713     }
714
715   if (!lstat (rc_file->canonical_name, &statbuf))
716     {
717       gint fd;
718       GSList *tmp_list;
719
720       rc_file->mtime = statbuf.st_mtime;
721
722       fd = open (rc_file->canonical_name, O_RDONLY);
723       if (fd < 0)
724         return;
725
726       /* Temporarily push directory name for this file on
727        * a stack of directory names while parsing it
728        */
729       rc_dir_stack = 
730         g_slist_prepend (rc_dir_stack,
731                          g_path_get_dirname (rc_file->canonical_name));
732       gtk_rc_parse_any (filename, fd, NULL);
733  
734       tmp_list = rc_dir_stack;
735       rc_dir_stack = rc_dir_stack->next;
736  
737       g_free (tmp_list->data);
738       g_slist_free_1 (tmp_list);
739
740       close (fd);
741     }
742 }
743
744 void
745 gtk_rc_parse (const gchar *filename)
746 {
747   g_return_if_fail (filename != NULL);
748
749   gtk_rc_parse_file (filename, TRUE);
750 }
751
752 /* Handling of RC styles */
753
754 GType
755 gtk_rc_style_get_type (void)
756 {
757   static GType object_type = 0;
758
759   if (!object_type)
760     {
761       static const GTypeInfo object_info =
762       {
763         sizeof (GtkRcStyleClass),
764         (GBaseInitFunc) NULL,
765         (GBaseFinalizeFunc) NULL,
766         (GClassInitFunc) gtk_rc_style_class_init,
767         NULL,           /* class_finalize */
768         NULL,           /* class_data */
769         sizeof (GtkRcStyle),
770         0,              /* n_preallocs */
771         (GInstanceInitFunc) gtk_rc_style_init,
772       };
773       
774       object_type = g_type_register_static (G_TYPE_OBJECT,
775                                             "GtkRcStyle",
776                                             &object_info, 0);
777     }
778   
779   return object_type;
780 }
781
782 static void
783 gtk_rc_style_init (GtkRcStyle *style)
784 {
785   guint i;
786
787   style->name = NULL;
788   for (i = 0; i < 5; i++)
789     {
790       static const GdkColor init_color = { 0, 0, 0, 0, };
791
792       style->bg_pixmap_name[i] = NULL;
793       style->color_flags[i] = 0;
794       style->fg[i] = init_color;
795       style->bg[i] = init_color;
796       style->text[i] = init_color;
797       style->base[i] = init_color;
798     }
799   style->xthickness = -1;
800   style->ythickness = -1;
801   style->rc_style_lists = NULL;
802 }
803
804 static void
805 gtk_rc_style_class_init (GtkRcStyleClass *klass)
806 {
807   GObjectClass *object_class = G_OBJECT_CLASS (klass);
808   
809   parent_class = g_type_class_peek_parent (klass);
810
811   object_class->finalize = gtk_rc_style_finalize;
812
813   klass->parse = NULL;
814   klass->clone = gtk_rc_style_real_clone;
815   klass->merge = gtk_rc_style_real_merge;
816   klass->create_style = gtk_rc_style_real_create_style;
817 }
818
819 /* Like g_slist_remove, but remove all copies of data */
820 static GSList*
821 gtk_rc_slist_remove_all (GSList   *list,
822                          gpointer  data)
823 {
824   GSList *tmp;
825   GSList *prev;
826
827   prev = NULL;
828   tmp = list;
829
830   while (tmp)
831     {
832       if (tmp->data == data)
833         {
834           if (list == tmp)
835             list = list->next;
836
837           if (prev) 
838             prev->next = tmp->next;
839
840           g_slist_free_1 (tmp);
841
842           if (prev)
843             tmp = prev->next;
844           else
845             tmp = list;
846         }
847       else
848         {
849           prev = tmp;
850           tmp = tmp->next;
851         }
852     }
853
854   return list;
855 }
856
857 static void
858 gtk_rc_style_finalize (GObject *object)
859 {
860   gint i;
861   GSList *tmp_list1, *tmp_list2;
862   GtkRcStyle *rc_style;
863
864   rc_style = GTK_RC_STYLE (object);
865   
866   if (rc_style->name)
867     g_free (rc_style->name);
868   if (rc_style->font_desc)
869     pango_font_description_free (rc_style->font_desc);
870       
871   for (i=0 ; i < 5 ; i++)
872     if (rc_style->bg_pixmap_name[i])
873       g_free (rc_style->bg_pixmap_name[i]);
874   
875   /* Now remove all references to this rc_style from
876    * realized_style_ht
877    */
878   tmp_list1 = rc_style->rc_style_lists;
879   while (tmp_list1)
880     {
881       GSList *rc_styles = tmp_list1->data;
882       GtkStyle *style = g_hash_table_lookup (realized_style_ht, rc_styles);
883       gtk_style_unref (style);
884
885       /* Remove the list of styles from the other rc_styles
886        * in the list
887        */
888       tmp_list2 = rc_styles;
889       while (tmp_list2)
890         {
891           GtkRcStyle *other_style = tmp_list2->data;
892
893           if (other_style != rc_style)
894             other_style->rc_style_lists =
895               gtk_rc_slist_remove_all (other_style->rc_style_lists, rc_styles);
896                   
897           tmp_list2 = tmp_list2->next;
898         }
899
900       /* And from the hash table itself
901        */
902       g_hash_table_remove (realized_style_ht, rc_styles);
903       g_slist_free (rc_styles);
904
905       tmp_list1 = tmp_list1->next;
906     }
907
908   g_slist_free (rc_style->rc_style_lists);
909
910   tmp_list1 = rc_style->icon_factories;
911   while (tmp_list1)
912     {
913       g_object_unref (G_OBJECT (tmp_list1->data));
914
915       tmp_list1 = tmp_list1->next;
916     }
917
918   g_slist_free (rc_style->icon_factories);
919   
920   G_OBJECT_CLASS (parent_class)->finalize (object);
921 }
922
923 GtkRcStyle *
924 gtk_rc_style_new (void)
925 {
926   GtkRcStyle *style;
927   
928   style = g_object_new (GTK_TYPE_RC_STYLE, NULL);
929   
930   return style;
931 }
932
933 /**
934  * gtk_rc_style_copy:
935  * @orig: the style to copy
936  * 
937  * Make a copy of the specified #GtkRcStyle. This function
938  * will correctly copy an rc style that is a member of a class
939  * derived from #GtkRcStyle.
940  * 
941  * Return value: the resulting #GtkRcStyle
942  **/
943 GtkRcStyle *
944 gtk_rc_style_copy (GtkRcStyle *orig)
945 {
946   GtkRcStyle *style;
947
948   g_return_val_if_fail (GTK_IS_RC_STYLE (orig), NULL);
949   
950   style = GTK_RC_STYLE_GET_CLASS (orig)->clone (orig);
951   GTK_RC_STYLE_GET_CLASS (style)->merge (style, orig);
952
953   return style;
954 }
955
956 void      
957 gtk_rc_style_ref (GtkRcStyle  *rc_style)
958 {
959   g_return_if_fail (GTK_IS_RC_STYLE (rc_style));
960
961   g_object_ref (G_OBJECT (rc_style));
962 }
963
964 void      
965 gtk_rc_style_unref (GtkRcStyle  *rc_style)
966 {
967   g_return_if_fail (GTK_IS_RC_STYLE (rc_style));
968
969   g_object_unref (G_OBJECT (rc_style));
970 }
971
972 static GtkRcStyle *
973 gtk_rc_style_real_clone (GtkRcStyle *style)
974 {
975   return GTK_RC_STYLE (g_object_new (G_OBJECT_TYPE (style), NULL));
976 }
977
978 static void
979 gtk_rc_style_real_merge (GtkRcStyle *dest,
980                          GtkRcStyle *src)
981 {
982   gint i;
983   
984   for (i = 0; i < 5; i++)
985     {
986       if (!dest->bg_pixmap_name[i] && src->bg_pixmap_name[i])
987         dest->bg_pixmap_name[i] = g_strdup (src->bg_pixmap_name[i]);
988       
989       if (!(dest->color_flags[i] & GTK_RC_FG) && 
990           src->color_flags[i] & GTK_RC_FG)
991         {
992           dest->fg[i] = src->fg[i];
993           dest->color_flags[i] |= GTK_RC_FG;
994         }
995       if (!(dest->color_flags[i] & GTK_RC_BG) && 
996           src->color_flags[i] & GTK_RC_BG)
997         {
998           dest->bg[i] = src->bg[i];
999           dest->color_flags[i] |= GTK_RC_BG;
1000         }
1001       if (!(dest->color_flags[i] & GTK_RC_TEXT) && 
1002           src->color_flags[i] & GTK_RC_TEXT)
1003         {
1004           dest->text[i] = src->text[i];
1005           dest->color_flags[i] |= GTK_RC_TEXT;
1006         }
1007       if (!(dest->color_flags[i] & GTK_RC_BASE) && 
1008           src->color_flags[i] & GTK_RC_BASE)
1009         {
1010           dest->base[i] = src->base[i];
1011           dest->color_flags[i] |= GTK_RC_BASE;
1012         }
1013     }
1014
1015   if (dest->xthickness < 0 && src->xthickness >= 0)
1016     dest->xthickness = src->xthickness;
1017   if (dest->ythickness < 0 && src->ythickness >= 0)
1018     dest->ythickness = src->ythickness;
1019
1020   if (!dest->font_desc && src->font_desc)
1021     dest->font_desc = pango_font_description_copy (src->font_desc);
1022 }
1023
1024 static GtkStyle *
1025 gtk_rc_style_real_create_style (GtkRcStyle *rc_style)
1026 {
1027   return gtk_style_new ();
1028 }
1029
1030 static void
1031 gtk_rc_clear_hash_node (gpointer key, 
1032                         gpointer data, 
1033                         gpointer user_data)
1034 {
1035   gtk_rc_style_unref (data);
1036 }
1037
1038 static void
1039 gtk_rc_free_rc_sets (GSList *slist)
1040 {
1041   while (slist)
1042     {
1043       GtkRcSet *rc_set;
1044
1045       rc_set = slist->data;
1046       gtk_pattern_spec_free_segs (&rc_set->pspec);
1047       g_free (rc_set);
1048
1049       slist = slist->next;
1050     }
1051 }
1052
1053 static void
1054 gtk_rc_clear_styles (void)
1055 {
1056   /* Clear out all old rc_styles */
1057
1058   if (rc_style_ht)
1059     {
1060       g_hash_table_foreach (rc_style_ht, gtk_rc_clear_hash_node, NULL);
1061       g_hash_table_destroy (rc_style_ht);
1062       rc_style_ht = NULL;
1063     }
1064
1065   gtk_rc_free_rc_sets (gtk_rc_sets_widget);
1066   g_slist_free (gtk_rc_sets_widget);
1067   gtk_rc_sets_widget = NULL;
1068
1069   gtk_rc_free_rc_sets (gtk_rc_sets_widget_class);
1070   g_slist_free (gtk_rc_sets_widget_class);
1071   gtk_rc_sets_widget_class = NULL;
1072
1073   gtk_rc_free_rc_sets (gtk_rc_sets_class);
1074   g_slist_free (gtk_rc_sets_class);
1075   gtk_rc_sets_class = NULL;
1076 }
1077
1078 gboolean
1079 gtk_rc_reparse_all (void)
1080 {
1081   GSList *tmp_list;
1082   gboolean mtime_modified = FALSE;
1083   GtkRcFile *rc_file;
1084
1085   struct stat statbuf;
1086
1087   /* Check through and see if any of the RC's have had their
1088    * mtime modified. If so, reparse everything.
1089    */
1090   tmp_list = rc_files;
1091   while (tmp_list)
1092     {
1093       rc_file = tmp_list->data;
1094       
1095       if (!lstat (rc_file->name, &statbuf) && 
1096           (statbuf.st_mtime > rc_file->mtime))
1097         {
1098           mtime_modified = TRUE;
1099           break;
1100         }
1101       
1102       tmp_list = tmp_list->next;
1103     }
1104
1105   if (mtime_modified)
1106     {
1107       gtk_rc_clear_styles();
1108
1109       tmp_list = rc_files;
1110       while (tmp_list)
1111         {
1112           rc_file = tmp_list->data;
1113           if (rc_file->reload)
1114             gtk_rc_parse_file (rc_file->name, FALSE);
1115           
1116           tmp_list = tmp_list->next;
1117         }
1118     }
1119
1120   return mtime_modified;
1121 }
1122
1123 static GSList *
1124 gtk_rc_styles_match (GSList       *rc_styles,
1125                      GSList       *sets,
1126                      guint         path_length,
1127                      gchar        *path,
1128                      gchar        *path_reversed)
1129                      
1130 {
1131   GtkRcSet *rc_set;
1132
1133   while (sets)
1134     {
1135       rc_set = sets->data;
1136       sets = sets->next;
1137
1138       if (gtk_pattern_match (&rc_set->pspec, path_length, path, path_reversed))
1139         rc_styles = g_slist_append (rc_styles, rc_set->rc_style);
1140     }
1141   
1142   return rc_styles;
1143 }
1144
1145 GtkStyle*
1146 gtk_rc_get_style (GtkWidget *widget)
1147 {
1148   GtkRcStyle *widget_rc_style;
1149   GSList *rc_styles = NULL;
1150
1151   static guint rc_style_key_id = 0;
1152
1153   /* We allow the specification of a single rc style to be bound
1154    * tightly to a widget, for application modifications
1155    */
1156   if (!rc_style_key_id)
1157     rc_style_key_id = g_quark_from_static_string ("gtk-rc-style");
1158
1159   widget_rc_style = gtk_object_get_data_by_id (GTK_OBJECT (widget),
1160                                                rc_style_key_id);
1161
1162   if (widget_rc_style)
1163     rc_styles = g_slist_prepend (rc_styles, widget_rc_style);
1164   
1165   if (gtk_rc_sets_widget)
1166     {
1167       gchar *path, *path_reversed;
1168       guint path_length;
1169
1170       gtk_widget_path (widget, &path_length, &path, &path_reversed);
1171       rc_styles = gtk_rc_styles_match (rc_styles, gtk_rc_sets_widget, path_length, path, path_reversed);
1172       g_free (path);
1173       g_free (path_reversed);
1174       
1175     }
1176   
1177   if (gtk_rc_sets_widget_class)
1178     {
1179       gchar *path, *path_reversed;
1180       guint path_length;
1181
1182       gtk_widget_class_path (widget, &path_length, &path, &path_reversed);
1183       rc_styles = gtk_rc_styles_match (rc_styles, gtk_rc_sets_widget_class, path_length, path, path_reversed);
1184       g_free (path);
1185       g_free (path_reversed);
1186     }
1187
1188   if (gtk_rc_sets_class)
1189     {
1190       GtkType type;
1191
1192       type = GTK_OBJECT_TYPE (widget);
1193       while (type)
1194         {
1195           gchar *path, *path_reversed;
1196           guint path_length;
1197
1198           path = gtk_type_name (type);
1199           path_length = strlen (path);
1200           path_reversed = g_strdup (path);
1201           g_strreverse (path_reversed);
1202           
1203           rc_styles = gtk_rc_styles_match (rc_styles, gtk_rc_sets_class, path_length, path, path_reversed);
1204           g_free (path_reversed);
1205       
1206           type = gtk_type_parent (type);
1207         }
1208     }
1209   
1210   if (rc_styles)
1211     return gtk_rc_init_style (rc_styles);
1212
1213   return NULL;
1214 }
1215
1216 static GSList*
1217 gtk_rc_add_rc_sets (GSList     *slist,
1218                     GtkRcStyle *rc_style,
1219                     const char *pattern)
1220 {
1221   GtkRcStyle *new_style;
1222   GtkRcSet *rc_set;
1223   guint i;
1224   
1225   new_style = gtk_rc_style_new ();
1226   *new_style = *rc_style;
1227   new_style->name = g_strdup (rc_style->name);
1228   if (rc_style->font_desc)
1229     new_style->font_desc = pango_font_description_copy (rc_style->font_desc);
1230   
1231   for (i = 0; i < 5; i++)
1232     new_style->bg_pixmap_name[i] = g_strdup (rc_style->bg_pixmap_name[i]);
1233   
1234   rc_set = g_new (GtkRcSet, 1);
1235   gtk_pattern_spec_init (&rc_set->pspec, pattern);
1236   rc_set->rc_style = rc_style;
1237   
1238   return g_slist_prepend (slist, rc_set);
1239 }
1240
1241 void
1242 gtk_rc_add_widget_name_style (GtkRcStyle  *rc_style,
1243                               const gchar *pattern)
1244 {
1245   g_return_if_fail (rc_style != NULL);
1246   g_return_if_fail (pattern != NULL);
1247
1248   gtk_rc_sets_widget = gtk_rc_add_rc_sets (gtk_rc_sets_widget, rc_style, pattern);
1249 }
1250
1251 void
1252 gtk_rc_add_widget_class_style (GtkRcStyle  *rc_style,
1253                                const gchar *pattern)
1254 {
1255   g_return_if_fail (rc_style != NULL);
1256   g_return_if_fail (pattern != NULL);
1257
1258   gtk_rc_sets_widget_class = gtk_rc_add_rc_sets (gtk_rc_sets_widget_class, rc_style, pattern);
1259 }
1260
1261 void
1262 gtk_rc_add_class_style (GtkRcStyle  *rc_style,
1263                         const gchar *pattern)
1264 {
1265   g_return_if_fail (rc_style != NULL);
1266   g_return_if_fail (pattern != NULL);
1267
1268   gtk_rc_sets_class = gtk_rc_add_rc_sets (gtk_rc_sets_class, rc_style, pattern);
1269 }
1270
1271 static void
1272 gtk_rc_parse_any (const gchar  *input_name,
1273                   gint          input_fd,
1274                   const gchar  *input_string)
1275 {
1276   GScanner *scanner;
1277   guint    i;
1278   gboolean done;
1279   
1280   scanner = g_scanner_new ((GScannerConfig *) &gtk_rc_scanner_config);
1281   
1282   if (input_fd >= 0)
1283     {
1284       g_assert (input_string == NULL);
1285       
1286       g_scanner_input_file (scanner, input_fd);
1287     }
1288   else
1289     {
1290       g_assert (input_string != NULL);
1291       
1292       g_scanner_input_text (scanner, input_string, strlen (input_string));
1293     }
1294   scanner->input_name = input_name;
1295
1296   for (i = 0; i < n_symbols; i++)
1297     g_scanner_add_symbol (scanner, symbols[i].name, GINT_TO_POINTER (symbols[i].token));
1298   
1299   done = FALSE;
1300   while (!done)
1301     {
1302       if (g_scanner_peek_next_token (scanner) == G_TOKEN_EOF)
1303         done = TRUE;
1304       else
1305         {
1306           guint expected_token;
1307           
1308           expected_token = gtk_rc_parse_statement (scanner);
1309
1310           if (expected_token != G_TOKEN_NONE)
1311             {
1312               gchar *symbol_name;
1313               gchar *msg;
1314               
1315               msg = NULL;
1316               symbol_name = NULL;
1317               if (scanner->scope_id == 0)
1318                 {
1319                   /* if we are in scope 0, we know the symbol names
1320                    * that are associated with certaintoken values.
1321                    * so we look them up to make the error messages
1322                    * more readable.
1323                    */
1324                   if (expected_token > GTK_RC_TOKEN_INVALID &&
1325                       expected_token < GTK_RC_TOKEN_LAST)
1326                     {
1327                       for (i = 0; i < n_symbols; i++)
1328                         if (symbols[i].token == expected_token)
1329                           msg = symbols[i].name;
1330                       if (msg)
1331                         msg = g_strconcat ("e.g. `", msg, "'", NULL);
1332                     }
1333                   if (scanner->token > GTK_RC_TOKEN_INVALID &&
1334                       scanner->token < GTK_RC_TOKEN_LAST)
1335                     {
1336                       symbol_name = "???";
1337                       for (i = 0; i < n_symbols; i++)
1338                         if (symbols[i].token == scanner->token)
1339                           symbol_name = symbols[i].name;
1340                     }
1341                 }
1342               g_scanner_unexp_token (scanner,
1343                                      expected_token,
1344                                      NULL,
1345                                      "keyword",
1346                                      symbol_name,
1347                                      msg,
1348                                      TRUE);
1349               g_free (msg);
1350               done = TRUE;
1351             }
1352         }
1353     }
1354   
1355   g_scanner_destroy (scanner);
1356 }
1357
1358 static guint       
1359 gtk_rc_styles_hash (const GSList *rc_styles)
1360 {
1361   guint result;
1362   
1363   result = 0;
1364   while (rc_styles)
1365     {
1366       result += (result << 9) + GPOINTER_TO_UINT (rc_styles->data);
1367       rc_styles = rc_styles->next;
1368     }
1369   
1370   return result;
1371 }
1372
1373 static gboolean
1374 gtk_rc_styles_equal (const GSList *a,
1375                      const GSList *b)
1376 {
1377   while (a && b)
1378     {
1379       if (a->data != b->data)
1380         return FALSE;
1381       a = a->next;
1382       b = b->next;
1383     }
1384   
1385   return (a == b);
1386 }
1387
1388 static guint
1389 gtk_rc_style_hash (const char *name)
1390 {
1391   guint result;
1392   
1393   result = 0;
1394   while (*name)
1395     result += (result << 3) + *name++;
1396   
1397   return result;
1398 }
1399
1400 static gboolean
1401 gtk_rc_style_equal (const char *a,
1402                     const char *b)
1403 {
1404   return (strcmp (a, b) == 0);
1405 }
1406
1407 static GtkRcStyle*
1408 gtk_rc_style_find (const char *name)
1409 {
1410   if (rc_style_ht)
1411     return g_hash_table_lookup (rc_style_ht, (gpointer) name);
1412   else
1413     return NULL;
1414 }
1415
1416 static GtkStyle *
1417 gtk_rc_style_to_style (GtkRcStyle *rc_style)
1418 {
1419   GtkStyle *style;
1420
1421   style = GTK_RC_STYLE_GET_CLASS (rc_style)->create_style (rc_style);
1422
1423   style->rc_style = rc_style;
1424
1425   gtk_rc_style_ref (rc_style);
1426   
1427   GTK_STYLE_GET_CLASS (style)->init_from_rc (style, rc_style);  
1428
1429   return style;
1430 }
1431
1432 /* Reuses or frees rc_styles */
1433 static GtkStyle *
1434 gtk_rc_init_style (GSList *rc_styles)
1435 {
1436   GtkStyle *style = NULL;
1437   gint i;
1438
1439   g_return_val_if_fail (rc_styles != NULL, NULL);
1440   
1441   if (!realized_style_ht)
1442     realized_style_ht = g_hash_table_new ((GHashFunc) gtk_rc_styles_hash,
1443                                           (GEqualFunc) gtk_rc_styles_equal);
1444
1445   style = g_hash_table_lookup (realized_style_ht, rc_styles);
1446
1447   if (!style)
1448     {
1449       GtkRcStyle *base_style = NULL;
1450       GtkRcStyle *proto_style;
1451       GtkRcStyleClass *proto_style_class;
1452       GSList *tmp_styles;
1453       GType rc_style_type = GTK_TYPE_RC_STYLE;
1454
1455       /* Find the first derived style in the list, and use that to
1456        * create the merged style. If we only have raw GtkRcStyles, use
1457        * the first style to create the merged style.
1458        */
1459       base_style = rc_styles->data;
1460       tmp_styles = rc_styles;
1461       while (tmp_styles)
1462         {
1463           GtkRcStyle *rc_style = tmp_styles->data;
1464           
1465           if (G_OBJECT_TYPE (rc_style) != rc_style_type)
1466             {
1467               base_style = rc_style;
1468               break;
1469             }
1470           
1471           tmp_styles = tmp_styles->next;
1472         }
1473       
1474       proto_style_class = GTK_RC_STYLE_GET_CLASS (base_style);
1475       proto_style = proto_style_class->clone (base_style);
1476       
1477       tmp_styles = rc_styles;
1478       while (tmp_styles)
1479         {
1480           GtkRcStyle *rc_style = tmp_styles->data;
1481           GSList *factories;
1482           
1483           proto_style_class->merge (proto_style, rc_style);       
1484           
1485           /* Point from each rc_style to the list of styles */
1486           if (!g_slist_find (rc_style->rc_style_lists, rc_styles))
1487             rc_style->rc_style_lists = g_slist_prepend (rc_style->rc_style_lists, rc_styles);
1488
1489           factories = g_slist_copy (rc_style->icon_factories);
1490           if (factories)
1491             {
1492               GSList *iter;
1493               
1494               iter = factories;
1495               while (iter != NULL)
1496                 {
1497                   g_object_ref (G_OBJECT (iter->data));
1498                   iter = g_slist_next (iter);
1499                 }
1500
1501               proto_style->icon_factories = g_slist_concat (proto_style->icon_factories,
1502                                                             factories);
1503
1504             }
1505           
1506           tmp_styles = tmp_styles->next;
1507         }
1508
1509       for (i = 0; i < 5; i++)
1510         if (proto_style->bg_pixmap_name[i] &&
1511             (strcmp (proto_style->bg_pixmap_name[i], "<none>") == 0))
1512           {
1513             g_free (proto_style->bg_pixmap_name[i]);
1514             proto_style->bg_pixmap_name[i] = NULL;
1515           }
1516
1517       style = gtk_rc_style_to_style (proto_style);
1518       gtk_rc_style_unref (proto_style);
1519
1520       g_hash_table_insert (realized_style_ht, rc_styles, style);
1521     }
1522   else
1523     g_slist_free (rc_styles);
1524
1525   return style;
1526 }
1527
1528 /*********************
1529  * Parsing functions *
1530  *********************/
1531
1532 static guint
1533 gtk_rc_parse_statement (GScanner *scanner)
1534 {
1535   guint token;
1536   
1537   token = g_scanner_peek_next_token (scanner);
1538
1539   switch (token)
1540     {
1541     case GTK_RC_TOKEN_INCLUDE:
1542       token = g_scanner_get_next_token (scanner);
1543       if (token != GTK_RC_TOKEN_INCLUDE)
1544         return GTK_RC_TOKEN_INCLUDE;
1545
1546       token = g_scanner_get_next_token (scanner);
1547       if (token != G_TOKEN_STRING)
1548         return G_TOKEN_STRING;
1549
1550       gtk_rc_parse_file (scanner->value.v_string, FALSE);
1551       return G_TOKEN_NONE;
1552
1553     case GTK_RC_TOKEN_STYLE:
1554       return gtk_rc_parse_style (scanner);
1555
1556     case GTK_RC_TOKEN_BINDING:
1557       return gtk_binding_parse_binding (scanner);
1558
1559     case GTK_RC_TOKEN_PIXMAP_PATH:
1560       return gtk_rc_parse_pixmap_path (scanner);
1561
1562     case GTK_RC_TOKEN_WIDGET:
1563       return gtk_rc_parse_path_pattern (scanner);
1564
1565     case GTK_RC_TOKEN_WIDGET_CLASS:
1566       return gtk_rc_parse_path_pattern (scanner);
1567
1568     case GTK_RC_TOKEN_CLASS:
1569       return gtk_rc_parse_path_pattern (scanner);
1570
1571     case GTK_RC_TOKEN_MODULE_PATH:
1572       return gtk_rc_parse_module_path (scanner);
1573        
1574     case GTK_RC_TOKEN_IM_MODULE_PATH:
1575       return gtk_rc_parse_im_module_path (scanner);
1576        
1577     case GTK_RC_TOKEN_IM_MODULE_FILE:
1578       return gtk_rc_parse_im_module_file (scanner);
1579        
1580     default:
1581       g_scanner_get_next_token (scanner);
1582       return /* G_TOKEN_SYMBOL */ GTK_RC_TOKEN_STYLE;
1583     }
1584 }
1585
1586 static guint
1587 gtk_rc_parse_style (GScanner *scanner)
1588 {
1589   GtkRcStyle *rc_style;
1590   GtkRcStyle *parent_style;
1591   guint token;
1592   gint insert;
1593   gint i;
1594   GtkIconFactory *our_factory = NULL;
1595   
1596   token = g_scanner_get_next_token (scanner);
1597   if (token != GTK_RC_TOKEN_STYLE)
1598     return GTK_RC_TOKEN_STYLE;
1599   
1600   token = g_scanner_get_next_token (scanner);
1601   if (token != G_TOKEN_STRING)
1602     return G_TOKEN_STRING;
1603   
1604   insert = FALSE;
1605   rc_style = gtk_rc_style_find (scanner->value.v_string);
1606
1607   /* If there's a list, its first member is always the factory belonging
1608    * to this RcStyle
1609    */
1610   if (rc_style && rc_style->icon_factories)
1611     our_factory = rc_style->icon_factories->data;
1612   
1613   if (!rc_style)
1614     {
1615       insert = TRUE;
1616       rc_style = gtk_rc_style_new ();
1617       rc_style->name = g_strdup (scanner->value.v_string);
1618       
1619       for (i = 0; i < 5; i++)
1620         rc_style->bg_pixmap_name[i] = NULL;
1621
1622       for (i = 0; i < 5; i++)
1623         rc_style->color_flags[i] = 0;
1624     }
1625
1626   token = g_scanner_peek_next_token (scanner);
1627   if (token == G_TOKEN_EQUAL_SIGN)
1628     {
1629       token = g_scanner_get_next_token (scanner);
1630       
1631       token = g_scanner_get_next_token (scanner);
1632       if (token != G_TOKEN_STRING)
1633         {
1634           if (insert)
1635             g_free (rc_style);
1636
1637           return G_TOKEN_STRING;
1638         }
1639       
1640       parent_style = gtk_rc_style_find (scanner->value.v_string);
1641       if (parent_style)
1642         {
1643           GSList *factories;
1644           
1645           for (i = 0; i < 5; i++)
1646             {
1647               rc_style->color_flags[i] = parent_style->color_flags[i];
1648               rc_style->fg[i] = parent_style->fg[i];
1649               rc_style->bg[i] = parent_style->bg[i];
1650               rc_style->text[i] = parent_style->text[i];
1651               rc_style->base[i] = parent_style->base[i];
1652             }
1653
1654           rc_style->xthickness = parent_style->xthickness;
1655           rc_style->ythickness = parent_style->ythickness;
1656           
1657           if (parent_style->font_desc)
1658             {
1659               if (rc_style->font_desc)
1660                 pango_font_description_free (rc_style->font_desc);
1661               rc_style->font_desc = pango_font_description_copy (parent_style->font_desc);
1662             }
1663           
1664           for (i = 0; i < 5; i++)
1665             {
1666               if (rc_style->bg_pixmap_name[i])
1667                 g_free (rc_style->bg_pixmap_name[i]);
1668               rc_style->bg_pixmap_name[i] = g_strdup (parent_style->bg_pixmap_name[i]);
1669             }
1670           
1671           /* Append parent's factories, adding a ref to them */
1672           if (parent_style->icon_factories != NULL)
1673             {
1674               /* Add a factory for ourselves if we have none,
1675                * in case we end up defining more stock icons.
1676                * I see no real way around this; we need to maintain
1677                * the invariant that the first factory in the list
1678                * is always our_factory, the one belonging to us,
1679                * and if we put parent factories in the list we can't
1680                * do that if the style is reopened.
1681                */
1682               if (our_factory == NULL)
1683                 {
1684                   our_factory = gtk_icon_factory_new ();
1685                   rc_style->icon_factories = g_slist_prepend (rc_style->icon_factories,
1686                                                               our_factory);
1687                 }
1688               
1689               rc_style->icon_factories = g_slist_concat (rc_style->icon_factories,
1690                                                          g_slist_copy (parent_style->icon_factories));
1691               
1692               factories = parent_style->icon_factories;
1693               while (factories != NULL)
1694                 {
1695                   g_object_ref (G_OBJECT (factories->data));
1696                   factories = factories->next;
1697                 }
1698             }
1699         }
1700     }
1701   
1702   token = g_scanner_get_next_token (scanner);
1703   if (token != G_TOKEN_LEFT_CURLY)
1704     {
1705       if (insert)
1706         g_free (rc_style);
1707
1708       return G_TOKEN_LEFT_CURLY;
1709     }
1710   
1711   token = g_scanner_peek_next_token (scanner);
1712   while (token != G_TOKEN_RIGHT_CURLY)
1713     {
1714       switch (token)
1715         {
1716         case GTK_RC_TOKEN_BG:
1717           token = gtk_rc_parse_bg (scanner, rc_style);
1718           break;
1719         case GTK_RC_TOKEN_FG:
1720           token = gtk_rc_parse_fg (scanner, rc_style);
1721           break;
1722         case GTK_RC_TOKEN_TEXT:
1723           token = gtk_rc_parse_text (scanner, rc_style);
1724           break;
1725         case GTK_RC_TOKEN_BASE:
1726           token = gtk_rc_parse_base (scanner, rc_style);
1727           break;
1728         case GTK_RC_TOKEN_XTHICKNESS:
1729           token = gtk_rc_parse_xthickness (scanner, rc_style);
1730           break;
1731         case GTK_RC_TOKEN_YTHICKNESS:
1732           token = gtk_rc_parse_ythickness (scanner, rc_style);
1733           break;
1734         case GTK_RC_TOKEN_BG_PIXMAP:
1735           token = gtk_rc_parse_bg_pixmap (scanner, rc_style);
1736           break;
1737         case GTK_RC_TOKEN_FONT:
1738           token = gtk_rc_parse_font (scanner, rc_style);
1739           break;
1740         case GTK_RC_TOKEN_FONTSET:
1741           token = gtk_rc_parse_fontset (scanner, rc_style);
1742           break;
1743         case GTK_RC_TOKEN_FONT_NAME:
1744           token = gtk_rc_parse_font_name (scanner, rc_style);
1745           break;
1746         case GTK_RC_TOKEN_ENGINE:
1747           token = gtk_rc_parse_engine (scanner, &rc_style);
1748           break;
1749         case GTK_RC_TOKEN_STOCK:
1750           if (our_factory == NULL)
1751             {
1752               our_factory = gtk_icon_factory_new ();
1753               rc_style->icon_factories = g_slist_prepend (rc_style->icon_factories,
1754                                                           our_factory);
1755             }
1756           token = gtk_rc_parse_stock (scanner, rc_style, our_factory);
1757           break;
1758         default:
1759           g_scanner_get_next_token (scanner);
1760           token = G_TOKEN_RIGHT_CURLY;
1761           break;
1762         }
1763
1764       if (token != G_TOKEN_NONE)
1765         {
1766           if (insert)
1767             {
1768               if (rc_style->font_desc)
1769                 pango_font_description_free (rc_style->font_desc);
1770               
1771               for (i = 0; i < 5; i++)
1772                 if (rc_style->bg_pixmap_name[i])
1773                   g_free (rc_style->bg_pixmap_name[i]);
1774               g_free (rc_style);
1775             }
1776           return token;
1777         }
1778       token = g_scanner_peek_next_token (scanner);
1779     }
1780   
1781   token = g_scanner_get_next_token (scanner);
1782   if (token != G_TOKEN_RIGHT_CURLY)
1783     {
1784       if (insert)
1785         {
1786           if (rc_style->font_desc)
1787             pango_font_description_free (rc_style->font_desc);
1788           
1789           for (i = 0; i < 5; i++)
1790             if (rc_style->bg_pixmap_name[i])
1791               g_free (rc_style->bg_pixmap_name[i]);
1792           
1793           g_free (rc_style);
1794         }
1795       return G_TOKEN_RIGHT_CURLY;
1796     }
1797   
1798   if (insert)
1799     {
1800       if (!rc_style_ht)
1801         rc_style_ht = g_hash_table_new ((GHashFunc) gtk_rc_style_hash,
1802                                         (GEqualFunc) gtk_rc_style_equal);
1803       
1804       g_hash_table_insert (rc_style_ht, rc_style->name, rc_style);
1805     }
1806   
1807   return G_TOKEN_NONE;
1808 }
1809
1810 static guint
1811 gtk_rc_parse_bg (GScanner   *scanner,
1812                  GtkRcStyle *style)
1813 {
1814   GtkStateType state;
1815   guint token;
1816   
1817   token = g_scanner_get_next_token (scanner);
1818   if (token != GTK_RC_TOKEN_BG)
1819     return GTK_RC_TOKEN_BG;
1820   
1821   token = gtk_rc_parse_state (scanner, &state);
1822   if (token != G_TOKEN_NONE)
1823     return token;
1824   
1825   token = g_scanner_get_next_token (scanner);
1826   if (token != G_TOKEN_EQUAL_SIGN)
1827     return G_TOKEN_EQUAL_SIGN;
1828
1829   style->color_flags[state] |= GTK_RC_BG;
1830   return gtk_rc_parse_color (scanner, &style->bg[state]);
1831 }
1832
1833 static guint
1834 gtk_rc_parse_fg (GScanner   *scanner,
1835                  GtkRcStyle *style)
1836 {
1837   GtkStateType state;
1838   guint token;
1839   
1840   token = g_scanner_get_next_token (scanner);
1841   if (token != GTK_RC_TOKEN_FG)
1842     return GTK_RC_TOKEN_FG;
1843   
1844   token = gtk_rc_parse_state (scanner, &state);
1845   if (token != G_TOKEN_NONE)
1846     return token;
1847   
1848   token = g_scanner_get_next_token (scanner);
1849   if (token != G_TOKEN_EQUAL_SIGN)
1850     return G_TOKEN_EQUAL_SIGN;
1851   
1852   style->color_flags[state] |= GTK_RC_FG;
1853   return gtk_rc_parse_color (scanner, &style->fg[state]);
1854 }
1855
1856 static guint
1857 gtk_rc_parse_text (GScanner   *scanner,
1858                    GtkRcStyle *style)
1859 {
1860   GtkStateType state;
1861   guint token;
1862   
1863   token = g_scanner_get_next_token (scanner);
1864   if (token != GTK_RC_TOKEN_TEXT)
1865     return GTK_RC_TOKEN_TEXT;
1866   
1867   token = gtk_rc_parse_state (scanner, &state);
1868   if (token != G_TOKEN_NONE)
1869     return token;
1870   
1871   token = g_scanner_get_next_token (scanner);
1872   if (token != G_TOKEN_EQUAL_SIGN)
1873     return G_TOKEN_EQUAL_SIGN;
1874   
1875   style->color_flags[state] |= GTK_RC_TEXT;
1876   return gtk_rc_parse_color (scanner, &style->text[state]);
1877 }
1878
1879 static guint
1880 gtk_rc_parse_base (GScanner   *scanner,
1881                    GtkRcStyle *style)
1882 {
1883   GtkStateType state;
1884   guint token;
1885   
1886   token = g_scanner_get_next_token (scanner);
1887   if (token != GTK_RC_TOKEN_BASE)
1888     return GTK_RC_TOKEN_BASE;
1889   
1890   token = gtk_rc_parse_state (scanner, &state);
1891   if (token != G_TOKEN_NONE)
1892     return token;
1893   
1894   token = g_scanner_get_next_token (scanner);
1895   if (token != G_TOKEN_EQUAL_SIGN)
1896     return G_TOKEN_EQUAL_SIGN;
1897
1898   style->color_flags[state] |= GTK_RC_BASE;
1899   return gtk_rc_parse_color (scanner, &style->base[state]);
1900 }
1901
1902 static guint
1903 gtk_rc_parse_xthickness (GScanner   *scanner,
1904                          GtkRcStyle *style)
1905 {
1906   if (g_scanner_get_next_token (scanner) != GTK_RC_TOKEN_XTHICKNESS)
1907     return GTK_RC_TOKEN_XTHICKNESS;
1908
1909   if (g_scanner_get_next_token (scanner) != G_TOKEN_EQUAL_SIGN)
1910     return G_TOKEN_EQUAL_SIGN;
1911
1912   if (g_scanner_get_next_token (scanner) != G_TOKEN_INT)
1913     return G_TOKEN_INT;
1914
1915   style->xthickness = scanner->value.v_int;
1916
1917   return G_TOKEN_NONE;
1918 }
1919
1920 static guint
1921 gtk_rc_parse_ythickness (GScanner   *scanner,
1922                          GtkRcStyle *style)
1923 {
1924   if (g_scanner_get_next_token (scanner) != GTK_RC_TOKEN_YTHICKNESS)
1925     return GTK_RC_TOKEN_YTHICKNESS;
1926
1927   if (g_scanner_get_next_token (scanner) != G_TOKEN_EQUAL_SIGN)
1928     return G_TOKEN_EQUAL_SIGN;
1929
1930   if (g_scanner_get_next_token (scanner) != G_TOKEN_INT)
1931     return G_TOKEN_INT;
1932
1933   style->ythickness = scanner->value.v_int;
1934
1935   return G_TOKEN_NONE;
1936 }
1937
1938 static guint
1939 gtk_rc_parse_bg_pixmap (GScanner   *scanner,
1940                         GtkRcStyle *rc_style)
1941 {
1942   GtkStateType state;
1943   guint token;
1944   gchar *pixmap_file;
1945   
1946   token = g_scanner_get_next_token (scanner);
1947   if (token != GTK_RC_TOKEN_BG_PIXMAP)
1948     return GTK_RC_TOKEN_BG_PIXMAP;
1949   
1950   token = gtk_rc_parse_state (scanner, &state);
1951   if (token != G_TOKEN_NONE)
1952     return token;
1953   
1954   token = g_scanner_get_next_token (scanner);
1955   if (token != G_TOKEN_EQUAL_SIGN)
1956     return G_TOKEN_EQUAL_SIGN;
1957   
1958   token = g_scanner_get_next_token (scanner);
1959   if (token != G_TOKEN_STRING)
1960     return G_TOKEN_STRING;
1961   
1962   if ((strcmp (scanner->value.v_string, "<parent>") == 0) ||
1963       (strcmp (scanner->value.v_string, "<none>") == 0))
1964     pixmap_file = g_strdup (scanner->value.v_string);
1965   else
1966     pixmap_file = gtk_rc_find_pixmap_in_path (scanner, scanner->value.v_string);
1967   
1968   if (pixmap_file)
1969     {
1970       if (rc_style->bg_pixmap_name[state])
1971         g_free (rc_style->bg_pixmap_name[state]);
1972       rc_style->bg_pixmap_name[state] = pixmap_file;
1973     }
1974   
1975   return G_TOKEN_NONE;
1976 }
1977
1978 static gchar*
1979 gtk_rc_check_pixmap_dir (const gchar *dir, const gchar *pixmap_file)
1980 {
1981   gchar *buf;
1982   gint fd;
1983
1984   buf = g_strdup_printf ("%s" G_DIR_SEPARATOR_S "%s", dir, pixmap_file);
1985   
1986   fd = open (buf, O_RDONLY);
1987   if (fd >= 0)
1988     {
1989       close (fd);
1990       return buf;
1991     }
1992    
1993   g_free (buf);
1994  
1995    return NULL;
1996  }
1997  
1998 gchar*
1999 gtk_rc_find_pixmap_in_path (GScanner *scanner,
2000                             const gchar *pixmap_file)
2001 {
2002   gint i;
2003   gchar *filename;
2004   GSList *tmp_list;
2005     
2006   for (i = 0; (i < GTK_RC_MAX_PIXMAP_PATHS) && (pixmap_path[i] != NULL); i++)
2007     {
2008       filename = gtk_rc_check_pixmap_dir (pixmap_path[i], pixmap_file);
2009       if (filename)
2010         return filename;
2011     }
2012  
2013   tmp_list = rc_dir_stack;
2014   while (tmp_list)
2015     {
2016       filename = gtk_rc_check_pixmap_dir (tmp_list->data, pixmap_file);
2017       if (filename)
2018         return filename;
2019        
2020       tmp_list = tmp_list->next;
2021     }
2022   
2023   if (scanner)
2024     g_warning (_("Unable to locate image file in pixmap_path: \"%s\" line %d"),
2025                pixmap_file, scanner->line);
2026   else
2027     g_warning (_("Unable to locate image file in pixmap_path: \"%s\""),
2028                pixmap_file);
2029     
2030   return NULL;
2031 }
2032
2033 gchar*
2034 gtk_rc_find_module_in_path (const gchar *module_file)
2035 {
2036   gint i;
2037   gint fd;
2038   gchar *buf;
2039   
2040   for (i = 0; (i < GTK_RC_MAX_MODULE_PATHS) && (module_path[i] != NULL); i++)
2041     {
2042       buf = g_strdup_printf ("%s" G_DIR_SEPARATOR_S "%s",
2043                              module_path[i], module_file);
2044       
2045       fd = open (buf, O_RDONLY);
2046       if (fd >= 0)
2047         {
2048           close (fd);
2049           return buf;
2050         }
2051       
2052       g_free (buf);
2053     }
2054     
2055   return NULL;
2056 }
2057
2058 static guint
2059 gtk_rc_parse_font (GScanner   *scanner,
2060                    GtkRcStyle *rc_style)
2061 {
2062   guint token;
2063   
2064   token = g_scanner_get_next_token (scanner);
2065   if (token != GTK_RC_TOKEN_FONT)
2066     return GTK_RC_TOKEN_FONT;
2067   
2068   token = g_scanner_get_next_token (scanner);
2069   if (token != G_TOKEN_EQUAL_SIGN)
2070     return G_TOKEN_EQUAL_SIGN;
2071   
2072   token = g_scanner_get_next_token (scanner);
2073   if (token != G_TOKEN_STRING)
2074     return G_TOKEN_STRING;
2075
2076   /* Ignore, do nothing */
2077   
2078   return G_TOKEN_NONE;
2079 }
2080
2081 static guint
2082 gtk_rc_parse_fontset (GScanner   *scanner,
2083                       GtkRcStyle *rc_style)
2084 {
2085   guint token;
2086   
2087   token = g_scanner_get_next_token (scanner);
2088   if (token != GTK_RC_TOKEN_FONTSET)
2089     return GTK_RC_TOKEN_FONTSET;
2090   
2091   token = g_scanner_get_next_token (scanner);
2092   if (token != G_TOKEN_EQUAL_SIGN)
2093     return G_TOKEN_EQUAL_SIGN;
2094   
2095   token = g_scanner_get_next_token (scanner);
2096   if (token != G_TOKEN_STRING)
2097     return G_TOKEN_STRING;
2098
2099   /* Do nothing - silently ignore */
2100   
2101   return G_TOKEN_NONE;
2102 }
2103
2104 static guint
2105 gtk_rc_parse_font_name (GScanner   *scanner,
2106                         GtkRcStyle *rc_style)
2107 {
2108   guint token;
2109   
2110   token = g_scanner_get_next_token (scanner);
2111   if (token != GTK_RC_TOKEN_FONT_NAME)
2112     return GTK_RC_TOKEN_FONT;
2113   
2114   token = g_scanner_get_next_token (scanner);
2115   if (token != G_TOKEN_EQUAL_SIGN)
2116     return G_TOKEN_EQUAL_SIGN;
2117   
2118   token = g_scanner_get_next_token (scanner);
2119   if (token != G_TOKEN_STRING)
2120     return G_TOKEN_STRING;
2121
2122   rc_style->font_desc = pango_font_description_from_string (scanner->value.v_string);
2123   
2124   return G_TOKEN_NONE;
2125 }
2126
2127 static guint       
2128 gtk_rc_parse_engine (GScanner    *scanner,
2129                      GtkRcStyle **rc_style)
2130 {
2131   guint token;
2132   GtkThemeEngine *engine;
2133   guint result = G_TOKEN_NONE;
2134   GtkRcStyle *new_style = NULL;
2135   gboolean parsed_curlies = FALSE;
2136   
2137   token = g_scanner_get_next_token (scanner);
2138   if (token != GTK_RC_TOKEN_ENGINE)
2139     return GTK_RC_TOKEN_ENGINE;
2140
2141   token = g_scanner_get_next_token (scanner);
2142   if (token != G_TOKEN_STRING)
2143     return G_TOKEN_STRING;
2144
2145   engine = gtk_theme_engine_get (scanner->value.v_string);
2146   
2147   token = g_scanner_get_next_token (scanner);
2148   if (token != G_TOKEN_LEFT_CURLY)
2149     return G_TOKEN_LEFT_CURLY;
2150
2151   if (engine)
2152     {
2153       GtkRcStyleClass *new_class;
2154       
2155       new_style = gtk_theme_engine_create_rc_style (engine);
2156       g_type_module_unuse (G_TYPE_MODULE (engine));
2157
2158       new_class = GTK_RC_STYLE_GET_CLASS (new_style);
2159
2160       new_class->merge (new_style, *rc_style);
2161       if ((*rc_style)->name)
2162         new_style->name = g_strdup ((*rc_style)->name);
2163       
2164       if (new_class->parse)
2165         {
2166           parsed_curlies = TRUE;
2167           result = new_class->parse (new_style, scanner);
2168
2169           if (result != G_TOKEN_NONE)
2170             {
2171               g_object_unref (G_OBJECT (new_style));
2172               new_style = NULL;
2173             }
2174         }
2175     }
2176
2177   if (!parsed_curlies)
2178     {
2179       /* Skip over remainder, looking for nested {}'s
2180        */
2181       guint count = 1;
2182       
2183       result = G_TOKEN_RIGHT_CURLY;
2184       while ((token = g_scanner_get_next_token (scanner)) != G_TOKEN_EOF)
2185         {
2186           if (token == G_TOKEN_LEFT_CURLY)
2187             count++;
2188           else if (token == G_TOKEN_RIGHT_CURLY)
2189             count--;
2190           
2191           if (count == 0)
2192             {
2193               result = G_TOKEN_NONE;
2194               break;
2195             }
2196         }
2197     }
2198
2199   if (new_style)
2200     {
2201       g_object_unref (G_OBJECT (*rc_style));
2202       *rc_style = new_style;
2203     }
2204
2205   return result;
2206 }
2207
2208 guint
2209 gtk_rc_parse_state (GScanner     *scanner,
2210                     GtkStateType *state)
2211 {
2212   guint old_scope;
2213   guint token;
2214
2215   g_return_val_if_fail (scanner != NULL, G_TOKEN_ERROR);
2216   g_return_val_if_fail (state != NULL, G_TOKEN_ERROR);
2217   
2218   /* we don't know where we got called from, so we reset the scope here.
2219    * if we bail out due to errors, we *don't* reset the scope, so the
2220    * error messaging code can make sense of our tokens.
2221    */
2222   old_scope = g_scanner_set_scope (scanner, 0);
2223   
2224   token = g_scanner_get_next_token (scanner);
2225   if (token != G_TOKEN_LEFT_BRACE)
2226     return G_TOKEN_LEFT_BRACE;
2227   
2228   token = g_scanner_get_next_token (scanner);
2229   switch (token)
2230     {
2231     case GTK_RC_TOKEN_ACTIVE:
2232       *state = GTK_STATE_ACTIVE;
2233       break;
2234     case GTK_RC_TOKEN_INSENSITIVE:
2235       *state = GTK_STATE_INSENSITIVE;
2236       break;
2237     case GTK_RC_TOKEN_NORMAL:
2238       *state = GTK_STATE_NORMAL;
2239       break;
2240     case GTK_RC_TOKEN_PRELIGHT:
2241       *state = GTK_STATE_PRELIGHT;
2242       break;
2243     case GTK_RC_TOKEN_SELECTED:
2244       *state = GTK_STATE_SELECTED;
2245       break;
2246     default:
2247       return /* G_TOKEN_SYMBOL */ GTK_RC_TOKEN_NORMAL;
2248     }
2249   
2250   token = g_scanner_get_next_token (scanner);
2251   if (token != G_TOKEN_RIGHT_BRACE)
2252     return G_TOKEN_RIGHT_BRACE;
2253   
2254   g_scanner_set_scope (scanner, old_scope);
2255
2256   return G_TOKEN_NONE;
2257 }
2258
2259 guint
2260 gtk_rc_parse_priority (GScanner            *scanner,
2261                        GtkPathPriorityType *priority)
2262 {
2263   guint old_scope;
2264   guint token;
2265
2266   g_return_val_if_fail (scanner != NULL, G_TOKEN_ERROR);
2267   g_return_val_if_fail (priority != NULL, G_TOKEN_ERROR);
2268
2269   /* we don't know where we got called from, so we reset the scope here.
2270    * if we bail out due to errors, we *don't* reset the scope, so the
2271    * error messaging code can make sense of our tokens.
2272    */
2273   old_scope = g_scanner_set_scope (scanner, 0);
2274   
2275   token = g_scanner_get_next_token (scanner);
2276   if (token != ':')
2277     return ':';
2278   
2279   token = g_scanner_get_next_token (scanner);
2280   switch (token)
2281     {
2282     case GTK_RC_TOKEN_LOWEST:
2283       *priority = GTK_PATH_PRIO_LOWEST;
2284       break;
2285     case GTK_RC_TOKEN_GTK:
2286       *priority = GTK_PATH_PRIO_GTK;
2287       break;
2288     case GTK_RC_TOKEN_APPLICATION:
2289       *priority = GTK_PATH_PRIO_APPLICATION;
2290       break;
2291     case GTK_RC_TOKEN_RC:
2292       *priority = GTK_PATH_PRIO_RC;
2293       break;
2294     case GTK_RC_TOKEN_HIGHEST:
2295       *priority = GTK_PATH_PRIO_HIGHEST;
2296       break;
2297     default:
2298       return /* G_TOKEN_SYMBOL */ GTK_RC_TOKEN_APPLICATION;
2299     }
2300   
2301   g_scanner_set_scope (scanner, old_scope);
2302
2303   return G_TOKEN_NONE;
2304 }
2305
2306 guint
2307 gtk_rc_parse_color (GScanner *scanner,
2308                     GdkColor *color)
2309 {
2310   guint token;
2311
2312   g_return_val_if_fail (scanner != NULL, G_TOKEN_ERROR);
2313
2314   /* we don't need to set our own scop here, because
2315    * we don't need own symbols
2316    */
2317   
2318   token = g_scanner_get_next_token (scanner);
2319   switch (token)
2320     {
2321       gint token_int;
2322       gint length;
2323       gint temp;
2324       gchar buf[9];
2325       gint i, j;
2326       
2327     case G_TOKEN_LEFT_CURLY:
2328       token = g_scanner_get_next_token (scanner);
2329       if (token == G_TOKEN_INT)
2330         token_int = scanner->value.v_int;
2331       else if (token == G_TOKEN_FLOAT)
2332         token_int = scanner->value.v_float * 65535.0;
2333       else
2334         return G_TOKEN_FLOAT;
2335       color->red = CLAMP (token_int, 0, 65535);
2336       
2337       token = g_scanner_get_next_token (scanner);
2338       if (token != G_TOKEN_COMMA)
2339         return G_TOKEN_COMMA;
2340       
2341       token = g_scanner_get_next_token (scanner);
2342       if (token == G_TOKEN_INT)
2343         token_int = scanner->value.v_int;
2344       else if (token == G_TOKEN_FLOAT)
2345         token_int = scanner->value.v_float * 65535.0;
2346       else
2347         return G_TOKEN_FLOAT;
2348       color->green = CLAMP (token_int, 0, 65535);
2349       
2350       token = g_scanner_get_next_token (scanner);
2351       if (token != G_TOKEN_COMMA)
2352         return G_TOKEN_COMMA;
2353       
2354       token = g_scanner_get_next_token (scanner);
2355       if (token == G_TOKEN_INT)
2356         token_int = scanner->value.v_int;
2357       else if (token == G_TOKEN_FLOAT)
2358         token_int = scanner->value.v_float * 65535.0;
2359       else
2360         return G_TOKEN_FLOAT;
2361       color->blue = CLAMP (token_int, 0, 65535);
2362       
2363       token = g_scanner_get_next_token (scanner);
2364       if (token != G_TOKEN_RIGHT_CURLY)
2365         return G_TOKEN_RIGHT_CURLY;
2366       return G_TOKEN_NONE;
2367       
2368     case G_TOKEN_STRING:
2369       if (scanner->value.v_string[0] != '#')
2370         return G_TOKEN_STRING;
2371       
2372       length = strlen (scanner->value.v_string) - 1;
2373       if (((length % 3) != 0) || (length > 12))
2374         return G_TOKEN_STRING;
2375       length /= 3;
2376       
2377       for (i = 0, j = 1; i < length; i++, j++)
2378         buf[i] = scanner->value.v_string[j];
2379       buf[i] = '\0';
2380       
2381       sscanf (buf, "%x", &temp);
2382       color->red = temp;
2383       
2384       for (i = 0; i < length; i++, j++)
2385         buf[i] = scanner->value.v_string[j];
2386       buf[i] = '\0';
2387       
2388       sscanf (buf, "%x", &temp);
2389       color->green = temp;
2390       
2391       for (i = 0; i < length; i++, j++)
2392         buf[i] = scanner->value.v_string[j];
2393       buf[i] = '\0';
2394       
2395       sscanf (buf, "%x", &temp);
2396       color->blue = temp;
2397       
2398       if (length == 1)
2399         {
2400           color->red *= 4369;
2401           color->green *= 4369;
2402           color->blue *= 4369;
2403         }
2404       else if (length == 2)
2405         {
2406           color->red *= 257;
2407           color->green *= 257;
2408           color->blue *= 257;
2409         }
2410       else if (length == 3)
2411         {
2412           color->red *= 16;
2413           color->green *= 16;
2414           color->blue *= 16;
2415         }
2416       return G_TOKEN_NONE;
2417       
2418     default:
2419       return G_TOKEN_STRING;
2420     }
2421 }
2422
2423 static guint
2424 gtk_rc_parse_pixmap_path (GScanner *scanner)
2425 {
2426   guint token;
2427   
2428   token = g_scanner_get_next_token (scanner);
2429   if (token != GTK_RC_TOKEN_PIXMAP_PATH)
2430     return GTK_RC_TOKEN_PIXMAP_PATH;
2431   
2432   token = g_scanner_get_next_token (scanner);
2433   if (token != G_TOKEN_STRING)
2434     return G_TOKEN_STRING;
2435   
2436   gtk_rc_parse_pixmap_path_string (scanner->value.v_string);
2437   
2438   return G_TOKEN_NONE;
2439 }
2440
2441 static void
2442 gtk_rc_parse_pixmap_path_string (gchar *pix_path)
2443 {
2444   gchar *buf;
2445   gint end_offset;
2446   gint start_offset = 0;
2447   gint path_len;
2448   gint path_num;
2449   
2450   /* free the old one, or just add to the old one ? */
2451   for (path_num=0; pixmap_path[path_num]; path_num++)
2452     {
2453       g_free (pixmap_path[path_num]);
2454       pixmap_path[path_num] = NULL;
2455     }
2456   
2457   path_num = 0;
2458   
2459   path_len = strlen (pix_path);
2460   
2461   buf = g_strdup (pix_path);
2462   
2463   for (end_offset = 0; end_offset <= path_len; end_offset++)
2464     {
2465       if ((buf[end_offset] == G_SEARCHPATH_SEPARATOR) ||
2466           (end_offset == path_len))
2467         {
2468           buf[end_offset] = '\0';
2469           pixmap_path[path_num] = g_strdup (buf + start_offset);
2470           path_num++;
2471           pixmap_path[path_num] = NULL;
2472           start_offset = end_offset + 1;
2473         }
2474     }
2475   g_free (buf);
2476 }
2477
2478 static guint
2479 gtk_rc_parse_module_path (GScanner *scanner)
2480 {
2481   guint token;
2482   
2483   token = g_scanner_get_next_token (scanner);
2484   if (token != GTK_RC_TOKEN_MODULE_PATH)
2485     return GTK_RC_TOKEN_MODULE_PATH;
2486   
2487   token = g_scanner_get_next_token (scanner);
2488   if (token != G_TOKEN_STRING)
2489     return G_TOKEN_STRING;
2490   
2491   gtk_rc_parse_module_path_string (scanner->value.v_string);
2492   
2493   return G_TOKEN_NONE;
2494 }
2495
2496 static guint
2497 gtk_rc_parse_im_module_path (GScanner *scanner)
2498 {
2499   guint token;
2500   
2501   token = g_scanner_get_next_token (scanner);
2502   if (token != GTK_RC_TOKEN_IM_MODULE_FILE)
2503     return GTK_RC_TOKEN_IM_MODULE_FILE;
2504   
2505   token = g_scanner_get_next_token (scanner);
2506   if (token != G_TOKEN_STRING)
2507     return G_TOKEN_STRING;
2508
2509   if (im_module_path)
2510     g_free (im_module_path);
2511     
2512   im_module_path = g_strdup (scanner->value.v_string);
2513
2514   return G_TOKEN_NONE;
2515 }
2516
2517 static guint
2518 gtk_rc_parse_im_module_file (GScanner *scanner)
2519 {
2520   guint token;
2521   
2522   token = g_scanner_get_next_token (scanner);
2523   if (token != GTK_RC_TOKEN_IM_MODULE_FILE)
2524     return GTK_RC_TOKEN_IM_MODULE_FILE;
2525   
2526   token = g_scanner_get_next_token (scanner);
2527   if (token != G_TOKEN_STRING)
2528     return G_TOKEN_STRING;
2529
2530   if (im_module_file)
2531     g_free (im_module_file);
2532     
2533   im_module_file = g_strdup (scanner->value.v_string);
2534
2535   return G_TOKEN_NONE;
2536 }
2537
2538 static void
2539 gtk_rc_parse_module_path_string (gchar *mod_path)
2540 {
2541   gchar *buf;
2542   gint end_offset;
2543   gint start_offset = 0;
2544   gint path_len;
2545   gint path_num;
2546   
2547   /* free the old one, or just add to the old one ? */
2548   for (path_num=0; module_path[path_num]; path_num++)
2549     {
2550       g_free (module_path[path_num]);
2551       module_path[path_num] = NULL;
2552     }
2553   
2554   path_num = 0;
2555   
2556   path_len = strlen (mod_path);
2557   
2558   buf = g_strdup (mod_path);
2559   
2560   for (end_offset = 0; end_offset <= path_len; end_offset++)
2561     {
2562       if ((buf[end_offset] == G_SEARCHPATH_SEPARATOR) ||
2563           (end_offset == path_len))
2564         {
2565           buf[end_offset] = '\0';
2566           module_path[path_num] = g_strdup (buf + start_offset);
2567           path_num++;
2568           module_path[path_num] = NULL;
2569           start_offset = end_offset + 1;
2570         }
2571     }
2572   g_free (buf);
2573   gtk_rc_append_default_module_path();
2574 }
2575
2576 static guint
2577 gtk_rc_parse_path_pattern (GScanner   *scanner)
2578 {
2579   guint token;
2580   GtkPathType path_type;
2581   gchar *pattern;
2582   gboolean is_binding;
2583   GtkPathPriorityType priority = GTK_PATH_PRIO_RC;
2584   
2585   token = g_scanner_get_next_token (scanner);
2586   switch (token)
2587     {
2588     case GTK_RC_TOKEN_WIDGET:
2589       path_type = GTK_PATH_WIDGET;
2590       break;
2591     case GTK_RC_TOKEN_WIDGET_CLASS:
2592       path_type = GTK_PATH_WIDGET_CLASS;
2593       break;
2594     case GTK_RC_TOKEN_CLASS:
2595       path_type = GTK_PATH_CLASS;
2596       break;
2597     default:
2598       return GTK_RC_TOKEN_WIDGET_CLASS;
2599     }
2600   
2601   token = g_scanner_get_next_token (scanner);
2602   if (token != G_TOKEN_STRING)
2603     return G_TOKEN_STRING;
2604
2605   pattern = g_strdup (scanner->value.v_string);
2606
2607   token = g_scanner_get_next_token (scanner);
2608   if (token == GTK_RC_TOKEN_STYLE)
2609     is_binding = FALSE;
2610   else if (token == GTK_RC_TOKEN_BINDING)
2611     {
2612       is_binding = TRUE;
2613       if (g_scanner_peek_next_token (scanner) == ':')
2614         {
2615           token = gtk_rc_parse_priority (scanner, &priority);
2616           if (token != G_TOKEN_NONE)
2617             {
2618               g_free (pattern);
2619               return token;
2620             }
2621         }
2622     }
2623   else
2624     {
2625       g_free (pattern);
2626       return GTK_RC_TOKEN_STYLE;
2627     }
2628   
2629   token = g_scanner_get_next_token (scanner);
2630   if (token != G_TOKEN_STRING)
2631     {
2632       g_free (pattern);
2633       return G_TOKEN_STRING;
2634     }
2635
2636   if (is_binding)
2637     {
2638       GtkBindingSet *binding;
2639
2640       binding = gtk_binding_set_find (scanner->value.v_string);
2641       if (!binding)
2642         {
2643           g_free (pattern);
2644           return G_TOKEN_STRING;
2645         }
2646       gtk_binding_set_add_path (binding, path_type, pattern, priority);
2647     }
2648   else
2649     {
2650       GtkRcStyle *rc_style;
2651       GtkRcSet *rc_set;
2652
2653       rc_style = gtk_rc_style_find (scanner->value.v_string);
2654       
2655       if (!rc_style)
2656         {
2657           g_free (pattern);
2658           return G_TOKEN_STRING;
2659         }
2660
2661       rc_set = g_new (GtkRcSet, 1);
2662       gtk_pattern_spec_init (&rc_set->pspec, pattern);
2663       rc_set->rc_style = rc_style;
2664
2665       if (path_type == GTK_PATH_WIDGET)
2666         gtk_rc_sets_widget = g_slist_prepend (gtk_rc_sets_widget, rc_set);
2667       else if (path_type == GTK_PATH_WIDGET_CLASS)
2668         gtk_rc_sets_widget_class = g_slist_prepend (gtk_rc_sets_widget_class, rc_set);
2669       else
2670         gtk_rc_sets_class = g_slist_prepend (gtk_rc_sets_class, rc_set);
2671     }
2672
2673   g_free (pattern);
2674   return G_TOKEN_NONE;
2675 }
2676
2677 static guint
2678 gtk_rc_parse_stock_id (GScanner  *scanner,
2679                        gchar    **stock_id)
2680 {
2681   guint token;
2682   
2683   token = g_scanner_get_next_token (scanner);
2684   if (token != G_TOKEN_LEFT_BRACE)
2685     return G_TOKEN_LEFT_BRACE;
2686
2687   token = g_scanner_get_next_token (scanner);
2688   
2689   if (token != G_TOKEN_STRING)
2690     return G_TOKEN_STRING;
2691   
2692   *stock_id = g_strdup (scanner->value.v_string);
2693   
2694   token = g_scanner_get_next_token (scanner);
2695   if (token != G_TOKEN_RIGHT_BRACE)
2696     {
2697       g_free (*stock_id);
2698       return G_TOKEN_RIGHT_BRACE;
2699     }
2700   
2701   return G_TOKEN_NONE;
2702 }
2703
2704 static void
2705 cleanup_source (GtkIconSource *source)
2706 {
2707   g_free (source->filename);
2708   g_free (source->size);
2709 }
2710
2711 static guint
2712 gtk_rc_parse_icon_source (GScanner       *scanner,
2713                           GtkIconSet     *icon_set)
2714 {
2715   guint token;
2716   GtkIconSource source = { NULL, NULL,
2717                            0, 0, 0,
2718                            TRUE, TRUE, TRUE };
2719   
2720   token = g_scanner_get_next_token (scanner);
2721   if (token != G_TOKEN_LEFT_CURLY)
2722     return G_TOKEN_LEFT_CURLY;
2723
2724   token = g_scanner_get_next_token (scanner);
2725   
2726   if (token != G_TOKEN_STRING)
2727     return G_TOKEN_STRING;
2728   
2729   source.filename = g_strdup (scanner->value.v_string);
2730   
2731   token = g_scanner_get_next_token (scanner);
2732
2733   if (token == G_TOKEN_RIGHT_CURLY)
2734     {
2735       gtk_icon_set_add_source (icon_set, &source);
2736       cleanup_source (&source);
2737       return G_TOKEN_NONE;
2738     }  
2739   else if (token != G_TOKEN_COMMA)
2740     {
2741       cleanup_source (&source);
2742       return G_TOKEN_COMMA;
2743     }
2744
2745   /* Get the direction */
2746   
2747   token = g_scanner_get_next_token (scanner);
2748
2749   switch (token)
2750     {
2751     case GTK_RC_TOKEN_RTL:
2752       source.any_direction = FALSE;
2753       source.direction = GTK_TEXT_DIR_RTL;
2754       break;
2755
2756     case GTK_RC_TOKEN_LTR:
2757       source.any_direction = FALSE;
2758       source.direction = GTK_TEXT_DIR_LTR;
2759       break;
2760       
2761     case '*':
2762       break;
2763       
2764     default:
2765       cleanup_source (&source);
2766       return GTK_RC_TOKEN_RTL;
2767       break;
2768     }
2769
2770   token = g_scanner_get_next_token (scanner);
2771
2772   if (token == G_TOKEN_RIGHT_CURLY)
2773     {
2774       gtk_icon_set_add_source (icon_set, &source);
2775       cleanup_source (&source);
2776       return G_TOKEN_NONE;
2777     }  
2778   else if (token != G_TOKEN_COMMA)
2779     {
2780       cleanup_source (&source);
2781       return G_TOKEN_COMMA;
2782     }
2783
2784   /* Get the state */
2785   
2786   token = g_scanner_get_next_token (scanner);
2787   
2788   switch (token)
2789     {
2790     case GTK_RC_TOKEN_NORMAL:
2791       source.any_state = FALSE;
2792       source.state = GTK_STATE_NORMAL;
2793       break;
2794
2795     case GTK_RC_TOKEN_PRELIGHT:
2796       source.any_state = FALSE;
2797       source.state = GTK_STATE_PRELIGHT;
2798       break;
2799       
2800
2801     case GTK_RC_TOKEN_INSENSITIVE:
2802       source.any_state = FALSE;
2803       source.state = GTK_STATE_INSENSITIVE;
2804       break;
2805
2806     case GTK_RC_TOKEN_ACTIVE:
2807       source.any_state = FALSE;
2808       source.state = GTK_STATE_ACTIVE;
2809       break;
2810
2811     case GTK_RC_TOKEN_SELECTED:
2812       source.any_state = FALSE;
2813       source.state = GTK_STATE_SELECTED;
2814       break;
2815
2816     case '*':
2817       break;
2818       
2819     default:
2820       cleanup_source (&source);
2821       return GTK_RC_TOKEN_PRELIGHT;
2822       break;
2823     }  
2824
2825   token = g_scanner_get_next_token (scanner);
2826
2827   if (token == G_TOKEN_RIGHT_CURLY)
2828     {
2829       gtk_icon_set_add_source (icon_set, &source);
2830       cleanup_source (&source);
2831       return G_TOKEN_NONE;
2832     }
2833   else if (token != G_TOKEN_COMMA)
2834     {
2835       cleanup_source (&source);
2836       return G_TOKEN_COMMA;
2837     }
2838   
2839   /* Get the size */
2840   
2841   token = g_scanner_get_next_token (scanner);
2842
2843   if (token != '*')
2844     {
2845       if (token != G_TOKEN_STRING)
2846         {
2847           cleanup_source (&source);
2848           return G_TOKEN_STRING;
2849         }
2850       
2851       source.size = g_strdup (scanner->value.v_string);
2852       source.any_size = FALSE;
2853     }
2854
2855   /* Check the close brace */
2856   
2857   token = g_scanner_get_next_token (scanner);
2858   if (token != G_TOKEN_RIGHT_CURLY)
2859     {
2860       cleanup_source (&source);
2861       return G_TOKEN_RIGHT_CURLY;
2862     }
2863
2864   gtk_icon_set_add_source (icon_set, &source);
2865
2866   cleanup_source (&source);
2867   
2868   return G_TOKEN_NONE;
2869 }
2870
2871 static guint
2872 gtk_rc_parse_stock (GScanner       *scanner,
2873                     GtkRcStyle     *rc_style,
2874                     GtkIconFactory *factory)
2875 {
2876   GtkIconSet *icon_set = NULL;
2877   gchar *stock_id = NULL;
2878   guint token;
2879   
2880   token = g_scanner_get_next_token (scanner);
2881   if (token != GTK_RC_TOKEN_STOCK)
2882     return GTK_RC_TOKEN_STOCK;
2883   
2884   token = gtk_rc_parse_stock_id (scanner, &stock_id);
2885   if (token != G_TOKEN_NONE)
2886     return token;
2887   
2888   token = g_scanner_get_next_token (scanner);
2889   if (token != G_TOKEN_EQUAL_SIGN)
2890     {
2891       g_free (stock_id);
2892       return G_TOKEN_EQUAL_SIGN;
2893     }
2894
2895   token = g_scanner_get_next_token (scanner);
2896   if (token != G_TOKEN_LEFT_CURLY)
2897     {
2898       g_free (stock_id);
2899       return G_TOKEN_LEFT_CURLY;
2900     }
2901
2902   token = g_scanner_peek_next_token (scanner);
2903   while (token != G_TOKEN_RIGHT_CURLY)
2904     {
2905       if (icon_set == NULL)
2906         icon_set = gtk_icon_set_new ();
2907       
2908       token = gtk_rc_parse_icon_source (scanner, icon_set);
2909       if (token != G_TOKEN_NONE)
2910         {
2911           g_free (stock_id);
2912           gtk_icon_set_unref (icon_set);
2913           return token;
2914         }
2915
2916       token = g_scanner_get_next_token (scanner);
2917       
2918       if (token != G_TOKEN_COMMA &&
2919           token != G_TOKEN_RIGHT_CURLY)
2920         {
2921           g_free (stock_id);
2922           gtk_icon_set_unref (icon_set);
2923           return G_TOKEN_RIGHT_CURLY;
2924         }
2925     }
2926
2927   if (icon_set)
2928     {
2929       gtk_icon_factory_add (factory,
2930                             stock_id,
2931                             icon_set);
2932       
2933       gtk_icon_set_unref (icon_set);
2934     }
2935   
2936   g_free (stock_id);
2937
2938   return G_TOKEN_NONE;
2939 }
2940
2941 /*
2942 typedef  GdkPixmap * (*GtkImageLoader) (GdkWindow   *window,
2943                                         GdkColormap *colormap,
2944                                         GdkBitmap  **mask,
2945                                         GdkColor    *transparent_color,
2946                                         const gchar *filename);
2947 */
2948
2949 void
2950 gtk_rc_set_image_loader(GtkImageLoader loader)
2951 {
2952   image_loader = loader;
2953 }
2954
2955 GdkPixmap *
2956 gtk_rc_load_image (GdkColormap *colormap,
2957                    GdkColor    *transparent_color,
2958                    const gchar *filename)
2959 {
2960   if (strcmp (filename, "<parent>") == 0)
2961     return (GdkPixmap*) GDK_PARENT_RELATIVE;
2962   else
2963     {
2964       if(image_loader)
2965         return image_loader(NULL, colormap, NULL,
2966                             transparent_color,
2967                             filename);
2968       else
2969         return gdk_pixmap_colormap_create_from_xpm (NULL, colormap, NULL,
2970                                                     transparent_color,
2971                                                     filename);
2972     }
2973 }