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