]> Pileus Git - ~andy/gtk/blob - gtk/gtkrc.c
Adapt cast macros to standard.
[~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 Library General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
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  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */
19
20 /*
21  * Modified by the GTK+ Team and others 1997-1999.  See the AUTHORS
22  * file for a list of people on the GTK+ Team.  See the ChangeLog
23  * files for a list of changes.  These files are distributed with
24  * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
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 #ifdef G_OS_WIN32
52 #include <io.h>
53 #endif
54
55 #include "gtkrc.h"
56 #include "gtkbindings.h"
57 #include "gtkthemes.h"
58 #include "gtkintl.h"
59
60 typedef struct _GtkRcSet    GtkRcSet;
61 typedef struct _GtkRcNode   GtkRcNode;
62 typedef struct _GtkRcFile   GtkRcFile;
63 typedef struct _GtkRcStylePrivate  GtkRcStylePrivate;
64
65 struct _GtkRcSet
66 {
67   GtkPatternSpec pspec;
68   GtkRcStyle    *rc_style;
69 };
70
71 struct _GtkRcFile
72 {
73   time_t mtime;
74   gchar *name;
75   gchar *canonical_name;
76   gboolean reload;
77 };
78
79 struct _GtkRcStylePrivate
80 {
81   GtkRcStyle style;
82
83   guint ref_count;
84   /* list of RC style lists including this RC style */
85   GSList *rc_style_lists;
86 };
87
88 static guint       gtk_rc_style_hash               (const char   *name);
89 static gint        gtk_rc_style_compare            (const char   *a,
90                                                     const char   *b);
91 static guint       gtk_rc_styles_hash              (const GSList *rc_styles);
92 static gint        gtk_rc_styles_compare           (const GSList *a,
93                                                     const GSList *b);
94 static GtkRcStyle* gtk_rc_style_find               (const char   *name);
95 static GSList *    gtk_rc_styles_match             (GSList       *rc_styles,
96                                                     GSList       *sets,
97                                                     guint         path_length,
98                                                     gchar        *path,
99                                                     gchar        *path_reversed);
100 static GtkStyle *  gtk_rc_style_to_style           (GtkRcStyle   *rc_style);
101 static GtkStyle*   gtk_rc_style_init               (GSList       *rc_styles);
102 static void        gtk_rc_parse_file               (const gchar  *filename,
103                                                     gboolean      reload);
104
105 static void        gtk_rc_parse_any                (const gchar  *input_name,
106                                                     gint          input_fd,
107                                                     const gchar  *input_string);
108 static guint       gtk_rc_parse_statement          (GScanner     *scanner);
109 static guint       gtk_rc_parse_style              (GScanner     *scanner);
110 static guint       gtk_rc_parse_base               (GScanner     *scanner,
111                                                     GtkRcStyle   *style);
112 static guint       gtk_rc_parse_bg                 (GScanner     *scanner,
113                                                     GtkRcStyle   *style);
114 static guint       gtk_rc_parse_fg                 (GScanner     *scanner,
115                                                     GtkRcStyle   *style);
116 static guint       gtk_rc_parse_text               (GScanner     *scanner,
117                                                     GtkRcStyle   *style);
118 static guint       gtk_rc_parse_bg_pixmap          (GScanner     *scanner,
119                                                     GtkRcStyle   *rc_style);
120 static guint       gtk_rc_parse_font               (GScanner     *scanner,
121                                                     GtkRcStyle   *rc_style);
122 static guint       gtk_rc_parse_fontset            (GScanner     *scanner,
123                                                     GtkRcStyle   *rc_style);
124 static guint       gtk_rc_parse_engine             (GScanner     *scanner,
125                                                     GtkRcStyle   *rc_style);
126 static guint       gtk_rc_parse_pixmap_path        (GScanner     *scanner);
127 static void        gtk_rc_parse_pixmap_path_string (gchar *pix_path);
128 static guint       gtk_rc_parse_module_path        (GScanner     *scanner);
129 static void        gtk_rc_parse_module_path_string (gchar *mod_path);
130 static guint       gtk_rc_parse_path_pattern       (GScanner     *scanner);
131 static void        gtk_rc_clear_hash_node          (gpointer   key, 
132                                                     gpointer   data, 
133                                                     gpointer   user_data);
134 static void        gtk_rc_clear_styles               (void);
135 static void        gtk_rc_append_default_pixmap_path (void);
136 static void        gtk_rc_append_default_module_path (void);
137 static void        gtk_rc_add_initial_default_files  (void);
138
139
140 static const GScannerConfig     gtk_rc_scanner_config =
141 {
142   (
143    " \t\r\n"
144    )                    /* cset_skip_characters */,
145   (
146    G_CSET_a_2_z
147    "_"
148    G_CSET_A_2_Z
149    )                    /* cset_identifier_first */,
150   (
151    G_CSET_a_2_z
152    "_-0123456789"
153    G_CSET_A_2_Z
154    )                    /* cset_identifier_nth */,
155   ( "#\n" )             /* cpair_comment_single */,
156   
157   TRUE                  /* case_sensitive */,
158   
159   TRUE                  /* skip_comment_multi */,
160   TRUE                  /* skip_comment_single */,
161   TRUE                  /* scan_comment_multi */,
162   TRUE                  /* scan_identifier */,
163   FALSE                 /* scan_identifier_1char */,
164   FALSE                 /* scan_identifier_NULL */,
165   TRUE                  /* scan_symbols */,
166   TRUE                  /* scan_binary */,
167   TRUE                  /* scan_octal */,
168   TRUE                  /* scan_float */,
169   TRUE                  /* scan_hex */,
170   TRUE                  /* scan_hex_dollar */,
171   TRUE                  /* scan_string_sq */,
172   TRUE                  /* scan_string_dq */,
173   TRUE                  /* numbers_2_int */,
174   FALSE                 /* int_2_float */,
175   FALSE                 /* identifier_2_string */,
176   TRUE                  /* char_2_token */,
177   TRUE                  /* symbol_2_token */,
178   FALSE                 /* scope_0_fallback */,
179 };
180
181 static const struct
182 {
183   gchar *name;
184   guint token;
185 } symbols[] = {
186   { "include", GTK_RC_TOKEN_INCLUDE },
187   { "NORMAL", GTK_RC_TOKEN_NORMAL },
188   { "ACTIVE", GTK_RC_TOKEN_ACTIVE },
189   { "PRELIGHT", GTK_RC_TOKEN_PRELIGHT },
190   { "SELECTED", GTK_RC_TOKEN_SELECTED },
191   { "INSENSITIVE", GTK_RC_TOKEN_INSENSITIVE },
192   { "fg", GTK_RC_TOKEN_FG },
193   { "bg", GTK_RC_TOKEN_BG },
194   { "base", GTK_RC_TOKEN_BASE },
195   { "text", GTK_RC_TOKEN_TEXT },
196   { "font", GTK_RC_TOKEN_FONT },
197   { "fontset", GTK_RC_TOKEN_FONTSET },
198   { "bg_pixmap", GTK_RC_TOKEN_BG_PIXMAP },
199   { "pixmap_path", GTK_RC_TOKEN_PIXMAP_PATH },
200   { "style", GTK_RC_TOKEN_STYLE },
201   { "binding", GTK_RC_TOKEN_BINDING },
202   { "bind", GTK_RC_TOKEN_BIND },
203   { "widget", GTK_RC_TOKEN_WIDGET },
204   { "widget_class", GTK_RC_TOKEN_WIDGET_CLASS },
205   { "class", GTK_RC_TOKEN_CLASS },
206   { "lowest", GTK_RC_TOKEN_LOWEST },
207   { "gtk", GTK_RC_TOKEN_GTK },
208   { "application", GTK_RC_TOKEN_APPLICATION },
209   { "rc", GTK_RC_TOKEN_RC },
210   { "highest", GTK_RC_TOKEN_HIGHEST },
211   { "engine", GTK_RC_TOKEN_ENGINE },
212   { "module_path", GTK_RC_TOKEN_MODULE_PATH },
213 };
214
215 static const guint n_symbols = sizeof (symbols) / sizeof (symbols[0]);
216
217 static GHashTable *rc_style_ht = NULL;
218 static GHashTable *realized_style_ht = NULL;
219 static GSList *gtk_rc_sets_widget = NULL;
220 static GSList *gtk_rc_sets_widget_class = NULL;
221 static GSList *gtk_rc_sets_class = NULL;
222
223 #define GTK_RC_MAX_DEFAULT_FILES 128
224 static gchar *gtk_rc_default_files[GTK_RC_MAX_DEFAULT_FILES];
225 static gboolean gtk_rc_auto_parse = TRUE;
226
227 #define GTK_RC_MAX_PIXMAP_PATHS 128
228 static gchar *pixmap_path[GTK_RC_MAX_PIXMAP_PATHS];
229 #define GTK_RC_MAX_MODULE_PATHS 128
230 static gchar *module_path[GTK_RC_MAX_MODULE_PATHS];
231
232 /* A stack of directories for RC files we are parsing currently.
233  * these are implicitely added to the end of PIXMAP_PATHS
234  */
235 GSList *rc_dir_stack = NULL;
236
237 /* The files we have parsed, to reread later if necessary */
238 GSList *rc_files = NULL;
239
240 static GtkImageLoader image_loader = NULL;
241
242 /* RC file handling */
243
244
245 #ifdef G_OS_WIN32
246
247 gchar *
248 get_gtk_sysconf_directory (void)
249 {
250   static gchar gtk_sysconf_dir[200];
251   gchar win_dir[100];
252
253   GetWindowsDirectory (win_dir, sizeof (win_dir));
254   sprintf (gtk_sysconf_dir, "%s\\gtk+", win_dir);
255   return gtk_sysconf_dir;
256 }
257
258 static gchar *
259 get_themes_directory (void)
260 {
261   /* We really should fetch this from the Registry. The GIMP
262    * installation program stores the Themes installation
263    * directory in HKLM\Software\GNU\GTk+\Themes\InstallDirectory.
264    * Later.
265    */
266   static gchar themes_dir[200];
267
268   sprintf (themes_dir, "%s\\themes", get_gtk_sysconf_directory ());
269   return themes_dir;
270 }
271
272 #endif
273  
274 gchar *
275 gtk_rc_get_theme_dir(void)
276 {
277   gchar *var, *path;
278
279 #ifndef G_OS_WIN32
280   var = getenv("GTK_DATA_PREFIX");
281   if (var)
282     path = g_strdup_printf("%s%s", var, "/share/themes");
283   else
284     path = g_strdup_printf("%s%s", GTK_DATA_PREFIX, "/share/themes");
285 #else
286   path = g_strdup (get_themes_directory ());
287 #endif
288
289   return path;
290 }
291
292 gchar *
293 gtk_rc_get_module_dir(void)
294 {
295   gchar *var, *path;
296
297 #ifndef G_OS_WIN32
298   var = getenv("GTK_EXE_PREFIX");
299   if (var)
300     path = g_strdup_printf("%s%s", var, "/lib/gtk/themes/engines");
301   else
302     path = g_strdup_printf("%s%s", GTK_EXE_PREFIX, "/lib/gtk/themes/engines");
303 #else
304   path = g_strdup_printf ("%s%s", get_themes_directory (), "\\engines");
305 #endif
306
307   return path;
308 }
309
310 static void
311 gtk_rc_append_default_pixmap_path(void)
312 {
313   gchar *var, *path;
314   gint n;
315
316 #ifndef G_OS_WIN32
317   var = getenv("GTK_DATA_PREFIX");
318   if (var)
319     path = g_strdup_printf("%s%s", var, "/share/gtk/themes");
320   else
321     path = g_strdup_printf("%s%s", GTK_DATA_PREFIX, "/share/gtk/themes");
322 #else
323   path = g_strdup (get_themes_directory ());
324 #endif      
325   
326   for (n = 0; pixmap_path[n]; n++) ;
327   if (n >= GTK_RC_MAX_PIXMAP_PATHS - 1)
328     {
329       g_free (path);
330       return;
331     }
332   pixmap_path[n++] = path;
333   pixmap_path[n] = NULL;
334 }
335
336 static void
337 gtk_rc_append_default_module_path(void)
338 {
339   gchar *var, *path;
340   gint n;
341
342   for (n = 0; module_path[n]; n++) ;
343   if (n >= GTK_RC_MAX_MODULE_PATHS - 1)
344     return;
345   
346 #ifndef G_OS_WIN32
347   var = getenv("GTK_EXE_PREFIX");
348   if (var)
349     path = g_strdup_printf("%s%s", var, "/lib/gtk/themes/engines");
350   else
351     path = g_strdup_printf("%s%s", GTK_EXE_PREFIX, "/lib/gtk/themes/engines");
352 #else
353   path = g_strdup_printf ("%s%s", get_themes_directory (), "\\engines");
354 #endif
355   module_path[n++] = path;
356
357   var = g_get_home_dir ();
358   if (var)
359     {
360 #ifndef G_OS_WIN32
361       path = g_strdup_printf ("%s%s", var, "/.gtk/lib/themes/engines");
362 #else
363       path = g_strdup_printf ("%s%s", var, "\\_gtk\\themes\\engines");
364 #endif
365       module_path[n++] = path;
366     }
367   module_path[n] = NULL;
368 }
369
370 static void
371 gtk_rc_add_initial_default_files (void)
372 {
373   static gint init = FALSE;
374   gchar *var, *str;
375   gchar **files;
376   gint i;
377
378   if (init)
379     return;
380   
381   gtk_rc_default_files[0] = NULL;
382   init = TRUE;
383
384   var = g_getenv("GTK_RC_FILES");
385   if (var)
386     {
387       files = g_strsplit (var, G_SEARCHPATH_SEPARATOR_S, 128);
388       i=0;
389       while (files[i])
390         {
391           gtk_rc_add_default_file (files[i]);
392           i++;
393         }
394       g_strfreev (files);
395     }
396   else
397     {
398 #ifndef G_OS_WIN32
399       str = g_strdup (GTK_SYSCONFDIR G_DIR_SEPARATOR_S "gtk" G_DIR_SEPARATOR_S "gtkrc");
400 #else
401       str = g_strdup_printf ("%s\\gtkrc", get_gtk_sysconf_directory ());
402 #endif
403       gtk_rc_add_default_file (str);
404       g_free (str);
405
406       var = g_get_home_dir ();
407       if (var)
408         {
409           str = g_strdup_printf ("%s" G_DIR_SEPARATOR_S ".gtkrc", var);
410           gtk_rc_add_default_file (str);
411           g_free (str);
412         }
413     }
414 }
415
416 void
417 gtk_rc_add_default_file (const gchar *file)
418 {
419   guint n;
420   
421   gtk_rc_add_initial_default_files ();
422
423   for (n = 0; gtk_rc_default_files[n]; n++) ;
424   if (n >= GTK_RC_MAX_DEFAULT_FILES - 1)
425     return;
426   
427   gtk_rc_default_files[n++] = g_strdup (file);
428   gtk_rc_default_files[n] = NULL;
429 }
430
431 void
432 gtk_rc_set_default_files (gchar **files)
433 {
434   gint i;
435
436   gtk_rc_add_initial_default_files ();
437
438   i = 0;
439   while (gtk_rc_default_files[i])
440     {
441       g_free (gtk_rc_default_files[i]);
442       i++;
443     }
444     
445   gtk_rc_default_files[0] = NULL;
446   gtk_rc_auto_parse = FALSE;
447
448   i = 0;
449   while (files[i] != NULL)
450     {
451       gtk_rc_add_default_file (files[i]);
452       i++;
453     }
454 }
455
456 gchar **
457 gtk_rc_get_default_files (void)
458 {
459   gtk_rc_add_initial_default_files ();
460
461   return gtk_rc_default_files;
462 }
463
464  /* The following routine is based on _nl_normalize_codeset from
465   * the GNU C library. Contributed by
466   *
467   * Contributed by Ulrich Drepper <drepper@gnu.ai.mit.edu>, 1995.
468   * Copyright (C) 1995, 1996, 1997, 1998, 1999 Free Software Foundation, Inc.
469   * 
470   * Normalize codeset name.  There is no standard for the codeset
471   * names.  Normalization allows the user to use any of the common
472   * names.
473   */
474  static char *
475  _gtk_normalize_codeset (const char *codeset, int name_len)
476  {
477    int len = 0;
478    int only_digit = 1;
479    char *retval;
480    char *wp;
481    int cnt;
482  
483    for (cnt = 0; cnt < name_len; ++cnt)
484      if (isalnum (codeset[cnt]))
485        {
486         ++len;
487  
488         if (isalpha (codeset[cnt]))
489           only_digit = 0;
490        }
491  
492    retval = g_malloc ((only_digit ? 3 : 0) + len + 1);
493  
494    if (only_digit)
495      {
496        strcpy (retval, "iso");
497        wp = retval + 3;
498      }
499    else
500      wp = retval;
501    
502    for (cnt = 0; cnt < name_len; ++cnt)
503      if (isalpha (codeset[cnt]))
504        *wp++ = isupper(codeset[cnt]) ? tolower (codeset[cnt]) : codeset[cnt];
505      else if (isdigit (codeset[cnt]))
506        *wp++ = codeset[cnt];
507    
508    *wp = '\0';
509  
510    return retval;
511  }
512  
513 void
514 gtk_rc_init (void)
515 {
516   static gchar *locale_suffixes[3];
517   static gint n_locale_suffixes = 0;
518
519   gint i, j;
520
521   static gboolean initted = FALSE;
522
523   if (!initted)
524     {
525       gint length;
526       gchar *locale;
527       gchar *p;
528
529 #ifdef G_OS_WIN32      
530       locale = g_win32_getlocale ();
531 #else      
532       locale = setlocale (LC_CTYPE, NULL);
533 #endif      
534       
535       initted = TRUE;
536
537       pixmap_path[0] = NULL;
538       module_path[0] = NULL;
539       gtk_rc_append_default_pixmap_path();
540       gtk_rc_append_default_module_path();
541       
542       gtk_rc_add_initial_default_files ();
543
544       if (strcmp (locale, "C") && strcmp (locale, "POSIX"))
545         {
546           /* Determine locale-specific suffixes for RC files
547            *
548            * We normalize the charset into a standard form,
549            * which has all '-' and '_' characters removed,
550            * and is lowercase.
551            */
552           gchar *normalized_locale;
553
554           p = strchr (locale, '@');
555           length = p ? (p -locale) : strlen (locale);
556
557           p = strchr (locale, '.');
558           if (p)
559             {
560               gchar *tmp1 = g_strndup (locale, p - locale + 1);
561               gchar *tmp2 = _gtk_normalize_codeset (p + 1, length - (p - locale + 1));
562               
563               normalized_locale = g_strconcat (tmp1, tmp2, NULL);
564               g_free (tmp1);
565               g_free (tmp2);
566                                                  
567               locale_suffixes[n_locale_suffixes++] = g_strdup (normalized_locale);
568               length = p - locale;
569             }
570           else
571             normalized_locale = g_strndup (locale, length);
572           
573           p = strchr (normalized_locale, '_');
574           if (p)
575             {
576               locale_suffixes[n_locale_suffixes++] = g_strndup (normalized_locale, length);
577               length = p - normalized_locale;
578             }
579           
580           locale_suffixes[n_locale_suffixes++] = g_strndup (normalized_locale, length);
581
582           g_free (normalized_locale);
583         }
584     }
585   
586   i = 0;
587   while (gtk_rc_default_files[i] != NULL)
588     {
589       /* Try to find a locale specific RC file corresponding to
590        * to parse before the default file.
591        */
592       for (j=n_locale_suffixes-1; j>=0; j--)
593         {
594           gchar *name = g_strconcat (gtk_rc_default_files[i],
595                                      ".",
596                                      locale_suffixes[j],
597                                      NULL);
598           gtk_rc_parse (name);
599           g_free (name);
600         }
601
602       gtk_rc_parse (gtk_rc_default_files[i]);
603       i++;
604     }
605 }
606
607 void
608 gtk_rc_parse_string (const gchar *rc_string)
609 {
610   g_return_if_fail (rc_string != NULL);
611
612   gtk_rc_parse_any ("-", -1, rc_string);
613 }
614
615 static void
616 gtk_rc_parse_file (const gchar *filename, gboolean reload)
617 {
618   GtkRcFile *rc_file = NULL;
619   struct stat statbuf;
620   GSList *tmp_list;
621
622   g_return_if_fail (filename != NULL);
623
624   tmp_list = rc_files;
625   while (tmp_list)
626     {
627       rc_file = tmp_list->data;
628       if (!strcmp (rc_file->name, filename))
629         break;
630       
631       tmp_list = tmp_list->next;
632     }
633
634   if (!tmp_list)
635     {
636       rc_file = g_new (GtkRcFile, 1);
637       rc_file->name = g_strdup (filename);
638       rc_file->canonical_name = NULL;
639       rc_file->mtime = 0;
640       rc_file->reload = reload;
641
642       rc_files = g_slist_append (rc_files, rc_file);
643     }
644
645   if (!rc_file->canonical_name)
646     {
647       /* Get the absolute pathname */
648
649       if (g_path_is_absolute (rc_file->name))
650         rc_file->canonical_name = rc_file->name;
651       else
652         {
653           GString *str;
654           gchar *cwd;
655
656           cwd = g_get_current_dir ();
657
658           str = g_string_new (cwd);
659           g_free (cwd);
660           g_string_append_c (str, G_DIR_SEPARATOR);
661           g_string_append (str, rc_file->name);
662           
663           rc_file->canonical_name = str->str;
664           g_string_free (str, FALSE);
665         }
666     }
667
668   if (!lstat (rc_file->canonical_name, &statbuf))
669     {
670       gint fd;
671       GSList *tmp_list;
672
673       rc_file->mtime = statbuf.st_mtime;
674
675       fd = open (rc_file->canonical_name, O_RDONLY);
676       if (fd < 0)
677         return;
678
679       /* Temporarily push directory name for this file on
680        * a stack of directory names while parsing it
681        */
682       rc_dir_stack = g_slist_prepend (rc_dir_stack,
683                                       g_dirname (rc_file->canonical_name));
684       gtk_rc_parse_any (filename, fd, NULL);
685  
686       tmp_list = rc_dir_stack;
687       rc_dir_stack = rc_dir_stack->next;
688  
689       g_free (tmp_list->data);
690       g_slist_free_1 (tmp_list);
691
692       close (fd);
693     }
694 }
695
696 void
697 gtk_rc_parse (const gchar *filename)
698 {
699   g_return_if_fail (filename != NULL);
700
701   gtk_rc_parse_file (filename, TRUE);
702 }
703
704 /* Handling of RC styles */
705
706 GtkRcStyle *
707 gtk_rc_style_new              (void)
708 {
709   GtkRcStylePrivate *new_style;
710
711   new_style = g_new0 (GtkRcStylePrivate, 1);
712   new_style->ref_count = 1;
713
714   return (GtkRcStyle *)new_style;
715 }
716
717 void      
718 gtk_rc_style_ref (GtkRcStyle  *rc_style)
719 {
720   g_return_if_fail (rc_style != NULL);
721
722   ((GtkRcStylePrivate *)rc_style)->ref_count++;
723 }
724
725 /* Like g_slist_remove, but remove all copies of data */
726 static GSList*
727 gtk_rc_slist_remove_all (GSList   *list,
728                          gpointer  data)
729 {
730   GSList *tmp;
731   GSList *prev;
732
733   prev = NULL;
734   tmp = list;
735
736   while (tmp)
737     {
738       if (tmp->data == data)
739         {
740           if (list == tmp)
741             list = list->next;
742
743           if (prev) 
744             prev->next = tmp->next;
745
746           g_slist_free_1 (tmp);
747
748           if (prev)
749             tmp = prev->next;
750           else
751             tmp = list;
752         }
753       else
754         {
755           prev = tmp;
756           tmp = tmp->next;
757         }
758     }
759
760   return list;
761 }
762
763 void      
764 gtk_rc_style_unref (GtkRcStyle  *rc_style)
765 {
766   GtkRcStylePrivate *private = (GtkRcStylePrivate *)rc_style;
767   gint i;
768
769   g_return_if_fail (rc_style != NULL);
770   g_return_if_fail (private->ref_count > 0);
771
772   private->ref_count--;
773
774   if (private->ref_count == 0)
775     {
776       GSList *tmp_list1, *tmp_list2;
777         
778       if (rc_style->engine)
779         {
780           rc_style->engine->destroy_rc_style (rc_style);
781           gtk_theme_engine_unref (rc_style->engine);
782         }
783
784       if (rc_style->name)
785         g_free (rc_style->name);
786       if (rc_style->fontset_name)
787         g_free (rc_style->fontset_name);
788       if (rc_style->font_name)
789         g_free (rc_style->font_name);
790       
791       for (i=0 ; i<5 ; i++)
792         if (rc_style->bg_pixmap_name[i])
793           g_free (rc_style->bg_pixmap_name[i]);
794       
795       /* Now remove all references to this rc_style from
796        * realized_style_ht
797        */
798       tmp_list1 = private->rc_style_lists;
799       while (tmp_list1)
800         {
801           GSList *rc_styles = tmp_list1->data;
802           GtkStyle *style = g_hash_table_lookup (realized_style_ht, rc_styles);
803           gtk_style_unref (style);
804
805           /* Remove the list of styles from the other rc_styles
806            * in the list
807            */
808           tmp_list2 = rc_styles;
809           while (tmp_list2)
810             {
811               GtkRcStylePrivate *other_style = tmp_list2->data;
812
813               if (other_style != private)
814                 other_style->rc_style_lists =
815                   gtk_rc_slist_remove_all (other_style->rc_style_lists, rc_styles);
816                   
817               tmp_list2 = tmp_list2->next;
818             }
819
820           /* And from the hash table itself
821            */
822           g_hash_table_remove (realized_style_ht, rc_styles);
823           g_slist_free (rc_styles);
824
825           tmp_list1 = tmp_list1->next;
826         }
827       g_slist_free (private->rc_style_lists);
828
829       g_free (private);
830     }
831 }
832
833 static void
834 gtk_rc_clear_hash_node (gpointer key, 
835                         gpointer data, 
836                         gpointer user_data)
837 {
838   gtk_rc_style_unref (data);
839 }
840
841 static void
842 gtk_rc_free_rc_sets (GSList *slist)
843 {
844   while (slist)
845     {
846       GtkRcSet *rc_set;
847
848       rc_set = slist->data;
849       gtk_pattern_spec_free_segs (&rc_set->pspec);
850       g_free (rc_set);
851
852       slist = slist->next;
853     }
854 }
855
856 static void
857 gtk_rc_clear_styles (void)
858 {
859   /* Clear out all old rc_styles */
860
861   if (rc_style_ht)
862     {
863       g_hash_table_foreach (rc_style_ht, gtk_rc_clear_hash_node, NULL);
864       g_hash_table_destroy (rc_style_ht);
865       rc_style_ht = NULL;
866     }
867
868   gtk_rc_free_rc_sets (gtk_rc_sets_widget);
869   g_slist_free (gtk_rc_sets_widget);
870   gtk_rc_sets_widget = NULL;
871
872   gtk_rc_free_rc_sets (gtk_rc_sets_widget_class);
873   g_slist_free (gtk_rc_sets_widget_class);
874   gtk_rc_sets_widget_class = NULL;
875
876   gtk_rc_free_rc_sets (gtk_rc_sets_class);
877   g_slist_free (gtk_rc_sets_class);
878   gtk_rc_sets_class = NULL;
879 }
880
881 gboolean
882 gtk_rc_reparse_all (void)
883 {
884   GSList *tmp_list;
885   gboolean mtime_modified = FALSE;
886   GtkRcFile *rc_file;
887
888   struct stat statbuf;
889
890   /* Check through and see if any of the RC's have had their
891    * mtime modified. If so, reparse everything.
892    */
893   tmp_list = rc_files;
894   while (tmp_list)
895     {
896       rc_file = tmp_list->data;
897       
898       if (!lstat (rc_file->name, &statbuf) && 
899           (statbuf.st_mtime > rc_file->mtime))
900         {
901           mtime_modified = TRUE;
902           break;
903         }
904       
905       tmp_list = tmp_list->next;
906     }
907
908   if (mtime_modified)
909     {
910       gtk_rc_clear_styles();
911
912       tmp_list = rc_files;
913       while (tmp_list)
914         {
915           rc_file = tmp_list->data;
916           if (rc_file->reload)
917             gtk_rc_parse_file (rc_file->name, FALSE);
918           
919           tmp_list = tmp_list->next;
920         }
921     }
922
923   return mtime_modified;
924 }
925
926 static GSList *
927 gtk_rc_styles_match (GSList       *rc_styles,
928                      GSList       *sets,
929                      guint         path_length,
930                      gchar        *path,
931                      gchar        *path_reversed)
932                      
933 {
934   GtkRcSet *rc_set;
935
936   while (sets)
937     {
938       rc_set = sets->data;
939       sets = sets->next;
940
941       if (gtk_pattern_match (&rc_set->pspec, path_length, path, path_reversed))
942         rc_styles = g_slist_append (rc_styles, rc_set->rc_style);
943     }
944   
945   return rc_styles;
946 }
947
948 GtkStyle*
949 gtk_rc_get_style (GtkWidget *widget)
950 {
951   GtkRcStyle *widget_rc_style;
952   GSList *rc_styles = NULL;
953
954   static guint rc_style_key_id = 0;
955
956   /* We allow the specification of a single rc style to be bound
957    * tightly to a widget, for application modifications
958    */
959   if (!rc_style_key_id)
960     rc_style_key_id = g_quark_from_static_string ("gtk-rc-style");
961
962   widget_rc_style = gtk_object_get_data_by_id (GTK_OBJECT (widget),
963                                                rc_style_key_id);
964
965   if (widget_rc_style)
966     rc_styles = g_slist_prepend (rc_styles, widget_rc_style);
967   
968   if (gtk_rc_sets_widget)
969     {
970       gchar *path, *path_reversed;
971       guint path_length;
972
973       gtk_widget_path (widget, &path_length, &path, &path_reversed);
974       rc_styles = gtk_rc_styles_match (rc_styles, gtk_rc_sets_widget, path_length, path, path_reversed);
975       g_free (path);
976       g_free (path_reversed);
977       
978     }
979   
980   if (gtk_rc_sets_widget_class)
981     {
982       gchar *path, *path_reversed;
983       guint path_length;
984
985       gtk_widget_class_path (widget, &path_length, &path, &path_reversed);
986       rc_styles = gtk_rc_styles_match (rc_styles, gtk_rc_sets_widget_class, path_length, path, path_reversed);
987       g_free (path);
988       g_free (path_reversed);
989     }
990
991   if (gtk_rc_sets_class)
992     {
993       GtkType type;
994
995       type = GTK_OBJECT_TYPE (widget);
996       while (type)
997         {
998           gchar *path, *path_reversed;
999           guint path_length;
1000
1001           path = gtk_type_name (type);
1002           path_length = strlen (path);
1003           path_reversed = g_strdup (path);
1004           g_strreverse (path_reversed);
1005           
1006           rc_styles = gtk_rc_styles_match (rc_styles, gtk_rc_sets_class, path_length, path, path_reversed);
1007           g_free (path_reversed);
1008       
1009           type = gtk_type_parent (type);
1010         }
1011     }
1012   
1013   if (rc_styles)
1014     return gtk_rc_style_init (rc_styles);
1015
1016   return NULL;
1017 }
1018
1019 static GSList*
1020 gtk_rc_add_rc_sets (GSList     *slist,
1021                     GtkRcStyle *rc_style,
1022                     const char *pattern)
1023 {
1024   GtkRcStyle *new_style;
1025   GtkRcSet *rc_set;
1026   guint i;
1027   
1028   new_style = gtk_rc_style_new ();
1029   *new_style = *rc_style;
1030   new_style->name = g_strdup (rc_style->name);
1031   new_style->font_name = g_strdup (rc_style->font_name);
1032   new_style->fontset_name = g_strdup (rc_style->fontset_name);
1033   
1034   for (i = 0; i < 5; i++)
1035     new_style->bg_pixmap_name[i] = g_strdup (rc_style->bg_pixmap_name[i]);
1036   
1037   rc_set = g_new (GtkRcSet, 1);
1038   gtk_pattern_spec_init (&rc_set->pspec, pattern);
1039   rc_set->rc_style = rc_style;
1040   
1041   return g_slist_prepend (slist, rc_set);
1042 }
1043
1044 void
1045 gtk_rc_add_widget_name_style (GtkRcStyle  *rc_style,
1046                               const gchar *pattern)
1047 {
1048   g_return_if_fail (rc_style != NULL);
1049   g_return_if_fail (pattern != NULL);
1050
1051   gtk_rc_sets_widget = gtk_rc_add_rc_sets (gtk_rc_sets_widget, rc_style, pattern);
1052 }
1053
1054 void
1055 gtk_rc_add_widget_class_style (GtkRcStyle  *rc_style,
1056                                const gchar *pattern)
1057 {
1058   g_return_if_fail (rc_style != NULL);
1059   g_return_if_fail (pattern != NULL);
1060
1061   gtk_rc_sets_widget_class = gtk_rc_add_rc_sets (gtk_rc_sets_widget_class, rc_style, pattern);
1062 }
1063
1064 void
1065 gtk_rc_add_class_style (GtkRcStyle  *rc_style,
1066                         const gchar *pattern)
1067 {
1068   g_return_if_fail (rc_style != NULL);
1069   g_return_if_fail (pattern != NULL);
1070
1071   gtk_rc_sets_class = gtk_rc_add_rc_sets (gtk_rc_sets_class, rc_style, pattern);
1072 }
1073
1074 static void
1075 gtk_rc_parse_any (const gchar  *input_name,
1076                   gint          input_fd,
1077                   const gchar  *input_string)
1078 {
1079   GScanner *scanner;
1080   guint    i;
1081   gboolean done;
1082   
1083   scanner = g_scanner_new ((GScannerConfig *) &gtk_rc_scanner_config);
1084   
1085   if (input_fd >= 0)
1086     {
1087       g_assert (input_string == NULL);
1088       
1089       g_scanner_input_file (scanner, input_fd);
1090     }
1091   else
1092     {
1093       g_assert (input_string != NULL);
1094       
1095       g_scanner_input_text (scanner, input_string, strlen (input_string));
1096     }
1097   scanner->input_name = input_name;
1098
1099   g_scanner_freeze_symbol_table (scanner);
1100   for (i = 0; i < n_symbols; i++)
1101     g_scanner_add_symbol (scanner, symbols[i].name, GINT_TO_POINTER (symbols[i].token));
1102   g_scanner_thaw_symbol_table (scanner);
1103   
1104   done = FALSE;
1105   while (!done)
1106     {
1107       if (g_scanner_peek_next_token (scanner) == G_TOKEN_EOF)
1108         done = TRUE;
1109       else
1110         {
1111           guint expected_token;
1112           
1113           expected_token = gtk_rc_parse_statement (scanner);
1114
1115           if (expected_token != G_TOKEN_NONE)
1116             {
1117               gchar *symbol_name;
1118               gchar *msg;
1119               
1120               msg = NULL;
1121               symbol_name = NULL;
1122               if (scanner->scope_id == 0)
1123                 {
1124                   /* if we are in scope 0, we know the symbol names
1125                    * that are associated with certaintoken values.
1126                    * so we look them up to make the error messages
1127                    * more readable.
1128                    */
1129                   if (expected_token > GTK_RC_TOKEN_INVALID &&
1130                       expected_token < GTK_RC_TOKEN_LAST)
1131                     {
1132                       for (i = 0; i < n_symbols; i++)
1133                         if (symbols[i].token == expected_token)
1134                           msg = symbols[i].name;
1135                       if (msg)
1136                         msg = g_strconcat ("e.g. `", msg, "'", NULL);
1137                     }
1138                   if (scanner->token > GTK_RC_TOKEN_INVALID &&
1139                       scanner->token < GTK_RC_TOKEN_LAST)
1140                     {
1141                       symbol_name = "???";
1142                       for (i = 0; i < n_symbols; i++)
1143                         if (symbols[i].token == scanner->token)
1144                           symbol_name = symbols[i].name;
1145                     }
1146                 }
1147               g_scanner_unexp_token (scanner,
1148                                      expected_token,
1149                                      NULL,
1150                                      "keyword",
1151                                      symbol_name,
1152                                      msg,
1153                                      TRUE);
1154               g_free (msg);
1155               done = TRUE;
1156             }
1157         }
1158     }
1159   
1160   g_scanner_destroy (scanner);
1161 }
1162
1163 static guint       
1164 gtk_rc_styles_hash (const GSList *rc_styles)
1165 {
1166   guint result;
1167   
1168   result = 0;
1169   while (rc_styles)
1170     {
1171       result += (result << 9) + GPOINTER_TO_UINT (rc_styles->data);
1172       rc_styles = rc_styles->next;
1173     }
1174   
1175   return result;
1176 }
1177
1178 static gint        
1179 gtk_rc_styles_compare (const GSList *a,
1180                        const GSList *b)
1181 {
1182   while (a && b)
1183     {
1184       if (a->data != b->data)
1185         return FALSE;
1186       a = a->next;
1187       b = b->next;
1188     }
1189   
1190   return (a == b);
1191 }
1192
1193 static guint
1194 gtk_rc_style_hash (const char *name)
1195 {
1196   guint result;
1197   
1198   result = 0;
1199   while (*name)
1200     result += (result << 3) + *name++;
1201   
1202   return result;
1203 }
1204
1205 static gint
1206 gtk_rc_style_compare (const char *a,
1207                       const char *b)
1208 {
1209   return (strcmp (a, b) == 0);
1210 }
1211
1212 static GtkRcStyle*
1213 gtk_rc_style_find (const char *name)
1214 {
1215   if (rc_style_ht)
1216     return g_hash_table_lookup (rc_style_ht, (gpointer) name);
1217   else
1218     return NULL;
1219 }
1220
1221 /* Assumes ownership of rc_style */
1222 static GtkStyle *
1223 gtk_rc_style_to_style (GtkRcStyle *rc_style)
1224 {
1225   GtkStyle *style;
1226   GdkFont *old_font;
1227   gint i;
1228
1229   style = gtk_style_new ();
1230
1231   style->rc_style = rc_style;
1232   
1233   if (rc_style->fontset_name)
1234     {
1235       old_font = style->font;
1236       style->font = gdk_fontset_load (rc_style->fontset_name);
1237       if (style->font)
1238         gdk_font_unref (old_font);
1239       else
1240         style->font = old_font;
1241     }
1242   else if (rc_style->font_name)
1243     {
1244       old_font = style->font;
1245       style->font = gdk_font_load (rc_style->font_name);
1246       if (style->font)
1247         gdk_font_unref (old_font);
1248       else
1249         style->font = old_font;
1250     }
1251   
1252   for (i = 0; i < 5; i++)
1253     {
1254       if (rc_style->color_flags[i] & GTK_RC_FG)
1255         style->fg[i] = rc_style->fg[i];
1256       if (rc_style->color_flags[i] & GTK_RC_BG)
1257         style->bg[i] = rc_style->bg[i];
1258       if (rc_style->color_flags[i] & GTK_RC_TEXT)
1259         style->text[i] = rc_style->text[i];
1260       if (rc_style->color_flags[i] & GTK_RC_BASE)
1261         style->base[i] = rc_style->base[i];
1262     }
1263
1264   if (rc_style->engine)
1265     {
1266       style->engine = rc_style->engine;
1267       gtk_theme_engine_ref (style->engine);
1268       rc_style->engine->rc_style_to_style (style, rc_style);
1269     }
1270
1271   return style;
1272 }
1273
1274 /* Reuses or frees rc_styles */
1275 static GtkStyle *
1276 gtk_rc_style_init (GSList *rc_styles)
1277 {
1278   gint i;
1279
1280   GtkStyle *style = NULL;
1281
1282   if (!realized_style_ht)
1283     realized_style_ht = g_hash_table_new ((GHashFunc)gtk_rc_styles_hash,
1284                                            (GCompareFunc)gtk_rc_styles_compare);
1285
1286   style = g_hash_table_lookup (realized_style_ht, rc_styles);
1287
1288   if (!style)
1289     {
1290       GtkRcStyle *proto_style;
1291       GSList *tmp_styles;
1292       
1293       proto_style = gtk_rc_style_new ();
1294
1295       tmp_styles = rc_styles;
1296       while (tmp_styles)
1297         {
1298           GtkRcStyle *rc_style = tmp_styles->data;
1299           GtkRcStylePrivate *rc_style_private;
1300
1301           for (i=0; i<5; i++)
1302             {
1303               if (!proto_style->bg_pixmap_name[i] && rc_style->bg_pixmap_name[i])
1304                 proto_style->bg_pixmap_name[i] = g_strdup (rc_style->bg_pixmap_name[i]);
1305
1306               if (!(proto_style->color_flags[i] & GTK_RC_FG) && 
1307                     rc_style->color_flags[i] & GTK_RC_FG)
1308                 {
1309                   proto_style->fg[i] = rc_style->fg[i];
1310                   proto_style->color_flags[i] |= GTK_RC_FG;
1311                 }
1312               if (!(proto_style->color_flags[i] & GTK_RC_BG) && 
1313                     rc_style->color_flags[i] & GTK_RC_BG)
1314                 {
1315                   proto_style->bg[i] = rc_style->bg[i];
1316                   proto_style->color_flags[i] |= GTK_RC_BG;
1317                 }
1318               if (!(proto_style->color_flags[i] & GTK_RC_TEXT) && 
1319                     rc_style->color_flags[i] & GTK_RC_TEXT)
1320                 {
1321                   proto_style->text[i] = rc_style->text[i];
1322                   proto_style->color_flags[i] |= GTK_RC_TEXT;
1323                 }
1324               if (!(proto_style->color_flags[i] & GTK_RC_BASE) && 
1325                     rc_style->color_flags[i] & GTK_RC_BASE)
1326                 {
1327                   proto_style->base[i] = rc_style->base[i];
1328                   proto_style->color_flags[i] |= GTK_RC_BASE;
1329                 }
1330             }
1331
1332           if (!proto_style->font_name && rc_style->font_name)
1333             proto_style->font_name = g_strdup (rc_style->font_name);
1334           if (!proto_style->fontset_name && rc_style->fontset_name)
1335             proto_style->fontset_name = g_strdup (rc_style->fontset_name);
1336
1337           if (!proto_style->engine && rc_style->engine)
1338             {
1339               proto_style->engine = rc_style->engine;
1340               gtk_theme_engine_ref (proto_style->engine);
1341             }
1342           
1343           if (proto_style->engine &&
1344               (proto_style->engine == rc_style->engine))
1345             proto_style->engine->merge_rc_style (proto_style, rc_style);
1346
1347           /* Point from each rc_style to the list of styles */
1348
1349           rc_style_private = (GtkRcStylePrivate *)rc_style;
1350           if (!g_slist_find (rc_style_private->rc_style_lists, rc_styles))
1351             rc_style_private->rc_style_lists = g_slist_prepend (rc_style_private->rc_style_lists, rc_styles);
1352
1353           tmp_styles = tmp_styles->next;
1354         }
1355
1356       for (i=0; i<5; i++)
1357         if (proto_style->bg_pixmap_name[i] &&
1358             (strcmp (proto_style->bg_pixmap_name[i], "<none>") == 0))
1359           {
1360             g_free (proto_style->bg_pixmap_name[i]);
1361             proto_style->bg_pixmap_name[i] = NULL;
1362           }
1363
1364       style = gtk_rc_style_to_style (proto_style);
1365
1366       g_hash_table_insert (realized_style_ht, rc_styles, style);
1367     }
1368   else
1369     g_slist_free (rc_styles);
1370
1371   return style;
1372 }
1373
1374 /*********************
1375  * Parsing functions *
1376  *********************/
1377
1378 static guint
1379 gtk_rc_parse_statement (GScanner *scanner)
1380 {
1381   guint token;
1382   
1383   token = g_scanner_peek_next_token (scanner);
1384
1385   switch (token)
1386     {
1387     case GTK_RC_TOKEN_INCLUDE:
1388       token = g_scanner_get_next_token (scanner);
1389       if (token != GTK_RC_TOKEN_INCLUDE)
1390         return GTK_RC_TOKEN_INCLUDE;
1391
1392       token = g_scanner_get_next_token (scanner);
1393       if (token != G_TOKEN_STRING)
1394         return G_TOKEN_STRING;
1395
1396       gtk_rc_parse_file (scanner->value.v_string, FALSE);
1397       return G_TOKEN_NONE;
1398
1399     case GTK_RC_TOKEN_STYLE:
1400       return gtk_rc_parse_style (scanner);
1401
1402     case GTK_RC_TOKEN_BINDING:
1403       return gtk_binding_parse_binding (scanner);
1404
1405     case GTK_RC_TOKEN_PIXMAP_PATH:
1406       return gtk_rc_parse_pixmap_path (scanner);
1407
1408     case GTK_RC_TOKEN_WIDGET:
1409       return gtk_rc_parse_path_pattern (scanner);
1410
1411     case GTK_RC_TOKEN_WIDGET_CLASS:
1412       return gtk_rc_parse_path_pattern (scanner);
1413
1414     case GTK_RC_TOKEN_CLASS:
1415       return gtk_rc_parse_path_pattern (scanner);
1416
1417     case GTK_RC_TOKEN_MODULE_PATH:
1418       return gtk_rc_parse_module_path (scanner);
1419        
1420     default:
1421       g_scanner_get_next_token (scanner);
1422       return /* G_TOKEN_SYMBOL */ GTK_RC_TOKEN_STYLE;
1423     }
1424 }
1425
1426 static guint
1427 gtk_rc_parse_style (GScanner *scanner)
1428 {
1429   GtkRcStyle *rc_style;
1430   GtkRcStyle *parent_style;
1431   guint token;
1432   gint insert;
1433   gint i;
1434   
1435   token = g_scanner_get_next_token (scanner);
1436   if (token != GTK_RC_TOKEN_STYLE)
1437     return GTK_RC_TOKEN_STYLE;
1438   
1439   token = g_scanner_get_next_token (scanner);
1440   if (token != G_TOKEN_STRING)
1441     return G_TOKEN_STRING;
1442   
1443   insert = FALSE;
1444   rc_style = gtk_rc_style_find (scanner->value.v_string);
1445   
1446   if (!rc_style)
1447     {
1448       insert = TRUE;
1449       rc_style = gtk_rc_style_new ();
1450       rc_style->name = g_strdup (scanner->value.v_string);
1451       
1452       for (i = 0; i < 5; i++)
1453         rc_style->bg_pixmap_name[i] = NULL;
1454
1455       for (i = 0; i < 5; i++)
1456         rc_style->color_flags[i] = 0;
1457
1458       rc_style->engine = NULL;
1459       rc_style->engine_data = NULL;
1460     }
1461   
1462   token = g_scanner_peek_next_token (scanner);
1463   if (token == G_TOKEN_EQUAL_SIGN)
1464     {
1465       token = g_scanner_get_next_token (scanner);
1466       
1467       token = g_scanner_get_next_token (scanner);
1468       if (token != G_TOKEN_STRING)
1469         {
1470           if (insert)
1471             g_free (rc_style);
1472
1473           return G_TOKEN_STRING;
1474         }
1475       
1476       parent_style = gtk_rc_style_find (scanner->value.v_string);
1477       if (parent_style)
1478         {
1479           for (i = 0; i < 5; i++)
1480             {
1481               rc_style->color_flags[i] = parent_style->color_flags[i];
1482               rc_style->fg[i] = parent_style->fg[i];
1483               rc_style->bg[i] = parent_style->bg[i];
1484               rc_style->text[i] = parent_style->text[i];
1485               rc_style->base[i] = parent_style->base[i];
1486             }
1487           
1488           if (parent_style->fontset_name)
1489             {
1490               if (rc_style->fontset_name)
1491                 g_free (rc_style->fontset_name);
1492               rc_style->fontset_name = g_strdup (parent_style->fontset_name);
1493             }
1494           else if (parent_style->font_name)
1495             {
1496               if (rc_style->font_name)
1497                 g_free (rc_style->font_name);
1498               rc_style->font_name = g_strdup (parent_style->font_name);
1499             }
1500           
1501           for (i = 0; i < 5; i++)
1502             {
1503               if (rc_style->bg_pixmap_name[i])
1504                 g_free (rc_style->bg_pixmap_name[i]);
1505               rc_style->bg_pixmap_name[i] = g_strdup (parent_style->bg_pixmap_name[i]);
1506             }
1507         }
1508     }
1509   
1510   token = g_scanner_get_next_token (scanner);
1511   if (token != G_TOKEN_LEFT_CURLY)
1512     {
1513       if (insert)
1514         g_free (rc_style);
1515
1516       return G_TOKEN_LEFT_CURLY;
1517     }
1518   
1519   token = g_scanner_peek_next_token (scanner);
1520   while (token != G_TOKEN_RIGHT_CURLY)
1521     {
1522       switch (token)
1523         {
1524         case GTK_RC_TOKEN_BASE:
1525           token = gtk_rc_parse_base (scanner, rc_style);
1526           break;
1527         case GTK_RC_TOKEN_BG:
1528           token = gtk_rc_parse_bg (scanner, rc_style);
1529           break;
1530         case GTK_RC_TOKEN_FG:
1531           token = gtk_rc_parse_fg (scanner, rc_style);
1532           break;
1533         case GTK_RC_TOKEN_TEXT:
1534           token = gtk_rc_parse_text (scanner, rc_style);
1535           break;
1536         case GTK_RC_TOKEN_BG_PIXMAP:
1537           token = gtk_rc_parse_bg_pixmap (scanner, rc_style);
1538           break;
1539         case GTK_RC_TOKEN_FONT:
1540           token = gtk_rc_parse_font (scanner, rc_style);
1541           break;
1542         case GTK_RC_TOKEN_FONTSET:
1543           token = gtk_rc_parse_fontset (scanner, rc_style);
1544           break;
1545         case GTK_RC_TOKEN_ENGINE:
1546           token = gtk_rc_parse_engine (scanner, rc_style);
1547           break;
1548         default:
1549           g_scanner_get_next_token (scanner);
1550           token = G_TOKEN_RIGHT_CURLY;
1551           break;
1552         }
1553
1554       if (token != G_TOKEN_NONE)
1555         {
1556           if (insert)
1557             {
1558               if (rc_style->fontset_name)
1559                 g_free (rc_style->fontset_name);
1560               if (rc_style->font_name)
1561                 g_free (rc_style->font_name);
1562               for (i = 0; i < 5; i++)
1563                 if (rc_style->bg_pixmap_name[i])
1564                   g_free (rc_style->bg_pixmap_name[i]);
1565               g_free (rc_style);
1566             }
1567           return token;
1568         }
1569       token = g_scanner_peek_next_token (scanner);
1570     }
1571   
1572   token = g_scanner_get_next_token (scanner);
1573   if (token != G_TOKEN_RIGHT_CURLY)
1574     {
1575       if (insert)
1576         {
1577           if (rc_style->fontset_name)
1578             g_free (rc_style->fontset_name);
1579           if (rc_style->font_name)
1580             g_free (rc_style->font_name);
1581           
1582           for (i = 0; i < 5; i++)
1583             if (rc_style->bg_pixmap_name[i])
1584               g_free (rc_style->bg_pixmap_name[i]);
1585           
1586           g_free (rc_style);
1587         }
1588       return G_TOKEN_RIGHT_CURLY;
1589     }
1590   
1591   if (insert)
1592     {
1593       if (!rc_style_ht)
1594         rc_style_ht = g_hash_table_new ((GHashFunc) gtk_rc_style_hash,
1595                                         (GCompareFunc) gtk_rc_style_compare);
1596       
1597       g_hash_table_insert (rc_style_ht, rc_style->name, rc_style);
1598     }
1599   
1600   return G_TOKEN_NONE;
1601 }
1602
1603 static guint
1604 gtk_rc_parse_base (GScanner   *scanner,
1605                    GtkRcStyle *style)
1606 {
1607   GtkStateType state;
1608   guint token;
1609   
1610   token = g_scanner_get_next_token (scanner);
1611   if (token != GTK_RC_TOKEN_BASE)
1612     return GTK_RC_TOKEN_BASE;
1613   
1614   token = gtk_rc_parse_state (scanner, &state);
1615   if (token != G_TOKEN_NONE)
1616     return token;
1617   
1618   token = g_scanner_get_next_token (scanner);
1619   if (token != G_TOKEN_EQUAL_SIGN)
1620     return G_TOKEN_EQUAL_SIGN;
1621
1622   style->color_flags[state] |= GTK_RC_BASE;
1623   return gtk_rc_parse_color (scanner, &style->base[state]);
1624 }
1625
1626 static guint
1627 gtk_rc_parse_bg (GScanner   *scanner,
1628                  GtkRcStyle *style)
1629 {
1630   GtkStateType state;
1631   guint token;
1632   
1633   token = g_scanner_get_next_token (scanner);
1634   if (token != GTK_RC_TOKEN_BG)
1635     return GTK_RC_TOKEN_BG;
1636   
1637   token = gtk_rc_parse_state (scanner, &state);
1638   if (token != G_TOKEN_NONE)
1639     return token;
1640   
1641   token = g_scanner_get_next_token (scanner);
1642   if (token != G_TOKEN_EQUAL_SIGN)
1643     return G_TOKEN_EQUAL_SIGN;
1644
1645   style->color_flags[state] |= GTK_RC_BG;
1646   return gtk_rc_parse_color (scanner, &style->bg[state]);
1647 }
1648
1649 static guint
1650 gtk_rc_parse_fg (GScanner   *scanner,
1651                  GtkRcStyle *style)
1652 {
1653   GtkStateType state;
1654   guint token;
1655   
1656   token = g_scanner_get_next_token (scanner);
1657   if (token != GTK_RC_TOKEN_FG)
1658     return GTK_RC_TOKEN_FG;
1659   
1660   token = gtk_rc_parse_state (scanner, &state);
1661   if (token != G_TOKEN_NONE)
1662     return token;
1663   
1664   token = g_scanner_get_next_token (scanner);
1665   if (token != G_TOKEN_EQUAL_SIGN)
1666     return G_TOKEN_EQUAL_SIGN;
1667   
1668   style->color_flags[state] |= GTK_RC_FG;
1669   return gtk_rc_parse_color (scanner, &style->fg[state]);
1670 }
1671
1672 static guint
1673 gtk_rc_parse_text (GScanner   *scanner,
1674                    GtkRcStyle *style)
1675 {
1676   GtkStateType state;
1677   guint token;
1678   
1679   token = g_scanner_get_next_token (scanner);
1680   if (token != GTK_RC_TOKEN_TEXT)
1681     return GTK_RC_TOKEN_TEXT;
1682   
1683   token = gtk_rc_parse_state (scanner, &state);
1684   if (token != G_TOKEN_NONE)
1685     return token;
1686   
1687   token = g_scanner_get_next_token (scanner);
1688   if (token != G_TOKEN_EQUAL_SIGN)
1689     return G_TOKEN_EQUAL_SIGN;
1690   
1691   style->color_flags[state] |= GTK_RC_TEXT;
1692   return gtk_rc_parse_color (scanner, &style->text[state]);
1693 }
1694
1695 static guint
1696 gtk_rc_parse_bg_pixmap (GScanner   *scanner,
1697                         GtkRcStyle *rc_style)
1698 {
1699   GtkStateType state;
1700   guint token;
1701   gchar *pixmap_file;
1702   
1703   token = g_scanner_get_next_token (scanner);
1704   if (token != GTK_RC_TOKEN_BG_PIXMAP)
1705     return GTK_RC_TOKEN_BG_PIXMAP;
1706   
1707   token = gtk_rc_parse_state (scanner, &state);
1708   if (token != G_TOKEN_NONE)
1709     return token;
1710   
1711   token = g_scanner_get_next_token (scanner);
1712   if (token != G_TOKEN_EQUAL_SIGN)
1713     return G_TOKEN_EQUAL_SIGN;
1714   
1715   token = g_scanner_get_next_token (scanner);
1716   if (token != G_TOKEN_STRING)
1717     return G_TOKEN_STRING;
1718   
1719   if ((strcmp (scanner->value.v_string, "<parent>") == 0) ||
1720       (strcmp (scanner->value.v_string, "<none>") == 0))
1721     pixmap_file = g_strdup (scanner->value.v_string);
1722   else
1723     pixmap_file = gtk_rc_find_pixmap_in_path (scanner, scanner->value.v_string);
1724   
1725   if (pixmap_file)
1726     {
1727       if (rc_style->bg_pixmap_name[state])
1728         g_free (rc_style->bg_pixmap_name[state]);
1729       rc_style->bg_pixmap_name[state] = pixmap_file;
1730     }
1731   
1732   return G_TOKEN_NONE;
1733 }
1734
1735 static gchar*
1736 gtk_rc_check_pixmap_dir (const gchar *dir, const gchar *pixmap_file)
1737 {
1738   gchar *buf;
1739   gint fd;
1740
1741   buf = g_strdup_printf ("%s" G_DIR_SEPARATOR_S "%s", dir, pixmap_file);
1742   
1743   fd = open (buf, O_RDONLY);
1744   if (fd >= 0)
1745     {
1746       close (fd);
1747       return buf;
1748     }
1749    
1750   g_free (buf);
1751  
1752    return NULL;
1753  }
1754  
1755 gchar*
1756 gtk_rc_find_pixmap_in_path (GScanner *scanner,
1757                             const gchar *pixmap_file)
1758 {
1759   gint i;
1760   gchar *filename;
1761   GSList *tmp_list;
1762     
1763   for (i = 0; (i < GTK_RC_MAX_PIXMAP_PATHS) && (pixmap_path[i] != NULL); i++)
1764     {
1765       filename = gtk_rc_check_pixmap_dir (pixmap_path[i], pixmap_file);
1766       if (filename)
1767         return filename;
1768     }
1769  
1770   tmp_list = rc_dir_stack;
1771   while (tmp_list)
1772     {
1773       filename = gtk_rc_check_pixmap_dir (tmp_list->data, pixmap_file);
1774       if (filename)
1775         return filename;
1776        
1777       tmp_list = tmp_list->next;
1778     }
1779   
1780   if (scanner)
1781     g_warning (_("Unable to locate image file in pixmap_path: \"%s\" line %d"),
1782                pixmap_file, scanner->line);
1783   else
1784     g_warning (_("Unable to locate image file in pixmap_path: \"%s\""),
1785                pixmap_file);
1786     
1787   return NULL;
1788 }
1789
1790 gchar*
1791 gtk_rc_find_module_in_path (const gchar *module_file)
1792 {
1793   gint i;
1794   gint fd;
1795   gchar *buf;
1796   
1797   for (i = 0; (i < GTK_RC_MAX_MODULE_PATHS) && (module_path[i] != NULL); i++)
1798     {
1799       buf = g_strdup_printf ("%s" G_DIR_SEPARATOR_S "%s",
1800                              module_path[i], module_file);
1801       
1802       fd = open (buf, O_RDONLY);
1803       if (fd >= 0)
1804         {
1805           close (fd);
1806           return buf;
1807         }
1808       
1809       g_free (buf);
1810     }
1811     
1812   return NULL;
1813 }
1814
1815 static guint
1816 gtk_rc_parse_font (GScanner   *scanner,
1817                    GtkRcStyle *rc_style)
1818 {
1819   guint token;
1820   
1821   token = g_scanner_get_next_token (scanner);
1822   if (token != GTK_RC_TOKEN_FONT)
1823     return GTK_RC_TOKEN_FONT;
1824   
1825   token = g_scanner_get_next_token (scanner);
1826   if (token != G_TOKEN_EQUAL_SIGN)
1827     return G_TOKEN_EQUAL_SIGN;
1828   
1829   token = g_scanner_get_next_token (scanner);
1830   if (token != G_TOKEN_STRING)
1831     return G_TOKEN_STRING;
1832   
1833   if (rc_style->font_name)
1834     g_free (rc_style->font_name);
1835   rc_style->font_name = g_strdup (scanner->value.v_string);
1836   
1837   return G_TOKEN_NONE;
1838 }
1839
1840 static guint
1841 gtk_rc_parse_fontset (GScanner   *scanner,
1842                       GtkRcStyle *rc_style)
1843 {
1844   guint token;
1845   
1846   token = g_scanner_get_next_token (scanner);
1847   if (token != GTK_RC_TOKEN_FONTSET)
1848     return GTK_RC_TOKEN_FONTSET;
1849   
1850   token = g_scanner_get_next_token (scanner);
1851   if (token != G_TOKEN_EQUAL_SIGN)
1852     return G_TOKEN_EQUAL_SIGN;
1853   
1854   token = g_scanner_get_next_token (scanner);
1855   if (token != G_TOKEN_STRING)
1856     return G_TOKEN_STRING;
1857   
1858   if (rc_style->fontset_name)
1859     g_free (rc_style->fontset_name);
1860   rc_style->fontset_name = g_strdup (scanner->value.v_string);
1861   
1862   return G_TOKEN_NONE;
1863 }
1864
1865 static guint       
1866 gtk_rc_parse_engine (GScanner    *scanner,
1867                      GtkRcStyle  *rc_style)
1868 {
1869   guint token;
1870
1871   token = g_scanner_get_next_token (scanner);
1872   if (token != GTK_RC_TOKEN_ENGINE)
1873     return GTK_RC_TOKEN_ENGINE;
1874
1875   token = g_scanner_get_next_token (scanner);
1876   if (token != G_TOKEN_STRING)
1877     return G_TOKEN_STRING;
1878
1879   rc_style->engine = gtk_theme_engine_get (scanner->value.v_string);
1880
1881   token = g_scanner_get_next_token (scanner);
1882   if (token != G_TOKEN_LEFT_CURLY)
1883     return G_TOKEN_LEFT_CURLY;
1884
1885   if (rc_style->engine)
1886     return rc_style->engine->parse_rc_style (scanner, rc_style);
1887   else
1888     {
1889       /* Skip over remainder, looking for nested {}'s */
1890       guint count = 1;
1891       
1892       while ((token = g_scanner_get_next_token (scanner)) != G_TOKEN_EOF)
1893         {
1894           if (token == G_TOKEN_LEFT_CURLY)
1895             count++;
1896           else if (token == G_TOKEN_RIGHT_CURLY)
1897             count--;
1898
1899           if (count == 0)
1900             return G_TOKEN_NONE;
1901         }
1902
1903       return G_TOKEN_RIGHT_CURLY;
1904     }
1905 }
1906
1907 guint
1908 gtk_rc_parse_state (GScanner     *scanner,
1909                     GtkStateType *state)
1910 {
1911   guint old_scope;
1912   guint token;
1913
1914   g_return_val_if_fail (scanner != NULL, G_TOKEN_ERROR);
1915   g_return_val_if_fail (state != NULL, G_TOKEN_ERROR);
1916   
1917   /* we don't know where we got called from, so we reset the scope here.
1918    * if we bail out due to errors, we *don't* reset the scope, so the
1919    * error messaging code can make sense of our tokens.
1920    */
1921   old_scope = g_scanner_set_scope (scanner, 0);
1922   
1923   token = g_scanner_get_next_token (scanner);
1924   if (token != G_TOKEN_LEFT_BRACE)
1925     return G_TOKEN_LEFT_BRACE;
1926   
1927   token = g_scanner_get_next_token (scanner);
1928   switch (token)
1929     {
1930     case GTK_RC_TOKEN_ACTIVE:
1931       *state = GTK_STATE_ACTIVE;
1932       break;
1933     case GTK_RC_TOKEN_INSENSITIVE:
1934       *state = GTK_STATE_INSENSITIVE;
1935       break;
1936     case GTK_RC_TOKEN_NORMAL:
1937       *state = GTK_STATE_NORMAL;
1938       break;
1939     case GTK_RC_TOKEN_PRELIGHT:
1940       *state = GTK_STATE_PRELIGHT;
1941       break;
1942     case GTK_RC_TOKEN_SELECTED:
1943       *state = GTK_STATE_SELECTED;
1944       break;
1945     default:
1946       return /* G_TOKEN_SYMBOL */ GTK_RC_TOKEN_NORMAL;
1947     }
1948   
1949   token = g_scanner_get_next_token (scanner);
1950   if (token != G_TOKEN_RIGHT_BRACE)
1951     return G_TOKEN_RIGHT_BRACE;
1952   
1953   g_scanner_set_scope (scanner, old_scope);
1954
1955   return G_TOKEN_NONE;
1956 }
1957
1958 guint
1959 gtk_rc_parse_priority (GScanner            *scanner,
1960                        GtkPathPriorityType *priority)
1961 {
1962   guint old_scope;
1963   guint token;
1964
1965   g_return_val_if_fail (scanner != NULL, G_TOKEN_ERROR);
1966   g_return_val_if_fail (priority != NULL, G_TOKEN_ERROR);
1967
1968   /* we don't know where we got called from, so we reset the scope here.
1969    * if we bail out due to errors, we *don't* reset the scope, so the
1970    * error messaging code can make sense of our tokens.
1971    */
1972   old_scope = g_scanner_set_scope (scanner, 0);
1973   
1974   token = g_scanner_get_next_token (scanner);
1975   if (token != ':')
1976     return ':';
1977   
1978   token = g_scanner_get_next_token (scanner);
1979   switch (token)
1980     {
1981     case GTK_RC_TOKEN_LOWEST:
1982       *priority = GTK_PATH_PRIO_LOWEST;
1983       break;
1984     case GTK_RC_TOKEN_GTK:
1985       *priority = GTK_PATH_PRIO_GTK;
1986       break;
1987     case GTK_RC_TOKEN_APPLICATION:
1988       *priority = GTK_PATH_PRIO_APPLICATION;
1989       break;
1990     case GTK_RC_TOKEN_RC:
1991       *priority = GTK_PATH_PRIO_RC;
1992       break;
1993     case GTK_RC_TOKEN_HIGHEST:
1994       *priority = GTK_PATH_PRIO_HIGHEST;
1995       break;
1996     default:
1997       return /* G_TOKEN_SYMBOL */ GTK_RC_TOKEN_APPLICATION;
1998     }
1999   
2000   g_scanner_set_scope (scanner, old_scope);
2001
2002   return G_TOKEN_NONE;
2003 }
2004
2005 guint
2006 gtk_rc_parse_color (GScanner *scanner,
2007                     GdkColor *color)
2008 {
2009   guint token;
2010
2011   g_return_val_if_fail (scanner != NULL, G_TOKEN_ERROR);
2012
2013   /* we don't need to set our own scop here, because
2014    * we don't need own symbols
2015    */
2016   
2017   token = g_scanner_get_next_token (scanner);
2018   switch (token)
2019     {
2020       gint token_int;
2021       gint length;
2022       gint temp;
2023       gchar buf[9];
2024       gint i, j;
2025       
2026     case G_TOKEN_LEFT_CURLY:
2027       token = g_scanner_get_next_token (scanner);
2028       if (token == G_TOKEN_INT)
2029         token_int = scanner->value.v_int;
2030       else if (token == G_TOKEN_FLOAT)
2031         token_int = scanner->value.v_float * 65535.0;
2032       else
2033         return G_TOKEN_FLOAT;
2034       color->red = CLAMP (token_int, 0, 65535);
2035       
2036       token = g_scanner_get_next_token (scanner);
2037       if (token != G_TOKEN_COMMA)
2038         return G_TOKEN_COMMA;
2039       
2040       token = g_scanner_get_next_token (scanner);
2041       if (token == G_TOKEN_INT)
2042         token_int = scanner->value.v_int;
2043       else if (token == G_TOKEN_FLOAT)
2044         token_int = scanner->value.v_float * 65535.0;
2045       else
2046         return G_TOKEN_FLOAT;
2047       color->green = CLAMP (token_int, 0, 65535);
2048       
2049       token = g_scanner_get_next_token (scanner);
2050       if (token != G_TOKEN_COMMA)
2051         return G_TOKEN_COMMA;
2052       
2053       token = g_scanner_get_next_token (scanner);
2054       if (token == G_TOKEN_INT)
2055         token_int = scanner->value.v_int;
2056       else if (token == G_TOKEN_FLOAT)
2057         token_int = scanner->value.v_float * 65535.0;
2058       else
2059         return G_TOKEN_FLOAT;
2060       color->blue = CLAMP (token_int, 0, 65535);
2061       
2062       token = g_scanner_get_next_token (scanner);
2063       if (token != G_TOKEN_RIGHT_CURLY)
2064         return G_TOKEN_RIGHT_CURLY;
2065       return G_TOKEN_NONE;
2066       
2067     case G_TOKEN_STRING:
2068       if (scanner->value.v_string[0] != '#')
2069         return G_TOKEN_STRING;
2070       
2071       length = strlen (scanner->value.v_string) - 1;
2072       if (((length % 3) != 0) || (length > 12))
2073         return G_TOKEN_STRING;
2074       length /= 3;
2075       
2076       for (i = 0, j = 1; i < length; i++, j++)
2077         buf[i] = scanner->value.v_string[j];
2078       buf[i] = '\0';
2079       
2080       sscanf (buf, "%x", &temp);
2081       color->red = temp;
2082       
2083       for (i = 0; i < length; i++, j++)
2084         buf[i] = scanner->value.v_string[j];
2085       buf[i] = '\0';
2086       
2087       sscanf (buf, "%x", &temp);
2088       color->green = temp;
2089       
2090       for (i = 0; i < length; i++, j++)
2091         buf[i] = scanner->value.v_string[j];
2092       buf[i] = '\0';
2093       
2094       sscanf (buf, "%x", &temp);
2095       color->blue = temp;
2096       
2097       if (length == 1)
2098         {
2099           color->red *= 4369;
2100           color->green *= 4369;
2101           color->blue *= 4369;
2102         }
2103       else if (length == 2)
2104         {
2105           color->red *= 257;
2106           color->green *= 257;
2107           color->blue *= 257;
2108         }
2109       else if (length == 3)
2110         {
2111           color->red *= 16;
2112           color->green *= 16;
2113           color->blue *= 16;
2114         }
2115       return G_TOKEN_NONE;
2116       
2117     default:
2118       return G_TOKEN_STRING;
2119     }
2120 }
2121
2122 static guint
2123 gtk_rc_parse_pixmap_path (GScanner *scanner)
2124 {
2125   guint token;
2126   
2127   token = g_scanner_get_next_token (scanner);
2128   if (token != GTK_RC_TOKEN_PIXMAP_PATH)
2129     return GTK_RC_TOKEN_PIXMAP_PATH;
2130   
2131   token = g_scanner_get_next_token (scanner);
2132   if (token != G_TOKEN_STRING)
2133     return G_TOKEN_STRING;
2134   
2135   gtk_rc_parse_pixmap_path_string (scanner->value.v_string);
2136   
2137   return G_TOKEN_NONE;
2138 }
2139
2140 static void
2141 gtk_rc_parse_pixmap_path_string (gchar *pix_path)
2142 {
2143   gchar *buf;
2144   gint end_offset;
2145   gint start_offset = 0;
2146   gint path_len;
2147   gint path_num;
2148   
2149   /* free the old one, or just add to the old one ? */
2150   for (path_num=0; pixmap_path[path_num]; path_num++)
2151     {
2152       g_free (pixmap_path[path_num]);
2153       pixmap_path[path_num] = NULL;
2154     }
2155   
2156   path_num = 0;
2157   
2158   path_len = strlen (pix_path);
2159   
2160   buf = g_strdup (pix_path);
2161   
2162   for (end_offset = 0; end_offset <= path_len; end_offset++)
2163     {
2164       if ((buf[end_offset] == G_SEARCHPATH_SEPARATOR) ||
2165           (end_offset == path_len))
2166         {
2167           buf[end_offset] = '\0';
2168           pixmap_path[path_num] = g_strdup (buf + start_offset);
2169           path_num++;
2170           pixmap_path[path_num] = NULL;
2171           start_offset = end_offset + 1;
2172         }
2173     }
2174   g_free (buf);
2175   gtk_rc_append_default_pixmap_path();
2176 }
2177
2178 static guint
2179 gtk_rc_parse_module_path (GScanner *scanner)
2180 {
2181   guint token;
2182   
2183   token = g_scanner_get_next_token (scanner);
2184   if (token != GTK_RC_TOKEN_MODULE_PATH)
2185     return GTK_RC_TOKEN_MODULE_PATH;
2186   
2187   token = g_scanner_get_next_token (scanner);
2188   if (token != G_TOKEN_STRING)
2189     return G_TOKEN_STRING;
2190   
2191   gtk_rc_parse_module_path_string (scanner->value.v_string);
2192   
2193   return G_TOKEN_NONE;
2194 }
2195
2196 static void
2197 gtk_rc_parse_module_path_string (gchar *mod_path)
2198 {
2199   gchar *buf;
2200   gint end_offset;
2201   gint start_offset = 0;
2202   gint path_len;
2203   gint path_num;
2204   
2205   /* free the old one, or just add to the old one ? */
2206   for (path_num=0; module_path[path_num]; path_num++)
2207     {
2208       g_free (module_path[path_num]);
2209       module_path[path_num] = NULL;
2210     }
2211   
2212   path_num = 0;
2213   
2214   path_len = strlen (mod_path);
2215   
2216   buf = g_strdup (mod_path);
2217   
2218   for (end_offset = 0; end_offset <= path_len; end_offset++)
2219     {
2220       if ((buf[end_offset] == G_SEARCHPATH_SEPARATOR) ||
2221           (end_offset == path_len))
2222         {
2223           buf[end_offset] = '\0';
2224           module_path[path_num] = g_strdup (buf + start_offset);
2225           path_num++;
2226           module_path[path_num] = NULL;
2227           start_offset = end_offset + 1;
2228         }
2229     }
2230   g_free (buf);
2231   gtk_rc_append_default_module_path();
2232 }
2233
2234 static guint
2235 gtk_rc_parse_path_pattern (GScanner   *scanner)
2236 {
2237   guint token;
2238   GtkPathType path_type;
2239   gchar *pattern;
2240   gboolean is_binding;
2241   GtkPathPriorityType priority = GTK_PATH_PRIO_RC;
2242   
2243   token = g_scanner_get_next_token (scanner);
2244   switch (token)
2245     {
2246     case GTK_RC_TOKEN_WIDGET:
2247       path_type = GTK_PATH_WIDGET;
2248       break;
2249     case GTK_RC_TOKEN_WIDGET_CLASS:
2250       path_type = GTK_PATH_WIDGET_CLASS;
2251       break;
2252     case GTK_RC_TOKEN_CLASS:
2253       path_type = GTK_PATH_CLASS;
2254       break;
2255     default:
2256       return GTK_RC_TOKEN_WIDGET_CLASS;
2257     }
2258   
2259   token = g_scanner_get_next_token (scanner);
2260   if (token != G_TOKEN_STRING)
2261     return G_TOKEN_STRING;
2262
2263   pattern = g_strdup (scanner->value.v_string);
2264
2265   token = g_scanner_get_next_token (scanner);
2266   if (token == GTK_RC_TOKEN_STYLE)
2267     is_binding = FALSE;
2268   else if (token == GTK_RC_TOKEN_BINDING)
2269     {
2270       is_binding = TRUE;
2271       if (g_scanner_peek_next_token (scanner) == ':')
2272         {
2273           token = gtk_rc_parse_priority (scanner, &priority);
2274           if (token != G_TOKEN_NONE)
2275             {
2276               g_free (pattern);
2277               return token;
2278             }
2279         }
2280     }
2281   else
2282     {
2283       g_free (pattern);
2284       return GTK_RC_TOKEN_STYLE;
2285     }
2286   
2287   token = g_scanner_get_next_token (scanner);
2288   if (token != G_TOKEN_STRING)
2289     {
2290       g_free (pattern);
2291       return G_TOKEN_STRING;
2292     }
2293
2294   if (is_binding)
2295     {
2296       GtkBindingSet *binding;
2297
2298       binding = gtk_binding_set_find (scanner->value.v_string);
2299       if (!binding)
2300         {
2301           g_free (pattern);
2302           return G_TOKEN_STRING;
2303         }
2304       gtk_binding_set_add_path (binding, path_type, pattern, priority);
2305     }
2306   else
2307     {
2308       GtkRcStyle *rc_style;
2309       GtkRcSet *rc_set;
2310
2311       rc_style = gtk_rc_style_find (scanner->value.v_string);
2312       
2313       if (!rc_style)
2314         {
2315           g_free (pattern);
2316           return G_TOKEN_STRING;
2317         }
2318
2319       rc_set = g_new (GtkRcSet, 1);
2320       gtk_pattern_spec_init (&rc_set->pspec, pattern);
2321       rc_set->rc_style = rc_style;
2322
2323       if (path_type == GTK_PATH_WIDGET)
2324         gtk_rc_sets_widget = g_slist_prepend (gtk_rc_sets_widget, rc_set);
2325       else if (path_type == GTK_PATH_WIDGET_CLASS)
2326         gtk_rc_sets_widget_class = g_slist_prepend (gtk_rc_sets_widget_class, rc_set);
2327       else
2328         gtk_rc_sets_class = g_slist_prepend (gtk_rc_sets_class, rc_set);
2329     }
2330
2331   g_free (pattern);
2332   return G_TOKEN_NONE;
2333 }
2334
2335 /*
2336 typedef  GdkPixmap * (*GtkImageLoader) (GdkWindow   *window,
2337                                         GdkColormap *colormap,
2338                                         GdkBitmap  **mask,
2339                                         GdkColor    *transparent_color,
2340                                         const gchar *filename);
2341 */
2342
2343 void
2344 gtk_rc_set_image_loader(GtkImageLoader loader)
2345 {
2346   image_loader = loader;
2347 }
2348
2349 GdkPixmap *
2350 gtk_rc_load_image (GdkColormap *colormap,
2351                    GdkColor    *transparent_color,
2352                    const gchar *filename)
2353 {
2354   if (strcmp (filename, "<parent>") == 0)
2355     return (GdkPixmap*) GDK_PARENT_RELATIVE;
2356   else
2357     {
2358       if(image_loader)
2359         return image_loader(NULL, colormap, NULL,
2360                             transparent_color,
2361                             filename);
2362       else
2363         return gdk_pixmap_colormap_create_from_xpm (NULL, colormap, NULL,
2364                                                     transparent_color,
2365                                                     filename);
2366     }
2367 }