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

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