1 /* GTK - The GIMP Toolkit
2 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
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.
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.
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.
22 #include <sys/param.h>
27 #include "gtkbindings.h"
30 typedef struct _GtkRcStyle GtkRcStyle;
31 typedef struct _GtkRcSet GtkRcSet;
32 typedef struct _GtkRcNode GtkRcNode;
33 typedef struct _GtkRcFile GtkRcFile;
46 char *bg_pixmap_name[5];
47 GtkStyle *proto_style;
61 gchar *canonical_name;
65 static guint gtk_rc_style_hash (const char *name);
66 static gint gtk_rc_style_compare (const char *a,
68 static GtkRcStyle* gtk_rc_style_find (const char *name);
69 static GtkRcStyle* gtk_rc_styles_match (GSList *sets,
72 gchar *path_reversed);
73 static GtkStyle* gtk_rc_style_init (GtkRcStyle *rc_style,
75 static void gtk_rc_parse_file (const gchar *filename,
78 static void gtk_rc_parse_any (const gchar *input_name,
80 const gchar *input_string);
81 static guint gtk_rc_parse_statement (GScanner *scanner);
82 static guint gtk_rc_parse_style (GScanner *scanner);
83 static guint gtk_rc_parse_base (GScanner *scanner,
85 static guint gtk_rc_parse_bg (GScanner *scanner,
87 static guint gtk_rc_parse_fg (GScanner *scanner,
89 static guint gtk_rc_parse_text (GScanner *scanner,
91 static guint gtk_rc_parse_bg_pixmap (GScanner *scanner,
92 GtkRcStyle *rc_style);
93 static guint gtk_rc_parse_font (GScanner *scanner,
94 GtkRcStyle *rc_style);
95 static guint gtk_rc_parse_fontset (GScanner *scanner,
96 GtkRcStyle *rc_style);
97 static guint gtk_rc_parse_state (GScanner *scanner,
99 static guint gtk_rc_parse_color (GScanner *scanner,
101 static guint gtk_rc_parse_pixmap_path (GScanner *scanner);
102 static void gtk_rc_parse_pixmap_path_string (gchar *pix_path);
103 static char* gtk_rc_find_pixmap_in_path (GScanner *scanner,
105 static guint gtk_rc_parse_path_pattern (GScanner *scanner);
106 static void gtk_rc_clear_hash_node (gpointer key,
109 static void gtk_rc_clear_styles (void);
113 static GScannerConfig gtk_rc_scanner_config =
117 ) /* cset_skip_characters */,
122 ) /* cset_identifier_first */,
129 ) /* cset_identifier_nth */,
130 ( "#\n" ) /* cpair_comment_single */,
132 TRUE /* case_sensitive */,
134 TRUE /* skip_comment_multi */,
135 TRUE /* skip_comment_single */,
136 TRUE /* scan_comment_multi */,
137 TRUE /* scan_identifier */,
138 FALSE /* scan_identifier_1char */,
139 FALSE /* scan_identifier_NULL */,
140 TRUE /* scan_symbols */,
141 TRUE /* scan_binary */,
142 TRUE /* scan_octal */,
143 TRUE /* scan_float */,
145 TRUE /* scan_hex_dollar */,
146 TRUE /* scan_string_sq */,
147 TRUE /* scan_string_dq */,
148 TRUE /* numbers_2_int */,
149 FALSE /* int_2_float */,
150 TRUE /* identifier_2_string */,
151 TRUE /* char_2_token */,
152 TRUE /* symbol_2_token */,
156 TOKEN_INVALID = G_TOKEN_LAST,
184 { "include", TOKEN_INCLUDE },
185 { "NORMAL", TOKEN_NORMAL },
186 { "ACTIVE", TOKEN_ACTIVE },
187 { "PRELIGHT", TOKEN_PRELIGHT },
188 { "SELECTED", TOKEN_SELECTED },
189 { "INSENSITIVE", TOKEN_INSENSITIVE },
192 { "base", TOKEN_BASE },
193 { "text", TOKEN_TEXT },
194 { "font", TOKEN_FONT },
195 { "fontset", TOKEN_FONTSET },
196 { "bg_pixmap", TOKEN_BG_PIXMAP },
197 { "pixmap_path", TOKEN_PIXMAP_PATH },
198 { "style", TOKEN_STYLE },
199 { "binding", TOKEN_BINDING },
200 { "widget", TOKEN_WIDGET },
201 { "widget_class", TOKEN_WIDGET_CLASS },
202 { "class", TOKEN_CLASS },
204 static guint nsymbols = sizeof (symbols) / sizeof (symbols[0]);
206 static GHashTable *rc_style_ht = NULL;
207 static GSList *gtk_rc_sets_widget = NULL;
208 static GSList *gtk_rc_sets_widget_class = NULL;
209 static GSList *gtk_rc_sets_class = NULL;
211 #define GTK_RC_MAX_PIXMAP_PATHS 128
212 static gchar *pixmap_path[GTK_RC_MAX_PIXMAP_PATHS];
214 /* The files we have parsed, to reread later if necessary */
215 GSList *rc_files = NULL;
217 static GtkImageLoader image_loader = NULL;
222 rc_style_ht = g_hash_table_new ((GHashFunc) gtk_rc_style_hash,
223 (GCompareFunc) gtk_rc_style_compare);
227 gtk_rc_parse_string (const gchar *rc_string)
229 g_return_if_fail (rc_string != NULL);
231 gtk_rc_parse_any ("-", -1, rc_string);
235 gtk_rc_parse_file (const gchar *filename, gboolean reload)
237 GtkRcFile *rc_file = NULL;
241 g_return_if_fail (filename != NULL);
246 rc_file = tmp_list->data;
247 if (!strcmp (rc_file->name, filename))
250 tmp_list = tmp_list->next;
255 rc_file = g_new (GtkRcFile, 1);
256 rc_file->name = g_strdup (filename);
257 rc_file->canonical_name = NULL;
259 rc_file->reload = reload;
261 rc_files = g_slist_append (rc_files, rc_file);
264 if (!rc_file->canonical_name)
266 /* Get the absolute pathname */
268 if (rc_file->name[0] == '/')
269 rc_file->canonical_name = rc_file->name;
273 gchar buffer[MAXPATHLEN];
275 #if defined(sun) && !defined(__SVR4)
278 if(!getcwd(buffer, MAXPATHLEN))
282 str = g_string_new (buffer);
283 g_string_append_c (str, '/');
284 g_string_append (str, rc_file->name);
286 rc_file->canonical_name = str->str;
287 g_string_free (str, FALSE);
291 if (!lstat (rc_file->canonical_name, &statbuf))
295 rc_file->mtime = statbuf.st_mtime;
297 fd = open (rc_file->canonical_name, O_RDONLY);
301 gtk_rc_parse_any (filename, fd, NULL);
308 gtk_rc_parse (const gchar *filename)
310 g_return_if_fail (filename != NULL);
312 gtk_rc_parse_file (filename, TRUE);
316 gtk_rc_clear_hash_node (gpointer key,
321 GtkRcStyle *rc_style = data;
324 g_free (rc_style->name);
325 g_free (rc_style->font_name);
326 g_free (rc_style->fontset_name);
328 for (i=0 ; i<5 ; i++)
329 g_free (rc_style->bg_pixmap_name[i]);
331 gtk_style_unref (rc_style->proto_style);
333 tmp_list = rc_style->styles;
336 GtkRcNode *node = tmp_list->data;
338 gdk_colormap_unref (node->cmap);
339 gtk_style_unref (node->style);
342 tmp_list = tmp_list->next;
349 gtk_rc_free_rc_sets (GSList *slist)
355 rc_set = slist->data;
356 gtk_pattern_spec_free_segs (&rc_set->pspec);
364 gtk_rc_clear_styles (void)
366 /* Clear out all old rc_styles */
368 g_hash_table_foreach (rc_style_ht, gtk_rc_clear_hash_node, NULL);
369 g_hash_table_destroy (rc_style_ht);
372 gtk_rc_free_rc_sets (gtk_rc_sets_widget);
373 g_slist_free (gtk_rc_sets_widget);
374 gtk_rc_sets_widget = NULL;
376 gtk_rc_free_rc_sets (gtk_rc_sets_widget_class);
377 g_slist_free (gtk_rc_sets_widget_class);
378 gtk_rc_sets_widget_class = NULL;
380 gtk_rc_free_rc_sets (gtk_rc_sets_class);
381 g_slist_free (gtk_rc_sets_class);
382 gtk_rc_sets_class = NULL;
388 gtk_rc_reparse_all (void)
391 gboolean mtime_modified = FALSE;
396 /* Check through and see if any of the RC's have had their
397 * mtime modified. If so, reparse everything.
402 rc_file = tmp_list->data;
404 if (!lstat (rc_file->name, &statbuf) &&
405 (statbuf.st_mtime > rc_file->mtime))
407 mtime_modified = TRUE;
411 tmp_list = tmp_list->next;
416 gtk_rc_clear_styles();
421 rc_file = tmp_list->data;
423 gtk_rc_parse_file (rc_file->name, FALSE);
425 tmp_list = tmp_list->next;
429 return mtime_modified;
433 gtk_rc_styles_match (GSList *sets,
436 gchar *path_reversed)
445 if (gtk_pattern_match (&rc_set->pspec, path_length, path, path_reversed))
446 return rc_set->rc_style;
453 gtk_rc_get_style (GtkWidget *widget)
455 GtkRcStyle *rc_style;
457 if (gtk_rc_sets_widget)
459 gchar *path, *path_reversed;
462 gtk_widget_path (widget, &path_length, &path, &path_reversed);
463 rc_style = gtk_rc_styles_match (gtk_rc_sets_widget, path_length, path, path_reversed);
465 g_free (path_reversed);
468 return gtk_rc_style_init (rc_style, gtk_widget_get_colormap (widget));
471 if (gtk_rc_sets_widget_class)
473 gchar *path, *path_reversed;
476 gtk_widget_class_path (widget, &path_length, &path, &path_reversed);
477 rc_style = gtk_rc_styles_match (gtk_rc_sets_widget_class, path_length, path, path_reversed);
479 g_free (path_reversed);
482 return gtk_rc_style_init (rc_style, gtk_widget_get_colormap (widget));
485 if (gtk_rc_sets_class)
489 type = GTK_OBJECT_TYPE (widget);
492 gchar *path, *path_reversed;
495 path = gtk_type_name (type);
496 path_length = strlen (path);
497 path_reversed = g_strdup (path);
498 g_strreverse (path_reversed);
500 rc_style = gtk_rc_styles_match (gtk_rc_sets_class, path_length, path, path_reversed);
501 g_free (path_reversed);
504 return gtk_rc_style_init (rc_style, gtk_widget_get_colormap (widget));
506 type = gtk_type_parent (type);
514 gtk_rc_add_rc_sets (GSList *slist,
518 GtkRcStyle *rc_style;
522 gtk_style_ref (style);
524 rc_style = g_new (GtkRcStyle, 1);
525 rc_style->name = NULL;
526 rc_style->font_name = NULL;
527 rc_style->fontset_name = NULL;
529 for (i = 0; i < 5; i++)
530 rc_style->bg_pixmap_name[i] = NULL;
532 rc_style->styles = g_list_append (NULL, style);
534 rc_set = g_new (GtkRcSet, 1);
535 gtk_pattern_spec_init (&rc_set->pspec, pattern);
536 rc_set->rc_style = rc_style;
538 return g_slist_prepend (slist, rc_set);
542 gtk_rc_add_widget_name_style (GtkStyle *style,
543 const gchar *pattern)
545 g_return_if_fail (style != NULL);
546 g_return_if_fail (pattern != NULL);
548 gtk_rc_sets_widget = gtk_rc_add_rc_sets (gtk_rc_sets_widget, style, pattern);
552 gtk_rc_add_widget_class_style (GtkStyle *style,
553 const gchar *pattern)
555 g_return_if_fail (style != NULL);
556 g_return_if_fail (pattern != NULL);
558 gtk_rc_sets_widget_class = gtk_rc_add_rc_sets (gtk_rc_sets_widget_class, style, pattern);
562 gtk_rc_add_class_style (GtkStyle *style,
563 const gchar *pattern)
565 g_return_if_fail (style != NULL);
566 g_return_if_fail (pattern != NULL);
568 gtk_rc_sets_class = gtk_rc_add_rc_sets (gtk_rc_sets_class, style, pattern);
572 gtk_rc_parse_any (const gchar *input_name,
574 const gchar *input_string)
580 scanner = g_scanner_new (>k_rc_scanner_config);
584 g_assert (input_string == NULL);
586 g_scanner_input_file (scanner, input_fd);
590 g_assert (input_string != NULL);
592 g_scanner_input_text (scanner, input_string, strlen (input_string));
594 scanner->input_name = input_name;
596 g_scanner_freeze_symbol_table (scanner);
597 for (i = 0; i < nsymbols; i++)
598 g_scanner_add_symbol (scanner, symbols[i].name, GINT_TO_POINTER (symbols[i].token));
599 g_scanner_thaw_symbol_table (scanner);
604 if (g_scanner_peek_next_token (scanner) == G_TOKEN_EOF)
608 guint expected_token;
610 expected_token = gtk_rc_parse_statement (scanner);
612 if (expected_token != G_TOKEN_NONE)
618 if (expected_token > TOKEN_INVALID &&
619 expected_token < TOKEN_LAST)
621 for (i = 0; i < nsymbols; i++)
622 if (symbols[i].token == expected_token)
623 msg = symbols[i].name;
625 msg = g_strconcat ("e.g. `", msg, "'", NULL);
627 if (scanner->token > TOKEN_INVALID &&
628 scanner->token < TOKEN_LAST)
631 for (i = 0; i < nsymbols; i++)
632 if (symbols[i].token == scanner->token)
633 symbol_name = symbols[i].name;
637 g_scanner_unexp_token (scanner,
650 g_scanner_destroy (scanner);
654 gtk_rc_style_hash (const char *name)
660 result += (result << 3) + *name++;
666 gtk_rc_style_compare (const char *a,
669 return (strcmp (a, b) == 0);
673 gtk_rc_style_find (const char *name)
675 GtkRcStyle *rc_style;
677 rc_style = g_hash_table_lookup (rc_style_ht, (gpointer) name);
683 gtk_rc_style_init (GtkRcStyle *rc_style, GdkColormap *cmap)
686 gboolean match_cmap = FALSE;
690 GtkStyle *style = NULL;
693 tmp_list = rc_style->styles;
696 if (rc_style->bg_pixmap_name[i])
701 node = (GtkRcNode *)tmp_list->data;
703 if (!match_cmap || (node->cmap == cmap))
709 tmp_list = tmp_list->next;
714 node = g_new (GtkRcNode, 1);
715 style = gtk_style_copy (rc_style->proto_style);
717 /* FIXME, this leaks colormaps, but if we don't do this, then we'll
718 * be screwed, because we identify colormaps by address equality
720 gdk_colormap_ref (cmap);
725 if (rc_style->fontset_name)
727 old_font = style->font;
728 style->font = gdk_fontset_load (rc_style->fontset_name);
730 gdk_font_unref (old_font);
732 style->font = old_font;
734 else if (rc_style->font_name)
736 old_font = style->font;
737 style->font = gdk_font_load (rc_style->font_name);
739 gdk_font_unref (old_font);
741 style->font = old_font;
744 for (i = 0; i < 5; i++)
745 if (rc_style->bg_pixmap_name[i])
747 if (strcmp (rc_style->bg_pixmap_name[i], "<parent>") == 0)
748 style->bg_pixmap[i] = (GdkPixmap*) GDK_PARENT_RELATIVE;
752 style->bg_pixmap[i] = image_loader(NULL, cmap, NULL,
754 rc_style->bg_pixmap_name[i]);
756 style->bg_pixmap[i] =
757 gdk_pixmap_colormap_create_from_xpm (NULL, cmap,
760 rc_style->bg_pixmap_name[i]);
764 rc_style->styles = g_list_append (rc_style->styles, node);
771 gtk_rc_parse_statement (GScanner *scanner)
775 token = g_scanner_peek_next_token (scanner);
780 token = g_scanner_get_next_token (scanner);
781 if (token != TOKEN_INCLUDE)
782 return TOKEN_INCLUDE;
784 token = g_scanner_get_next_token (scanner);
785 if (token != G_TOKEN_STRING)
786 return G_TOKEN_STRING;
788 gtk_rc_parse_file (scanner->value.v_string, FALSE);
792 return gtk_rc_parse_style (scanner);
794 case TOKEN_PIXMAP_PATH:
795 return gtk_rc_parse_pixmap_path (scanner);
798 return gtk_rc_parse_path_pattern (scanner);
800 case TOKEN_WIDGET_CLASS:
801 return gtk_rc_parse_path_pattern (scanner);
804 return gtk_rc_parse_path_pattern (scanner);
807 g_scanner_get_next_token (scanner);
808 return /* G_TOKEN_SYMBOL */ TOKEN_STYLE;
813 gtk_rc_parse_style (GScanner *scanner)
815 GtkRcStyle *rc_style;
816 GtkRcStyle *parent_style;
821 token = g_scanner_get_next_token (scanner);
822 if (token != TOKEN_STYLE)
825 token = g_scanner_get_next_token (scanner);
826 if (token != G_TOKEN_STRING)
827 return G_TOKEN_STRING;
830 rc_style = g_hash_table_lookup (rc_style_ht, scanner->value.v_string);
835 rc_style = g_new (GtkRcStyle, 1);
836 rc_style->name = g_strdup (scanner->value.v_string);
837 rc_style->font_name = NULL;
838 rc_style->fontset_name = NULL;
840 for (i = 0; i < 5; i++)
841 rc_style->bg_pixmap_name[i] = NULL;
843 rc_style->proto_style = gtk_style_new();
844 rc_style->styles = NULL;
847 token = g_scanner_peek_next_token (scanner);
848 if (token == G_TOKEN_EQUAL_SIGN)
850 token = g_scanner_get_next_token (scanner);
852 token = g_scanner_get_next_token (scanner);
853 if (token != G_TOKEN_STRING)
857 gtk_style_unref (rc_style->proto_style);
860 return G_TOKEN_STRING;
863 parent_style = g_hash_table_lookup (rc_style_ht, scanner->value.v_string);
866 for (i = 0; i < 5; i++)
868 rc_style->proto_style->fg[i] = parent_style->proto_style->fg[i];
869 rc_style->proto_style->bg[i] = parent_style->proto_style->bg[i];
870 rc_style->proto_style->light[i] = parent_style->proto_style->light[i];
871 rc_style->proto_style->dark[i] = parent_style->proto_style->dark[i];
872 rc_style->proto_style->mid[i] = parent_style->proto_style->mid[i];
873 rc_style->proto_style->text[i] = parent_style->proto_style->text[i];
874 rc_style->proto_style->base[i] = parent_style->proto_style->base[i];
877 rc_style->proto_style->black = parent_style->proto_style->black;
878 rc_style->proto_style->white = parent_style->proto_style->white;
880 if (rc_style->fontset_name)
882 g_free (rc_style->fontset_name);
883 rc_style->fontset_name = g_strdup (parent_style->fontset_name);
885 else if (rc_style->font_name)
887 g_free (rc_style->font_name);
888 rc_style->font_name = g_strdup (parent_style->font_name);
891 for (i = 0; i < 5; i++)
893 if (rc_style->bg_pixmap_name[i])
894 g_free (rc_style->bg_pixmap_name[i]);
895 rc_style->bg_pixmap_name[i] = g_strdup (parent_style->bg_pixmap_name[i]);
900 token = g_scanner_get_next_token (scanner);
901 if (token != G_TOKEN_LEFT_CURLY)
905 gtk_style_unref (rc_style->proto_style);
908 return G_TOKEN_LEFT_CURLY;
911 token = g_scanner_peek_next_token (scanner);
912 while (token != G_TOKEN_RIGHT_CURLY)
917 token = gtk_rc_parse_base (scanner, rc_style->proto_style);
920 token = gtk_rc_parse_bg (scanner, rc_style->proto_style);
923 token = gtk_rc_parse_fg (scanner, rc_style->proto_style);
926 token = gtk_rc_parse_text (scanner, rc_style->proto_style);
928 case TOKEN_BG_PIXMAP:
929 token = gtk_rc_parse_bg_pixmap (scanner, rc_style);
932 token = gtk_rc_parse_font (scanner, rc_style);
935 token = gtk_rc_parse_fontset (scanner, rc_style);
938 g_scanner_get_next_token (scanner);
939 token = G_TOKEN_RIGHT_CURLY;
943 if (token != G_TOKEN_NONE)
947 if (rc_style->fontset_name)
948 g_free (rc_style->fontset_name);
949 if (rc_style->font_name)
950 g_free (rc_style->font_name);
951 for (i = 0; i < 5; i++)
952 if (rc_style->bg_pixmap_name[i])
953 g_free (rc_style->bg_pixmap_name[i]);
954 gtk_style_unref (rc_style->proto_style);
959 token = g_scanner_peek_next_token (scanner);
962 token = g_scanner_get_next_token (scanner);
963 if (token != G_TOKEN_RIGHT_CURLY)
967 if (rc_style->fontset_name)
968 g_free (rc_style->fontset_name);
969 if (rc_style->font_name)
970 g_free (rc_style->font_name);
972 for (i = 0; i < 5; i++)
973 if (rc_style->bg_pixmap_name[i])
974 g_free (rc_style->bg_pixmap_name[i]);
976 gtk_style_unref (rc_style->proto_style);
979 return G_TOKEN_RIGHT_CURLY;
983 g_hash_table_insert (rc_style_ht, rc_style->name, rc_style);
989 gtk_rc_parse_base (GScanner *scanner,
995 token = g_scanner_get_next_token (scanner);
996 if (token != TOKEN_BASE)
999 token = gtk_rc_parse_state (scanner, &state);
1000 if (token != G_TOKEN_NONE)
1003 token = g_scanner_get_next_token (scanner);
1004 if (token != G_TOKEN_EQUAL_SIGN)
1005 return G_TOKEN_EQUAL_SIGN;
1007 return gtk_rc_parse_color (scanner, &style->base[state]);
1011 gtk_rc_parse_bg (GScanner *scanner,
1017 token = g_scanner_get_next_token (scanner);
1018 if (token != TOKEN_BG)
1021 token = gtk_rc_parse_state (scanner, &state);
1022 if (token != G_TOKEN_NONE)
1025 token = g_scanner_get_next_token (scanner);
1026 if (token != G_TOKEN_EQUAL_SIGN)
1027 return G_TOKEN_EQUAL_SIGN;
1029 return gtk_rc_parse_color (scanner, &style->bg[state]);
1033 gtk_rc_parse_fg (GScanner *scanner,
1039 token = g_scanner_get_next_token (scanner);
1040 if (token != TOKEN_FG)
1043 token = gtk_rc_parse_state (scanner, &state);
1044 if (token != G_TOKEN_NONE)
1047 token = g_scanner_get_next_token (scanner);
1048 if (token != G_TOKEN_EQUAL_SIGN)
1049 return G_TOKEN_EQUAL_SIGN;
1051 return gtk_rc_parse_color (scanner, &style->fg[state]);
1055 gtk_rc_parse_text (GScanner *scanner,
1061 token = g_scanner_get_next_token (scanner);
1062 if (token != TOKEN_TEXT)
1065 token = gtk_rc_parse_state (scanner, &state);
1066 if (token != G_TOKEN_NONE)
1069 token = g_scanner_get_next_token (scanner);
1070 if (token != G_TOKEN_EQUAL_SIGN)
1071 return G_TOKEN_EQUAL_SIGN;
1073 return gtk_rc_parse_color (scanner, &style->text[state]);
1077 gtk_rc_parse_bg_pixmap (GScanner *scanner,
1078 GtkRcStyle *rc_style)
1084 token = g_scanner_get_next_token (scanner);
1085 if (token != TOKEN_BG_PIXMAP)
1086 return TOKEN_BG_PIXMAP;
1088 token = gtk_rc_parse_state (scanner, &state);
1089 if (token != G_TOKEN_NONE)
1092 token = g_scanner_get_next_token (scanner);
1093 if (token != G_TOKEN_EQUAL_SIGN)
1094 return G_TOKEN_EQUAL_SIGN;
1096 token = g_scanner_get_next_token (scanner);
1097 if (token != G_TOKEN_STRING)
1098 return G_TOKEN_STRING;
1100 if (strcmp (scanner->value.v_string, "<parent>"))
1101 pixmap_file = gtk_rc_find_pixmap_in_path (scanner, scanner->value.v_string);
1103 pixmap_file = g_strdup (scanner->value.v_string);
1107 if (rc_style->bg_pixmap_name[state])
1108 g_free (rc_style->bg_pixmap_name[state]);
1109 rc_style->bg_pixmap_name[state] = pixmap_file;
1112 return G_TOKEN_NONE;
1116 gtk_rc_find_pixmap_in_path (GScanner *scanner,
1123 for (i = 0; (i < GTK_RC_MAX_PIXMAP_PATHS) && (pixmap_path[i] != NULL); i++)
1125 buf = g_malloc (strlen (pixmap_path[i]) + strlen (pixmap_file) + 2);
1126 sprintf (buf, "%s%c%s", pixmap_path[i], '/', pixmap_file);
1128 fd = open (buf, O_RDONLY);
1138 g_warning ("Unable to locate image file in pixmap_path: \"%s\" line %d",
1139 pixmap_file, scanner->line);
1145 gtk_rc_parse_font (GScanner *scanner,
1146 GtkRcStyle *rc_style)
1150 token = g_scanner_get_next_token (scanner);
1151 if (token != TOKEN_FONT)
1154 token = g_scanner_get_next_token (scanner);
1155 if (token != G_TOKEN_EQUAL_SIGN)
1156 return G_TOKEN_EQUAL_SIGN;
1158 token = g_scanner_get_next_token (scanner);
1159 if (token != G_TOKEN_STRING)
1160 return G_TOKEN_STRING;
1162 if (rc_style->font_name)
1163 g_free (rc_style->font_name);
1164 rc_style->font_name = g_strdup (scanner->value.v_string);
1166 return G_TOKEN_NONE;
1170 gtk_rc_parse_fontset (GScanner *scanner,
1171 GtkRcStyle *rc_style)
1175 token = g_scanner_get_next_token (scanner);
1176 if (token != TOKEN_FONTSET)
1177 return TOKEN_FONTSET;
1179 token = g_scanner_get_next_token (scanner);
1180 if (token != G_TOKEN_EQUAL_SIGN)
1181 return G_TOKEN_EQUAL_SIGN;
1183 token = g_scanner_get_next_token (scanner);
1184 if (token != G_TOKEN_STRING)
1185 return G_TOKEN_STRING;
1187 if (rc_style->fontset_name)
1188 g_free (rc_style->fontset_name);
1189 rc_style->fontset_name = g_strdup (scanner->value.v_string);
1191 return G_TOKEN_NONE;
1195 gtk_rc_parse_state (GScanner *scanner,
1196 GtkStateType *state)
1200 token = g_scanner_get_next_token (scanner);
1201 if (token != G_TOKEN_LEFT_BRACE)
1202 return G_TOKEN_LEFT_BRACE;
1204 token = g_scanner_get_next_token (scanner);
1208 *state = GTK_STATE_ACTIVE;
1210 case TOKEN_INSENSITIVE:
1211 *state = GTK_STATE_INSENSITIVE;
1214 *state = GTK_STATE_NORMAL;
1216 case TOKEN_PRELIGHT:
1217 *state = GTK_STATE_PRELIGHT;
1219 case TOKEN_SELECTED:
1220 *state = GTK_STATE_SELECTED;
1223 return /* G_TOKEN_SYMBOL */ TOKEN_NORMAL;
1226 token = g_scanner_get_next_token (scanner);
1227 if (token != G_TOKEN_RIGHT_BRACE)
1228 return G_TOKEN_RIGHT_BRACE;
1230 return G_TOKEN_NONE;
1234 gtk_rc_parse_color (GScanner *scanner,
1239 token = g_scanner_get_next_token (scanner);
1248 case G_TOKEN_LEFT_CURLY:
1249 token = g_scanner_get_next_token (scanner);
1250 if (token == G_TOKEN_INT)
1251 token_int = scanner->value.v_int;
1252 else if (token == G_TOKEN_FLOAT)
1253 token_int = scanner->value.v_float * 65535.0;
1255 return G_TOKEN_FLOAT;
1256 color->red = CLAMP (token_int, 0, 65535);
1258 token = g_scanner_get_next_token (scanner);
1259 if (token != G_TOKEN_COMMA)
1260 return G_TOKEN_COMMA;
1262 token = g_scanner_get_next_token (scanner);
1263 if (token == G_TOKEN_INT)
1264 token_int = scanner->value.v_int;
1265 else if (token == G_TOKEN_FLOAT)
1266 token_int = scanner->value.v_float * 65535.0;
1268 return G_TOKEN_FLOAT;
1269 color->green = CLAMP (token_int, 0, 65535);
1271 token = g_scanner_get_next_token (scanner);
1272 if (token != G_TOKEN_COMMA)
1273 return G_TOKEN_COMMA;
1275 token = g_scanner_get_next_token (scanner);
1276 if (token == G_TOKEN_INT)
1277 token_int = scanner->value.v_int;
1278 else if (token == G_TOKEN_FLOAT)
1279 token_int = scanner->value.v_float * 65535.0;
1281 return G_TOKEN_FLOAT;
1282 color->blue = CLAMP (token_int, 0, 65535);
1284 token = g_scanner_get_next_token (scanner);
1285 if (token != G_TOKEN_RIGHT_CURLY)
1286 return G_TOKEN_RIGHT_CURLY;
1287 return G_TOKEN_NONE;
1289 case G_TOKEN_STRING:
1290 if (scanner->value.v_string[0] != '#')
1291 return G_TOKEN_STRING;
1293 length = strlen (scanner->value.v_string) - 1;
1294 if (((length % 3) != 0) || (length > 12))
1295 return G_TOKEN_STRING;
1298 for (i = 0, j = 1; i < length; i++, j++)
1299 buf[i] = scanner->value.v_string[j];
1302 sscanf (buf, "%x", &temp);
1305 for (i = 0; i < length; i++, j++)
1306 buf[i] = scanner->value.v_string[j];
1309 sscanf (buf, "%x", &temp);
1310 color->green = temp;
1312 for (i = 0; i < length; i++, j++)
1313 buf[i] = scanner->value.v_string[j];
1316 sscanf (buf, "%x", &temp);
1322 color->green *= 4369;
1323 color->blue *= 4369;
1325 else if (length == 2)
1328 color->green *= 257;
1331 else if (length == 3)
1337 return G_TOKEN_NONE;
1340 return G_TOKEN_STRING;
1345 gtk_rc_parse_pixmap_path (GScanner *scanner)
1349 token = g_scanner_get_next_token (scanner);
1350 if (token != TOKEN_PIXMAP_PATH)
1351 return TOKEN_PIXMAP_PATH;
1353 token = g_scanner_get_next_token (scanner);
1354 if (token != G_TOKEN_STRING)
1355 return G_TOKEN_STRING;
1357 gtk_rc_parse_pixmap_path_string (scanner->value.v_string);
1359 return G_TOKEN_NONE;
1363 gtk_rc_parse_pixmap_path_string (gchar *pix_path)
1367 gint start_offset = 0;
1371 /* free the old one, or just add to the old one ? */
1372 for (path_num=0; pixmap_path[path_num]; path_num++)
1374 g_free (pixmap_path[path_num]);
1375 pixmap_path[path_num] = NULL;
1380 path_len = strlen (pix_path);
1382 buf = g_strdup (pix_path);
1384 for (end_offset = 0; end_offset <= path_len; end_offset++)
1386 if ((buf[end_offset] == ':') ||
1387 (end_offset == path_len))
1389 buf[end_offset] = '\0';
1390 pixmap_path[path_num] = g_strdup (buf + start_offset);
1392 pixmap_path[path_num] = NULL;
1393 start_offset = end_offset + 1;
1400 gtk_rc_parse_path_pattern (GScanner *scanner)
1403 GtkPathType path_type;
1405 gboolean is_binding;
1407 token = g_scanner_get_next_token (scanner);
1411 path_type = GTK_PATH_WIDGET;
1413 case TOKEN_WIDGET_CLASS:
1414 path_type = GTK_PATH_WIDGET_CLASS;
1417 path_type = GTK_PATH_CLASS;
1420 return TOKEN_WIDGET_CLASS;
1423 token = g_scanner_get_next_token (scanner);
1424 if (token != G_TOKEN_STRING)
1425 return G_TOKEN_STRING;
1427 pattern = g_strdup (scanner->value.v_string);
1429 token = g_scanner_get_next_token (scanner);
1430 if (token == TOKEN_STYLE)
1432 else if (token == TOKEN_BINDING)
1440 token = g_scanner_get_next_token (scanner);
1441 if (token != G_TOKEN_STRING)
1444 return G_TOKEN_STRING;
1449 GtkBindingSet *binding;
1451 binding = gtk_binding_set_find (scanner->value.v_string);
1455 return G_TOKEN_STRING;
1457 gtk_binding_set_add_path (binding, path_type, pattern, GTK_PATH_PRIO_RC);
1461 GtkRcStyle *rc_style;
1464 rc_style = gtk_rc_style_find (scanner->value.v_string);
1469 return G_TOKEN_STRING;
1472 rc_set = g_new (GtkRcSet, 1);
1473 gtk_pattern_spec_init (&rc_set->pspec, pattern);
1474 rc_set->rc_style = rc_style;
1476 if (path_type == GTK_PATH_WIDGET)
1477 gtk_rc_sets_widget = g_slist_prepend (gtk_rc_sets_widget, rc_set);
1478 else if (path_type == GTK_PATH_WIDGET_CLASS)
1479 gtk_rc_sets_widget_class = g_slist_prepend (gtk_rc_sets_widget_class, rc_set);
1481 gtk_rc_sets_class = g_slist_prepend (gtk_rc_sets_class, rc_set);
1485 return G_TOKEN_NONE;
1489 typedef GdkPixmap * (*GtkImageLoader) (GdkWindow *window,
1490 GdkColormap *colormap,
1492 GdkColor *transparent_color,
1493 const gchar *filename);
1497 gtk_rc_set_image_loader(GtkImageLoader loader)
1499 image_loader = loader;