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