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"
31 TOKEN_INVALID = G_TOKEN_LAST,
52 typedef struct _GtkRcStyle GtkRcStyle;
53 typedef struct _GtkRcSet GtkRcSet;
54 typedef struct _GtkRcNode GtkRcNode;
55 typedef struct _GtkRcFile GtkRcFile;
68 char *bg_pixmap_name[5];
69 GtkStyle *proto_style;
83 gchar *canonical_name;
87 static guint gtk_rc_style_hash (const char *name);
88 static gint gtk_rc_style_compare (const char *a,
90 static GtkRcStyle* gtk_rc_style_find (const char *name);
91 static GtkRcStyle* gtk_rc_styles_match (GSList *sets,
94 gchar *path_reversed);
95 static GtkStyle* gtk_rc_style_init (GtkRcStyle *rc_style,
97 static void gtk_rc_parse_file (const gchar *filename,
100 static void gtk_rc_parse_any (const gchar *input_name,
102 const gchar *input_string);
103 static guint gtk_rc_parse_statement (GScanner *scanner);
104 static guint gtk_rc_parse_style (GScanner *scanner);
105 static guint gtk_rc_parse_base (GScanner *scanner,
107 static guint gtk_rc_parse_bg (GScanner *scanner,
109 static guint gtk_rc_parse_fg (GScanner *scanner,
111 static guint gtk_rc_parse_text (GScanner *scanner,
113 static guint gtk_rc_parse_bg_pixmap (GScanner *scanner,
114 GtkRcStyle *rc_style);
115 static guint gtk_rc_parse_font (GScanner *scanner,
116 GtkRcStyle *rc_style);
117 static guint gtk_rc_parse_fontset (GScanner *scanner,
118 GtkRcStyle *rc_style);
119 static guint gtk_rc_parse_state (GScanner *scanner,
120 GtkStateType *state);
121 static guint gtk_rc_parse_color (GScanner *scanner,
123 static guint gtk_rc_parse_pixmap_path (GScanner *scanner);
124 static void gtk_rc_parse_pixmap_path_string (gchar *pix_path);
125 static char* gtk_rc_find_pixmap_in_path (GScanner *scanner,
127 static guint gtk_rc_parse_widget_style (GScanner *scanner);
128 static guint gtk_rc_parse_widget_class_style (GScanner *scanner);
129 static void gtk_rc_clear_hash_node (gpointer key,
132 static void gtk_rc_clear_styles (void);
136 static GScannerConfig gtk_rc_scanner_config =
140 ) /* cset_skip_characters */,
145 ) /* cset_identifier_first */,
152 ) /* cset_identifier_nth */,
153 ( "#\n" ) /* cpair_comment_single */,
155 TRUE /* case_sensitive */,
157 TRUE /* skip_comment_multi */,
158 TRUE /* skip_comment_single */,
159 TRUE /* scan_comment_multi */,
160 TRUE /* scan_identifier */,
161 FALSE /* scan_identifier_1char */,
162 FALSE /* scan_identifier_NULL */,
163 TRUE /* scan_symbols */,
164 TRUE /* scan_binary */,
165 TRUE /* scan_octal */,
166 TRUE /* scan_float */,
168 TRUE /* scan_hex_dollar */,
169 TRUE /* scan_string_sq */,
170 TRUE /* scan_string_dq */,
171 TRUE /* numbers_2_int */,
172 FALSE /* int_2_float */,
173 TRUE /* identifier_2_string */,
174 TRUE /* char_2_token */,
175 TRUE /* symbol_2_token */,
183 { "include", TOKEN_INCLUDE },
184 { "ACTIVE", TOKEN_ACTIVE },
185 { "base", TOKEN_BASE },
187 { "bg_pixmap", TOKEN_BG_PIXMAP },
189 { "font", TOKEN_FONT },
190 { "fontset", TOKEN_FONTSET },
191 { "INSENSITIVE", TOKEN_INSENSITIVE },
192 { "NORMAL", TOKEN_NORMAL },
193 { "pixmap_path", TOKEN_PIXMAP_PATH },
194 { "PRELIGHT", TOKEN_PRELIGHT },
195 { "SELECTED", TOKEN_SELECTED },
196 { "style", TOKEN_STYLE },
197 { "text", TOKEN_TEXT },
198 { "widget", TOKEN_WIDGET },
199 { "widget_class", TOKEN_WIDGET_CLASS },
201 static guint nsymbols = sizeof (symbols) / sizeof (symbols[0]);
203 static GHashTable *rc_style_ht = NULL;
204 static GSList *gtk_rc_sets_widget = NULL;
205 static GSList *gtk_rc_sets_widget_class = NULL;
207 #define GTK_RC_MAX_PIXMAP_PATHS 128
208 static gchar *pixmap_path[GTK_RC_MAX_PIXMAP_PATHS];
210 /* The files we have parsed, to reread later if necessary */
211 GSList *rc_files = NULL;
213 static GtkImageLoader image_loader = NULL;
218 rc_style_ht = g_hash_table_new ((GHashFunc) gtk_rc_style_hash,
219 (GCompareFunc) gtk_rc_style_compare);
223 gtk_rc_parse_string (const gchar *rc_string)
225 g_return_if_fail (rc_string != NULL);
227 gtk_rc_parse_any ("-", -1, rc_string);
231 gtk_rc_parse_file (const gchar *filename, gboolean reload)
233 GtkRcFile *rc_file = NULL;
237 g_return_if_fail (filename != NULL);
242 rc_file = tmp_list->data;
243 if (!strcmp (rc_file->name, filename))
246 tmp_list = tmp_list->next;
251 rc_file = g_new (GtkRcFile, 1);
252 rc_file->name = g_strdup (filename);
253 rc_file->canonical_name = NULL;
255 rc_file->reload = reload;
257 rc_files = g_slist_append (rc_files, rc_file);
260 if (!rc_file->canonical_name)
262 /* Get the absolute pathname */
264 if (rc_file->name[0] == '/')
265 rc_file->canonical_name = rc_file->name;
269 gchar buffer[MAXPATHLEN];
271 #if defined(sun) && !defined(__SVR4)
274 if(!getcwd(buffer, MAXPATHLEN))
278 str = g_string_new (buffer);
279 g_string_append_c (str, '/');
280 g_string_append (str, rc_file->name);
282 rc_file->canonical_name = str->str;
283 g_string_free (str, FALSE);
287 if (!lstat (rc_file->canonical_name, &statbuf))
291 rc_file->mtime = statbuf.st_mtime;
293 fd = open (rc_file->canonical_name, O_RDONLY);
297 gtk_rc_parse_any (filename, fd, NULL);
304 gtk_rc_parse (const gchar *filename)
306 g_return_if_fail (filename != NULL);
308 gtk_rc_parse_file (filename, TRUE);
312 gtk_rc_clear_hash_node (gpointer key,
317 GtkRcStyle *rc_style = data;
320 g_free (rc_style->name);
321 g_free (rc_style->font_name);
322 g_free (rc_style->fontset_name);
324 for (i=0 ; i<5 ; i++)
325 g_free (rc_style->bg_pixmap_name[i]);
327 gtk_style_unref (rc_style->proto_style);
329 tmp_list = rc_style->styles;
332 GtkRcNode *node = tmp_list->data;
334 gdk_colormap_unref (node->cmap);
335 gtk_style_unref (node->style);
338 tmp_list = tmp_list->next;
345 gtk_rc_clear_styles (void)
349 /* Clear out all old rc_styles */
351 g_hash_table_foreach (rc_style_ht, gtk_rc_clear_hash_node, NULL);
352 g_hash_table_destroy (rc_style_ht);
355 tmp_list = gtk_rc_sets_widget;
360 rc_set = tmp_list->data;
361 gtk_pattern_spec_free_segs (&rc_set->pspec);
364 tmp_list = tmp_list->next;
366 g_slist_free (gtk_rc_sets_widget);
367 gtk_rc_sets_widget = NULL;
369 tmp_list = gtk_rc_sets_widget_class;
374 rc_set = tmp_list->data;
375 gtk_pattern_spec_free_segs (&rc_set->pspec);
378 tmp_list = tmp_list->next;
380 g_slist_free (gtk_rc_sets_widget_class);
381 gtk_rc_sets_widget_class = NULL;
387 gtk_rc_reparse_all (void)
390 gboolean mtime_modified = FALSE;
395 /* Check through and see if any of the RC's have had their
396 * mtime modified. If so, reparse everything.
401 rc_file = tmp_list->data;
403 if (!lstat (rc_file->name, &statbuf) &&
404 (statbuf.st_mtime > rc_file->mtime))
406 mtime_modified = TRUE;
410 tmp_list = tmp_list->next;
415 gtk_rc_clear_styles();
420 rc_file = tmp_list->data;
422 gtk_rc_parse_file (rc_file->name, FALSE);
424 tmp_list = tmp_list->next;
428 return mtime_modified;
432 gtk_rc_get_style (GtkWidget *widget)
434 GtkRcStyle *rc_style;
436 if (gtk_rc_sets_widget)
438 gchar *path, *path_reversed;
441 gtk_widget_path (widget, &path_length, &path, &path_reversed);
442 rc_style = gtk_rc_styles_match (gtk_rc_sets_widget, path_length, path, path_reversed);
444 g_free (path_reversed);
447 return gtk_rc_style_init (rc_style, gtk_widget_get_colormap (widget));
450 if (gtk_rc_sets_widget_class)
452 gchar *path, *path_reversed;
455 gtk_widget_class_path (widget, &path_length, &path, &path_reversed);
456 rc_style = gtk_rc_styles_match (gtk_rc_sets_widget_class, path_length, path, path_reversed);
458 g_free (path_reversed);
461 return gtk_rc_style_init (rc_style, gtk_widget_get_colormap (widget));
468 gtk_rc_add_widget_name_style (GtkStyle *style,
471 GtkRcStyle *rc_style;
475 gtk_style_ref (style);
477 rc_style = g_new (GtkRcStyle, 1);
478 rc_style->name = NULL;
479 rc_style->font_name = NULL;
480 rc_style->fontset_name = NULL;
482 for (i = 0; i < 5; i++)
483 rc_style->bg_pixmap_name[i] = NULL;
485 rc_style->styles = g_list_append (NULL, style);
487 rc_set = g_new (GtkRcSet, 1);
488 gtk_pattern_spec_init (&rc_set->pspec, pattern);
489 rc_set->rc_style = rc_style;
491 gtk_rc_sets_widget = g_slist_prepend (gtk_rc_sets_widget, rc_set);
495 gtk_rc_add_widget_class_style (GtkStyle *style,
498 GtkRcStyle *rc_style;
502 gtk_style_ref (style);
504 rc_style = g_new (GtkRcStyle, 1);
505 rc_style->name = NULL;
506 rc_style->font_name = NULL;
507 rc_style->fontset_name = NULL;
509 for (i = 0; i < 5; i++)
510 rc_style->bg_pixmap_name[i] = NULL;
512 rc_style->styles = g_list_append (NULL, style);
514 rc_set = g_new (GtkRcSet, 1);
515 gtk_pattern_spec_init (&rc_set->pspec, pattern);
516 rc_set->rc_style = rc_style;
518 gtk_rc_sets_widget_class = g_slist_prepend (gtk_rc_sets_widget_class, rc_set);
522 gtk_rc_parse_any (const gchar *input_name,
524 const gchar *input_string)
530 scanner = g_scanner_new (>k_rc_scanner_config);
534 g_assert (input_string == NULL);
536 g_scanner_input_file (scanner, input_fd);
540 g_assert (input_string != NULL);
542 g_scanner_input_text (scanner, input_string, strlen (input_string));
544 scanner->input_name = input_name;
546 g_scanner_freeze_symbol_table (scanner);
547 for (i = 0; i < nsymbols; i++)
548 g_scanner_add_symbol (scanner, symbols[i].name, GINT_TO_POINTER (symbols[i].token));
549 g_scanner_thaw_symbol_table (scanner);
554 if (g_scanner_peek_next_token (scanner) == G_TOKEN_EOF)
558 guint expected_token;
560 expected_token = gtk_rc_parse_statement (scanner);
562 if (expected_token != G_TOKEN_NONE)
568 if (expected_token > TOKEN_INVALID &&
569 expected_token < TOKEN_LAST)
571 for (i = 0; i < nsymbols; i++)
572 if (symbols[i].token == expected_token)
573 msg = symbols[i].name;
575 msg = g_strconcat ("e.g. `", msg, "'", NULL);
577 if (scanner->token > TOKEN_INVALID &&
578 scanner->token < TOKEN_LAST)
581 for (i = 0; i < nsymbols; i++)
582 if (symbols[i].token == scanner->token)
583 symbol_name = symbols[i].name;
587 g_scanner_unexp_token (scanner,
600 g_scanner_destroy (scanner);
604 gtk_rc_style_hash (const char *name)
610 result += (result << 3) + *name++;
616 gtk_rc_style_compare (const char *a,
619 return (strcmp (a, b) == 0);
623 gtk_rc_style_find (const char *name)
625 GtkRcStyle *rc_style;
627 rc_style = g_hash_table_lookup (rc_style_ht, (gpointer) name);
633 gtk_rc_styles_match (GSList *sets,
636 gchar *path_reversed)
645 if (gtk_pattern_match (&rc_set->pspec, path_length, path, path_reversed))
646 return rc_set->rc_style;
653 gtk_rc_style_init (GtkRcStyle *rc_style, GdkColormap *cmap)
656 gboolean match_cmap = FALSE;
660 GtkStyle *style = NULL;
663 tmp_list = rc_style->styles;
666 if (rc_style->bg_pixmap_name[i])
671 node = (GtkRcNode *)tmp_list->data;
673 if (!match_cmap || (node->cmap == cmap))
679 tmp_list = tmp_list->next;
684 node = g_new (GtkRcNode, 1);
685 style = gtk_style_copy (rc_style->proto_style);
687 /* FIXME, this leaks colormaps, but if we don't do this, then we'll
688 * be screwed, because we identify colormaps by address equality
690 gdk_colormap_ref (cmap);
695 if (rc_style->fontset_name)
697 old_font = style->font;
698 style->font = gdk_fontset_load (rc_style->fontset_name);
700 gdk_font_unref (old_font);
702 style->font = old_font;
704 else if (rc_style->font_name)
706 old_font = style->font;
707 style->font = gdk_font_load (rc_style->font_name);
709 gdk_font_unref (old_font);
711 style->font = old_font;
714 for (i = 0; i < 5; i++)
715 if (rc_style->bg_pixmap_name[i])
717 if (strcmp (rc_style->bg_pixmap_name[i], "<parent>") == 0)
718 style->bg_pixmap[i] = (GdkPixmap*) GDK_PARENT_RELATIVE;
722 style->bg_pixmap[i] = image_loader(NULL, cmap, NULL,
724 rc_style->bg_pixmap_name[i]);
726 style->bg_pixmap[i] =
727 gdk_pixmap_colormap_create_from_xpm (NULL, cmap,
730 rc_style->bg_pixmap_name[i]);
734 rc_style->styles = g_list_append (rc_style->styles, node);
741 gtk_rc_parse_statement (GScanner *scanner)
745 token = g_scanner_peek_next_token (scanner);
750 token = g_scanner_get_next_token (scanner);
751 if (token != TOKEN_INCLUDE)
752 return TOKEN_INCLUDE;
754 token = g_scanner_get_next_token (scanner);
755 if (token != G_TOKEN_STRING)
756 return G_TOKEN_STRING;
758 gtk_rc_parse_file (scanner->value.v_string, FALSE);
762 return gtk_rc_parse_style (scanner);
764 case TOKEN_PIXMAP_PATH:
765 return gtk_rc_parse_pixmap_path (scanner);
768 return gtk_rc_parse_widget_style (scanner);
770 case TOKEN_WIDGET_CLASS:
771 return gtk_rc_parse_widget_class_style (scanner);
774 g_scanner_get_next_token (scanner);
775 return /* G_TOKEN_SYMBOL */ TOKEN_STYLE;
780 gtk_rc_parse_style (GScanner *scanner)
782 GtkRcStyle *rc_style;
783 GtkRcStyle *parent_style;
788 token = g_scanner_get_next_token (scanner);
789 if (token != TOKEN_STYLE)
792 token = g_scanner_get_next_token (scanner);
793 if (token != G_TOKEN_STRING)
794 return G_TOKEN_STRING;
797 rc_style = g_hash_table_lookup (rc_style_ht, scanner->value.v_string);
802 rc_style = g_new (GtkRcStyle, 1);
803 rc_style->name = g_strdup (scanner->value.v_string);
804 rc_style->font_name = NULL;
805 rc_style->fontset_name = NULL;
807 for (i = 0; i < 5; i++)
808 rc_style->bg_pixmap_name[i] = NULL;
810 rc_style->proto_style = gtk_style_new();
811 rc_style->styles = NULL;
814 token = g_scanner_peek_next_token (scanner);
815 if (token == G_TOKEN_EQUAL_SIGN)
817 token = g_scanner_get_next_token (scanner);
819 token = g_scanner_get_next_token (scanner);
820 if (token != G_TOKEN_STRING)
824 gtk_style_unref (rc_style->proto_style);
827 return G_TOKEN_STRING;
830 parent_style = g_hash_table_lookup (rc_style_ht, scanner->value.v_string);
833 for (i = 0; i < 5; i++)
835 rc_style->proto_style->fg[i] = parent_style->proto_style->fg[i];
836 rc_style->proto_style->bg[i] = parent_style->proto_style->bg[i];
837 rc_style->proto_style->light[i] = parent_style->proto_style->light[i];
838 rc_style->proto_style->dark[i] = parent_style->proto_style->dark[i];
839 rc_style->proto_style->mid[i] = parent_style->proto_style->mid[i];
840 rc_style->proto_style->text[i] = parent_style->proto_style->text[i];
841 rc_style->proto_style->base[i] = parent_style->proto_style->base[i];
844 rc_style->proto_style->black = parent_style->proto_style->black;
845 rc_style->proto_style->white = parent_style->proto_style->white;
847 if (rc_style->fontset_name)
849 g_free (rc_style->fontset_name);
850 rc_style->fontset_name = g_strdup (parent_style->fontset_name);
852 else if (rc_style->font_name)
854 g_free (rc_style->font_name);
855 rc_style->font_name = g_strdup (parent_style->font_name);
858 for (i = 0; i < 5; i++)
860 if (rc_style->bg_pixmap_name[i])
861 g_free (rc_style->bg_pixmap_name[i]);
862 rc_style->bg_pixmap_name[i] = g_strdup (parent_style->bg_pixmap_name[i]);
867 token = g_scanner_get_next_token (scanner);
868 if (token != G_TOKEN_LEFT_CURLY)
872 gtk_style_unref (rc_style->proto_style);
875 return G_TOKEN_LEFT_CURLY;
878 token = g_scanner_peek_next_token (scanner);
879 while (token != G_TOKEN_RIGHT_CURLY)
884 token = gtk_rc_parse_base (scanner, rc_style->proto_style);
887 token = gtk_rc_parse_bg (scanner, rc_style->proto_style);
890 token = gtk_rc_parse_fg (scanner, rc_style->proto_style);
893 token = gtk_rc_parse_text (scanner, rc_style->proto_style);
895 case TOKEN_BG_PIXMAP:
896 token = gtk_rc_parse_bg_pixmap (scanner, rc_style);
899 token = gtk_rc_parse_font (scanner, rc_style);
902 token = gtk_rc_parse_fontset (scanner, rc_style);
905 g_scanner_get_next_token (scanner);
906 token = G_TOKEN_RIGHT_CURLY;
910 if (token != G_TOKEN_NONE)
914 if (rc_style->fontset_name)
915 g_free (rc_style->fontset_name);
916 if (rc_style->font_name)
917 g_free (rc_style->font_name);
918 for (i = 0; i < 5; i++)
919 if (rc_style->bg_pixmap_name[i])
920 g_free (rc_style->bg_pixmap_name[i]);
921 gtk_style_unref (rc_style->proto_style);
926 token = g_scanner_peek_next_token (scanner);
929 token = g_scanner_get_next_token (scanner);
930 if (token != G_TOKEN_RIGHT_CURLY)
934 if (rc_style->fontset_name)
935 g_free (rc_style->fontset_name);
936 if (rc_style->font_name)
937 g_free (rc_style->font_name);
939 for (i = 0; i < 5; i++)
940 if (rc_style->bg_pixmap_name[i])
941 g_free (rc_style->bg_pixmap_name[i]);
943 gtk_style_unref (rc_style->proto_style);
946 return G_TOKEN_RIGHT_CURLY;
950 g_hash_table_insert (rc_style_ht, rc_style->name, rc_style);
956 gtk_rc_parse_base (GScanner *scanner,
962 token = g_scanner_get_next_token (scanner);
963 if (token != TOKEN_BASE)
966 token = gtk_rc_parse_state (scanner, &state);
967 if (token != G_TOKEN_NONE)
970 token = g_scanner_get_next_token (scanner);
971 if (token != G_TOKEN_EQUAL_SIGN)
972 return G_TOKEN_EQUAL_SIGN;
974 return gtk_rc_parse_color (scanner, &style->base[state]);
978 gtk_rc_parse_bg (GScanner *scanner,
984 token = g_scanner_get_next_token (scanner);
985 if (token != TOKEN_BG)
988 token = gtk_rc_parse_state (scanner, &state);
989 if (token != G_TOKEN_NONE)
992 token = g_scanner_get_next_token (scanner);
993 if (token != G_TOKEN_EQUAL_SIGN)
994 return G_TOKEN_EQUAL_SIGN;
996 return gtk_rc_parse_color (scanner, &style->bg[state]);
1000 gtk_rc_parse_fg (GScanner *scanner,
1006 token = g_scanner_get_next_token (scanner);
1007 if (token != TOKEN_FG)
1010 token = gtk_rc_parse_state (scanner, &state);
1011 if (token != G_TOKEN_NONE)
1014 token = g_scanner_get_next_token (scanner);
1015 if (token != G_TOKEN_EQUAL_SIGN)
1016 return G_TOKEN_EQUAL_SIGN;
1018 return gtk_rc_parse_color (scanner, &style->fg[state]);
1022 gtk_rc_parse_text (GScanner *scanner,
1028 token = g_scanner_get_next_token (scanner);
1029 if (token != TOKEN_TEXT)
1032 token = gtk_rc_parse_state (scanner, &state);
1033 if (token != G_TOKEN_NONE)
1036 token = g_scanner_get_next_token (scanner);
1037 if (token != G_TOKEN_EQUAL_SIGN)
1038 return G_TOKEN_EQUAL_SIGN;
1040 return gtk_rc_parse_color (scanner, &style->text[state]);
1044 gtk_rc_parse_bg_pixmap (GScanner *scanner,
1045 GtkRcStyle *rc_style)
1051 token = g_scanner_get_next_token (scanner);
1052 if (token != TOKEN_BG_PIXMAP)
1053 return TOKEN_BG_PIXMAP;
1055 token = gtk_rc_parse_state (scanner, &state);
1056 if (token != G_TOKEN_NONE)
1059 token = g_scanner_get_next_token (scanner);
1060 if (token != G_TOKEN_EQUAL_SIGN)
1061 return G_TOKEN_EQUAL_SIGN;
1063 token = g_scanner_get_next_token (scanner);
1064 if (token != G_TOKEN_STRING)
1065 return G_TOKEN_STRING;
1067 if (strcmp (scanner->value.v_string, "<parent>"))
1068 pixmap_file = gtk_rc_find_pixmap_in_path (scanner, scanner->value.v_string);
1070 pixmap_file = g_strdup (scanner->value.v_string);
1074 if (rc_style->bg_pixmap_name[state])
1075 g_free (rc_style->bg_pixmap_name[state]);
1076 rc_style->bg_pixmap_name[state] = pixmap_file;
1079 return G_TOKEN_NONE;
1083 gtk_rc_find_pixmap_in_path (GScanner *scanner,
1090 for (i = 0; (i < GTK_RC_MAX_PIXMAP_PATHS) && (pixmap_path[i] != NULL); i++)
1092 buf = g_malloc (strlen (pixmap_path[i]) + strlen (pixmap_file) + 2);
1093 sprintf (buf, "%s%c%s", pixmap_path[i], '/', pixmap_file);
1095 fd = open (buf, O_RDONLY);
1105 g_warning ("Unable to locate image file in pixmap_path: \"%s\" line %d",
1106 pixmap_file, scanner->line);
1112 gtk_rc_parse_font (GScanner *scanner,
1113 GtkRcStyle *rc_style)
1117 token = g_scanner_get_next_token (scanner);
1118 if (token != TOKEN_FONT)
1121 token = g_scanner_get_next_token (scanner);
1122 if (token != G_TOKEN_EQUAL_SIGN)
1123 return G_TOKEN_EQUAL_SIGN;
1125 token = g_scanner_get_next_token (scanner);
1126 if (token != G_TOKEN_STRING)
1127 return G_TOKEN_STRING;
1129 if (rc_style->font_name)
1130 g_free (rc_style->font_name);
1131 rc_style->font_name = g_strdup (scanner->value.v_string);
1133 return G_TOKEN_NONE;
1137 gtk_rc_parse_fontset (GScanner *scanner,
1138 GtkRcStyle *rc_style)
1142 token = g_scanner_get_next_token (scanner);
1143 if (token != TOKEN_FONTSET)
1144 return TOKEN_FONTSET;
1146 token = g_scanner_get_next_token (scanner);
1147 if (token != G_TOKEN_EQUAL_SIGN)
1148 return G_TOKEN_EQUAL_SIGN;
1150 token = g_scanner_get_next_token (scanner);
1151 if (token != G_TOKEN_STRING)
1152 return G_TOKEN_STRING;
1154 if (rc_style->fontset_name)
1155 g_free (rc_style->fontset_name);
1156 rc_style->fontset_name = g_strdup (scanner->value.v_string);
1158 return G_TOKEN_NONE;
1162 gtk_rc_parse_state (GScanner *scanner,
1163 GtkStateType *state)
1167 token = g_scanner_get_next_token (scanner);
1168 if (token != G_TOKEN_LEFT_BRACE)
1169 return G_TOKEN_LEFT_BRACE;
1171 token = g_scanner_get_next_token (scanner);
1175 *state = GTK_STATE_ACTIVE;
1177 case TOKEN_INSENSITIVE:
1178 *state = GTK_STATE_INSENSITIVE;
1181 *state = GTK_STATE_NORMAL;
1183 case TOKEN_PRELIGHT:
1184 *state = GTK_STATE_PRELIGHT;
1186 case TOKEN_SELECTED:
1187 *state = GTK_STATE_SELECTED;
1190 return /* G_TOKEN_SYMBOL */ TOKEN_NORMAL;
1193 token = g_scanner_get_next_token (scanner);
1194 if (token != G_TOKEN_RIGHT_BRACE)
1195 return G_TOKEN_RIGHT_BRACE;
1197 return G_TOKEN_NONE;
1201 gtk_rc_parse_color (GScanner *scanner,
1206 token = g_scanner_get_next_token (scanner);
1215 case G_TOKEN_LEFT_CURLY:
1216 token = g_scanner_get_next_token (scanner);
1217 if (token == G_TOKEN_INT)
1218 token_int = scanner->value.v_int;
1219 else if (token == G_TOKEN_FLOAT)
1220 token_int = scanner->value.v_float * 65535.0;
1222 return G_TOKEN_FLOAT;
1223 color->red = CLAMP (token_int, 0, 65535);
1225 token = g_scanner_get_next_token (scanner);
1226 if (token != G_TOKEN_COMMA)
1227 return G_TOKEN_COMMA;
1229 token = g_scanner_get_next_token (scanner);
1230 if (token == G_TOKEN_INT)
1231 token_int = scanner->value.v_int;
1232 else if (token == G_TOKEN_FLOAT)
1233 token_int = scanner->value.v_float * 65535.0;
1235 return G_TOKEN_FLOAT;
1236 color->green = CLAMP (token_int, 0, 65535);
1238 token = g_scanner_get_next_token (scanner);
1239 if (token != G_TOKEN_COMMA)
1240 return G_TOKEN_COMMA;
1242 token = g_scanner_get_next_token (scanner);
1243 if (token == G_TOKEN_INT)
1244 token_int = scanner->value.v_int;
1245 else if (token == G_TOKEN_FLOAT)
1246 token_int = scanner->value.v_float * 65535.0;
1248 return G_TOKEN_FLOAT;
1249 color->blue = CLAMP (token_int, 0, 65535);
1251 token = g_scanner_get_next_token (scanner);
1252 if (token != G_TOKEN_RIGHT_CURLY)
1253 return G_TOKEN_RIGHT_CURLY;
1254 return G_TOKEN_NONE;
1256 case G_TOKEN_STRING:
1257 if (scanner->value.v_string[0] != '#')
1258 return G_TOKEN_STRING;
1260 length = strlen (scanner->value.v_string) - 1;
1261 if (((length % 3) != 0) || (length > 12))
1262 return G_TOKEN_STRING;
1265 for (i = 0, j = 1; i < length; i++, j++)
1266 buf[i] = scanner->value.v_string[j];
1269 sscanf (buf, "%x", &temp);
1272 for (i = 0; i < length; i++, j++)
1273 buf[i] = scanner->value.v_string[j];
1276 sscanf (buf, "%x", &temp);
1277 color->green = temp;
1279 for (i = 0; i < length; i++, j++)
1280 buf[i] = scanner->value.v_string[j];
1283 sscanf (buf, "%x", &temp);
1289 color->green *= 4369;
1290 color->blue *= 4369;
1292 else if (length == 2)
1295 color->green *= 257;
1298 else if (length == 3)
1304 return G_TOKEN_NONE;
1307 return G_TOKEN_STRING;
1312 gtk_rc_parse_pixmap_path (GScanner *scanner)
1316 token = g_scanner_get_next_token (scanner);
1317 if (token != TOKEN_PIXMAP_PATH)
1318 return TOKEN_PIXMAP_PATH;
1320 token = g_scanner_get_next_token (scanner);
1321 if (token != G_TOKEN_STRING)
1322 return G_TOKEN_STRING;
1324 gtk_rc_parse_pixmap_path_string (scanner->value.v_string);
1326 return G_TOKEN_NONE;
1330 gtk_rc_parse_pixmap_path_string (gchar *pix_path)
1334 gint start_offset = 0;
1338 /* free the old one, or just add to the old one ? */
1339 for (path_num=0; pixmap_path[path_num]; path_num++)
1341 g_free (pixmap_path[path_num]);
1342 pixmap_path[path_num] = NULL;
1347 path_len = strlen (pix_path);
1349 buf = g_strdup (pix_path);
1351 for (end_offset = 0; end_offset <= path_len; end_offset++)
1353 if ((buf[end_offset] == ':') ||
1354 (end_offset == path_len))
1356 buf[end_offset] = '\0';
1357 pixmap_path[path_num] = g_strdup (buf + start_offset);
1359 pixmap_path[path_num] = NULL;
1360 start_offset = end_offset + 1;
1367 gtk_rc_parse_widget_style (GScanner *scanner)
1372 token = g_scanner_get_next_token (scanner);
1373 if (token != TOKEN_WIDGET)
1374 return TOKEN_WIDGET;
1376 token = g_scanner_get_next_token (scanner);
1377 if (token != G_TOKEN_STRING)
1378 return G_TOKEN_STRING;
1380 rc_set = g_new (GtkRcSet, 1);
1381 gtk_pattern_spec_init (&rc_set->pspec, scanner->value.v_string);
1383 token = g_scanner_get_next_token (scanner);
1384 if (token != TOKEN_STYLE)
1386 gtk_pattern_spec_free_segs (&rc_set->pspec);
1391 token = g_scanner_get_next_token (scanner);
1392 if (token != G_TOKEN_STRING)
1394 gtk_pattern_spec_free_segs (&rc_set->pspec);
1396 return G_TOKEN_STRING;
1399 rc_set->rc_style = gtk_rc_style_find (scanner->value.v_string);
1400 if (!rc_set->rc_style)
1402 gtk_pattern_spec_free_segs (&rc_set->pspec);
1404 return G_TOKEN_STRING;
1407 gtk_rc_sets_widget = g_slist_prepend (gtk_rc_sets_widget, rc_set);
1409 return G_TOKEN_NONE;
1413 gtk_rc_parse_widget_class_style (GScanner *scanner)
1418 token = g_scanner_get_next_token (scanner);
1419 if (token != TOKEN_WIDGET_CLASS)
1420 return TOKEN_WIDGET_CLASS;
1422 token = g_scanner_get_next_token (scanner);
1423 if (token != G_TOKEN_STRING)
1424 return G_TOKEN_STRING;
1426 rc_set = g_new (GtkRcSet, 1);
1427 gtk_pattern_spec_init (&rc_set->pspec, scanner->value.v_string);
1429 token = g_scanner_get_next_token (scanner);
1430 if (token != TOKEN_STYLE)
1432 gtk_pattern_spec_free_segs (&rc_set->pspec);
1434 return G_TOKEN_STRING;
1437 token = g_scanner_get_next_token (scanner);
1438 if (token != G_TOKEN_STRING)
1440 gtk_pattern_spec_free_segs (&rc_set->pspec);
1442 return G_TOKEN_STRING;
1445 rc_set->rc_style = gtk_rc_style_find (scanner->value.v_string);
1446 if (!rc_set->rc_style)
1448 gtk_pattern_spec_free_segs (&rc_set->pspec);
1450 return G_TOKEN_STRING;
1453 gtk_rc_sets_widget_class = g_slist_prepend (gtk_rc_sets_widget_class, rc_set);
1455 return G_TOKEN_NONE;
1459 typedef GdkPixmap * (*GtkImageLoader) (GdkWindow *window,
1460 GdkColormap *colormap,
1462 GdkColor *transparent_color,
1463 const gchar *filename);
1467 gtk_rc_set_image_loader(GtkImageLoader loader)
1469 image_loader = loader;