]> Pileus Git - ~andy/gtk/blob - gtk/gtkrc.c
use g_get_current_dir() instead of getcwd().
[~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 <ctype.h>
20 #include <unistd.h>
21 #include <sys/stat.h>
22 #include <sys/param.h>
23 #include <fcntl.h>
24 #include <string.h>
25 #include <stdio.h>
26 #include "gtkrc.h"
27 #include "gtkbindings.h"
28
29
30 typedef struct _GtkRcStyle  GtkRcStyle;
31 typedef struct _GtkRcSet    GtkRcSet;
32 typedef struct _GtkRcNode   GtkRcNode;
33 typedef struct _GtkRcFile   GtkRcFile;
34
35 struct _GtkRcNode
36 {
37   GdkColormap *cmap;
38   GtkStyle *style;
39 };
40
41 struct _GtkRcStyle
42 {
43   char *name;
44   char *font_name;
45   char *fontset_name;
46   char *bg_pixmap_name[5];
47   GtkStyle *proto_style;
48   GList *styles;
49 };
50
51 struct _GtkRcSet
52 {
53   GtkPatternSpec pspec;
54   GtkRcStyle    *rc_style;
55 };
56
57 struct _GtkRcFile
58 {
59   time_t mtime;
60   gchar *name;
61   gchar *canonical_name;
62   gboolean reload;
63 };
64
65 static guint       gtk_rc_style_hash               (const char   *name);
66 static gint        gtk_rc_style_compare            (const char   *a,
67                                                     const char   *b);
68 static GtkRcStyle* gtk_rc_style_find               (const char   *name);
69 static GtkRcStyle* gtk_rc_styles_match             (GSList       *sets,
70                                                     guint         path_length,
71                                                     gchar        *path,
72                                                     gchar        *path_reversed);
73 static GtkStyle*   gtk_rc_style_init               (GtkRcStyle   *rc_style,
74                                                     GdkColormap  *cmap);
75 static void        gtk_rc_parse_file               (const gchar  *filename,
76                                                     gboolean      reload);
77
78 static void        gtk_rc_parse_any                (const gchar  *input_name,
79                                                     gint          input_fd,
80                                                     const gchar  *input_string);
81 static guint       gtk_rc_parse_statement          (GScanner     *scanner);
82 static guint       gtk_rc_parse_style              (GScanner     *scanner);
83 static guint       gtk_rc_parse_base               (GScanner     *scanner,
84                                                     GtkStyle     *style);
85 static guint       gtk_rc_parse_bg                 (GScanner     *scanner,
86                                                     GtkStyle     *style);
87 static guint       gtk_rc_parse_fg                 (GScanner     *scanner,
88                                                     GtkStyle     *style);
89 static guint       gtk_rc_parse_text               (GScanner     *scanner,
90                                                     GtkStyle     *style);
91 static guint       gtk_rc_parse_bg_pixmap          (GScanner     *scanner,
92                                                     GtkRcStyle   *rc_style);
93 static guint       gtk_rc_parse_font               (GScanner     *scanner,
94                                                     GtkRcStyle   *rc_style);
95 static guint       gtk_rc_parse_fontset            (GScanner     *scanner,
96                                                     GtkRcStyle   *rc_style);
97 static guint       gtk_rc_parse_pixmap_path        (GScanner     *scanner);
98 static void        gtk_rc_parse_pixmap_path_string (gchar *pix_path);
99 static char*       gtk_rc_find_pixmap_in_path      (GScanner     *scanner,
100                                                     gchar *pixmap_file);
101 static guint       gtk_rc_parse_path_pattern       (GScanner     *scanner);
102 static void        gtk_rc_clear_hash_node          (gpointer   key, 
103                                                     gpointer   data, 
104                                                     gpointer   user_data);
105 static void        gtk_rc_clear_styles             (void);
106
107
108
109 static  GScannerConfig  gtk_rc_scanner_config =
110 {
111   (
112    " \t\n"
113    )                    /* cset_skip_characters */,
114   (
115    G_CSET_a_2_z
116    "_"
117    G_CSET_A_2_Z
118    )                    /* cset_identifier_first */,
119   (
120    G_CSET_a_2_z
121    "_-0123456789"
122    G_CSET_A_2_Z
123    )                    /* cset_identifier_nth */,
124   ( "#\n" )             /* cpair_comment_single */,
125   
126   TRUE                  /* case_sensitive */,
127   
128   TRUE                  /* skip_comment_multi */,
129   TRUE                  /* skip_comment_single */,
130   TRUE                  /* scan_comment_multi */,
131   TRUE                  /* scan_identifier */,
132   FALSE                 /* scan_identifier_1char */,
133   FALSE                 /* scan_identifier_NULL */,
134   TRUE                  /* scan_symbols */,
135   TRUE                  /* scan_binary */,
136   TRUE                  /* scan_octal */,
137   TRUE                  /* scan_float */,
138   TRUE                  /* scan_hex */,
139   TRUE                  /* scan_hex_dollar */,
140   TRUE                  /* scan_string_sq */,
141   TRUE                  /* scan_string_dq */,
142   TRUE                  /* numbers_2_int */,
143   FALSE                 /* int_2_float */,
144   FALSE                 /* identifier_2_string */,
145   TRUE                  /* char_2_token */,
146   TRUE                  /* symbol_2_token */,
147   FALSE                 /* scope_0_fallback */,
148 };
149
150 static struct
151 {
152   gchar *name;
153   guint token;
154 } symbols[] = {
155   { "include", GTK_RC_TOKEN_INCLUDE },
156   { "NORMAL", GTK_RC_TOKEN_NORMAL },
157   { "ACTIVE", GTK_RC_TOKEN_ACTIVE },
158   { "PRELIGHT", GTK_RC_TOKEN_PRELIGHT },
159   { "SELECTED", GTK_RC_TOKEN_SELECTED },
160   { "INSENSITIVE", GTK_RC_TOKEN_INSENSITIVE },
161   { "fg", GTK_RC_TOKEN_FG },
162   { "bg", GTK_RC_TOKEN_BG },
163   { "base", GTK_RC_TOKEN_BASE },
164   { "text", GTK_RC_TOKEN_TEXT },
165   { "font", GTK_RC_TOKEN_FONT },
166   { "fontset", GTK_RC_TOKEN_FONTSET },
167   { "bg_pixmap", GTK_RC_TOKEN_BG_PIXMAP },
168   { "pixmap_path", GTK_RC_TOKEN_PIXMAP_PATH },
169   { "style", GTK_RC_TOKEN_STYLE },
170   { "binding", GTK_RC_TOKEN_BINDING },
171   { "bind", GTK_RC_TOKEN_BIND },
172   { "widget", GTK_RC_TOKEN_WIDGET },
173   { "widget_class", GTK_RC_TOKEN_WIDGET_CLASS },
174   { "class", GTK_RC_TOKEN_CLASS },
175   { "lowest", GTK_RC_TOKEN_LOWEST },
176   { "gtk", GTK_RC_TOKEN_GTK },
177   { "application", GTK_RC_TOKEN_APPLICATION },
178   { "rc", GTK_RC_TOKEN_RC },
179   { "highest", GTK_RC_TOKEN_HIGHEST },
180 };
181
182 static guint n_symbols = sizeof (symbols) / sizeof (symbols[0]);
183
184 static GHashTable *rc_style_ht = NULL;
185 static GSList *gtk_rc_sets_widget = NULL;
186 static GSList *gtk_rc_sets_widget_class = NULL;
187 static GSList *gtk_rc_sets_class = NULL;
188
189 #define GTK_RC_MAX_PIXMAP_PATHS 128
190 static gchar *pixmap_path[GTK_RC_MAX_PIXMAP_PATHS];
191
192 /* The files we have parsed, to reread later if necessary */
193 GSList *rc_files = NULL;
194
195 static GtkImageLoader image_loader = NULL;
196
197 void
198 gtk_rc_init (void)
199 {
200   rc_style_ht = g_hash_table_new ((GHashFunc) gtk_rc_style_hash,
201                                   (GCompareFunc) gtk_rc_style_compare);
202 }
203
204 void
205 gtk_rc_parse_string (const gchar *rc_string)
206 {
207   g_return_if_fail (rc_string != NULL);
208
209   gtk_rc_parse_any ("-", -1, rc_string);
210 }
211
212 static void
213 gtk_rc_parse_file (const gchar *filename, gboolean reload)
214 {
215   GtkRcFile *rc_file = NULL;
216   struct stat statbuf;
217   GSList *tmp_list;
218
219   g_return_if_fail (filename != NULL);
220
221   tmp_list = rc_files;
222   while (tmp_list)
223     {
224       rc_file = tmp_list->data;
225       if (!strcmp (rc_file->name, filename))
226         break;
227       
228       tmp_list = tmp_list->next;
229     }
230
231   if (!tmp_list)
232     {
233       rc_file = g_new (GtkRcFile, 1);
234       rc_file->name = g_strdup (filename);
235       rc_file->canonical_name = NULL;
236       rc_file->mtime = 0;
237       rc_file->reload = reload;
238
239       rc_files = g_slist_append (rc_files, rc_file);
240     }
241
242   if (!rc_file->canonical_name)
243     {
244       /* Get the absolute pathname */
245
246       if (rc_file->name[0] == '/')
247         rc_file->canonical_name = rc_file->name;
248       else
249         {
250           GString *str;
251           gchar *cwd;
252
253           cwd = g_get_current_dir ();
254
255           str = g_string_new (cwd);
256           g_free (cwd);
257           g_string_append_c (str, '/');
258           g_string_append (str, rc_file->name);
259           
260           rc_file->canonical_name = str->str;
261           g_string_free (str, FALSE);
262         }
263     }
264
265   if (!lstat (rc_file->canonical_name, &statbuf))
266     {
267       gint fd;
268
269       rc_file->mtime = statbuf.st_mtime;
270
271       fd = open (rc_file->canonical_name, O_RDONLY);
272       if (fd < 0)
273         return;
274
275       gtk_rc_parse_any (filename, fd, NULL);
276
277       close (fd);
278     }
279 }
280
281 void
282 gtk_rc_parse (const gchar *filename)
283 {
284   g_return_if_fail (filename != NULL);
285
286   gtk_rc_parse_file (filename, TRUE);
287 }
288
289 static void
290 gtk_rc_clear_hash_node (gpointer key, 
291                         gpointer data, 
292                         gpointer user_data)
293 {
294   int i;
295   GtkRcStyle *rc_style = data;
296   GList *tmp_list;
297
298   g_free (rc_style->name);
299   g_free (rc_style->font_name);
300   g_free (rc_style->fontset_name);
301
302   for (i=0 ; i<5 ; i++)
303     g_free (rc_style->bg_pixmap_name[i]);
304
305   gtk_style_unref (rc_style->proto_style);
306
307   tmp_list = rc_style->styles;
308   while (tmp_list)
309     {
310       GtkRcNode *node = tmp_list->data;
311
312       gdk_colormap_unref (node->cmap);
313       gtk_style_unref (node->style);
314
315       g_free (node);
316       tmp_list = tmp_list->next;
317     }
318
319   g_free (rc_style);
320 }
321
322 static void
323 gtk_rc_free_rc_sets (GSList *slist)
324 {
325   while (slist)
326     {
327       GtkRcSet *rc_set;
328
329       rc_set = slist->data;
330       gtk_pattern_spec_free_segs (&rc_set->pspec);
331       g_free (rc_set);
332
333       slist = slist->next;
334     }
335 }
336
337 static void
338 gtk_rc_clear_styles (void)
339 {
340   /* Clear out all old rc_styles */
341
342   g_hash_table_foreach (rc_style_ht, gtk_rc_clear_hash_node, NULL);
343   g_hash_table_destroy (rc_style_ht);
344   rc_style_ht = NULL;
345
346   gtk_rc_free_rc_sets (gtk_rc_sets_widget);
347   g_slist_free (gtk_rc_sets_widget);
348   gtk_rc_sets_widget = NULL;
349
350   gtk_rc_free_rc_sets (gtk_rc_sets_widget_class);
351   g_slist_free (gtk_rc_sets_widget_class);
352   gtk_rc_sets_widget_class = NULL;
353
354   gtk_rc_free_rc_sets (gtk_rc_sets_class);
355   g_slist_free (gtk_rc_sets_class);
356   gtk_rc_sets_class = NULL;
357
358   gtk_rc_init ();
359 }
360
361 gboolean
362 gtk_rc_reparse_all (void)
363 {
364   GSList *tmp_list;
365   gboolean mtime_modified = FALSE;
366   GtkRcFile *rc_file;
367
368   struct stat statbuf;
369
370   /* Check through and see if any of the RC's have had their
371    * mtime modified. If so, reparse everything.
372    */
373   tmp_list = rc_files;
374   while (tmp_list)
375     {
376       rc_file = tmp_list->data;
377       
378       if (!lstat (rc_file->name, &statbuf) && 
379           (statbuf.st_mtime > rc_file->mtime))
380         {
381           mtime_modified = TRUE;
382           break;
383         }
384       
385       tmp_list = tmp_list->next;
386     }
387
388   if (mtime_modified)
389     {
390       gtk_rc_clear_styles();
391
392       tmp_list = rc_files;
393       while (tmp_list)
394         {
395           rc_file = tmp_list->data;
396           if (rc_file->reload)
397             gtk_rc_parse_file (rc_file->name, FALSE);
398           
399           tmp_list = tmp_list->next;
400         }
401     }
402
403   return mtime_modified;
404 }
405
406 static GtkRcStyle*
407 gtk_rc_styles_match (GSList       *sets,
408                      guint         path_length,
409                      gchar        *path,
410                      gchar        *path_reversed)
411 {
412   GtkRcSet *rc_set;
413
414   while (sets)
415     {
416       rc_set = sets->data;
417       sets = sets->next;
418
419       if (gtk_pattern_match (&rc_set->pspec, path_length, path, path_reversed))
420         return rc_set->rc_style;
421     }
422   
423   return NULL;
424 }
425
426 GtkStyle*
427 gtk_rc_get_style (GtkWidget *widget)
428 {
429   GtkRcStyle *rc_style;
430   
431   if (gtk_rc_sets_widget)
432     {
433       gchar *path, *path_reversed;
434       guint path_length;
435
436       gtk_widget_path (widget, &path_length, &path, &path_reversed);
437       rc_style = gtk_rc_styles_match (gtk_rc_sets_widget, path_length, path, path_reversed);
438       g_free (path);
439       g_free (path_reversed);
440       
441       if (rc_style)
442         return gtk_rc_style_init (rc_style, gtk_widget_get_colormap (widget));
443     }
444   
445   if (gtk_rc_sets_widget_class)
446     {
447       gchar *path, *path_reversed;
448       guint path_length;
449
450       gtk_widget_class_path (widget, &path_length, &path, &path_reversed);
451       rc_style = gtk_rc_styles_match (gtk_rc_sets_widget_class, path_length, path, path_reversed);
452       g_free (path);
453       g_free (path_reversed);
454       
455       if (rc_style)
456         return gtk_rc_style_init (rc_style, gtk_widget_get_colormap (widget));
457     }
458
459   if (gtk_rc_sets_class)
460     {
461       GtkType type;
462
463       type = GTK_OBJECT_TYPE (widget);
464       while (type)
465         {
466           gchar *path, *path_reversed;
467           guint path_length;
468
469           path = gtk_type_name (type);
470           path_length = strlen (path);
471           path_reversed = g_strdup (path);
472           g_strreverse (path_reversed);
473           
474           rc_style = gtk_rc_styles_match (gtk_rc_sets_class, path_length, path, path_reversed);
475           g_free (path_reversed);
476       
477           if (rc_style)
478             return gtk_rc_style_init (rc_style, gtk_widget_get_colormap (widget));
479
480           type = gtk_type_parent (type);
481         }
482     }
483   
484   return NULL;
485 }
486
487 static GSList*
488 gtk_rc_add_rc_sets (GSList     *slist,
489                     GtkStyle   *style,
490                     const char *pattern)
491 {
492   GtkRcStyle *rc_style;
493   GtkRcSet *rc_set;
494   guint i;
495   
496   gtk_style_ref (style);
497   
498   rc_style = g_new (GtkRcStyle, 1);
499   rc_style->name = NULL;
500   rc_style->font_name = NULL;
501   rc_style->fontset_name = NULL;
502   
503   for (i = 0; i < 5; i++)
504     rc_style->bg_pixmap_name[i] = NULL;
505   
506   rc_style->styles = g_list_append (NULL, style);
507
508   rc_set = g_new (GtkRcSet, 1);
509   gtk_pattern_spec_init (&rc_set->pspec, pattern);
510   rc_set->rc_style = rc_style;
511   
512   return g_slist_prepend (slist, rc_set);
513 }
514
515 void
516 gtk_rc_add_widget_name_style (GtkStyle    *style,
517                               const gchar *pattern)
518 {
519   g_return_if_fail (style != NULL);
520   g_return_if_fail (pattern != NULL);
521
522   gtk_rc_sets_widget = gtk_rc_add_rc_sets (gtk_rc_sets_widget, style, pattern);
523 }
524
525 void
526 gtk_rc_add_widget_class_style (GtkStyle    *style,
527                                const gchar *pattern)
528 {
529   g_return_if_fail (style != NULL);
530   g_return_if_fail (pattern != NULL);
531
532   gtk_rc_sets_widget_class = gtk_rc_add_rc_sets (gtk_rc_sets_widget_class, style, pattern);
533 }
534
535 void
536 gtk_rc_add_class_style (GtkStyle    *style,
537                         const gchar *pattern)
538 {
539   g_return_if_fail (style != NULL);
540   g_return_if_fail (pattern != NULL);
541
542   gtk_rc_sets_class = gtk_rc_add_rc_sets (gtk_rc_sets_class, style, pattern);
543 }
544
545 static void
546 gtk_rc_parse_any (const gchar  *input_name,
547                   gint          input_fd,
548                   const gchar  *input_string)
549 {
550   GScanner *scanner;
551   guint    i;
552   gboolean done;
553   
554   scanner = g_scanner_new (&gtk_rc_scanner_config);
555   
556   if (input_fd >= 0)
557     {
558       g_assert (input_string == NULL);
559       
560       g_scanner_input_file (scanner, input_fd);
561     }
562   else
563     {
564       g_assert (input_string != NULL);
565       
566       g_scanner_input_text (scanner, input_string, strlen (input_string));
567     }
568   scanner->input_name = input_name;
569
570   g_scanner_freeze_symbol_table (scanner);
571   for (i = 0; i < n_symbols; i++)
572     g_scanner_add_symbol (scanner, symbols[i].name, GINT_TO_POINTER (symbols[i].token));
573   g_scanner_thaw_symbol_table (scanner);
574   
575   done = FALSE;
576   while (!done)
577     {
578       if (g_scanner_peek_next_token (scanner) == G_TOKEN_EOF)
579         done = TRUE;
580       else
581         {
582           guint expected_token;
583           
584           expected_token = gtk_rc_parse_statement (scanner);
585
586           if (expected_token != G_TOKEN_NONE)
587             {
588               gchar *symbol_name;
589               gchar *msg;
590               
591               msg = NULL;
592               symbol_name = NULL;
593               if (scanner->scope_id == 0)
594                 {
595                   /* if we are in scope 0, we know the symbol names
596                    * that are associated with certaintoken values.
597                    * so we look them up to make the error messages
598                    * more readable.
599                    */
600                   if (expected_token > GTK_RC_TOKEN_INVALID &&
601                       expected_token < GTK_RC_TOKEN_LAST)
602                     {
603                       for (i = 0; i < n_symbols; i++)
604                         if (symbols[i].token == expected_token)
605                           msg = symbols[i].name;
606                       if (msg)
607                         msg = g_strconcat ("e.g. `", msg, "'", NULL);
608                     }
609                   if (scanner->token > GTK_RC_TOKEN_INVALID &&
610                       scanner->token < GTK_RC_TOKEN_LAST)
611                     {
612                       symbol_name = "???";
613                       for (i = 0; i < n_symbols; i++)
614                         if (symbols[i].token == scanner->token)
615                           symbol_name = symbols[i].name;
616                     }
617                 }
618               g_scanner_unexp_token (scanner,
619                                      expected_token,
620                                      NULL,
621                                      "keyword",
622                                      symbol_name,
623                                      msg,
624                                      TRUE);
625               g_free (msg);
626               done = TRUE;
627             }
628         }
629     }
630   
631   g_scanner_destroy (scanner);
632 }
633
634 static guint
635 gtk_rc_style_hash (const char *name)
636 {
637   guint result;
638   
639   result = 0;
640   while (*name)
641     result += (result << 3) + *name++;
642   
643   return result;
644 }
645
646 static gint
647 gtk_rc_style_compare (const char *a,
648                       const char *b)
649 {
650   return (strcmp (a, b) == 0);
651 }
652
653 static GtkRcStyle*
654 gtk_rc_style_find (const char *name)
655 {
656   GtkRcStyle *rc_style;
657   
658   rc_style = g_hash_table_lookup (rc_style_ht, (gpointer) name);
659   
660   return rc_style;
661 }
662
663 static GtkStyle *
664 gtk_rc_style_init (GtkRcStyle *rc_style, GdkColormap *cmap)
665 {
666   GdkFont *old_font;
667   gboolean match_cmap = FALSE;
668   gint i;
669
670   GList *tmp_list;
671   GtkStyle *style = NULL;
672   GtkRcNode *node;
673
674   tmp_list = rc_style->styles;
675
676   for (i=0; i<5; i++)
677     if (rc_style->bg_pixmap_name[i])
678       match_cmap = TRUE;
679       
680   while (tmp_list)
681     {
682       node = (GtkRcNode *)tmp_list->data;
683
684       if (!match_cmap || (node->cmap == cmap))
685         {
686           style = node->style;
687           break;
688         }
689
690       tmp_list = tmp_list->next;
691     }
692   
693   if (!style)
694     {
695       node = g_new (GtkRcNode, 1);
696       style = gtk_style_copy (rc_style->proto_style);
697
698      /* FIXME, this leaks colormaps, but if we don't do this, then we'll
699        * be screwed, because we identify colormaps by address equality
700        */
701       gdk_colormap_ref (cmap);
702  
703       node->style = style;
704       node->cmap = cmap;
705       
706       if (rc_style->fontset_name)
707         {
708           old_font = style->font;
709           style->font = gdk_fontset_load (rc_style->fontset_name);
710           if (style->font)
711             gdk_font_unref (old_font);
712           else
713             style->font = old_font;
714         }
715       else if (rc_style->font_name)
716         {
717           old_font = style->font;
718           style->font = gdk_font_load (rc_style->font_name);
719           if (style->font)
720             gdk_font_unref (old_font);
721           else
722             style->font = old_font;
723         }
724       
725       for (i = 0; i < 5; i++)
726         if (rc_style->bg_pixmap_name[i])
727           {
728             if (strcmp (rc_style->bg_pixmap_name[i], "<parent>") == 0)
729               style->bg_pixmap[i] = (GdkPixmap*) GDK_PARENT_RELATIVE;
730             else
731               {
732                 if(image_loader)
733                   style->bg_pixmap[i] = image_loader(NULL, cmap, NULL,
734                                                      &style->bg[i],
735                                                      rc_style->bg_pixmap_name[i]);
736                 else
737                   style->bg_pixmap[i] = 
738                     gdk_pixmap_colormap_create_from_xpm (NULL, cmap,
739                                                          NULL,
740                                                          &style->bg[i],
741                                                          rc_style->bg_pixmap_name[i]);
742               }
743           }
744
745       rc_style->styles = g_list_append (rc_style->styles, node);
746     }
747
748   return style;
749 }
750
751 static guint
752 gtk_rc_parse_statement (GScanner *scanner)
753 {
754   guint token;
755   
756   token = g_scanner_peek_next_token (scanner);
757
758   switch (token)
759     {
760     case GTK_RC_TOKEN_INCLUDE:
761       token = g_scanner_get_next_token (scanner);
762       if (token != GTK_RC_TOKEN_INCLUDE)
763         return GTK_RC_TOKEN_INCLUDE;
764
765       token = g_scanner_get_next_token (scanner);
766       if (token != G_TOKEN_STRING)
767         return G_TOKEN_STRING;
768
769       gtk_rc_parse_file (scanner->value.v_string, FALSE);
770       return G_TOKEN_NONE;
771
772     case GTK_RC_TOKEN_STYLE:
773       return gtk_rc_parse_style (scanner);
774
775     case GTK_RC_TOKEN_BINDING:
776       return gtk_binding_parse_binding (scanner);
777
778     case GTK_RC_TOKEN_PIXMAP_PATH:
779       return gtk_rc_parse_pixmap_path (scanner);
780
781     case GTK_RC_TOKEN_WIDGET:
782       return gtk_rc_parse_path_pattern (scanner);
783
784     case GTK_RC_TOKEN_WIDGET_CLASS:
785       return gtk_rc_parse_path_pattern (scanner);
786
787     case GTK_RC_TOKEN_CLASS:
788       return gtk_rc_parse_path_pattern (scanner);
789
790     default:
791       g_scanner_get_next_token (scanner);
792       return /* G_TOKEN_SYMBOL */ GTK_RC_TOKEN_STYLE;
793     }
794 }
795
796 static guint
797 gtk_rc_parse_style (GScanner *scanner)
798 {
799   GtkRcStyle *rc_style;
800   GtkRcStyle *parent_style;
801   guint token;
802   gint insert;
803   gint i;
804   
805   token = g_scanner_get_next_token (scanner);
806   if (token != GTK_RC_TOKEN_STYLE)
807     return GTK_RC_TOKEN_STYLE;
808   
809   token = g_scanner_get_next_token (scanner);
810   if (token != G_TOKEN_STRING)
811     return G_TOKEN_STRING;
812   
813   insert = FALSE;
814   rc_style = g_hash_table_lookup (rc_style_ht, scanner->value.v_string);
815   
816   if (!rc_style)
817     {
818       insert = TRUE;
819       rc_style = g_new (GtkRcStyle, 1);
820       rc_style->name = g_strdup (scanner->value.v_string);
821       rc_style->font_name = NULL;
822       rc_style->fontset_name = NULL;
823       
824       for (i = 0; i < 5; i++)
825         rc_style->bg_pixmap_name[i] = NULL;
826
827       rc_style->proto_style = gtk_style_new();
828       rc_style->styles = NULL;
829     }
830   
831   token = g_scanner_peek_next_token (scanner);
832   if (token == G_TOKEN_EQUAL_SIGN)
833     {
834       token = g_scanner_get_next_token (scanner);
835       
836       token = g_scanner_get_next_token (scanner);
837       if (token != G_TOKEN_STRING)
838         {
839           if (insert)
840             {
841               gtk_style_unref (rc_style->proto_style);
842               g_free (rc_style);
843             }
844           return G_TOKEN_STRING;
845         }
846       
847       parent_style = g_hash_table_lookup (rc_style_ht, scanner->value.v_string);
848       if (parent_style)
849         {
850           for (i = 0; i < 5; i++)
851             {
852               rc_style->proto_style->fg[i] = parent_style->proto_style->fg[i];
853               rc_style->proto_style->bg[i] = parent_style->proto_style->bg[i];
854               rc_style->proto_style->light[i] = parent_style->proto_style->light[i];
855               rc_style->proto_style->dark[i] = parent_style->proto_style->dark[i];
856               rc_style->proto_style->mid[i] = parent_style->proto_style->mid[i];
857               rc_style->proto_style->text[i] = parent_style->proto_style->text[i];
858               rc_style->proto_style->base[i] = parent_style->proto_style->base[i];
859             }
860           
861           rc_style->proto_style->black = parent_style->proto_style->black;
862           rc_style->proto_style->white = parent_style->proto_style->white;
863           
864           if (rc_style->fontset_name)
865             {
866               g_free (rc_style->fontset_name);
867               rc_style->fontset_name = g_strdup (parent_style->fontset_name);
868             }
869           else if (rc_style->font_name)
870             {
871               g_free (rc_style->font_name);
872               rc_style->font_name = g_strdup (parent_style->font_name);
873             }
874           
875           for (i = 0; i < 5; i++)
876             {
877               if (rc_style->bg_pixmap_name[i])
878                 g_free (rc_style->bg_pixmap_name[i]);
879               rc_style->bg_pixmap_name[i] = g_strdup (parent_style->bg_pixmap_name[i]);
880             }
881         }
882     }
883   
884   token = g_scanner_get_next_token (scanner);
885   if (token != G_TOKEN_LEFT_CURLY)
886     {
887       if (insert)
888         {
889           gtk_style_unref (rc_style->proto_style);
890           g_free (rc_style);
891         }
892       return G_TOKEN_LEFT_CURLY;
893     }
894   
895   token = g_scanner_peek_next_token (scanner);
896   while (token != G_TOKEN_RIGHT_CURLY)
897     {
898       switch (token)
899         {
900         case GTK_RC_TOKEN_BASE:
901           token = gtk_rc_parse_base (scanner, rc_style->proto_style);
902           break;
903         case GTK_RC_TOKEN_BG:
904           token = gtk_rc_parse_bg (scanner, rc_style->proto_style);
905           break;
906         case GTK_RC_TOKEN_FG:
907           token = gtk_rc_parse_fg (scanner, rc_style->proto_style);
908           break;
909         case GTK_RC_TOKEN_TEXT:
910           token = gtk_rc_parse_text (scanner, rc_style->proto_style);
911           break;
912         case GTK_RC_TOKEN_BG_PIXMAP:
913           token = gtk_rc_parse_bg_pixmap (scanner, rc_style);
914           break;
915         case GTK_RC_TOKEN_FONT:
916           token = gtk_rc_parse_font (scanner, rc_style);
917           break;
918         case GTK_RC_TOKEN_FONTSET:
919           token = gtk_rc_parse_fontset (scanner, rc_style);
920           break;
921         default:
922           g_scanner_get_next_token (scanner);
923           token = G_TOKEN_RIGHT_CURLY;
924           break;
925         }
926
927       if (token != G_TOKEN_NONE)
928         {
929           if (insert)
930             {
931               if (rc_style->fontset_name)
932                 g_free (rc_style->fontset_name);
933               if (rc_style->font_name)
934                 g_free (rc_style->font_name);
935               for (i = 0; i < 5; i++)
936                 if (rc_style->bg_pixmap_name[i])
937                   g_free (rc_style->bg_pixmap_name[i]);
938               gtk_style_unref (rc_style->proto_style);
939               g_free (rc_style);
940             }
941           return token;
942         }
943       token = g_scanner_peek_next_token (scanner);
944     }
945   
946   token = g_scanner_get_next_token (scanner);
947   if (token != G_TOKEN_RIGHT_CURLY)
948     {
949       if (insert)
950         {
951           if (rc_style->fontset_name)
952             g_free (rc_style->fontset_name);
953           if (rc_style->font_name)
954             g_free (rc_style->font_name);
955           
956           for (i = 0; i < 5; i++)
957             if (rc_style->bg_pixmap_name[i])
958               g_free (rc_style->bg_pixmap_name[i]);
959           
960           gtk_style_unref (rc_style->proto_style);
961           g_free (rc_style);
962         }
963       return G_TOKEN_RIGHT_CURLY;
964     }
965   
966   if (insert)
967     g_hash_table_insert (rc_style_ht, rc_style->name, rc_style);
968   
969   return G_TOKEN_NONE;
970 }
971
972 static guint
973 gtk_rc_parse_base (GScanner *scanner,
974                    GtkStyle *style)
975 {
976   GtkStateType state;
977   guint token;
978   
979   token = g_scanner_get_next_token (scanner);
980   if (token != GTK_RC_TOKEN_BASE)
981     return GTK_RC_TOKEN_BASE;
982   
983   token = gtk_rc_parse_state (scanner, &state);
984   if (token != G_TOKEN_NONE)
985     return token;
986   
987   token = g_scanner_get_next_token (scanner);
988   if (token != G_TOKEN_EQUAL_SIGN)
989     return G_TOKEN_EQUAL_SIGN;
990   
991   return gtk_rc_parse_color (scanner, &style->base[state]);
992 }
993
994 static guint
995 gtk_rc_parse_bg (GScanner *scanner,
996                  GtkStyle *style)
997 {
998   GtkStateType state;
999   guint token;
1000   
1001   token = g_scanner_get_next_token (scanner);
1002   if (token != GTK_RC_TOKEN_BG)
1003     return GTK_RC_TOKEN_BG;
1004   
1005   token = gtk_rc_parse_state (scanner, &state);
1006   if (token != G_TOKEN_NONE)
1007     return token;
1008   
1009   token = g_scanner_get_next_token (scanner);
1010   if (token != G_TOKEN_EQUAL_SIGN)
1011     return G_TOKEN_EQUAL_SIGN;
1012   
1013   return gtk_rc_parse_color (scanner, &style->bg[state]);
1014 }
1015
1016 static guint
1017 gtk_rc_parse_fg (GScanner *scanner,
1018                  GtkStyle *style)
1019 {
1020   GtkStateType state;
1021   guint token;
1022   
1023   token = g_scanner_get_next_token (scanner);
1024   if (token != GTK_RC_TOKEN_FG)
1025     return GTK_RC_TOKEN_FG;
1026   
1027   token = gtk_rc_parse_state (scanner, &state);
1028   if (token != G_TOKEN_NONE)
1029     return token;
1030   
1031   token = g_scanner_get_next_token (scanner);
1032   if (token != G_TOKEN_EQUAL_SIGN)
1033     return G_TOKEN_EQUAL_SIGN;
1034   
1035   return gtk_rc_parse_color (scanner, &style->fg[state]);
1036 }
1037
1038 static guint
1039 gtk_rc_parse_text (GScanner *scanner,
1040                    GtkStyle *style)
1041 {
1042   GtkStateType state;
1043   guint token;
1044   
1045   token = g_scanner_get_next_token (scanner);
1046   if (token != GTK_RC_TOKEN_TEXT)
1047     return GTK_RC_TOKEN_TEXT;
1048   
1049   token = gtk_rc_parse_state (scanner, &state);
1050   if (token != G_TOKEN_NONE)
1051     return token;
1052   
1053   token = g_scanner_get_next_token (scanner);
1054   if (token != G_TOKEN_EQUAL_SIGN)
1055     return G_TOKEN_EQUAL_SIGN;
1056   
1057   return gtk_rc_parse_color (scanner, &style->text[state]);
1058 }
1059
1060 static guint
1061 gtk_rc_parse_bg_pixmap (GScanner   *scanner,
1062                         GtkRcStyle *rc_style)
1063 {
1064   GtkStateType state;
1065   guint token;
1066   gchar *pixmap_file;
1067   
1068   token = g_scanner_get_next_token (scanner);
1069   if (token != GTK_RC_TOKEN_BG_PIXMAP)
1070     return GTK_RC_TOKEN_BG_PIXMAP;
1071   
1072   token = gtk_rc_parse_state (scanner, &state);
1073   if (token != G_TOKEN_NONE)
1074     return token;
1075   
1076   token = g_scanner_get_next_token (scanner);
1077   if (token != G_TOKEN_EQUAL_SIGN)
1078     return G_TOKEN_EQUAL_SIGN;
1079   
1080   token = g_scanner_get_next_token (scanner);
1081   if (token != G_TOKEN_STRING)
1082     return G_TOKEN_STRING;
1083   
1084   if (strcmp (scanner->value.v_string, "<parent>"))
1085     pixmap_file = gtk_rc_find_pixmap_in_path (scanner, scanner->value.v_string);
1086   else
1087     pixmap_file = g_strdup (scanner->value.v_string);
1088   
1089   if (pixmap_file)
1090     {
1091       if (rc_style->bg_pixmap_name[state])
1092         g_free (rc_style->bg_pixmap_name[state]);
1093       rc_style->bg_pixmap_name[state] = pixmap_file;
1094     }
1095   
1096   return G_TOKEN_NONE;
1097 }
1098
1099 static gchar*
1100 gtk_rc_find_pixmap_in_path (GScanner *scanner,
1101                             gchar    *pixmap_file)
1102 {
1103   gint i;
1104   gint fd;
1105   gchar *buf;
1106   
1107   for (i = 0; (i < GTK_RC_MAX_PIXMAP_PATHS) && (pixmap_path[i] != NULL); i++)
1108     {
1109       buf = g_malloc (strlen (pixmap_path[i]) + strlen (pixmap_file) + 2);
1110       sprintf (buf, "%s%c%s", pixmap_path[i], '/', pixmap_file);
1111       
1112       fd = open (buf, O_RDONLY);
1113       if (fd >= 0)
1114         {
1115           close (fd);
1116           return buf;
1117         }
1118       
1119       g_free (buf);
1120     }
1121   
1122   g_warning ("Unable to locate image file in pixmap_path: \"%s\" line %d",
1123              pixmap_file, scanner->line);
1124   
1125   return NULL;
1126 }
1127
1128 static guint
1129 gtk_rc_parse_font (GScanner   *scanner,
1130                    GtkRcStyle *rc_style)
1131 {
1132   guint token;
1133   
1134   token = g_scanner_get_next_token (scanner);
1135   if (token != GTK_RC_TOKEN_FONT)
1136     return GTK_RC_TOKEN_FONT;
1137   
1138   token = g_scanner_get_next_token (scanner);
1139   if (token != G_TOKEN_EQUAL_SIGN)
1140     return G_TOKEN_EQUAL_SIGN;
1141   
1142   token = g_scanner_get_next_token (scanner);
1143   if (token != G_TOKEN_STRING)
1144     return G_TOKEN_STRING;
1145   
1146   if (rc_style->font_name)
1147     g_free (rc_style->font_name);
1148   rc_style->font_name = g_strdup (scanner->value.v_string);
1149   
1150   return G_TOKEN_NONE;
1151 }
1152
1153 static guint
1154 gtk_rc_parse_fontset (GScanner   *scanner,
1155                       GtkRcStyle *rc_style)
1156 {
1157   guint token;
1158   
1159   token = g_scanner_get_next_token (scanner);
1160   if (token != GTK_RC_TOKEN_FONTSET)
1161     return GTK_RC_TOKEN_FONTSET;
1162   
1163   token = g_scanner_get_next_token (scanner);
1164   if (token != G_TOKEN_EQUAL_SIGN)
1165     return G_TOKEN_EQUAL_SIGN;
1166   
1167   token = g_scanner_get_next_token (scanner);
1168   if (token != G_TOKEN_STRING)
1169     return G_TOKEN_STRING;
1170   
1171   if (rc_style->fontset_name)
1172     g_free (rc_style->fontset_name);
1173   rc_style->fontset_name = g_strdup (scanner->value.v_string);
1174   
1175   return G_TOKEN_NONE;
1176 }
1177
1178 guint
1179 gtk_rc_parse_state (GScanner     *scanner,
1180                     GtkStateType *state)
1181 {
1182   guint old_scope;
1183   guint token;
1184
1185   g_return_val_if_fail (scanner != NULL, G_TOKEN_ERROR);
1186   g_return_val_if_fail (state != NULL, G_TOKEN_ERROR);
1187   
1188   /* we don't know where we got called from, so we reset the scope here.
1189    * if we bail out due to errors, we *don't* reset the scope, so the
1190    * error messaging code can make sense of our tokens.
1191    */
1192   old_scope = g_scanner_set_scope (scanner, 0);
1193   
1194   token = g_scanner_get_next_token (scanner);
1195   if (token != G_TOKEN_LEFT_BRACE)
1196     return G_TOKEN_LEFT_BRACE;
1197   
1198   token = g_scanner_get_next_token (scanner);
1199   switch (token)
1200     {
1201     case GTK_RC_TOKEN_ACTIVE:
1202       *state = GTK_STATE_ACTIVE;
1203       break;
1204     case GTK_RC_TOKEN_INSENSITIVE:
1205       *state = GTK_STATE_INSENSITIVE;
1206       break;
1207     case GTK_RC_TOKEN_NORMAL:
1208       *state = GTK_STATE_NORMAL;
1209       break;
1210     case GTK_RC_TOKEN_PRELIGHT:
1211       *state = GTK_STATE_PRELIGHT;
1212       break;
1213     case GTK_RC_TOKEN_SELECTED:
1214       *state = GTK_STATE_SELECTED;
1215       break;
1216     default:
1217       return /* G_TOKEN_SYMBOL */ GTK_RC_TOKEN_NORMAL;
1218     }
1219   
1220   token = g_scanner_get_next_token (scanner);
1221   if (token != G_TOKEN_RIGHT_BRACE)
1222     return G_TOKEN_RIGHT_BRACE;
1223   
1224   g_scanner_set_scope (scanner, old_scope);
1225
1226   return G_TOKEN_NONE;
1227 }
1228
1229 guint
1230 gtk_rc_parse_priority (GScanner            *scanner,
1231                        GtkPathPriorityType *priority)
1232 {
1233   guint old_scope;
1234   guint token;
1235
1236   g_return_val_if_fail (scanner != NULL, G_TOKEN_ERROR);
1237   g_return_val_if_fail (priority != NULL, G_TOKEN_ERROR);
1238
1239   /* we don't know where we got called from, so we reset the scope here.
1240    * if we bail out due to errors, we *don't* reset the scope, so the
1241    * error messaging code can make sense of our tokens.
1242    */
1243   old_scope = g_scanner_set_scope (scanner, 0);
1244   
1245   token = g_scanner_get_next_token (scanner);
1246   if (token != ':')
1247     return ':';
1248   
1249   token = g_scanner_get_next_token (scanner);
1250   switch (token)
1251     {
1252     case GTK_RC_TOKEN_LOWEST:
1253       *priority = GTK_PATH_PRIO_LOWEST;
1254       break;
1255     case GTK_RC_TOKEN_GTK:
1256       *priority = GTK_PATH_PRIO_GTK;
1257       break;
1258     case GTK_RC_TOKEN_APPLICATION:
1259       *priority = GTK_PATH_PRIO_APPLICATION;
1260       break;
1261     case GTK_RC_TOKEN_RC:
1262       *priority = GTK_PATH_PRIO_RC;
1263       break;
1264     case GTK_RC_TOKEN_HIGHEST:
1265       *priority = GTK_PATH_PRIO_HIGHEST;
1266       break;
1267     default:
1268       return /* G_TOKEN_SYMBOL */ GTK_RC_TOKEN_APPLICATION;
1269     }
1270   
1271   g_scanner_set_scope (scanner, old_scope);
1272
1273   return G_TOKEN_NONE;
1274 }
1275
1276 guint
1277 gtk_rc_parse_color (GScanner *scanner,
1278                     GdkColor *color)
1279 {
1280   guint token;
1281
1282   g_return_val_if_fail (scanner != NULL, G_TOKEN_ERROR);
1283
1284   /* we don't need to set our own scop here, because
1285    * we don't need own symbols
1286    */
1287   
1288   token = g_scanner_get_next_token (scanner);
1289   switch (token)
1290     {
1291       gint token_int;
1292       gint length;
1293       gint temp;
1294       gchar buf[9];
1295       gint i, j;
1296       
1297     case G_TOKEN_LEFT_CURLY:
1298       token = g_scanner_get_next_token (scanner);
1299       if (token == G_TOKEN_INT)
1300         token_int = scanner->value.v_int;
1301       else if (token == G_TOKEN_FLOAT)
1302         token_int = scanner->value.v_float * 65535.0;
1303       else
1304         return G_TOKEN_FLOAT;
1305       color->red = CLAMP (token_int, 0, 65535);
1306       
1307       token = g_scanner_get_next_token (scanner);
1308       if (token != G_TOKEN_COMMA)
1309         return G_TOKEN_COMMA;
1310       
1311       token = g_scanner_get_next_token (scanner);
1312       if (token == G_TOKEN_INT)
1313         token_int = scanner->value.v_int;
1314       else if (token == G_TOKEN_FLOAT)
1315         token_int = scanner->value.v_float * 65535.0;
1316       else
1317         return G_TOKEN_FLOAT;
1318       color->green = CLAMP (token_int, 0, 65535);
1319       
1320       token = g_scanner_get_next_token (scanner);
1321       if (token != G_TOKEN_COMMA)
1322         return G_TOKEN_COMMA;
1323       
1324       token = g_scanner_get_next_token (scanner);
1325       if (token == G_TOKEN_INT)
1326         token_int = scanner->value.v_int;
1327       else if (token == G_TOKEN_FLOAT)
1328         token_int = scanner->value.v_float * 65535.0;
1329       else
1330         return G_TOKEN_FLOAT;
1331       color->blue = CLAMP (token_int, 0, 65535);
1332       
1333       token = g_scanner_get_next_token (scanner);
1334       if (token != G_TOKEN_RIGHT_CURLY)
1335         return G_TOKEN_RIGHT_CURLY;
1336       return G_TOKEN_NONE;
1337       
1338     case G_TOKEN_STRING:
1339       if (scanner->value.v_string[0] != '#')
1340         return G_TOKEN_STRING;
1341       
1342       length = strlen (scanner->value.v_string) - 1;
1343       if (((length % 3) != 0) || (length > 12))
1344         return G_TOKEN_STRING;
1345       length /= 3;
1346       
1347       for (i = 0, j = 1; i < length; i++, j++)
1348         buf[i] = scanner->value.v_string[j];
1349       buf[i] = '\0';
1350       
1351       sscanf (buf, "%x", &temp);
1352       color->red = temp;
1353       
1354       for (i = 0; i < length; i++, j++)
1355         buf[i] = scanner->value.v_string[j];
1356       buf[i] = '\0';
1357       
1358       sscanf (buf, "%x", &temp);
1359       color->green = temp;
1360       
1361       for (i = 0; i < length; i++, j++)
1362         buf[i] = scanner->value.v_string[j];
1363       buf[i] = '\0';
1364       
1365       sscanf (buf, "%x", &temp);
1366       color->blue = temp;
1367       
1368       if (length == 1)
1369         {
1370           color->red *= 4369;
1371           color->green *= 4369;
1372           color->blue *= 4369;
1373         }
1374       else if (length == 2)
1375         {
1376           color->red *= 257;
1377           color->green *= 257;
1378           color->blue *= 257;
1379         }
1380       else if (length == 3)
1381         {
1382           color->red *= 16;
1383           color->green *= 16;
1384           color->blue *= 16;
1385         }
1386       return G_TOKEN_NONE;
1387       
1388     default:
1389       return G_TOKEN_STRING;
1390     }
1391 }
1392
1393 static guint
1394 gtk_rc_parse_pixmap_path (GScanner *scanner)
1395 {
1396   guint token;
1397   
1398   token = g_scanner_get_next_token (scanner);
1399   if (token != GTK_RC_TOKEN_PIXMAP_PATH)
1400     return GTK_RC_TOKEN_PIXMAP_PATH;
1401   
1402   token = g_scanner_get_next_token (scanner);
1403   if (token != G_TOKEN_STRING)
1404     return G_TOKEN_STRING;
1405   
1406   gtk_rc_parse_pixmap_path_string (scanner->value.v_string);
1407   
1408   return G_TOKEN_NONE;
1409 }
1410
1411 static void
1412 gtk_rc_parse_pixmap_path_string (gchar *pix_path)
1413 {
1414   gchar *buf;
1415   gint end_offset;
1416   gint start_offset = 0;
1417   gint path_len;
1418   gint path_num;
1419   
1420   /* free the old one, or just add to the old one ? */
1421   for (path_num=0; pixmap_path[path_num]; path_num++)
1422     {
1423       g_free (pixmap_path[path_num]);
1424       pixmap_path[path_num] = NULL;
1425     }
1426   
1427   path_num = 0;
1428   
1429   path_len = strlen (pix_path);
1430   
1431   buf = g_strdup (pix_path);
1432   
1433   for (end_offset = 0; end_offset <= path_len; end_offset++)
1434     {
1435       if ((buf[end_offset] == ':') ||
1436           (end_offset == path_len))
1437         {
1438           buf[end_offset] = '\0';
1439           pixmap_path[path_num] = g_strdup (buf + start_offset);
1440           path_num++;
1441           pixmap_path[path_num] = NULL;
1442           start_offset = end_offset + 1;
1443         }
1444     }
1445   g_free (buf);
1446 }
1447
1448 static guint
1449 gtk_rc_parse_path_pattern (GScanner   *scanner)
1450 {
1451   guint token;
1452   GtkPathType path_type;
1453   gchar *pattern;
1454   gboolean is_binding;
1455   GtkPathPriorityType priority = GTK_PATH_PRIO_RC;
1456   
1457   token = g_scanner_get_next_token (scanner);
1458   switch (token)
1459     {
1460     case GTK_RC_TOKEN_WIDGET:
1461       path_type = GTK_PATH_WIDGET;
1462       break;
1463     case GTK_RC_TOKEN_WIDGET_CLASS:
1464       path_type = GTK_PATH_WIDGET_CLASS;
1465       break;
1466     case GTK_RC_TOKEN_CLASS:
1467       path_type = GTK_PATH_CLASS;
1468       break;
1469     default:
1470       return GTK_RC_TOKEN_WIDGET_CLASS;
1471     }
1472   
1473   token = g_scanner_get_next_token (scanner);
1474   if (token != G_TOKEN_STRING)
1475     return G_TOKEN_STRING;
1476
1477   pattern = g_strdup (scanner->value.v_string);
1478
1479   token = g_scanner_get_next_token (scanner);
1480   if (token == GTK_RC_TOKEN_STYLE)
1481     is_binding = FALSE;
1482   else if (token == GTK_RC_TOKEN_BINDING)
1483     {
1484       is_binding = TRUE;
1485       if (g_scanner_peek_next_token (scanner) == ':')
1486         {
1487           token = gtk_rc_parse_priority (scanner, &priority);
1488           if (token != G_TOKEN_NONE)
1489             {
1490               g_free (pattern);
1491               return token;
1492             }
1493         }
1494     }
1495   else
1496     {
1497       g_free (pattern);
1498       return GTK_RC_TOKEN_STYLE;
1499     }
1500   
1501   token = g_scanner_get_next_token (scanner);
1502   if (token != G_TOKEN_STRING)
1503     {
1504       g_free (pattern);
1505       return G_TOKEN_STRING;
1506     }
1507
1508   if (is_binding)
1509     {
1510       GtkBindingSet *binding;
1511
1512       binding = gtk_binding_set_find (scanner->value.v_string);
1513       if (!binding)
1514         {
1515           g_free (pattern);
1516           return G_TOKEN_STRING;
1517         }
1518       gtk_binding_set_add_path (binding, path_type, pattern, priority);
1519     }
1520   else
1521     {
1522       GtkRcStyle *rc_style;
1523       GtkRcSet *rc_set;
1524
1525       rc_style = gtk_rc_style_find (scanner->value.v_string);
1526       
1527       if (!rc_style)
1528         {
1529           g_free (pattern);
1530           return G_TOKEN_STRING;
1531         }
1532
1533       rc_set = g_new (GtkRcSet, 1);
1534       gtk_pattern_spec_init (&rc_set->pspec, pattern);
1535       rc_set->rc_style = rc_style;
1536
1537       if (path_type == GTK_PATH_WIDGET)
1538         gtk_rc_sets_widget = g_slist_prepend (gtk_rc_sets_widget, rc_set);
1539       else if (path_type == GTK_PATH_WIDGET_CLASS)
1540         gtk_rc_sets_widget_class = g_slist_prepend (gtk_rc_sets_widget_class, rc_set);
1541       else
1542         gtk_rc_sets_class = g_slist_prepend (gtk_rc_sets_class, rc_set);
1543     }
1544
1545   g_free (pattern);
1546   return G_TOKEN_NONE;
1547 }
1548
1549 /*
1550 typedef  GdkPixmap * (*GtkImageLoader) (GdkWindow   *window,
1551                                         GdkColormap *colormap,
1552                                         GdkBitmap  **mask,
1553                                         GdkColor    *transparent_color,
1554                                         const gchar *filename);
1555 */
1556
1557 void
1558 gtk_rc_set_image_loader(GtkImageLoader loader)
1559 {
1560         image_loader = loader;
1561 }
1562