summaryrefslogtreecommitdiff
path: root/gtk/gtkrc.c
diff options
context:
space:
mode:
authorOwen Taylor <otaylor@src.gnome.org>1998-11-06 22:05:02 +0000
committerOwen Taylor <otaylor@src.gnome.org>1998-11-06 22:05:02 +0000
commite2a521922085c8010028e227f61bba59ea6b8242 (patch)
tree2500d6aa6f63aab4b58c17546532ecce8fdcca37 /gtk/gtkrc.c
parent3c0df19a588bd96f328bda975db8eb9fa7f79e81 (diff)
downloadgdk-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.c822
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);
+ }
+}