diff options
Diffstat (limited to 'gtk/gtkrc.c')
-rw-r--r-- | gtk/gtkrc.c | 1489 |
1 files changed, 1489 insertions, 0 deletions
diff --git a/gtk/gtkrc.c b/gtk/gtkrc.c new file mode 100644 index 0000000000..86bc20121b --- /dev/null +++ b/gtk/gtkrc.c @@ -0,0 +1,1489 @@ +/* GTK - The GIMP Toolkit + * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free + * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#include <ctype.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include "gtkrc.h" + + +enum { + TOKEN_EOF, + TOKEN_LEFT_CURLY, + TOKEN_RIGHT_CURLY, + TOKEN_LEFT_BRACE, + TOKEN_RIGHT_BRACE, + TOKEN_EQUAL_SIGN, + TOKEN_COMMA, + TOKEN_INTEGER, + TOKEN_FLOAT, + TOKEN_STRING, + TOKEN_SYMBOL, + TOKEN_ACTIVE, + TOKEN_BASE, + TOKEN_BG, + TOKEN_BG_PIXMAP, + TOKEN_FG, + TOKEN_FONT, + TOKEN_FONTSET, + TOKEN_INSENSITIVE, + TOKEN_NORMAL, + TOKEN_PIXMAP_PATH, + TOKEN_PRELIGHT, + TOKEN_SELECTED, + TOKEN_STYLE, + TOKEN_TEXT, + TOKEN_WIDGET, + TOKEN_WIDGET_CLASS +}; + +enum { + PARSE_OK, + PARSE_ERROR, + PARSE_SYNTAX +}; + +enum { + PARSE_START, + PARSE_COMMENT, + PARSE_STRING, + PARSE_SYMBOL, + PARSE_NUMBER +}; + + +typedef struct _GtkRcStyle GtkRcStyle; +typedef struct _GtkRcSet GtkRcSet; + +struct _GtkRcStyle +{ + int initialize; + char *name; + char *font_name; + char *fontset_name; + char *bg_pixmap_name[5]; + GtkStyle *style; +}; + +struct _GtkRcSet +{ + char *set; + GtkRcStyle *rc_style; +}; + + +static guint gtk_rc_style_hash (const char *name); +static gint gtk_rc_style_compare (const char *a, + const char *b); +static GtkRcStyle* gtk_rc_style_find (const char *name); +static GtkRcStyle* gtk_rc_styles_match (GSList *sets, + const char *path); +static gint gtk_rc_style_match (const char *set, + const char *path); +static void gtk_rc_style_init (GtkRcStyle *rc_style); +static gint gtk_rc_get_token (void); +static gint gtk_rc_simple_token (char ch); +static gint gtk_rc_symbol_token (const char *sym); +static gint gtk_rc_get_next_token (void); +static gint gtk_rc_peek_next_token (void); +static gint gtk_rc_parse_statement (void); +static gint gtk_rc_parse_style (void); +static gint gtk_rc_parse_style_option (GtkRcStyle *rc_style); +static gint gtk_rc_parse_base (GtkStyle *style); +static gint gtk_rc_parse_bg (GtkStyle *style); +static gint gtk_rc_parse_fg (GtkStyle *style); +static gint gtk_rc_parse_bg_pixmap (GtkRcStyle *rc_style); +static gint gtk_rc_parse_font (GtkRcStyle *rc_style); +static gint gtk_rc_parse_fontset (GtkRcStyle *rc_style); +static gint gtk_rc_parse_state (GtkStateType *state); +static gint gtk_rc_parse_color (GdkColor *color); +static gint gtk_rc_parse_pixmap_path (void); +static void gtk_rc_parse_pixmap_path_string (gchar *pix_path); +static char* gtk_rc_find_pixmap_in_path (gchar *pixmap_file); +static gint gtk_rc_parse_widget_style (void); +static gint gtk_rc_parse_widget_class_style (void); +static char* gtk_rc_widget_path (GtkWidget *widget); +static char* gtk_rc_widget_class_path (GtkWidget *widget); + + +static struct +{ + char *name; + int token; +} symbols[] = + { + { "ACTIVE", TOKEN_ACTIVE }, + { "base", TOKEN_BASE }, + { "bg", TOKEN_BG }, + { "bg_pixmap", TOKEN_BG_PIXMAP }, + { "fg", TOKEN_FG }, + { "font", TOKEN_FONT }, + { "fontset", TOKEN_FONTSET }, + { "INSENSITIVE", TOKEN_INSENSITIVE }, + { "NORMAL", TOKEN_NORMAL }, + { "pixmap_path", TOKEN_PIXMAP_PATH }, + { "PRELIGHT", TOKEN_PRELIGHT }, + { "SELECTED", TOKEN_SELECTED }, + { "style", TOKEN_STYLE }, + { "text", TOKEN_TEXT }, + { "widget", TOKEN_WIDGET }, + { "widget_class", TOKEN_WIDGET_CLASS }, + }; + +static int nsymbols = sizeof (symbols) / sizeof (symbols[0]); + +static struct +{ + char ch; + int token; +} simple_tokens[] = + { + { '{', TOKEN_LEFT_CURLY }, + { '}', TOKEN_RIGHT_CURLY }, + { '[', TOKEN_LEFT_BRACE }, + { ']', TOKEN_RIGHT_BRACE }, + { '=', TOKEN_EQUAL_SIGN }, + { ',', TOKEN_COMMA }, + }; + +static int nsimple_tokens = sizeof (simple_tokens) / sizeof (simple_tokens[0]); + +static FILE *input_fp = NULL; +static char *buffer = NULL; +static char *tokenbuf = NULL; +static int position = 0; +static int linenum = 1; +static int buffer_size = 1024; +static int tokenbuf_size = 1024; + +static int done; +static int cur_token; +static int next_token; + +static char *token_str; +static double token_float; +static int token_int; + +static GHashTable *rc_style_ht = NULL; +static GSList *widget_sets = NULL; +static GSList *widget_class_sets = NULL; + +#define GTK_RC_MAX_PIXMAP_PATHS 128 +static gchar *pixmap_path[GTK_RC_MAX_PIXMAP_PATHS]; + + +void +gtk_rc_init () +{ + rc_style_ht = g_hash_table_new ((GHashFunc) gtk_rc_style_hash, + (GCompareFunc) gtk_rc_style_compare); +} + +void +gtk_rc_parse (const char *filename) +{ + input_fp = fopen (filename, "r"); + if (!input_fp) + return; + + buffer = g_new (char, buffer_size + tokenbuf_size); + tokenbuf = buffer + buffer_size; + position = 0; + linenum = 1; + + cur_token = -1; + next_token = -1; + done = FALSE; + + while (!done) + { + if (gtk_rc_parse_statement () != PARSE_OK) + { + g_warning ("rc file parse error: \"%s\" line %d", + filename, linenum); + done = TRUE; + } + } + + fclose (input_fp); + + g_free (buffer); + + buffer = NULL; + tokenbuf = NULL; + position = 0; + linenum = 1; +} + +GtkStyle* +gtk_rc_get_style (GtkWidget *widget) +{ + GtkRcStyle *rc_style; + char *path; + + if (widget_sets) + { + path = gtk_rc_widget_path (widget); + if (path) + { + rc_style = gtk_rc_styles_match (widget_sets, path); + g_free (path); + + if (rc_style) + { + gtk_rc_style_init (rc_style); + return rc_style->style; + } + } + } + + if (widget_class_sets) + { + path = gtk_rc_widget_class_path (widget); + if (path) + { + rc_style = gtk_rc_styles_match (widget_class_sets, path); + g_free (path); + + if (rc_style) + { + gtk_rc_style_init (rc_style); + return rc_style->style; + } + } + } + + return widget->style; +} + +void +gtk_rc_add_widget_name_style (GtkStyle *style, + const char *pattern) +{ + GtkRcStyle *rc_style; + GtkRcSet *rc_set; + int i; + + gtk_style_ref (style); + + rc_style = g_new (GtkRcStyle, 1); + rc_style->initialize = FALSE; + rc_style->name = NULL; + rc_style->font_name = NULL; + rc_style->fontset_name = NULL; + + for (i = 0; i < 5; i++) + rc_style->bg_pixmap_name[i] = NULL; + + rc_style->style = style; + + rc_set = g_new (GtkRcSet, 1); + rc_set->set = g_strdup (pattern); + rc_set->rc_style = rc_style; + + widget_sets = g_slist_append (widget_sets, rc_set); +} + +void +gtk_rc_add_widget_class_style (GtkStyle *style, + const char *pattern) +{ + GtkRcStyle *rc_style; + GtkRcSet *rc_set; + int i; + + gtk_style_ref (style); + + rc_style = g_new (GtkRcStyle, 1); + rc_style->initialize = FALSE; + rc_style->name = NULL; + rc_style->font_name = NULL; + rc_style->fontset_name = NULL; + + for (i = 0; i < 5; i++) + rc_style->bg_pixmap_name[i] = NULL; + + rc_style->style = style; + + rc_set = g_new (GtkRcSet, 1); + rc_set->set = g_strdup (pattern); + rc_set->rc_style = rc_style; + + widget_class_sets = g_slist_append (widget_class_sets, rc_set); +} + + +static guint +gtk_rc_style_hash (const char *name) +{ + guint result; + + result = 0; + while (*name) + result += (result << 3) + *name++; + + return result; +} + +static gint +gtk_rc_style_compare (const char *a, + const char *b) +{ + return (strcmp (a, b) == 0); +} + +static GtkRcStyle* +gtk_rc_style_find (const char *name) +{ + GtkRcStyle *rc_style; + + rc_style = g_hash_table_lookup (rc_style_ht, (gpointer) name); + + return rc_style; +} + +static GtkRcStyle* +gtk_rc_styles_match (GSList *sets, + const char *path) +{ + GtkRcSet *rc_set; + + while (sets) + { + rc_set = sets->data; + sets = sets->next; + + if (gtk_rc_style_match (rc_set->set, path)) + return rc_set->rc_style; + } + + return NULL; +} + +static gint +gtk_rc_style_match (const char *set, + const char *path) +{ + char ch; + + while (1) + { + ch = *set++; + if (ch == '\0') + return (*path == '\0'); + + switch (ch) + { + case '*': + while (*set == '*') + set++; + + ch = *set++; + if (ch == '\0') + return TRUE; + + while (*path) + { + while (*path && (ch != *path)) + path++; + + if (!(*path)) + return FALSE; + + path++; + if (gtk_rc_style_match (set, path)) + return TRUE; + } + break; + + case '?': + break; + + default: + if (ch == *path) + path++; + else + return FALSE; + break; + } + } + + return TRUE; +} + +static void +gtk_rc_style_init (GtkRcStyle *rc_style) +{ + GdkFont *old_font; + gint i; + + if (rc_style->initialize) + { + rc_style->initialize = FALSE; + + if (rc_style->fontset_name) + { + old_font = rc_style->style->font; + rc_style->style->font = gdk_fontset_load (rc_style->fontset_name); + if (rc_style->style->font) + gdk_fontset_free (old_font); + else + rc_style->style->font = old_font; + } + else if (rc_style->font_name) + { + old_font = rc_style->style->font; + rc_style->style->font = gdk_font_load (rc_style->font_name); + if (rc_style->style->font) + gdk_font_free (old_font); + else + rc_style->style->font = old_font; + } + + for (i = 0; i < 5; i++) + if (rc_style->bg_pixmap_name[i]) + { + if (strcmp (rc_style->bg_pixmap_name[i], "<parent>") == 0) + rc_style->style->bg_pixmap[i] = (GdkPixmap*) GDK_PARENT_RELATIVE; + else + rc_style->style->bg_pixmap[i] = gdk_pixmap_create_from_xpm (NULL, NULL, + &rc_style->style->bg[i], + rc_style->bg_pixmap_name[i]); + } + } +} + +static gint +gtk_rc_get_token () +{ + int tokenpos; + int state; + int count; + int token; + int hex_number = FALSE; + int float_number = FALSE; + char ch; + + tokenpos = 0; + state = PARSE_START; + + while (1) + { + if (position >= (buffer_size - 1)) + position = 0; + if (!position || (buffer[position] == '\0')) + { + count = fread (buffer, sizeof (char), buffer_size - 1, input_fp); + if ((count == 0) && feof (input_fp)) + return TOKEN_EOF; + buffer[count] = '\0'; + } + + ch = buffer[position++]; + if (ch == '\n') + linenum += 1; + + switch (state) + { + case PARSE_START: + token = gtk_rc_simple_token (ch); + + if (token) + return token; + else if (ch == '#') + state = PARSE_COMMENT; + else if (ch == '"') + state = PARSE_STRING; + else if ((ch == ' ') || (ch == '\t') || (ch == '\n')) + break; + else if (ch == '.') + { + hex_number = FALSE; + float_number = TRUE; + tokenbuf[tokenpos++] = ch; + state = PARSE_NUMBER; + } + else if ((ch == '$') || (ch == '#')) + { + hex_number = TRUE; + float_number = FALSE; + state = PARSE_NUMBER; + } + else if (isdigit (ch)) + { + hex_number = FALSE; + float_number = FALSE; + tokenbuf[tokenpos++] = ch; + state = PARSE_NUMBER; + } + else + { + tokenbuf[tokenpos++] = ch; + state = PARSE_SYMBOL; + } + break; + + case PARSE_COMMENT: + if (ch == '\n') + state = PARSE_START; + break; + + case PARSE_STRING: + if (ch != '"') + { + tokenbuf[tokenpos++] = ch; + } + else + { + tokenbuf[tokenpos] = '\0'; + token_str = tokenbuf; + return TOKEN_STRING; + } + break; + + case PARSE_SYMBOL: + if ((ch != ' ') && (ch != '\t') && (ch != '\n') && + (gtk_rc_simple_token (ch) == 0)) + { + tokenbuf[tokenpos++] = ch; + } + else + { + position -= 1; + tokenbuf[tokenpos] = '\0'; + token_str = tokenbuf; + return gtk_rc_symbol_token (tokenbuf); + } + break; + + case PARSE_NUMBER: + if (isdigit (ch) || (hex_number && isxdigit (ch))) + { + tokenbuf[tokenpos++] = ch; + } + else if (!hex_number && !float_number && (ch == '.')) + { + float_number = TRUE; + tokenbuf[tokenpos++] = ch; + } + else if (!float_number && + (ch == 'x') && (tokenpos == 1) && + (tokenbuf[0] == '0')) + { + hex_number = TRUE; + tokenpos = 0; + } + else + { + position -= 1; + tokenbuf[tokenpos] = '\0'; + if (float_number) + { + sscanf (tokenbuf, "%lf", &token_float); + return TOKEN_FLOAT; + } + else + { + sscanf (tokenbuf, (hex_number ? "%x" : "%d"), &token_int); + return TOKEN_INTEGER; + } + } + break; + } + } +} + +static gint +gtk_rc_simple_token (char ch) +{ + gint i; + + for (i = 0; i < nsimple_tokens; i++) + if (simple_tokens[i].ch == ch) + return simple_tokens[i].token; + + return 0; +} + +static gint +gtk_rc_symbol_token (const char *sym) +{ + gint i; + + for (i = 0; i < nsymbols; i++) + if (strcmp (symbols[i].name, sym) == 0) + return symbols[i].token; + + return TOKEN_STRING; +} + +static gint +gtk_rc_get_next_token () +{ + if (next_token != -1) + { + cur_token = next_token; + next_token = -1; + } + else + { + cur_token = gtk_rc_get_token (); + } + + return cur_token; +} + +static gint +gtk_rc_peek_next_token () +{ + if (next_token == -1) + next_token = gtk_rc_get_token (); + + return next_token; +} + +static gint +gtk_rc_parse_statement () +{ + gint token; + gint error; + + token = gtk_rc_peek_next_token (); + if (!token) + { + done = TRUE; + return PARSE_OK; + } + + error = gtk_rc_parse_style (); + if (error != PARSE_SYNTAX) + return error; + + error = gtk_rc_parse_pixmap_path (); + if (error != PARSE_SYNTAX) + return error; + + error = gtk_rc_parse_widget_style (); + if (error != PARSE_SYNTAX) + return error; + + error = gtk_rc_parse_widget_class_style (); + + return error; +} + +static gint +gtk_rc_parse_style () +{ + GtkRcStyle *rc_style; + GtkRcStyle *parent_style; + gint token; + gint error; + gint insert; + gint i; + + token = gtk_rc_peek_next_token (); + if (!token) + return PARSE_ERROR; + if (token != TOKEN_STYLE) + return PARSE_SYNTAX; + token = gtk_rc_get_next_token (); + + token = gtk_rc_get_next_token (); + if (!token || (token != TOKEN_STRING)) + return PARSE_ERROR; + + insert = FALSE; + rc_style = g_hash_table_lookup (rc_style_ht, token_str); + + if (!rc_style) + { + insert = TRUE; + rc_style = g_new (GtkRcStyle, 1); + rc_style->initialize = TRUE; + rc_style->name = g_strdup (token_str); + rc_style->font_name = NULL; + rc_style->fontset_name = NULL; + + for (i = 0; i < 5; i++) + rc_style->bg_pixmap_name[i] = NULL; + + rc_style->style = gtk_style_new (); + gtk_style_ref (rc_style->style); + } + + token = gtk_rc_peek_next_token (); + if (token == TOKEN_EQUAL_SIGN) + { + token = gtk_rc_get_next_token (); + + token = gtk_rc_get_next_token (); + if (!token || (token != TOKEN_STRING)) + { + if (insert) + { + gtk_style_unref (rc_style->style); + g_free (rc_style); + } + return PARSE_ERROR; + } + + parent_style = g_hash_table_lookup (rc_style_ht, token_str); + if (parent_style) + { + for (i = 0; i < 5; i++) + { + rc_style->style->fg[i] = parent_style->style->fg[i]; + rc_style->style->bg[i] = parent_style->style->bg[i]; + rc_style->style->light[i] = parent_style->style->light[i]; + rc_style->style->dark[i] = parent_style->style->dark[i]; + rc_style->style->mid[i] = parent_style->style->mid[i]; + rc_style->style->text[i] = parent_style->style->text[i]; + rc_style->style->base[i] = parent_style->style->base[i]; + } + + rc_style->style->black = parent_style->style->black; + rc_style->style->white = parent_style->style->white; + + if (rc_style->fontset_name) + { + g_free (rc_style->fontset_name); + rc_style->fontset_name = g_strdup (parent_style->fontset_name); + } + else if (rc_style->font_name) + { + g_free (rc_style->font_name); + rc_style->font_name = g_strdup (parent_style->font_name); + } + + for (i = 0; i < 5; i++) + { + if (rc_style->bg_pixmap_name[i]) + g_free (rc_style->bg_pixmap_name[i]); + rc_style->bg_pixmap_name[i] = g_strdup (parent_style->bg_pixmap_name[i]); + } + } + } + + token = gtk_rc_get_next_token (); + if (!token || (token != TOKEN_LEFT_CURLY)) + { + if (insert) + { + gtk_style_unref (rc_style->style); + g_free (rc_style); + } + return PARSE_ERROR; + } + + while (1) + { + error = gtk_rc_parse_style_option (rc_style); + if (error == PARSE_SYNTAX) + break; + if (error == PARSE_ERROR) + { + if (insert) + { + gtk_style_unref (rc_style->style); + g_free (rc_style); + } + return error; + } + } + + token = gtk_rc_get_next_token (); + if (!token || (token != TOKEN_RIGHT_CURLY)) + { + if (insert) + { + if (rc_style->fontset_name) + g_free (rc_style->fontset_name); + else if (rc_style->font_name) + g_free (rc_style->font_name); + + for (i = 0; i < 5; i++) + if (rc_style->bg_pixmap_name[i]) + g_free (rc_style->bg_pixmap_name[i]); + + gtk_style_unref (rc_style->style); + g_free (rc_style); + } + return PARSE_ERROR; + } + + if (insert) + g_hash_table_insert (rc_style_ht, rc_style->name, rc_style); + + return PARSE_OK; +} + +static gint +gtk_rc_parse_style_option (GtkRcStyle *rc_style) +{ + gint token; + gint error; + + token = gtk_rc_peek_next_token (); + if (!token) + return PARSE_ERROR; + + error = gtk_rc_parse_base (rc_style->style); + if (error != PARSE_SYNTAX) + return error; + + error = gtk_rc_parse_bg (rc_style->style); + if (error != PARSE_SYNTAX) + return error; + + error = gtk_rc_parse_fg (rc_style->style); + if (error != PARSE_SYNTAX) + return error; + + error = gtk_rc_parse_bg_pixmap (rc_style); + if (error != PARSE_SYNTAX) + return error; + + error = gtk_rc_parse_font (rc_style); + if (error != PARSE_SYNTAX) + return error; + + error = gtk_rc_parse_fontset (rc_style); + + return error; +} + +static gint +gtk_rc_parse_base (GtkStyle *style) +{ + GtkStateType state; + gint token; + gint error; + + token = gtk_rc_peek_next_token (); + if (!token) + return PARSE_ERROR; + if (token != TOKEN_BASE) + return PARSE_SYNTAX; + token = gtk_rc_get_next_token (); + + error = gtk_rc_parse_state (&state); + if (error != PARSE_OK) + return error; + + token = gtk_rc_get_next_token (); + if (!token || (token != TOKEN_EQUAL_SIGN)) + return PARSE_ERROR; + + error = gtk_rc_parse_color (&style->base[state]); + + return error; +} + +static gint +gtk_rc_parse_bg (GtkStyle *style) +{ + GtkStateType state; + gint token; + gint error; + + token = gtk_rc_peek_next_token (); + if (!token) + return PARSE_ERROR; + if (token != TOKEN_BG) + return PARSE_SYNTAX; + token = gtk_rc_get_next_token (); + + error = gtk_rc_parse_state (&state); + if (error != PARSE_OK) + return error; + + token = gtk_rc_get_next_token (); + if (!token || (token != TOKEN_EQUAL_SIGN)) + return PARSE_ERROR; + + error = gtk_rc_parse_color (&style->bg[state]); + + return error; +} + +static gint +gtk_rc_parse_fg (GtkStyle *style) +{ + GtkStateType state; + gint token; + gint error; + + token = gtk_rc_peek_next_token (); + if (!token) + return PARSE_ERROR; + if (token != TOKEN_FG) + return PARSE_SYNTAX; + token = gtk_rc_get_next_token (); + + error = gtk_rc_parse_state (&state); + if (error != PARSE_OK) + return error; + + token = gtk_rc_get_next_token (); + if (!token || (token != TOKEN_EQUAL_SIGN)) + return PARSE_ERROR; + + error = gtk_rc_parse_color (&style->fg[state]); + + return error; +} + +static gint +gtk_rc_parse_bg_pixmap (GtkRcStyle *rc_style) +{ + GtkStateType state; + gint token; + gint error; + gchar *pixmap_file; + + token = gtk_rc_peek_next_token (); + if (!token) + return PARSE_ERROR; + if (token != TOKEN_BG_PIXMAP) + return PARSE_SYNTAX; + token = gtk_rc_get_next_token (); + + error = gtk_rc_parse_state (&state); + if (error != PARSE_OK) + return error; + + token = gtk_rc_get_next_token (); + if (!token || (token != TOKEN_EQUAL_SIGN)) + return PARSE_ERROR; + + token = gtk_rc_get_next_token (); + if (!token || (token != TOKEN_STRING)) + return PARSE_ERROR; + + if (strcmp (token_str, "<parent>")) + pixmap_file = gtk_rc_find_pixmap_in_path (token_str); + else + pixmap_file = g_strdup(token_str); + + if (pixmap_file) + { + if (rc_style->bg_pixmap_name[state]) + g_free (rc_style->bg_pixmap_name[state]); + rc_style->bg_pixmap_name[state] = pixmap_file; + } + + return PARSE_OK; +} + +static char* +gtk_rc_find_pixmap_in_path (gchar *pixmap_file) +{ + gint i; + FILE *fp; + gchar *buf; + + for (i = 0; (i < GTK_RC_MAX_PIXMAP_PATHS) && (pixmap_path[i] != NULL); i++) + { + buf = g_malloc (strlen (pixmap_path[i]) + strlen (pixmap_file) + 2); + sprintf (buf, "%s%c%s", pixmap_path[i], '/', pixmap_file); + + fp = fopen (buf, "r"); + if (fp) + { + fclose (fp); + return buf; + } + + g_free (buf); + } + + g_warning ("Unable to locate image file in pixmap_path: \"%s\" line %d", + pixmap_file, linenum); + + return NULL; +} + +static gint +gtk_rc_parse_font (GtkRcStyle *rc_style) +{ + gint token; + + token = gtk_rc_peek_next_token (); + if (!token) + return PARSE_ERROR; + if (token != TOKEN_FONT) + return PARSE_SYNTAX; + token = gtk_rc_get_next_token (); + + token = gtk_rc_get_next_token (); + if (!token || (token != TOKEN_EQUAL_SIGN)) + return PARSE_ERROR; + + token = gtk_rc_get_next_token (); + if (!token || (token != TOKEN_STRING)) + return PARSE_ERROR; + + if (rc_style->font_name) + g_free (rc_style->font_name); + rc_style->font_name = g_strdup (token_str); + + return PARSE_OK; +} + +static gint +gtk_rc_parse_fontset (GtkRcStyle *rc_style) +{ + gint token; + + token = gtk_rc_peek_next_token (); + if (!token) + return PARSE_ERROR; + if (token != TOKEN_FONTSET) + return PARSE_SYNTAX; + token = gtk_rc_get_next_token (); + + token = gtk_rc_get_next_token (); + if (!token || (token != TOKEN_EQUAL_SIGN)) + return PARSE_ERROR; + + token = gtk_rc_get_next_token (); + if (!token || (token != TOKEN_STRING)) + return PARSE_ERROR; + + if (rc_style->fontset_name) + g_free (rc_style->fontset_name); + rc_style->fontset_name = g_strdup (token_str); + + return PARSE_OK; +} + +static gint +gtk_rc_parse_state (GtkStateType *state) +{ + gint token; + + token = gtk_rc_peek_next_token (); + if (!token) + return PARSE_ERROR; + if (token != TOKEN_LEFT_BRACE) + return PARSE_SYNTAX; + token = gtk_rc_get_next_token (); + + token = gtk_rc_get_next_token (); + if (token == TOKEN_ACTIVE) + *state = GTK_STATE_ACTIVE; + else if (token == TOKEN_INSENSITIVE) + *state = GTK_STATE_INSENSITIVE; + else if (token == TOKEN_NORMAL) + *state = GTK_STATE_NORMAL; + else if (token == TOKEN_PRELIGHT) + *state = GTK_STATE_PRELIGHT; + else if (token == TOKEN_SELECTED) + *state = GTK_STATE_SELECTED; + else + return PARSE_ERROR; + + token = gtk_rc_get_next_token (); + if (!token || (token != TOKEN_RIGHT_BRACE)) + return PARSE_ERROR; + + return PARSE_OK; +} + +static gint +gtk_rc_parse_color (GdkColor *color) +{ + gint token; + gint length; + gint temp; + gchar buf[9]; + gint i, j; + + token = gtk_rc_peek_next_token (); + if (!token) + return PARSE_ERROR; + + switch (token) + { + case TOKEN_LEFT_CURLY: + token = gtk_rc_get_next_token (); + + token = gtk_rc_get_next_token (); + if (!token || ((token != TOKEN_INTEGER) && (token != TOKEN_FLOAT))) + return PARSE_ERROR; + + if (token == TOKEN_FLOAT) + token_int = token_float * 65535.0; + if (token_int < 0) + token_int = 0; + if (token_int > 65535) + token_int = 65535; + + color->red = token_int; + + token = gtk_rc_get_next_token (); + if (!token || (token != TOKEN_COMMA)) + return PARSE_ERROR; + + token = gtk_rc_get_next_token (); + if (!token || ((token != TOKEN_INTEGER) && (token != TOKEN_FLOAT))) + return PARSE_ERROR; + + if (token == TOKEN_FLOAT) + token_int = token_float * 65535.0; + if (token_int < 0) + token_int = 0; + if (token_int > 65535) + token_int = 65535; + + color->green = token_int; + + token = gtk_rc_get_next_token (); + if (!token || (token != TOKEN_COMMA)) + return PARSE_ERROR; + + token = gtk_rc_get_next_token (); + if (!token || ((token != TOKEN_INTEGER) && (token != TOKEN_FLOAT))) + return PARSE_ERROR; + + if (token == TOKEN_FLOAT) + token_int = token_float * 65535.0; + if (token_int < 0) + token_int = 0; + if (token_int > 65535) + token_int = 65535; + + color->blue = token_int; + + token = gtk_rc_get_next_token (); + if (!token || (token != TOKEN_RIGHT_CURLY)) + return PARSE_ERROR; + break; + + case TOKEN_STRING: + token = gtk_rc_get_next_token (); + + if (token_str[0] != '#') + return PARSE_ERROR; + + length = strlen (token_str) - 1; + if (((length % 3) != 0) || (length > 12)) + return PARSE_ERROR; + length /= 3; + + for (i = 0, j = 1; i < length; i++, j++) + buf[i] = token_str[j]; + buf[i] = '\0'; + + sscanf (buf, "%x", &temp); + color->red = temp; + + for (i = 0; i < length; i++, j++) + buf[i] = token_str[j]; + buf[i] = '\0'; + + sscanf (buf, "%x", &temp); + color->green = temp; + + for (i = 0; i < length; i++, j++) + buf[i] = token_str[j]; + buf[i] = '\0'; + + sscanf (buf, "%x", &temp); + color->blue = temp; + + if (length == 1) + { + color->red *= 4369; + color->green *= 4369; + color->blue *= 4369; + } + else if (length == 2) + { + color->red *= 257; + color->green *= 257; + color->blue *= 257; + } + else if (length == 3) + { + color->red *= 16; + color->green *= 16; + color->blue *= 16; + } + break; + + default: + return PARSE_SYNTAX; + } + + return PARSE_OK; +} + +static gint +gtk_rc_parse_pixmap_path () +{ + gint token; + + token = gtk_rc_peek_next_token (); + if (!token) + return PARSE_ERROR; + if (token != TOKEN_PIXMAP_PATH) + return PARSE_SYNTAX; + token = gtk_rc_get_next_token (); + + token = gtk_rc_get_next_token (); + + if (!token || (token != TOKEN_STRING)) + return PARSE_ERROR; + + gtk_rc_parse_pixmap_path_string(token_str); + + return PARSE_OK; +} + +static void gtk_rc_parse_pixmap_path_string(gchar *pix_path) +{ + gchar *buf; + gint end_offset; + gint start_offset = 0; + gint path_len; + gint path_num; + + /* free the old one, or just add to the old one ? */ + for (path_num=0; pixmap_path[path_num]; path_num++) + { + g_free(pixmap_path[path_num]); + pixmap_path[path_num] = NULL; + } + + path_num = 0; + + path_len = strlen(pix_path); + + buf = g_strdup(pix_path); + + for(end_offset = 0; end_offset <= path_len; end_offset++) + { + if ( (buf[end_offset] == ':') || (end_offset == path_len) ) + { + buf[end_offset] = '\0'; + pixmap_path[path_num] = g_strdup(buf + start_offset); + path_num++; + pixmap_path[path_num] = NULL; + start_offset = end_offset + 1; + g_free(buf); + buf = g_strdup(pix_path); + } + } + g_free(buf); +} + +static gint +gtk_rc_parse_widget_style () +{ + GtkRcSet *rc_set; + gint token; + + token = gtk_rc_peek_next_token (); + if (!token) + return PARSE_ERROR; + if (token != TOKEN_WIDGET) + return PARSE_SYNTAX; + token = gtk_rc_get_next_token (); + + token = gtk_rc_get_next_token (); + if (!token || (token != TOKEN_STRING)) + return PARSE_ERROR; + + rc_set = g_new (GtkRcSet, 1); + rc_set->set = g_strdup (token_str); + + token = gtk_rc_get_next_token (); + if (!token || (token != TOKEN_STYLE)) + { + g_free (rc_set->set); + g_free (rc_set); + return PARSE_ERROR; + } + + token = gtk_rc_get_next_token (); + if (!token || (token != TOKEN_STRING)) + { + g_free (rc_set->set); + g_free (rc_set); + return PARSE_ERROR; + } + + rc_set->rc_style = gtk_rc_style_find (token_str); + if (!rc_set->rc_style) + { + g_free (rc_set->set); + g_free (rc_set); + return PARSE_ERROR; + } + + widget_sets = g_slist_append (widget_sets, rc_set); + + return PARSE_OK; +} + +static gint +gtk_rc_parse_widget_class_style () +{ + GtkRcSet *rc_set; + gint token; + + token = gtk_rc_peek_next_token (); + if (!token) + return PARSE_ERROR; + if (token != TOKEN_WIDGET_CLASS) + return PARSE_SYNTAX; + token = gtk_rc_get_next_token (); + + token = gtk_rc_get_next_token (); + if (!token || (token != TOKEN_STRING)) + return PARSE_ERROR; + + rc_set = g_new (GtkRcSet, 1); + rc_set->set = g_strdup (token_str); + + token = gtk_rc_get_next_token (); + if (!token || (token != TOKEN_STYLE)) + { + g_free (rc_set->set); + g_free (rc_set); + return PARSE_ERROR; + } + + token = gtk_rc_get_next_token (); + if (!token || (token != TOKEN_STRING)) + { + g_free (rc_set->set); + g_free (rc_set); + return PARSE_ERROR; + } + + rc_set->rc_style = gtk_rc_style_find (token_str); + if (!rc_set->rc_style) + { + g_free (rc_set->set); + g_free (rc_set); + return PARSE_ERROR; + } + + widget_class_sets = g_slist_append (widget_class_sets, rc_set); + + return PARSE_OK; +} + +static char* +gtk_rc_widget_path (GtkWidget *widget) +{ + GtkWidget *tmp_widget; + char *path; + char *name; + int pathlength; + int namelength; + + path = NULL; + pathlength = 0; + + tmp_widget = widget; + while (tmp_widget) + { + name = gtk_widget_get_name (tmp_widget); + pathlength += strlen (name); + + tmp_widget = tmp_widget->parent; + + if (tmp_widget) + pathlength += 1; + } + + path = g_new (char, pathlength + 1); + path[pathlength] = '\0'; + + tmp_widget = widget; + while (tmp_widget) + { + name = gtk_widget_get_name (tmp_widget); + namelength = strlen (name); + + strncpy (&path[pathlength - namelength], name, namelength); + pathlength -= namelength; + + tmp_widget = tmp_widget->parent; + + if (tmp_widget) + { + pathlength -= 1; + path[pathlength] = '.'; + } + } + + return path; +} + +static char* +gtk_rc_widget_class_path (GtkWidget *widget) +{ + GtkWidget *tmp_widget; + char *path; + char *name; + int pathlength; + int namelength; + + path = NULL; + pathlength = 0; + + tmp_widget = widget; + while (tmp_widget) + { + name = gtk_type_name (GTK_WIDGET_TYPE (tmp_widget)); + pathlength += strlen (name); + + tmp_widget = tmp_widget->parent; + + if (tmp_widget) + pathlength += 1; + } + + path = g_new (char, pathlength + 1); + path[pathlength] = '\0'; + + tmp_widget = widget; + while (tmp_widget) + { + name = gtk_type_name (GTK_WIDGET_TYPE (tmp_widget)); + namelength = strlen (name); + + strncpy (&path[pathlength - namelength], name, namelength); + pathlength -= namelength; + + tmp_widget = tmp_widget->parent; + + if (tmp_widget) + { + pathlength -= 1; + path[pathlength] = '.'; + } + } + + return path; +} |