X-Git-Url: http://pileus.org/git/?a=blobdiff_plain;f=gtk%2Fgtkrc.c;h=adfa045a663e15bcc60f65bb6d2f67ee66f85944;hb=4af7480f8f64bd7709500bc27af91e2243898969;hp=9f4fc4ef19ea3030c1c2a24708605c9139a5c7d0;hpb=2b2667e791aab4d0cfa46d3e9de560a9f50692d9;p=~andy%2Fgtk diff --git a/gtk/gtkrc.c b/gtk/gtkrc.c index 9f4fc4ef1..adfa045a6 100644 --- a/gtk/gtkrc.c +++ b/gtk/gtkrc.c @@ -12,112 +12,98 @@ * 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. + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. */ #include #include +#include +#include #include #include #include #include "gtkrc.h" - - -enum { - TOKEN_INVALID = G_TOKEN_LAST, - 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 -}; +#include "gtkbindings.h" typedef struct _GtkRcStyle GtkRcStyle; typedef struct _GtkRcSet GtkRcSet; +typedef struct _GtkRcNode GtkRcNode; +typedef struct _GtkRcFile GtkRcFile; + +struct _GtkRcNode +{ + GdkColormap *cmap; + GtkStyle *style; +}; struct _GtkRcStyle { - int initialize; char *name; char *font_name; char *fontset_name; char *bg_pixmap_name[5]; - GtkStyle *style; + GtkStyle *proto_style; + GList *styles; }; struct _GtkRcSet { - char *set; - GtkRcStyle *rc_style; + GtkPatternSpec pspec; + GtkRcStyle *rc_style; }; +struct _GtkRcFile +{ + time_t mtime; + gchar *name; + gchar *canonical_name; + gboolean reload; +}; 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); + guint path_length, + gchar *path, + gchar *path_reversed); +static GtkStyle* gtk_rc_style_init (GtkRcStyle *rc_style, + GdkColormap *cmap); +static void gtk_rc_parse_file (const gchar *filename, + gboolean reload); + static void gtk_rc_parse_any (const gchar *input_name, gint input_fd, const gchar *input_string); -static gint gtk_rc_parse_statement (GScanner *scanner); -static gint gtk_rc_parse_style (GScanner *scanner); -static gint gtk_rc_parse_style_option (GScanner *scanner, - GtkRcStyle *rc_style); -static gint gtk_rc_parse_base (GScanner *scanner, +static guint gtk_rc_parse_statement (GScanner *scanner); +static guint gtk_rc_parse_style (GScanner *scanner); +static guint gtk_rc_parse_base (GScanner *scanner, GtkStyle *style); -static gint gtk_rc_parse_bg (GScanner *scanner, +static guint gtk_rc_parse_bg (GScanner *scanner, GtkStyle *style); -static gint gtk_rc_parse_fg (GScanner *scanner, +static guint gtk_rc_parse_fg (GScanner *scanner, GtkStyle *style); -static gint gtk_rc_parse_bg_pixmap (GScanner *scanner, +static guint gtk_rc_parse_text (GScanner *scanner, + GtkStyle *style); +static guint gtk_rc_parse_bg_pixmap (GScanner *scanner, GtkRcStyle *rc_style); -static gint gtk_rc_parse_font (GScanner *scanner, +static guint gtk_rc_parse_font (GScanner *scanner, GtkRcStyle *rc_style); -static gint gtk_rc_parse_fontset (GScanner *scanner, +static guint gtk_rc_parse_fontset (GScanner *scanner, GtkRcStyle *rc_style); -static gint gtk_rc_parse_state (GScanner *scanner, - GtkStateType *state); -static gint gtk_rc_parse_color (GScanner *scanner, - GdkColor *color); -static gint gtk_rc_parse_pixmap_path (GScanner *scanner); +static guint gtk_rc_parse_pixmap_path (GScanner *scanner); static void gtk_rc_parse_pixmap_path_string (gchar *pix_path); static char* gtk_rc_find_pixmap_in_path (GScanner *scanner, gchar *pixmap_file); -static gint gtk_rc_parse_widget_style (GScanner *scanner); -static gint gtk_rc_parse_widget_class_style (GScanner *scanner); -static char* gtk_rc_widget_path (GtkWidget *widget); -static char* gtk_rc_widget_class_path (GtkWidget *widget); +static guint gtk_rc_parse_path_pattern (GScanner *scanner); +static void gtk_rc_clear_hash_node (gpointer key, + gpointer data, + gpointer user_data); +static void gtk_rc_clear_styles (void); + static GScannerConfig gtk_rc_scanner_config = @@ -132,10 +118,8 @@ static GScannerConfig gtk_rc_scanner_config = ) /* cset_identifier_first */, ( G_CSET_a_2_z - "_0123456789" + "_-0123456789" G_CSET_A_2_Z - G_CSET_LATINS - G_CSET_LATINC ) /* cset_identifier_nth */, ( "#\n" ) /* cpair_comment_single */, @@ -153,52 +137,65 @@ static GScannerConfig gtk_rc_scanner_config = TRUE /* scan_float */, TRUE /* scan_hex */, TRUE /* scan_hex_dollar */, - FALSE /* scan_string_sq */, + TRUE /* scan_string_sq */, TRUE /* scan_string_dq */, TRUE /* numbers_2_int */, FALSE /* int_2_float */, - TRUE /* identifier_2_string */, + FALSE /* identifier_2_string */, TRUE /* char_2_token */, TRUE /* symbol_2_token */, + FALSE /* scope_0_fallback */, }; 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 int done; + gchar *name; + guint token; +} symbols[] = { + { "include", GTK_RC_TOKEN_INCLUDE }, + { "NORMAL", GTK_RC_TOKEN_NORMAL }, + { "ACTIVE", GTK_RC_TOKEN_ACTIVE }, + { "PRELIGHT", GTK_RC_TOKEN_PRELIGHT }, + { "SELECTED", GTK_RC_TOKEN_SELECTED }, + { "INSENSITIVE", GTK_RC_TOKEN_INSENSITIVE }, + { "fg", GTK_RC_TOKEN_FG }, + { "bg", GTK_RC_TOKEN_BG }, + { "base", GTK_RC_TOKEN_BASE }, + { "text", GTK_RC_TOKEN_TEXT }, + { "font", GTK_RC_TOKEN_FONT }, + { "fontset", GTK_RC_TOKEN_FONTSET }, + { "bg_pixmap", GTK_RC_TOKEN_BG_PIXMAP }, + { "pixmap_path", GTK_RC_TOKEN_PIXMAP_PATH }, + { "style", GTK_RC_TOKEN_STYLE }, + { "binding", GTK_RC_TOKEN_BINDING }, + { "bind", GTK_RC_TOKEN_BIND }, + { "widget", GTK_RC_TOKEN_WIDGET }, + { "widget_class", GTK_RC_TOKEN_WIDGET_CLASS }, + { "class", GTK_RC_TOKEN_CLASS }, + { "lowest", GTK_RC_TOKEN_LOWEST }, + { "gtk", GTK_RC_TOKEN_GTK }, + { "application", GTK_RC_TOKEN_APPLICATION }, + { "rc", GTK_RC_TOKEN_RC }, + { "highest", GTK_RC_TOKEN_HIGHEST }, +}; + +static guint n_symbols = sizeof (symbols) / sizeof (symbols[0]); static GHashTable *rc_style_ht = NULL; -static GSList *widget_sets = NULL; -static GSList *widget_class_sets = NULL; +static GSList *gtk_rc_sets_widget = NULL; +static GSList *gtk_rc_sets_widget_class = NULL; +static GSList *gtk_rc_sets_class = NULL; #define GTK_RC_MAX_PIXMAP_PATHS 128 static gchar *pixmap_path[GTK_RC_MAX_PIXMAP_PATHS]; +/* The files we have parsed, to reread later if necessary */ +GSList *rc_files = NULL; + +static GtkImageLoader image_loader = NULL; void -gtk_rc_init () +gtk_rc_init (void) { rc_style_ht = g_hash_table_new ((GHashFunc) gtk_rc_style_hash, (GCompareFunc) gtk_rc_style_compare); @@ -212,75 +209,297 @@ gtk_rc_parse_string (const gchar *rc_string) gtk_rc_parse_any ("-", -1, rc_string); } +static void +gtk_rc_parse_file (const gchar *filename, gboolean reload) +{ + GtkRcFile *rc_file = NULL; + struct stat statbuf; + GSList *tmp_list; + + g_return_if_fail (filename != NULL); + + tmp_list = rc_files; + while (tmp_list) + { + rc_file = tmp_list->data; + if (!strcmp (rc_file->name, filename)) + break; + + tmp_list = tmp_list->next; + } + + if (!tmp_list) + { + rc_file = g_new (GtkRcFile, 1); + rc_file->name = g_strdup (filename); + rc_file->canonical_name = NULL; + rc_file->mtime = 0; + rc_file->reload = reload; + + rc_files = g_slist_append (rc_files, rc_file); + } + + if (!rc_file->canonical_name) + { + /* Get the absolute pathname */ + + if (rc_file->name[0] == '/') + rc_file->canonical_name = rc_file->name; + else + { + GString *str; + gchar buffer[MAXPATHLEN]; + +#if defined(sun) && !defined(__SVR4) + if(!getwd(buffer)) +#else + if(!getcwd(buffer, MAXPATHLEN)) +#endif + return; + + str = g_string_new (buffer); + g_string_append_c (str, '/'); + g_string_append (str, rc_file->name); + + rc_file->canonical_name = str->str; + g_string_free (str, FALSE); + } + } + + if (!lstat (rc_file->canonical_name, &statbuf)) + { + gint fd; + + rc_file->mtime = statbuf.st_mtime; + + fd = open (rc_file->canonical_name, O_RDONLY); + if (fd < 0) + return; + + gtk_rc_parse_any (filename, fd, NULL); + + close (fd); + } +} + void gtk_rc_parse (const gchar *filename) { - gint fd; - g_return_if_fail (filename != NULL); - fd = open (filename, O_RDONLY); - if (fd < 0) - return; + gtk_rc_parse_file (filename, TRUE); +} + +static void +gtk_rc_clear_hash_node (gpointer key, + gpointer data, + gpointer user_data) +{ + int i; + GtkRcStyle *rc_style = data; + GList *tmp_list; + + g_free (rc_style->name); + g_free (rc_style->font_name); + g_free (rc_style->fontset_name); + + for (i=0 ; i<5 ; i++) + g_free (rc_style->bg_pixmap_name[i]); + + gtk_style_unref (rc_style->proto_style); + + tmp_list = rc_style->styles; + while (tmp_list) + { + GtkRcNode *node = tmp_list->data; + + gdk_colormap_unref (node->cmap); + gtk_style_unref (node->style); + + g_free (node); + tmp_list = tmp_list->next; + } + + g_free (rc_style); +} + +static void +gtk_rc_free_rc_sets (GSList *slist) +{ + while (slist) + { + GtkRcSet *rc_set; + + rc_set = slist->data; + gtk_pattern_spec_free_segs (&rc_set->pspec); + g_free (rc_set); + + slist = slist->next; + } +} - gtk_rc_parse_any (filename, fd, NULL); +static void +gtk_rc_clear_styles (void) +{ + /* Clear out all old rc_styles */ - close (fd); + g_hash_table_foreach (rc_style_ht, gtk_rc_clear_hash_node, NULL); + g_hash_table_destroy (rc_style_ht); + rc_style_ht = NULL; + + gtk_rc_free_rc_sets (gtk_rc_sets_widget); + g_slist_free (gtk_rc_sets_widget); + gtk_rc_sets_widget = NULL; + + gtk_rc_free_rc_sets (gtk_rc_sets_widget_class); + g_slist_free (gtk_rc_sets_widget_class); + gtk_rc_sets_widget_class = NULL; + + gtk_rc_free_rc_sets (gtk_rc_sets_class); + g_slist_free (gtk_rc_sets_class); + gtk_rc_sets_class = NULL; + + gtk_rc_init (); +} + +gboolean +gtk_rc_reparse_all (void) +{ + GSList *tmp_list; + gboolean mtime_modified = FALSE; + GtkRcFile *rc_file; + + struct stat statbuf; + + /* Check through and see if any of the RC's have had their + * mtime modified. If so, reparse everything. + */ + tmp_list = rc_files; + while (tmp_list) + { + rc_file = tmp_list->data; + + if (!lstat (rc_file->name, &statbuf) && + (statbuf.st_mtime > rc_file->mtime)) + { + mtime_modified = TRUE; + break; + } + + tmp_list = tmp_list->next; + } + + if (mtime_modified) + { + gtk_rc_clear_styles(); + + tmp_list = rc_files; + while (tmp_list) + { + rc_file = tmp_list->data; + if (rc_file->reload) + gtk_rc_parse_file (rc_file->name, FALSE); + + tmp_list = tmp_list->next; + } + } + + return mtime_modified; +} + +static GtkRcStyle* +gtk_rc_styles_match (GSList *sets, + guint path_length, + gchar *path, + gchar *path_reversed) +{ + GtkRcSet *rc_set; + + while (sets) + { + rc_set = sets->data; + sets = sets->next; + + if (gtk_pattern_match (&rc_set->pspec, path_length, path, path_reversed)) + return rc_set->rc_style; + } + + return NULL; } GtkStyle* gtk_rc_get_style (GtkWidget *widget) { GtkRcStyle *rc_style; - char *path; - if (widget_sets) + if (gtk_rc_sets_widget) { - 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; - } - } + gchar *path, *path_reversed; + guint path_length; + + gtk_widget_path (widget, &path_length, &path, &path_reversed); + rc_style = gtk_rc_styles_match (gtk_rc_sets_widget, path_length, path, path_reversed); + g_free (path); + g_free (path_reversed); + + if (rc_style) + return gtk_rc_style_init (rc_style, gtk_widget_get_colormap (widget)); } - if (widget_class_sets) + if (gtk_rc_sets_widget_class) + { + gchar *path, *path_reversed; + guint path_length; + + gtk_widget_class_path (widget, &path_length, &path, &path_reversed); + rc_style = gtk_rc_styles_match (gtk_rc_sets_widget_class, path_length, path, path_reversed); + g_free (path); + g_free (path_reversed); + + if (rc_style) + return gtk_rc_style_init (rc_style, gtk_widget_get_colormap (widget)); + } + + if (gtk_rc_sets_class) { - path = gtk_rc_widget_class_path (widget); - if (path) + GtkType type; + + type = GTK_OBJECT_TYPE (widget); + while (type) { - rc_style = gtk_rc_styles_match (widget_class_sets, path); - g_free (path); + gchar *path, *path_reversed; + guint path_length; + + path = gtk_type_name (type); + path_length = strlen (path); + path_reversed = g_strdup (path); + g_strreverse (path_reversed); + rc_style = gtk_rc_styles_match (gtk_rc_sets_class, path_length, path, path_reversed); + g_free (path_reversed); + if (rc_style) - { - gtk_rc_style_init (rc_style); - return rc_style->style; - } + return gtk_rc_style_init (rc_style, gtk_widget_get_colormap (widget)); + + type = gtk_type_parent (type); } } - return widget->style; + return NULL; } -void -gtk_rc_add_widget_name_style (GtkStyle *style, - const char *pattern) +static GSList* +gtk_rc_add_rc_sets (GSList *slist, + GtkStyle *style, + const char *pattern) { GtkRcStyle *rc_style; GtkRcSet *rc_set; - int i; + guint 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; @@ -288,41 +507,43 @@ gtk_rc_add_widget_name_style (GtkStyle *style, for (i = 0; i < 5; i++) rc_style->bg_pixmap_name[i] = NULL; - rc_style->style = style; - + rc_style->styles = g_list_append (NULL, style); + rc_set = g_new (GtkRcSet, 1); - rc_set->set = g_strdup (pattern); + gtk_pattern_spec_init (&rc_set->pspec, pattern); rc_set->rc_style = rc_style; - widget_sets = g_slist_append (widget_sets, rc_set); + return g_slist_prepend (slist, rc_set); } void -gtk_rc_add_widget_class_style (GtkStyle *style, - const char *pattern) +gtk_rc_add_widget_name_style (GtkStyle *style, + const gchar *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); + g_return_if_fail (style != NULL); + g_return_if_fail (pattern != NULL); + + gtk_rc_sets_widget = gtk_rc_add_rc_sets (gtk_rc_sets_widget, style, pattern); +} + +void +gtk_rc_add_widget_class_style (GtkStyle *style, + const gchar *pattern) +{ + g_return_if_fail (style != NULL); + g_return_if_fail (pattern != NULL); + + gtk_rc_sets_widget_class = gtk_rc_add_rc_sets (gtk_rc_sets_widget_class, style, pattern); +} + +void +gtk_rc_add_class_style (GtkStyle *style, + const gchar *pattern) +{ + g_return_if_fail (style != NULL); + g_return_if_fail (pattern != NULL); + + gtk_rc_sets_class = gtk_rc_add_rc_sets (gtk_rc_sets_class, style, pattern); } static void @@ -332,6 +553,7 @@ gtk_rc_parse_any (const gchar *input_name, { GScanner *scanner; guint i; + gboolean done; scanner = g_scanner_new (>k_rc_scanner_config); @@ -347,29 +569,69 @@ gtk_rc_parse_any (const gchar *input_name, g_scanner_input_text (scanner, input_string, strlen (input_string)); } - - for (i = 0; i < nsymbols; i++) - g_scanner_add_symbol (scanner, symbols[i].name, (gpointer) symbols[i].token); + scanner->input_name = input_name; + + g_scanner_freeze_symbol_table (scanner); + for (i = 0; i < n_symbols; i++) + g_scanner_add_symbol (scanner, symbols[i].name, GINT_TO_POINTER (symbols[i].token)); + g_scanner_thaw_symbol_table (scanner); done = FALSE; while (!done) { - if (gtk_rc_parse_statement (scanner) != PARSE_OK) + if (g_scanner_peek_next_token (scanner) == G_TOKEN_EOF) + done = TRUE; + else { - if (scanner->next_token != G_TOKEN_NONE) - g_scanner_get_next_token (scanner); - - if (input_string) - g_warning ("rc string parse error: line %d", - scanner->line); - else - g_warning ("rc file parse error: \"%s\" line %d", - input_name, - scanner->line); + guint expected_token; - done = TRUE; + expected_token = gtk_rc_parse_statement (scanner); + + if (expected_token != G_TOKEN_NONE) + { + gchar *symbol_name; + gchar *msg; + + msg = NULL; + symbol_name = NULL; + if (scanner->scope_id == 0) + { + /* if we are in scope 0, we know the symbol names + * that are associated with certaintoken values. + * so we look them up to make the error messages + * more readable. + */ + if (expected_token > GTK_RC_TOKEN_INVALID && + expected_token < GTK_RC_TOKEN_LAST) + { + for (i = 0; i < n_symbols; i++) + if (symbols[i].token == expected_token) + msg = symbols[i].name; + if (msg) + msg = g_strconcat ("e.g. `", msg, "'", NULL); + } + if (scanner->token > GTK_RC_TOKEN_INVALID && + scanner->token < GTK_RC_TOKEN_LAST) + { + symbol_name = "???"; + for (i = 0; i < n_symbols; i++) + if (symbols[i].token == scanner->token) + symbol_name = symbols[i].name; + } + } + g_scanner_unexp_token (scanner, + expected_token, + NULL, + "keyword", + symbol_name, + msg, + TRUE); + g_free (msg); + done = TRUE; + } } } + g_scanner_destroy (scanner); } @@ -402,167 +664,155 @@ gtk_rc_style_find (const char *name) return rc_style; } -static GtkRcStyle* -gtk_rc_styles_match (GSList *sets, - const char *path) +static GtkStyle * +gtk_rc_style_init (GtkRcStyle *rc_style, GdkColormap *cmap) { - 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; -} + GdkFont *old_font; + gboolean match_cmap = FALSE; + gint i; -static gint -gtk_rc_style_match (const char *set, - const char *path) -{ - char ch; - - while (1) - { - ch = *set++; - if (ch == '\0') - return (*path == '\0'); + GList *tmp_list; + GtkStyle *style = NULL; + GtkRcNode *node; + + tmp_list = rc_style->styles; + + for (i=0; i<5; i++) + if (rc_style->bg_pixmap_name[i]) + match_cmap = TRUE; - switch (ch) + while (tmp_list) + { + node = (GtkRcNode *)tmp_list->data; + + if (!match_cmap || (node->cmap == cmap)) { - 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; + style = node->style; break; } - } - - return TRUE; -} -static void -gtk_rc_style_init (GtkRcStyle *rc_style) -{ - GdkFont *old_font; - gint i; + tmp_list = tmp_list->next; + } - if (rc_style->initialize) + if (!style) { - rc_style->initialize = FALSE; + node = g_new (GtkRcNode, 1); + style = gtk_style_copy (rc_style->proto_style); + + /* FIXME, this leaks colormaps, but if we don't do this, then we'll + * be screwed, because we identify colormaps by address equality + */ + gdk_colormap_ref (cmap); + + node->style = style; + node->cmap = cmap; 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) + old_font = style->font; + style->font = gdk_fontset_load (rc_style->fontset_name); + if (style->font) gdk_font_unref (old_font); else - rc_style->style->font = old_font; + 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) + old_font = style->font; + style->font = gdk_font_load (rc_style->font_name); + if (style->font) gdk_font_unref (old_font); else - rc_style->style->font = old_font; + 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], "") == 0) - rc_style->style->bg_pixmap[i] = (GdkPixmap*) GDK_PARENT_RELATIVE; + 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]); + { + if(image_loader) + style->bg_pixmap[i] = image_loader(NULL, cmap, NULL, + &style->bg[i], + rc_style->bg_pixmap_name[i]); + else + style->bg_pixmap[i] = + gdk_pixmap_colormap_create_from_xpm (NULL, cmap, + NULL, + &style->bg[i], + rc_style->bg_pixmap_name[i]); + } } + + rc_style->styles = g_list_append (rc_style->styles, node); } + + return style; } -static gint +static guint gtk_rc_parse_statement (GScanner *scanner) { - gint token; - gint error; + guint token; token = g_scanner_peek_next_token (scanner); - if (token == G_TOKEN_EOF) + + switch (token) { - done = TRUE; - return PARSE_OK; + case GTK_RC_TOKEN_INCLUDE: + token = g_scanner_get_next_token (scanner); + if (token != GTK_RC_TOKEN_INCLUDE) + return GTK_RC_TOKEN_INCLUDE; + + token = g_scanner_get_next_token (scanner); + if (token != G_TOKEN_STRING) + return G_TOKEN_STRING; + + gtk_rc_parse_file (scanner->value.v_string, FALSE); + return G_TOKEN_NONE; + + case GTK_RC_TOKEN_STYLE: + return gtk_rc_parse_style (scanner); + + case GTK_RC_TOKEN_BINDING: + return gtk_binding_parse_binding (scanner); + + case GTK_RC_TOKEN_PIXMAP_PATH: + return gtk_rc_parse_pixmap_path (scanner); + + case GTK_RC_TOKEN_WIDGET: + return gtk_rc_parse_path_pattern (scanner); + + case GTK_RC_TOKEN_WIDGET_CLASS: + return gtk_rc_parse_path_pattern (scanner); + + case GTK_RC_TOKEN_CLASS: + return gtk_rc_parse_path_pattern (scanner); + + default: + g_scanner_get_next_token (scanner); + return /* G_TOKEN_SYMBOL */ GTK_RC_TOKEN_STYLE; } - - error = gtk_rc_parse_style (scanner); - if (error != PARSE_SYNTAX) - return error; - - error = gtk_rc_parse_pixmap_path (scanner); - if (error != PARSE_SYNTAX) - return error; - - error = gtk_rc_parse_widget_style (scanner); - if (error != PARSE_SYNTAX) - return error; - - error = gtk_rc_parse_widget_class_style (scanner); - - return error; } -static gint +static guint gtk_rc_parse_style (GScanner *scanner) { GtkRcStyle *rc_style; GtkRcStyle *parent_style; - gint token; - gint error; + guint token; gint insert; gint i; - token = g_scanner_peek_next_token (scanner); - if (token == G_TOKEN_EOF || token == G_TOKEN_ERROR) - return PARSE_ERROR; - if (token != TOKEN_STYLE) - return PARSE_SYNTAX; token = g_scanner_get_next_token (scanner); + if (token != GTK_RC_TOKEN_STYLE) + return GTK_RC_TOKEN_STYLE; token = g_scanner_get_next_token (scanner); if (token != G_TOKEN_STRING) - return PARSE_ERROR; + return G_TOKEN_STRING; insert = FALSE; rc_style = g_hash_table_lookup (rc_style_ht, scanner->value.v_string); @@ -571,16 +821,15 @@ gtk_rc_parse_style (GScanner *scanner) { insert = TRUE; rc_style = g_new (GtkRcStyle, 1); - rc_style->initialize = TRUE; rc_style->name = g_strdup (scanner->value.v_string); 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); + + rc_style->proto_style = gtk_style_new(); + rc_style->styles = NULL; } token = g_scanner_peek_next_token (scanner); @@ -593,10 +842,10 @@ gtk_rc_parse_style (GScanner *scanner) { if (insert) { - gtk_style_unref (rc_style->style); + gtk_style_unref (rc_style->proto_style); g_free (rc_style); } - return PARSE_ERROR; + return G_TOKEN_STRING; } parent_style = g_hash_table_lookup (rc_style_ht, scanner->value.v_string); @@ -604,17 +853,17 @@ gtk_rc_parse_style (GScanner *scanner) { 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->proto_style->fg[i] = parent_style->proto_style->fg[i]; + rc_style->proto_style->bg[i] = parent_style->proto_style->bg[i]; + rc_style->proto_style->light[i] = parent_style->proto_style->light[i]; + rc_style->proto_style->dark[i] = parent_style->proto_style->dark[i]; + rc_style->proto_style->mid[i] = parent_style->proto_style->mid[i]; + rc_style->proto_style->text[i] = parent_style->proto_style->text[i]; + rc_style->proto_style->base[i] = parent_style->proto_style->base[i]; } - rc_style->style->black = parent_style->style->black; - rc_style->style->white = parent_style->style->white; + rc_style->proto_style->black = parent_style->proto_style->black; + rc_style->proto_style->white = parent_style->proto_style->white; if (rc_style->fontset_name) { @@ -641,26 +890,61 @@ gtk_rc_parse_style (GScanner *scanner) { if (insert) { - gtk_style_unref (rc_style->style); + gtk_style_unref (rc_style->proto_style); g_free (rc_style); } - return PARSE_ERROR; + return G_TOKEN_LEFT_CURLY; } - while (1) + token = g_scanner_peek_next_token (scanner); + while (token != G_TOKEN_RIGHT_CURLY) { - error = gtk_rc_parse_style_option (scanner, rc_style); - if (error == PARSE_SYNTAX) - break; - if (error == PARSE_ERROR) + switch (token) + { + case GTK_RC_TOKEN_BASE: + token = gtk_rc_parse_base (scanner, rc_style->proto_style); + break; + case GTK_RC_TOKEN_BG: + token = gtk_rc_parse_bg (scanner, rc_style->proto_style); + break; + case GTK_RC_TOKEN_FG: + token = gtk_rc_parse_fg (scanner, rc_style->proto_style); + break; + case GTK_RC_TOKEN_TEXT: + token = gtk_rc_parse_text (scanner, rc_style->proto_style); + break; + case GTK_RC_TOKEN_BG_PIXMAP: + token = gtk_rc_parse_bg_pixmap (scanner, rc_style); + break; + case GTK_RC_TOKEN_FONT: + token = gtk_rc_parse_font (scanner, rc_style); + break; + case GTK_RC_TOKEN_FONTSET: + token = gtk_rc_parse_fontset (scanner, rc_style); + break; + default: + g_scanner_get_next_token (scanner); + token = G_TOKEN_RIGHT_CURLY; + break; + } + + if (token != G_TOKEN_NONE) { if (insert) { - gtk_style_unref (rc_style->style); + if (rc_style->fontset_name) + g_free (rc_style->fontset_name); + 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->proto_style); g_free (rc_style); } - return error; + return token; } + token = g_scanner_peek_next_token (scanner); } token = g_scanner_get_next_token (scanner); @@ -670,172 +954,136 @@ gtk_rc_parse_style (GScanner *scanner) { if (rc_style->fontset_name) g_free (rc_style->fontset_name); - else if (rc_style->font_name) + 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); + gtk_style_unref (rc_style->proto_style); g_free (rc_style); } - return PARSE_ERROR; + return G_TOKEN_RIGHT_CURLY; } if (insert) g_hash_table_insert (rc_style_ht, rc_style->name, rc_style); - return PARSE_OK; + return G_TOKEN_NONE; } -static gint -gtk_rc_parse_style_option (GScanner *scanner, - GtkRcStyle *rc_style) +static guint +gtk_rc_parse_base (GScanner *scanner, + GtkStyle *style) { - gint token; - gint error; - - token = g_scanner_peek_next_token (scanner); - if (token == G_TOKEN_EOF || token == G_TOKEN_ERROR) - return PARSE_ERROR; - - error = gtk_rc_parse_base (scanner, rc_style->style); - if (error != PARSE_SYNTAX) - return error; - - error = gtk_rc_parse_bg (scanner, rc_style->style); - if (error != PARSE_SYNTAX) - return error; - - error = gtk_rc_parse_fg (scanner, rc_style->style); - if (error != PARSE_SYNTAX) - return error; + GtkStateType state; + guint token; - error = gtk_rc_parse_bg_pixmap (scanner, rc_style); - if (error != PARSE_SYNTAX) - return error; + token = g_scanner_get_next_token (scanner); + if (token != GTK_RC_TOKEN_BASE) + return GTK_RC_TOKEN_BASE; - error = gtk_rc_parse_font (scanner, rc_style); - if (error != PARSE_SYNTAX) - return error; + token = gtk_rc_parse_state (scanner, &state); + if (token != G_TOKEN_NONE) + return token; - error = gtk_rc_parse_fontset (scanner, rc_style); + token = g_scanner_get_next_token (scanner); + if (token != G_TOKEN_EQUAL_SIGN) + return G_TOKEN_EQUAL_SIGN; - return error; + return gtk_rc_parse_color (scanner, &style->base[state]); } -static gint -gtk_rc_parse_base (GScanner *scanner, - GtkStyle *style) +static guint +gtk_rc_parse_bg (GScanner *scanner, + GtkStyle *style) { GtkStateType state; - gint token; - gint error; + guint token; - token = g_scanner_peek_next_token (scanner); - if (token == G_TOKEN_EOF || token == G_TOKEN_ERROR) - return PARSE_ERROR; - if (token != TOKEN_BASE) - return PARSE_SYNTAX; token = g_scanner_get_next_token (scanner); + if (token != GTK_RC_TOKEN_BG) + return GTK_RC_TOKEN_BG; - error = gtk_rc_parse_state (scanner, &state); - if (error != PARSE_OK) - return error; + token = gtk_rc_parse_state (scanner, &state); + if (token != G_TOKEN_NONE) + return token; token = g_scanner_get_next_token (scanner); if (token != G_TOKEN_EQUAL_SIGN) - return PARSE_ERROR; + return G_TOKEN_EQUAL_SIGN; - error = gtk_rc_parse_color (scanner, &style->base[state]); - - return error; + return gtk_rc_parse_color (scanner, &style->bg[state]); } -static gint -gtk_rc_parse_bg (GScanner *scanner, +static guint +gtk_rc_parse_fg (GScanner *scanner, GtkStyle *style) { GtkStateType state; - gint token; - gint error; + guint token; - token = g_scanner_peek_next_token (scanner); - if (token == G_TOKEN_EOF || token == G_TOKEN_ERROR) - return PARSE_ERROR; - if (token != TOKEN_BG) - return PARSE_SYNTAX; token = g_scanner_get_next_token (scanner); + if (token != GTK_RC_TOKEN_FG) + return GTK_RC_TOKEN_FG; - error = gtk_rc_parse_state (scanner, &state); - if (error != PARSE_OK) - return error; + token = gtk_rc_parse_state (scanner, &state); + if (token != G_TOKEN_NONE) + return token; token = g_scanner_get_next_token (scanner); if (token != G_TOKEN_EQUAL_SIGN) - return PARSE_ERROR; + return G_TOKEN_EQUAL_SIGN; - error = gtk_rc_parse_color (scanner, &style->bg[state]); - - return error; + return gtk_rc_parse_color (scanner, &style->fg[state]); } -static gint -gtk_rc_parse_fg (GScanner *scanner, - GtkStyle *style) +static guint +gtk_rc_parse_text (GScanner *scanner, + GtkStyle *style) { GtkStateType state; - gint token; - gint error; + guint token; - token = g_scanner_peek_next_token (scanner); - if (token == G_TOKEN_EOF || token == G_TOKEN_ERROR) - return PARSE_ERROR; - if (token != TOKEN_FG) - return PARSE_SYNTAX; token = g_scanner_get_next_token (scanner); + if (token != GTK_RC_TOKEN_TEXT) + return GTK_RC_TOKEN_TEXT; - error = gtk_rc_parse_state (scanner, &state); - if (error != PARSE_OK) - return error; + token = gtk_rc_parse_state (scanner, &state); + if (token != G_TOKEN_NONE) + return token; token = g_scanner_get_next_token (scanner); if (token != G_TOKEN_EQUAL_SIGN) - return PARSE_ERROR; - - error = gtk_rc_parse_color (scanner, &style->fg[state]); + return G_TOKEN_EQUAL_SIGN; - return error; + return gtk_rc_parse_color (scanner, &style->text[state]); } -static gint +static guint gtk_rc_parse_bg_pixmap (GScanner *scanner, GtkRcStyle *rc_style) { GtkStateType state; - gint token; - gint error; + guint token; gchar *pixmap_file; - token = g_scanner_peek_next_token (scanner); - if (token == G_TOKEN_EOF || token == G_TOKEN_ERROR) - return PARSE_ERROR; - if (token != TOKEN_BG_PIXMAP) - return PARSE_SYNTAX; token = g_scanner_get_next_token (scanner); + if (token != GTK_RC_TOKEN_BG_PIXMAP) + return GTK_RC_TOKEN_BG_PIXMAP; - error = gtk_rc_parse_state (scanner, &state); - if (error != PARSE_OK) - return error; + token = gtk_rc_parse_state (scanner, &state); + if (token != G_TOKEN_NONE) + return token; token = g_scanner_get_next_token (scanner); if (token != G_TOKEN_EQUAL_SIGN) - return PARSE_ERROR; + return G_TOKEN_EQUAL_SIGN; token = g_scanner_get_next_token (scanner); if (token != G_TOKEN_STRING) - return PARSE_ERROR; + return G_TOKEN_STRING; if (strcmp (scanner->value.v_string, "")) pixmap_file = gtk_rc_find_pixmap_in_path (scanner, scanner->value.v_string); @@ -849,10 +1097,10 @@ gtk_rc_parse_bg_pixmap (GScanner *scanner, rc_style->bg_pixmap_name[state] = pixmap_file; } - return PARSE_OK; + return G_TOKEN_NONE; } -static char* +static gchar* gtk_rc_find_pixmap_in_path (GScanner *scanner, gchar *pixmap_file) { @@ -881,128 +1129,188 @@ gtk_rc_find_pixmap_in_path (GScanner *scanner, return NULL; } -static gint +static guint gtk_rc_parse_font (GScanner *scanner, GtkRcStyle *rc_style) { - gint token; + guint token; - token = g_scanner_peek_next_token (scanner); - if (token == G_TOKEN_EOF || token == G_TOKEN_ERROR) - return PARSE_ERROR; - if (token != TOKEN_FONT) - return PARSE_SYNTAX; token = g_scanner_get_next_token (scanner); + if (token != GTK_RC_TOKEN_FONT) + return GTK_RC_TOKEN_FONT; token = g_scanner_get_next_token (scanner); if (token != G_TOKEN_EQUAL_SIGN) - return PARSE_ERROR; + return G_TOKEN_EQUAL_SIGN; token = g_scanner_get_next_token (scanner); if (token != G_TOKEN_STRING) - return PARSE_ERROR; + return G_TOKEN_STRING; if (rc_style->font_name) g_free (rc_style->font_name); rc_style->font_name = g_strdup (scanner->value.v_string); - return PARSE_OK; + return G_TOKEN_NONE; } -static gint +static guint gtk_rc_parse_fontset (GScanner *scanner, GtkRcStyle *rc_style) { - gint token; + guint token; - token = g_scanner_peek_next_token (scanner); - if (token == G_TOKEN_EOF || token == G_TOKEN_ERROR) - return PARSE_ERROR; - if (token != TOKEN_FONTSET) - return PARSE_SYNTAX; token = g_scanner_get_next_token (scanner); + if (token != GTK_RC_TOKEN_FONTSET) + return GTK_RC_TOKEN_FONTSET; token = g_scanner_get_next_token (scanner); if (token != G_TOKEN_EQUAL_SIGN) - return PARSE_ERROR; + return G_TOKEN_EQUAL_SIGN; token = g_scanner_get_next_token (scanner); if (token != G_TOKEN_STRING) - return PARSE_ERROR; + return G_TOKEN_STRING; if (rc_style->fontset_name) g_free (rc_style->fontset_name); rc_style->fontset_name = g_strdup (scanner->value.v_string); - return PARSE_OK; + return G_TOKEN_NONE; } -static gint +guint gtk_rc_parse_state (GScanner *scanner, GtkStateType *state) { - gint token; + guint old_scope; + guint token; + + g_return_val_if_fail (scanner != NULL, G_TOKEN_ERROR); + g_return_val_if_fail (state != NULL, G_TOKEN_ERROR); + + /* we don't know where we got called from, so we reset the scope here. + * if we bail out due to errors, we *don't* reset the scope, so the + * error messaging code can make sense of our tokens. + */ + old_scope = g_scanner_set_scope (scanner, 0); - token = g_scanner_peek_next_token (scanner); - if (token == G_TOKEN_EOF || token == G_TOKEN_ERROR) - return PARSE_ERROR; - if (token != G_TOKEN_LEFT_BRACE) - return PARSE_SYNTAX; token = g_scanner_get_next_token (scanner); + if (token != G_TOKEN_LEFT_BRACE) + return G_TOKEN_LEFT_BRACE; token = g_scanner_get_next_token (scanner); - 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; + switch (token) + { + case GTK_RC_TOKEN_ACTIVE: + *state = GTK_STATE_ACTIVE; + break; + case GTK_RC_TOKEN_INSENSITIVE: + *state = GTK_STATE_INSENSITIVE; + break; + case GTK_RC_TOKEN_NORMAL: + *state = GTK_STATE_NORMAL; + break; + case GTK_RC_TOKEN_PRELIGHT: + *state = GTK_STATE_PRELIGHT; + break; + case GTK_RC_TOKEN_SELECTED: + *state = GTK_STATE_SELECTED; + break; + default: + return /* G_TOKEN_SYMBOL */ GTK_RC_TOKEN_NORMAL; + } token = g_scanner_get_next_token (scanner); if (token != G_TOKEN_RIGHT_BRACE) - return PARSE_ERROR; + return G_TOKEN_RIGHT_BRACE; - return PARSE_OK; + g_scanner_set_scope (scanner, old_scope); + + return G_TOKEN_NONE; } -static gint +guint +gtk_rc_parse_priority (GScanner *scanner, + GtkPathPriorityType *priority) +{ + guint old_scope; + guint token; + + g_return_val_if_fail (scanner != NULL, G_TOKEN_ERROR); + g_return_val_if_fail (priority != NULL, G_TOKEN_ERROR); + + /* we don't know where we got called from, so we reset the scope here. + * if we bail out due to errors, we *don't* reset the scope, so the + * error messaging code can make sense of our tokens. + */ + old_scope = g_scanner_set_scope (scanner, 0); + + token = g_scanner_get_next_token (scanner); + if (token != ':') + return ':'; + + token = g_scanner_get_next_token (scanner); + switch (token) + { + case GTK_RC_TOKEN_LOWEST: + *priority = GTK_PATH_PRIO_LOWEST; + break; + case GTK_RC_TOKEN_GTK: + *priority = GTK_PATH_PRIO_GTK; + break; + case GTK_RC_TOKEN_APPLICATION: + *priority = GTK_PATH_PRIO_APPLICATION; + break; + case GTK_RC_TOKEN_RC: + *priority = GTK_PATH_PRIO_RC; + break; + case GTK_RC_TOKEN_HIGHEST: + *priority = GTK_PATH_PRIO_HIGHEST; + break; + default: + return /* G_TOKEN_SYMBOL */ GTK_RC_TOKEN_APPLICATION; + } + + g_scanner_set_scope (scanner, old_scope); + + return G_TOKEN_NONE; +} + +guint gtk_rc_parse_color (GScanner *scanner, GdkColor *color) { - gint token; - gint token_int; - gint length; - gint temp; - gchar buf[9]; - gint i, j; - - token = g_scanner_peek_next_token (scanner); - if (token == G_TOKEN_EOF || token == G_TOKEN_ERROR) - return PARSE_ERROR; + guint token; + + g_return_val_if_fail (scanner != NULL, G_TOKEN_ERROR); + + /* we don't need to set our own scop here, because + * we don't need own symbols + */ + token = g_scanner_get_next_token (scanner); switch (token) { - case G_TOKEN_LEFT_CURLY: - token = g_scanner_get_next_token (scanner); + gint token_int; + gint length; + gint temp; + gchar buf[9]; + gint i, j; + case G_TOKEN_LEFT_CURLY: token = g_scanner_get_next_token (scanner); if (token == G_TOKEN_INT) token_int = scanner->value.v_int; else if (token == G_TOKEN_FLOAT) token_int = scanner->value.v_float * 65535.0; else - return PARSE_ERROR; + return G_TOKEN_FLOAT; color->red = CLAMP (token_int, 0, 65535); token = g_scanner_get_next_token (scanner); if (token != G_TOKEN_COMMA) - return PARSE_ERROR; + return G_TOKEN_COMMA; token = g_scanner_get_next_token (scanner); if (token == G_TOKEN_INT) @@ -1010,12 +1318,12 @@ gtk_rc_parse_color (GScanner *scanner, else if (token == G_TOKEN_FLOAT) token_int = scanner->value.v_float * 65535.0; else - return PARSE_ERROR; + return G_TOKEN_FLOAT; color->green = CLAMP (token_int, 0, 65535); token = g_scanner_get_next_token (scanner); if (token != G_TOKEN_COMMA) - return PARSE_ERROR; + return G_TOKEN_COMMA; token = g_scanner_get_next_token (scanner); if (token == G_TOKEN_INT) @@ -1023,23 +1331,21 @@ gtk_rc_parse_color (GScanner *scanner, else if (token == G_TOKEN_FLOAT) token_int = scanner->value.v_float * 65535.0; else - return PARSE_ERROR; + return G_TOKEN_FLOAT; color->blue = CLAMP (token_int, 0, 65535); token = g_scanner_get_next_token (scanner); if (token != G_TOKEN_RIGHT_CURLY) - return PARSE_ERROR; - break; + return G_TOKEN_RIGHT_CURLY; + return G_TOKEN_NONE; case G_TOKEN_STRING: - token = g_scanner_get_next_token (scanner); - if (scanner->value.v_string[0] != '#') - return PARSE_ERROR; + return G_TOKEN_STRING; length = strlen (scanner->value.v_string) - 1; if (((length % 3) != 0) || (length > 12)) - return PARSE_ERROR; + return G_TOKEN_STRING; length /= 3; for (i = 0, j = 1; i < length; i++, j++) @@ -1081,38 +1387,29 @@ gtk_rc_parse_color (GScanner *scanner, color->green *= 16; color->blue *= 16; } - break; - - case G_TOKEN_ERROR: - return PARSE_ERROR; + return G_TOKEN_NONE; default: - return PARSE_SYNTAX; + return G_TOKEN_STRING; } - - return PARSE_OK; } -static gint +static guint gtk_rc_parse_pixmap_path (GScanner *scanner) { - gint token; + guint token; - token = g_scanner_peek_next_token (scanner); - if (token == G_TOKEN_EOF || token == G_TOKEN_ERROR) - return PARSE_ERROR; - if (token != TOKEN_PIXMAP_PATH) - return PARSE_SYNTAX; token = g_scanner_get_next_token (scanner); + if (token != GTK_RC_TOKEN_PIXMAP_PATH) + return GTK_RC_TOKEN_PIXMAP_PATH; token = g_scanner_get_next_token (scanner); - if (token != G_TOKEN_STRING) - return PARSE_ERROR; + return G_TOKEN_STRING; gtk_rc_parse_pixmap_path_string (scanner->value.v_string); - return PARSE_OK; + return G_TOKEN_NONE; } static void @@ -1152,196 +1449,118 @@ gtk_rc_parse_pixmap_path_string (gchar *pix_path) g_free (buf); } -static gint -gtk_rc_parse_widget_style (GScanner *scanner) +static guint +gtk_rc_parse_path_pattern (GScanner *scanner) { - GtkRcSet *rc_set; - gint token; - - token = g_scanner_peek_next_token (scanner); - if (token == G_TOKEN_EOF || token == G_TOKEN_ERROR) - return PARSE_ERROR; - if (token != TOKEN_WIDGET) - return PARSE_SYNTAX; - token = g_scanner_get_next_token (scanner); + guint token; + GtkPathType path_type; + gchar *pattern; + gboolean is_binding; + GtkPathPriorityType priority = GTK_PATH_PRIO_RC; token = g_scanner_get_next_token (scanner); - if (token != G_TOKEN_STRING) - return PARSE_ERROR; - - rc_set = g_new (GtkRcSet, 1); - rc_set->set = g_strdup (scanner->value.v_string); - - token = g_scanner_get_next_token (scanner); - if (token != TOKEN_STYLE) + switch (token) { - g_free (rc_set->set); - g_free (rc_set); - return PARSE_ERROR; + case GTK_RC_TOKEN_WIDGET: + path_type = GTK_PATH_WIDGET; + break; + case GTK_RC_TOKEN_WIDGET_CLASS: + path_type = GTK_PATH_WIDGET_CLASS; + break; + case GTK_RC_TOKEN_CLASS: + path_type = GTK_PATH_CLASS; + break; + default: + return GTK_RC_TOKEN_WIDGET_CLASS; } token = g_scanner_get_next_token (scanner); if (token != G_TOKEN_STRING) - { - g_free (rc_set->set); - g_free (rc_set); - return PARSE_ERROR; - } - - rc_set->rc_style = gtk_rc_style_find (scanner->value.v_string); - 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; -} + return G_TOKEN_STRING; + + pattern = g_strdup (scanner->value.v_string); -static gint -gtk_rc_parse_widget_class_style (GScanner *scanner) -{ - GtkRcSet *rc_set; - gint token; - - token = g_scanner_peek_next_token (scanner); - if (token == G_TOKEN_EOF || token == G_TOKEN_ERROR) - return PARSE_ERROR; - if (token != TOKEN_WIDGET_CLASS) - return PARSE_SYNTAX; - token = g_scanner_get_next_token (scanner); - - token = g_scanner_get_next_token (scanner); - if (token != G_TOKEN_STRING) - return PARSE_ERROR; - - rc_set = g_new (GtkRcSet, 1); - rc_set->set = g_strdup (scanner->value.v_string); - token = g_scanner_get_next_token (scanner); - if (token != TOKEN_STYLE) + if (token == GTK_RC_TOKEN_STYLE) + is_binding = FALSE; + else if (token == GTK_RC_TOKEN_BINDING) { - g_free (rc_set->set); - g_free (rc_set); - return PARSE_ERROR; + is_binding = TRUE; + if (g_scanner_peek_next_token (scanner) == ':') + { + token = gtk_rc_parse_priority (scanner, &priority); + if (token != G_TOKEN_NONE) + { + g_free (pattern); + return token; + } + } } - - token = g_scanner_get_next_token (scanner); - if (token != G_TOKEN_STRING) + else { - g_free (rc_set->set); - g_free (rc_set); - return PARSE_ERROR; + g_free (pattern); + return GTK_RC_TOKEN_STYLE; } - rc_set->rc_style = gtk_rc_style_find (scanner->value.v_string); - if (!rc_set->rc_style) + token = g_scanner_get_next_token (scanner); + if (token != G_TOKEN_STRING) { - g_free (rc_set->set); - g_free (rc_set); - return PARSE_ERROR; + g_free (pattern); + return G_TOKEN_STRING; } - - 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) + if (is_binding) { - name = gtk_widget_get_name (tmp_widget); - pathlength += strlen (name); - - tmp_widget = tmp_widget->parent; - - if (tmp_widget) - pathlength += 1; + GtkBindingSet *binding; + + binding = gtk_binding_set_find (scanner->value.v_string); + if (!binding) + { + g_free (pattern); + return G_TOKEN_STRING; + } + gtk_binding_set_add_path (binding, path_type, pattern, priority); } - - path = g_new (char, pathlength + 1); - path[pathlength] = '\0'; - - tmp_widget = widget; - while (tmp_widget) + else { - name = gtk_widget_get_name (tmp_widget); - namelength = strlen (name); - - strncpy (&path[pathlength - namelength], name, namelength); - pathlength -= namelength; - - tmp_widget = tmp_widget->parent; + GtkRcStyle *rc_style; + GtkRcSet *rc_set; + + rc_style = gtk_rc_style_find (scanner->value.v_string); - if (tmp_widget) + if (!rc_style) { - pathlength -= 1; - path[pathlength] = '.'; + g_free (pattern); + return G_TOKEN_STRING; } + + rc_set = g_new (GtkRcSet, 1); + gtk_pattern_spec_init (&rc_set->pspec, pattern); + rc_set->rc_style = rc_style; + + if (path_type == GTK_PATH_WIDGET) + gtk_rc_sets_widget = g_slist_prepend (gtk_rc_sets_widget, rc_set); + else if (path_type == GTK_PATH_WIDGET_CLASS) + gtk_rc_sets_widget_class = g_slist_prepend (gtk_rc_sets_widget_class, rc_set); + else + gtk_rc_sets_class = g_slist_prepend (gtk_rc_sets_class, rc_set); } - - return path; + + g_free (pattern); + return G_TOKEN_NONE; } -static char* -gtk_rc_widget_class_path (GtkWidget *widget) +/* +typedef GdkPixmap * (*GtkImageLoader) (GdkWindow *window, + GdkColormap *colormap, + GdkBitmap **mask, + GdkColor *transparent_color, + const gchar *filename); +*/ + +void +gtk_rc_set_image_loader(GtkImageLoader loader) { - 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; + image_loader = loader; } +