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