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