diff options
author | Owen Taylor <otaylor@src.gnome.org> | 1998-11-06 22:05:02 +0000 |
---|---|---|
committer | Owen Taylor <otaylor@src.gnome.org> | 1998-11-06 22:05:02 +0000 |
commit | e2a521922085c8010028e227f61bba59ea6b8242 (patch) | |
tree | 2500d6aa6f63aab4b58c17546532ecce8fdcca37 /gtk/gtkrc.c | |
parent | 3c0df19a588bd96f328bda975db8eb9fa7f79e81 (diff) | |
download | gdk-pixbuf-e2a521922085c8010028e227f61bba59ea6b8242.tar.gz |
Merge from themes-2. See the ChangeLog for a somewhat detailed
history of the evolution of the changes involved. Most of this
is actually minor painting tweaks.
Diffstat (limited to 'gtk/gtkrc.c')
-rw-r--r-- | gtk/gtkrc.c | 822 |
1 files changed, 618 insertions, 204 deletions
diff --git a/gtk/gtkrc.c b/gtk/gtkrc.c index 84b24c24e..0f3767a03 100644 --- a/gtk/gtkrc.c +++ b/gtk/gtkrc.c @@ -25,29 +25,12 @@ #include <stdio.h> #include "gtkrc.h" #include "gtkbindings.h" +#include "gtkthemes.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 -{ - char *name; - char *font_name; - char *fontset_name; - char *bg_pixmap_name[5]; - GtkStyle *proto_style; - GList *styles; -}; - struct _GtkRcSet { GtkPatternSpec pspec; @@ -65,13 +48,17 @@ struct _GtkRcFile static guint gtk_rc_style_hash (const char *name); static gint gtk_rc_style_compare (const char *a, const char *b); +static guint gtk_rc_styles_hash (const GSList *rc_styles); +static gint gtk_rc_styles_compare (const GSList *a, + const GSList *b); static GtkRcStyle* gtk_rc_style_find (const char *name); -static GtkRcStyle* gtk_rc_styles_match (GSList *sets, - guint path_length, - gchar *path, - gchar *path_reversed); -static GtkStyle* gtk_rc_style_init (GtkRcStyle *rc_style, - GdkColormap *cmap); +static GSList * gtk_rc_styles_match (GSList *rc_styles, + GSList *sets, + guint path_length, + gchar *path, + gchar *path_reversed); +static GtkStyle * gtk_rc_style_to_style (GtkRcStyle *rc_style); +static GtkStyle* gtk_rc_style_init (GSList *rc_styles); static void gtk_rc_parse_file (const gchar *filename, gboolean reload); @@ -81,29 +68,33 @@ static void gtk_rc_parse_any (const gchar *input_name, 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); + GtkRcStyle *style); static guint gtk_rc_parse_bg (GScanner *scanner, - GtkStyle *style); + GtkRcStyle *style); static guint gtk_rc_parse_fg (GScanner *scanner, - GtkStyle *style); + GtkRcStyle *style); static guint gtk_rc_parse_text (GScanner *scanner, - GtkStyle *style); + GtkRcStyle *style); static guint gtk_rc_parse_bg_pixmap (GScanner *scanner, GtkRcStyle *rc_style); static guint gtk_rc_parse_font (GScanner *scanner, GtkRcStyle *rc_style); static guint gtk_rc_parse_fontset (GScanner *scanner, GtkRcStyle *rc_style); +static guint gtk_rc_parse_engine (GScanner *scanner, + GtkRcStyle *rc_style); 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 guint gtk_rc_parse_module_path (GScanner *scanner); +static void gtk_rc_parse_module_path_string (gchar *mod_path); 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 void gtk_rc_clear_styles (void); +static void gtk_rc_append_default_pixmap_path (void); +static void gtk_rc_append_default_module_path (void); +static void gtk_rc_append_pixmap_path (gchar *dir); static GScannerConfig gtk_rc_scanner_config = @@ -177,28 +168,150 @@ static struct { "application", GTK_RC_TOKEN_APPLICATION }, { "rc", GTK_RC_TOKEN_RC }, { "highest", GTK_RC_TOKEN_HIGHEST }, + { "engine", GTK_RC_TOKEN_ENGINE }, + { "module_path", GTK_RC_TOKEN_MODULE_PATH }, }; static guint n_symbols = sizeof (symbols) / sizeof (symbols[0]); static GHashTable *rc_style_ht = NULL; +static GHashTable *realized_style_ht = 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]; +#define GTK_RC_MAX_MODULE_PATHS 128 +static gchar *module_path[GTK_RC_MAX_MODULE_PATHS]; /* The files we have parsed, to reread later if necessary */ GSList *rc_files = NULL; static GtkImageLoader image_loader = NULL; +/* RC file handling */ + + +gchar * +gtk_rc_get_theme_dir(void) +{ + gchar *var, *path; + + var = getenv("GTK_DATA_PREFIX"); + if (var) + { + path = g_malloc(strlen(var) + strlen("/share/themes") +1); + sprintf(path, "%s%s", var, "/share/themes"); + } + else + { + path = g_malloc(strlen(GTK_DATA_PREFIX) + strlen("/share/themes") +1); + sprintf(path, "%s%s", GTK_DATA_PREFIX, "/share/themes"); + } + return path; +} + +gchar * +gtk_rc_get_module_dir(void) +{ + gchar *var, *path; + + var = getenv("GTK_EXE_PREFIX"); + if (var) + { + path = g_malloc(strlen(var) + strlen("/lib/gtk/themes/engines") +1); + sprintf(path, "%s%s", var, "/lib/gtk/themes/engines"); + } + else + { + path = g_malloc(strlen(GTK_EXE_PREFIX) + strlen("/lib/gtk/themes/engines") +1); + sprintf(path, "%s%s", GTK_EXE_PREFIX, "/lib/gtk/themes/engines"); + } + return path; +} + +static void +gtk_rc_append_default_pixmap_path(void) +{ + gchar *var, *path; + gint n; + + var = getenv("GTK_DATA_PREFIX"); + if (var) + { + path = g_malloc(strlen(var) + strlen("/share/gtk/themes") +1); + sprintf(path, "%s%s", var, "/share/gtk/themes"); + } + else + { + path = g_malloc(strlen(GTK_DATA_PREFIX) + strlen("/share/gtk/themes") +1); + sprintf(path, "%s%s", GTK_DATA_PREFIX, "/share/gtk/themes"); + } + + for (n = 0; pixmap_path[n]; n++) ; + if (n >= GTK_RC_MAX_PIXMAP_PATHS - 1) + return; + pixmap_path[n++] = g_strdup(path); + pixmap_path[n] = NULL; + g_free(path); +} + +static void +gtk_rc_append_pixmap_path(gchar *dir) +{ + gint n; + + for (n = 0; pixmap_path[n]; n++) ; + if (n >= GTK_RC_MAX_MODULE_PATHS - 1) + return; + pixmap_path[n++] = g_strdup(dir); + pixmap_path[n] = NULL; +} + +static void +gtk_rc_append_default_module_path(void) +{ + gchar *var, *path; + gint n; + + for (n = 0; module_path[n]; n++) ; + if (n >= GTK_RC_MAX_MODULE_PATHS - 1) + return; + + var = getenv("GTK_EXE_PREFIX"); + if (var) + { + path = g_malloc(strlen(var) + strlen("/lib/gtk/themes/engines") +1); + sprintf(path, "%s%s", var, "/lib/gtk/themes/engines"); + } + else + { + path = g_malloc(strlen(GTK_EXE_PREFIX) + strlen("/lib/gtk/themes/engines") +1); + sprintf(path, "%s%s", GTK_EXE_PREFIX, "/lib/gtk/themes/engines"); + } + module_path[n++] = g_strdup(path); + g_free(path); + var = getenv("HOME"); + if (var) + { + path = g_malloc(strlen(var) + strlen(".gtk/lib/themes/engines") +1); + sprintf(path, "%s%s", var, ".gtk/lib/themes/engines"); + } + module_path[n++] = g_strdup(path); + module_path[n] = NULL; + g_free(path); +} + void gtk_rc_init (void) { rc_style_ht = g_hash_table_new ((GHashFunc) gtk_rc_style_hash, (GCompareFunc) gtk_rc_style_compare); + pixmap_path[0] = NULL; + module_path[0] = NULL; + gtk_rc_append_default_pixmap_path(); + gtk_rc_append_default_module_path(); } void @@ -272,6 +385,16 @@ gtk_rc_parse_file (const gchar *filename, gboolean reload) if (fd < 0) return; + { + gint i; + gchar *dir; + + dir = g_strdup(rc_file->canonical_name); + for (i = strlen(dir) - 1; (i >= 0) && (dir[i] != '/'); i--) + dir[i] = 0; + gtk_rc_append_pixmap_path(dir); + g_free(dir); + } gtk_rc_parse_any (filename, fd, NULL); close (fd); @@ -286,37 +409,73 @@ gtk_rc_parse (const gchar *filename) gtk_rc_parse_file (filename, TRUE); } -static void -gtk_rc_clear_hash_node (gpointer key, - gpointer data, - gpointer user_data) +/* Handling of RC styles */ + +GtkRcStyle * +gtk_rc_style_new (void) { - int i; - GtkRcStyle *rc_style = data; - GList *tmp_list; + GtkRcStyle *new_style; - g_free (rc_style->name); - g_free (rc_style->font_name); - g_free (rc_style->fontset_name); + new_style = g_new0 (GtkRcStyle, 1); + new_style->ref_count = 1; - for (i=0 ; i<5 ; i++) - g_free (rc_style->bg_pixmap_name[i]); + return new_style; +} - gtk_style_unref (rc_style->proto_style); +void +gtk_rc_style_ref (GtkRcStyle *rc_style) +{ + g_return_if_fail (rc_style != NULL); - tmp_list = rc_style->styles; - while (tmp_list) - { - GtkRcNode *node = tmp_list->data; + rc_style->ref_count++; +} - gdk_colormap_unref (node->cmap); - gtk_style_unref (node->style); +void +gtk_rc_style_unref (GtkRcStyle *rc_style) +{ + gint i; - g_free (node); - tmp_list = tmp_list->next; + g_return_if_fail (rc_style != NULL); + + rc_style->ref_count--; + + if (rc_style->ref_count == 0) + { + if (rc_style->engine) + { + rc_style->engine->destroy_rc_style (rc_style); + gtk_theme_engine_unref (rc_style->engine); + } + + if (rc_style->name) + g_free (rc_style->name); + 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]); + + g_free (rc_style); } +} - g_free (rc_style); +static void +gtk_rc_clear_realized_node (gpointer key, + gpointer data, + gpointer user_data) +{ + gtk_style_unref (data); +} + +static void +gtk_rc_clear_hash_node (gpointer key, + gpointer data, + gpointer user_data) +{ + gtk_rc_style_unref (data); } static void @@ -339,9 +498,19 @@ gtk_rc_clear_styles (void) { /* Clear out all old rc_styles */ - g_hash_table_foreach (rc_style_ht, gtk_rc_clear_hash_node, NULL); - g_hash_table_destroy (rc_style_ht); - rc_style_ht = NULL; + if (rc_style_ht) + { + g_hash_table_foreach (rc_style_ht, gtk_rc_clear_hash_node, NULL); + g_hash_table_destroy (rc_style_ht); + rc_style_ht = NULL; + } + + if (realized_style_ht) + { + g_hash_table_foreach (realized_style_ht, gtk_rc_clear_realized_node, NULL); + g_hash_table_destroy (realized_style_ht); + realized_style_ht = NULL; + } gtk_rc_free_rc_sets (gtk_rc_sets_widget); g_slist_free (gtk_rc_sets_widget); @@ -403,11 +572,13 @@ gtk_rc_reparse_all (void) return mtime_modified; } -static GtkRcStyle* -gtk_rc_styles_match (GSList *sets, +static GSList * +gtk_rc_styles_match (GSList *rc_styles, + GSList *sets, guint path_length, gchar *path, gchar *path_reversed) + { GtkRcSet *rc_set; @@ -417,16 +588,31 @@ gtk_rc_styles_match (GSList *sets, sets = sets->next; if (gtk_pattern_match (&rc_set->pspec, path_length, path, path_reversed)) - return rc_set->rc_style; + rc_styles = g_slist_append (rc_styles, rc_set->rc_style); } - return NULL; + return rc_styles; } GtkStyle* gtk_rc_get_style (GtkWidget *widget) { - GtkRcStyle *rc_style; + GtkRcStyle *widget_rc_style; + GSList *rc_styles = NULL; + + static guint rc_style_key_id = 0; + + /* We allow the specification of a single rc style to be bound + * tightly to a widget, for application modifications + */ + if (!rc_style_key_id) + rc_style_key_id = g_quark_from_static_string ("gtk-rc-style"); + + widget_rc_style = gtk_object_get_data_by_id (GTK_OBJECT (widget), + rc_style_key_id); + + if (widget_rc_style) + rc_styles = g_list_prepend (rc_styles, widget_rc_style); if (gtk_rc_sets_widget) { @@ -434,12 +620,10 @@ gtk_rc_get_style (GtkWidget *widget) 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); + rc_styles = gtk_rc_styles_match (rc_styles, 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 (gtk_rc_sets_widget_class) @@ -448,12 +632,9 @@ gtk_rc_get_style (GtkWidget *widget) 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); + rc_styles = gtk_rc_styles_match (rc_styles, 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) @@ -471,40 +652,37 @@ gtk_rc_get_style (GtkWidget *widget) path_reversed = g_strdup (path); g_strreverse (path_reversed); - rc_style = gtk_rc_styles_match (gtk_rc_sets_class, path_length, path, path_reversed); + rc_styles = gtk_rc_styles_match (rc_styles, gtk_rc_sets_class, path_length, path, path_reversed); g_free (path_reversed); - if (rc_style) - return gtk_rc_style_init (rc_style, gtk_widget_get_colormap (widget)); - type = gtk_type_parent (type); } } + if (rc_styles) + return gtk_rc_style_init (rc_styles); + return NULL; } static GSList* gtk_rc_add_rc_sets (GSList *slist, - GtkStyle *style, + GtkRcStyle *rc_style, const char *pattern) { - GtkRcStyle *rc_style; + GtkRcStyle *new_style; GtkRcSet *rc_set; guint i; - gtk_style_ref (style); - - rc_style = g_new (GtkRcStyle, 1); - rc_style->name = NULL; - rc_style->font_name = NULL; - rc_style->fontset_name = NULL; + new_style = gtk_rc_style_new (); + *new_style = *rc_style; + new_style->name = g_strdup (rc_style->name); + new_style->font_name = g_strdup (rc_style->font_name); + new_style->fontset_name = g_strdup (rc_style->fontset_name); for (i = 0; i < 5; i++) - rc_style->bg_pixmap_name[i] = NULL; + new_style->bg_pixmap_name[i] = g_strdup (rc_style->bg_pixmap_name[i]); - rc_style->styles = g_list_append (NULL, style); - rc_set = g_new (GtkRcSet, 1); gtk_pattern_spec_init (&rc_set->pspec, pattern); rc_set->rc_style = rc_style; @@ -513,33 +691,33 @@ gtk_rc_add_rc_sets (GSList *slist, } void -gtk_rc_add_widget_name_style (GtkStyle *style, +gtk_rc_add_widget_name_style (GtkRcStyle *rc_style, const gchar *pattern) { - g_return_if_fail (style != NULL); + g_return_if_fail (rc_style != NULL); g_return_if_fail (pattern != NULL); - gtk_rc_sets_widget = gtk_rc_add_rc_sets (gtk_rc_sets_widget, style, pattern); + gtk_rc_sets_widget = gtk_rc_add_rc_sets (gtk_rc_sets_widget, rc_style, pattern); } void -gtk_rc_add_widget_class_style (GtkStyle *style, +gtk_rc_add_widget_class_style (GtkRcStyle *rc_style, const gchar *pattern) { - g_return_if_fail (style != NULL); + g_return_if_fail (rc_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); + gtk_rc_sets_widget_class = gtk_rc_add_rc_sets (gtk_rc_sets_widget_class, rc_style, pattern); } void -gtk_rc_add_class_style (GtkStyle *style, +gtk_rc_add_class_style (GtkRcStyle *rc_style, const gchar *pattern) { - g_return_if_fail (style != NULL); + g_return_if_fail (rc_style != NULL); g_return_if_fail (pattern != NULL); - gtk_rc_sets_class = gtk_rc_add_rc_sets (gtk_rc_sets_class, style, pattern); + gtk_rc_sets_class = gtk_rc_add_rc_sets (gtk_rc_sets_class, rc_style, pattern); } static void @@ -631,6 +809,36 @@ gtk_rc_parse_any (const gchar *input_name, g_scanner_destroy (scanner); } +static guint +gtk_rc_styles_hash (const GSList *rc_styles) +{ + guint result; + + result = 0; + while (rc_styles) + { + result += (result << 9) + GPOINTER_TO_UINT (rc_styles->data); + rc_styles = rc_styles->next; + } + + return result; +} + +static gint +gtk_rc_styles_compare (const GSList *a, + const GSList *b) +{ + while (a && b) + { + if (a->data != b->data) + return FALSE; + a = a->next; + b = b->next; + } + + return (a == b); +} + static guint gtk_rc_style_hash (const char *name) { @@ -660,94 +868,145 @@ gtk_rc_style_find (const char *name) return rc_style; } +/* Assumes ownership of rc_style */ static GtkStyle * -gtk_rc_style_init (GtkRcStyle *rc_style, GdkColormap *cmap) +gtk_rc_style_to_style (GtkRcStyle *rc_style) { + GtkStyle *style; GdkFont *old_font; - gboolean match_cmap = FALSE; gint i; - GList *tmp_list; - GtkStyle *style = NULL; - GtkRcNode *node; + style = gtk_style_new (); - tmp_list = rc_style->styles; + style->rc_style = rc_style; + + if (rc_style->fontset_name) + { + old_font = style->font; + style->font = gdk_fontset_load (rc_style->fontset_name); + if (style->font) + gdk_font_unref (old_font); + else + style->font = old_font; + } + else if (rc_style->font_name) + { + old_font = style->font; + style->font = gdk_font_load (rc_style->font_name); + if (style->font) + gdk_font_unref (old_font); + else + style->font = old_font; + } + + for (i = 0; i < 5; i++) + { + if (rc_style->color_flags[i] & GTK_RC_FG) + style->fg[i] = rc_style->fg[i]; + if (rc_style->color_flags[i] & GTK_RC_BG) + style->bg[i] = rc_style->bg[i]; + if (rc_style->color_flags[i] & GTK_RC_TEXT) + style->text[i] = rc_style->text[i]; + if (rc_style->color_flags[i] & GTK_RC_BASE) + style->base[i] = rc_style->base[i]; + } - for (i=0; i<5; i++) - if (rc_style->bg_pixmap_name[i]) - match_cmap = TRUE; - - while (tmp_list) + if (rc_style->engine) { - node = (GtkRcNode *)tmp_list->data; + style->engine = rc_style->engine; + gtk_theme_engine_ref (style->engine); + rc_style->engine->rc_style_to_style (style, rc_style); + } - if (!match_cmap || (node->cmap == cmap)) - { - style = node->style; - break; - } + return style; +} + +/* Reuses or frees rc_styles */ +static GtkStyle * +gtk_rc_style_init (GSList *rc_styles) +{ + gint i; + + GtkStyle *style = NULL; + GtkRcStyle *proto_style; + + if (!realized_style_ht) + realized_style_ht = g_hash_table_new ((GHashFunc)gtk_rc_styles_hash, + (GCompareFunc)gtk_rc_styles_compare); + + style = g_hash_table_lookup (realized_style_ht, rc_styles); - tmp_list = tmp_list->next; - } - if (!style) { - 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; + GSList *tmp_styles = rc_styles; - if (rc_style->fontset_name) - { - old_font = style->font; - style->font = gdk_fontset_load (rc_style->fontset_name); - if (style->font) - gdk_font_unref (old_font); - else - style->font = old_font; - } - else if (rc_style->font_name) + proto_style = gtk_rc_style_new (); + + while (tmp_styles) { - old_font = style->font; - style->font = gdk_font_load (rc_style->font_name); - if (style->font) - gdk_font_unref (old_font); - else - style->font = old_font; + GtkRcStyle *rc_style = tmp_styles->data; + + for (i=0; i<5; i++) + { + if (!proto_style->bg_pixmap_name[i] && rc_style->bg_pixmap_name[i]) + proto_style->bg_pixmap_name[i] = g_strdup (rc_style->bg_pixmap_name[i]); + + if (!(proto_style->color_flags[i] & GTK_RC_FG) && + rc_style->color_flags[i] & GTK_RC_FG) + { + proto_style->fg[i] = rc_style->fg[i]; + proto_style->color_flags[i] |= GTK_RC_FG; + } + if (!(proto_style->color_flags[i] & GTK_RC_BG) && + rc_style->color_flags[i] & GTK_RC_BG) + { + proto_style->bg[i] = rc_style->bg[i]; + proto_style->color_flags[i] |= GTK_RC_BG; + } + if (!(proto_style->color_flags[i] & GTK_RC_TEXT) && + rc_style->color_flags[i] & GTK_RC_TEXT) + { + proto_style->text[i] = rc_style->text[i]; + proto_style->color_flags[i] |= GTK_RC_TEXT; + } + if (!(proto_style->color_flags[i] & GTK_RC_BASE) && + rc_style->color_flags[i] & GTK_RC_BASE) + { + proto_style->base[i] = rc_style->base[i]; + proto_style->color_flags[i] |= GTK_RC_BASE; + } + } + + if (!proto_style->font_name && rc_style->font_name) + proto_style->font_name = g_strdup (rc_style->font_name); + if (!proto_style->fontset_name && rc_style->fontset_name) + proto_style->fontset_name = g_strdup (rc_style->fontset_name); + + if (!proto_style->engine && rc_style->engine) + { + proto_style->engine = rc_style->engine; + gtk_theme_engine_ref (proto_style->engine); + } + + if (proto_style->engine && + (proto_style->engine == rc_style->engine)) + proto_style->engine->merge_rc_style (proto_style, rc_style); + + tmp_styles = tmp_styles->next; } - - for (i = 0; i < 5; i++) - if (rc_style->bg_pixmap_name[i]) - { - if (strcmp (rc_style->bg_pixmap_name[i], "<parent>") == 0) - style->bg_pixmap[i] = (GdkPixmap*) GDK_PARENT_RELATIVE; - else - { - 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); + + style = gtk_rc_style_to_style (proto_style); + + g_hash_table_insert (realized_style_ht, rc_styles, style); } return style; } +/********************* + * Parsing functions * + *********************/ + static guint gtk_rc_parse_statement (GScanner *scanner) { @@ -787,6 +1046,9 @@ gtk_rc_parse_statement (GScanner *scanner) case GTK_RC_TOKEN_CLASS: return gtk_rc_parse_path_pattern (scanner); + case GTK_RC_TOKEN_MODULE_PATH: + return gtk_rc_parse_module_path (scanner); + default: g_scanner_get_next_token (scanner); return /* G_TOKEN_SYMBOL */ GTK_RC_TOKEN_STYLE; @@ -816,16 +1078,17 @@ gtk_rc_parse_style (GScanner *scanner) if (!rc_style) { insert = TRUE; - rc_style = g_new (GtkRcStyle, 1); + rc_style = gtk_rc_style_new (); 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->proto_style = gtk_style_new(); - rc_style->styles = NULL; + for (i = 0; i < 5; i++) + rc_style->color_flags[i] = 0; + + rc_style->engine = NULL; + rc_style->engine_data = NULL; } token = g_scanner_peek_next_token (scanner); @@ -837,10 +1100,8 @@ gtk_rc_parse_style (GScanner *scanner) if (token != G_TOKEN_STRING) { if (insert) - { - gtk_style_unref (rc_style->proto_style); - g_free (rc_style); - } + g_free (rc_style); + return G_TOKEN_STRING; } @@ -849,18 +1110,13 @@ gtk_rc_parse_style (GScanner *scanner) { for (i = 0; i < 5; 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->color_flags[i] = parent_style->color_flags[i]; + rc_style->fg[i] = parent_style->fg[i]; + rc_style->bg[i] = parent_style->bg[i]; + rc_style->text[i] = parent_style->text[i]; + rc_style->base[i] = parent_style->base[i]; } - 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) { g_free (rc_style->fontset_name); @@ -885,10 +1141,8 @@ gtk_rc_parse_style (GScanner *scanner) if (token != G_TOKEN_LEFT_CURLY) { if (insert) - { - gtk_style_unref (rc_style->proto_style); - g_free (rc_style); - } + g_free (rc_style); + return G_TOKEN_LEFT_CURLY; } @@ -898,16 +1152,16 @@ gtk_rc_parse_style (GScanner *scanner) switch (token) { case GTK_RC_TOKEN_BASE: - token = gtk_rc_parse_base (scanner, rc_style->proto_style); + token = gtk_rc_parse_base (scanner, rc_style); break; case GTK_RC_TOKEN_BG: - token = gtk_rc_parse_bg (scanner, rc_style->proto_style); + token = gtk_rc_parse_bg (scanner, rc_style); break; case GTK_RC_TOKEN_FG: - token = gtk_rc_parse_fg (scanner, rc_style->proto_style); + token = gtk_rc_parse_fg (scanner, rc_style); break; case GTK_RC_TOKEN_TEXT: - token = gtk_rc_parse_text (scanner, rc_style->proto_style); + token = gtk_rc_parse_text (scanner, rc_style); break; case GTK_RC_TOKEN_BG_PIXMAP: token = gtk_rc_parse_bg_pixmap (scanner, rc_style); @@ -918,6 +1172,9 @@ gtk_rc_parse_style (GScanner *scanner) case GTK_RC_TOKEN_FONTSET: token = gtk_rc_parse_fontset (scanner, rc_style); break; + case GTK_RC_TOKEN_ENGINE: + token = gtk_rc_parse_engine (scanner, rc_style); + break; default: g_scanner_get_next_token (scanner); token = G_TOKEN_RIGHT_CURLY; @@ -935,7 +1192,6 @@ gtk_rc_parse_style (GScanner *scanner) 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 token; @@ -957,7 +1213,6 @@ gtk_rc_parse_style (GScanner *scanner) 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 G_TOKEN_RIGHT_CURLY; @@ -970,8 +1225,8 @@ gtk_rc_parse_style (GScanner *scanner) } static guint -gtk_rc_parse_base (GScanner *scanner, - GtkStyle *style) +gtk_rc_parse_base (GScanner *scanner, + GtkRcStyle *style) { GtkStateType state; guint token; @@ -987,13 +1242,14 @@ gtk_rc_parse_base (GScanner *scanner, token = g_scanner_get_next_token (scanner); if (token != G_TOKEN_EQUAL_SIGN) return G_TOKEN_EQUAL_SIGN; - + + style->color_flags[state] |= GTK_RC_BASE; return gtk_rc_parse_color (scanner, &style->base[state]); } static guint -gtk_rc_parse_bg (GScanner *scanner, - GtkStyle *style) +gtk_rc_parse_bg (GScanner *scanner, + GtkRcStyle *style) { GtkStateType state; guint token; @@ -1009,13 +1265,14 @@ gtk_rc_parse_bg (GScanner *scanner, token = g_scanner_get_next_token (scanner); if (token != G_TOKEN_EQUAL_SIGN) return G_TOKEN_EQUAL_SIGN; - + + style->color_flags[state] |= GTK_RC_BG; return gtk_rc_parse_color (scanner, &style->bg[state]); } static guint -gtk_rc_parse_fg (GScanner *scanner, - GtkStyle *style) +gtk_rc_parse_fg (GScanner *scanner, + GtkRcStyle *style) { GtkStateType state; guint token; @@ -1032,12 +1289,13 @@ gtk_rc_parse_fg (GScanner *scanner, if (token != G_TOKEN_EQUAL_SIGN) return G_TOKEN_EQUAL_SIGN; + style->color_flags[state] |= GTK_RC_FG; return gtk_rc_parse_color (scanner, &style->fg[state]); } static guint -gtk_rc_parse_text (GScanner *scanner, - GtkStyle *style) +gtk_rc_parse_text (GScanner *scanner, + GtkRcStyle *style) { GtkStateType state; guint token; @@ -1054,6 +1312,7 @@ gtk_rc_parse_text (GScanner *scanner, if (token != G_TOKEN_EQUAL_SIGN) return G_TOKEN_EQUAL_SIGN; + style->color_flags[state] |= GTK_RC_TEXT; return gtk_rc_parse_color (scanner, &style->text[state]); } @@ -1096,7 +1355,7 @@ gtk_rc_parse_bg_pixmap (GScanner *scanner, return G_TOKEN_NONE; } -static gchar* +gchar* gtk_rc_find_pixmap_in_path (GScanner *scanner, gchar *pixmap_file) { @@ -1118,10 +1377,47 @@ gtk_rc_find_pixmap_in_path (GScanner *scanner, g_free (buf); } + + if (scanner) + g_warning ("Unable to locate image file in pixmap_path: \"%s\" line %d", + pixmap_file, scanner->line); + else + g_warning ("Unable to locate image file in pixmap_path: \"%s\"", + pixmap_file); + + return NULL; +} + +gchar* +gtk_rc_find_module_in_path (GScanner *scanner, + gchar *module_file) +{ + gint i; + gint fd; + gchar *buf; - g_warning ("Unable to locate image file in pixmap_path: \"%s\" line %d", - pixmap_file, scanner->line); + for (i = 0; (i < GTK_RC_MAX_MODULE_PATHS) && (module_path[i] != NULL); i++) + { + buf = g_malloc (strlen (module_path[i]) + strlen (module_file) + 2); + sprintf (buf, "%s%c%s", module_path[i], '/', module_file); + + fd = open (buf, O_RDONLY); + if (fd >= 0) + { + close (fd); + return buf; + } + + g_free (buf); + } + if (scanner) + g_warning ("Unable to locate loadable module in module_path: \"%s\" line %d", + module_file, scanner->line); + else + g_warning ("Unable to locate loadable module in module_path: \"%s\",", + module_file); + return NULL; } @@ -1175,6 +1471,48 @@ gtk_rc_parse_fontset (GScanner *scanner, return G_TOKEN_NONE; } +static guint +gtk_rc_parse_engine (GScanner *scanner, + GtkRcStyle *rc_style) +{ + guint token; + + token = g_scanner_get_next_token (scanner); + if (token != GTK_RC_TOKEN_ENGINE) + return GTK_RC_TOKEN_ENGINE; + + token = g_scanner_get_next_token (scanner); + if (token != G_TOKEN_STRING) + return G_TOKEN_STRING; + + rc_style->engine = gtk_theme_engine_get (scanner->value.v_string); + + token = g_scanner_get_next_token (scanner); + if (token != G_TOKEN_LEFT_CURLY) + return G_TOKEN_LEFT_CURLY; + + if (rc_style->engine) + return rc_style->engine->parse_rc_style (scanner, rc_style); + else + { + /* Skip over remainder, looking for nested {}'s */ + guint count = 1; + + while ((token = g_scanner_get_next_token (scanner)) != G_TOKEN_EOF) + { + if (token == G_TOKEN_LEFT_CURLY) + count++; + else if (token == G_TOKEN_RIGHT_CURLY) + count--; + + if (count == 0) + return G_TOKEN_NONE; + } + + return G_TOKEN_RIGHT_CURLY; + } +} + guint gtk_rc_parse_state (GScanner *scanner, GtkStateType *state) @@ -1443,6 +1781,63 @@ gtk_rc_parse_pixmap_path_string (gchar *pix_path) } } g_free (buf); + gtk_rc_append_default_pixmap_path(); +} + +static guint +gtk_rc_parse_module_path (GScanner *scanner) +{ + guint token; + + token = g_scanner_get_next_token (scanner); + if (token != GTK_RC_TOKEN_MODULE_PATH) + return GTK_RC_TOKEN_MODULE_PATH; + + token = g_scanner_get_next_token (scanner); + if (token != G_TOKEN_STRING) + return G_TOKEN_STRING; + + gtk_rc_parse_module_path_string (scanner->value.v_string); + + return G_TOKEN_NONE; +} + +static void +gtk_rc_parse_module_path_string (gchar *mod_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; module_path[path_num]; path_num++) + { + g_free (module_path[path_num]); + module_path[path_num] = NULL; + } + + path_num = 0; + + path_len = strlen (mod_path); + + buf = g_strdup (mod_path); + + for (end_offset = 0; end_offset <= path_len; end_offset++) + { + if ((buf[end_offset] == ':') || + (end_offset == path_len)) + { + buf[end_offset] = '\0'; + module_path[path_num] = g_strdup (buf + start_offset); + path_num++; + module_path[path_num] = NULL; + start_offset = end_offset + 1; + } + } + g_free (buf); + gtk_rc_append_default_module_path(); } static guint @@ -1557,6 +1952,25 @@ typedef GdkPixmap * (*GtkImageLoader) (GdkWindow *window, void gtk_rc_set_image_loader(GtkImageLoader loader) { - image_loader = loader; + image_loader = loader; } +GdkPixmap * +gtk_rc_load_image (GdkColormap *colormap, + GdkColor *transparent_color, + const gchar *filename) +{ + if (strcmp (filename, "<parent>") == 0) + return (GdkPixmap*) GDK_PARENT_RELATIVE; + else + { + if(image_loader) + return image_loader(NULL, colormap, NULL, + transparent_color, + filename); + else + return gdk_pixmap_colormap_create_from_xpm (NULL, colormap, NULL, + transparent_color, + filename); + } +} |