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