source: trunk/third/gtk/gtk/gtkrc.c @ 15781

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