diff --git a/eek/eek-theme-context.c b/eek/eek-theme-context.c
deleted file mode 100644
index 36b63370..00000000
--- a/eek/eek-theme-context.c
+++ /dev/null
@@ -1,287 +0,0 @@
-/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; c-basic-offset: 2; -*- */
-/*
- * eek-theme-context.c: holds global information about a tree of styled objects
- *
- * Copyright 2009, 2010 Red Hat, Inc.
- * Copyright 2009 Florian Müllner
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation, either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT ANY
- * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
- * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
- * more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program. If not, see .
- */
-
-#include "config.h"
-
-#include "eek-theme.h"
-#include "eek-theme-context.h"
-
-struct _EekThemeContext {
- GObject parent;
-
- double resolution;
- PangoFontDescription *font;
- EekThemeNode *root_node;
- EekTheme *theme;
-};
-
-struct _EekThemeContextClass {
- GObjectClass parent_class;
-};
-
-#define DEFAULT_RESOLUTION 96.
-#define DEFAULT_FONT "sans-serif 10"
-
-enum
-{
- CHANGED,
-
- LAST_SIGNAL
-};
-
-static guint signals[LAST_SIGNAL] = { 0, };
-
-G_DEFINE_TYPE (EekThemeContext, eek_theme_context, G_TYPE_OBJECT)
-
-static void
-eek_theme_context_finalize (GObject *object)
-{
- EekThemeContext *context = EEK_THEME_CONTEXT (object);
-
- if (context->root_node)
- g_object_unref (context->root_node);
- if (context->theme)
- g_object_unref (context->theme);
-
- pango_font_description_free (context->font);
-
- G_OBJECT_CLASS (eek_theme_context_parent_class)->finalize (object);
-}
-
-static void
-eek_theme_context_class_init (EekThemeContextClass *klass)
-{
- GObjectClass *object_class = G_OBJECT_CLASS (klass);
-
- object_class->finalize = eek_theme_context_finalize;
-
- signals[CHANGED] =
- g_signal_new ("changed",
- G_TYPE_FROM_CLASS (klass),
- G_SIGNAL_RUN_LAST,
- 0, /* no default handler slot */
- NULL, NULL,
- g_cclosure_marshal_VOID__VOID,
- G_TYPE_NONE, 0);
-}
-
-static void
-eek_theme_context_init (EekThemeContext *context)
-{
- context->resolution = DEFAULT_RESOLUTION;
- context->font = pango_font_description_from_string (DEFAULT_FONT);
-}
-
-/**
- * eek_theme_context_new:
- *
- * Create a new theme context.
- */
-EekThemeContext *
-eek_theme_context_new (void)
-{
- EekThemeContext *context;
-
- context = g_object_new (EEK_TYPE_THEME_CONTEXT, NULL);
-
- return context;
-}
-
-static void
-eek_theme_context_changed (EekThemeContext *context)
-{
- EekThemeNode *old_root = context->root_node;
- context->root_node = NULL;
-
- g_signal_emit (context, signals[CHANGED], 0);
-
- if (old_root)
- g_object_unref (old_root);
-}
-
-/**
- * eek_theme_context_set_theme:
- * @context: an #EekThemeContext
- * @theme: an #EekTheme
- *
- * Sets the default set of theme stylesheets for the context. This theme will
- * be used for the root node and for nodes descending from it, unless some other
- * style is explicitely specified.
- */
-void
-eek_theme_context_set_theme (EekThemeContext *context,
- EekTheme *theme)
-{
- g_return_if_fail (EEK_IS_THEME_CONTEXT (context));
- g_return_if_fail (theme == NULL || EEK_IS_THEME (theme));
-
- if (context->theme != theme)
- {
- if (context->theme)
- g_object_unref (context->theme);
-
- context->theme = theme;
-
- if (context->theme)
- g_object_ref (context->theme);
-
- eek_theme_context_changed (context);
- }
-}
-
-/**
- * eek_theme_context_get_theme:
- * @context: a #EekThemeContext
- *
- * Gets the default theme for the context. See eek_theme_context_set_theme()
- *
- * Return value: (transfer none): the default theme for the context
- */
-EekTheme *
-eek_theme_context_get_theme (EekThemeContext *context)
-{
- g_return_val_if_fail (EEK_IS_THEME_CONTEXT (context), NULL);
-
- return context->theme;
-}
-
-/**
- * eek_theme_context_set_resolution:
- * @context: a #EekThemeContext
- * @resolution: resolution of the context (number of pixels in an "inch")
- *
- * Sets the resolution of the theme context. This is the scale factor
- * used to convert between points and the length units pt, in, and cm.
- * This does not necessarily need to correspond to the actual number
- * resolution of the device. A value of 72. means that points and
- * pixels are identical. The default value is 96.
- */
-void
-eek_theme_context_set_resolution (EekThemeContext *context,
- double resolution)
-{
- g_return_if_fail (EEK_IS_THEME_CONTEXT (context));
-
- if (resolution == context->resolution)
- return;
-
- context->resolution = resolution;
- eek_theme_context_changed (context);
-}
-
-/**
- * eek_theme_context_set_default_resolution:
- * @context: a #EekThemeContext
- *
- * Sets the resolution of the theme context to the default value of 96.
- * See eek_theme_context_set_resolution().
- */
-void
-eek_theme_context_set_default_resolution (EekThemeContext *context)
-{
- g_return_if_fail (EEK_IS_THEME_CONTEXT (context));
-
- if (context->resolution == DEFAULT_RESOLUTION)
- return;
-
- context->resolution = DEFAULT_RESOLUTION;
- eek_theme_context_changed (context);
-}
-
-/**
- * eek_theme_context_get_resolution:
- * @context: a #EekThemeContext
- *
- * Gets the current resolution of the theme context.
- * See eek_theme_context_set_resolution().
- *
- * Return value: the resolution (in dots-per-"inch")
- */
-double
-eek_theme_context_get_resolution (EekThemeContext *context)
-{
- g_return_val_if_fail (EEK_IS_THEME_CONTEXT (context), DEFAULT_RESOLUTION);
-
- return context->resolution;
-}
-
-/**
- * eek_theme_context_set_font:
- * @context: a #EekThemeContext
- * @font: the default font for theme context
- *
- * Sets the default font for the theme context. This is the font that
- * is inherited by the root node of the tree of theme nodes. If the
- * font is not overriden, then this font will be used. If the font is
- * partially modified (for example, with 'font-size: 110%', then that
- * modification is based on this font.
- */
-void
-eek_theme_context_set_font (EekThemeContext *context,
- const PangoFontDescription *font)
-{
- g_return_if_fail (EEK_IS_THEME_CONTEXT (context));
- g_return_if_fail (font != NULL);
-
- if (context->font == font ||
- pango_font_description_equal (context->font, font))
- return;
-
- pango_font_description_free (context->font);
- context->font = pango_font_description_copy (font);
- eek_theme_context_changed (context);
-}
-
-/**
- * eek_theme_context_get_font:
- * @context: a #EekThemeContext
- *
- * Gets the default font for the theme context. See eek_theme_context_set_font().
- *
- * Return value: the default font for the theme context.
- */
-const PangoFontDescription *
-eek_theme_context_get_font (EekThemeContext *context)
-{
- g_return_val_if_fail (EEK_IS_THEME_CONTEXT (context), NULL);
-
- return context->font;
-}
-
-/**
- * eek_theme_context_get_root_node:
- * @context: a #EekThemeContext
- *
- * Gets the root node of the tree of theme style nodes that associated with this
- * context. For the node tree associated with a stage, this node represents
- * styles applied to the stage itself.
- *
- * Return value: (transfer none): the root node of the context's style tree
- */
-EekThemeNode *
-eek_theme_context_get_root_node (EekThemeContext *context)
-{
- if (context->root_node == NULL)
- context->root_node = eek_theme_node_new (context, NULL, context->theme,
- G_TYPE_NONE, NULL, NULL, NULL, NULL);
-
- return context->root_node;
-}
diff --git a/eek/eek-theme-context.h b/eek/eek-theme-context.h
deleted file mode 100644
index a8498739..00000000
--- a/eek/eek-theme-context.h
+++ /dev/null
@@ -1,78 +0,0 @@
-/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
-/*
- * eek-theme-context.c: holds global information about a tree of styled objects
- *
- * Copyright 2009, 2010 Red Hat, Inc.
- * Copyright 2009 Florian Müllner
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation, either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT ANY
- * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
- * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
- * more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program. If not, see .
- */
-
-#ifndef __EEK_THEME_CONTEXT_H__
-#define __EEK_THEME_CONTEXT_H__
-
-#include
-#include "eek-theme-node.h"
-
-G_BEGIN_DECLS
-
-/**
- * SECTION:eek-theme-context
- * @short_description: holds global information about a tree of styled objects
- *
- * #EekThemeContext is responsible for managing information global to
- * a tree of styled objects, such as the set of stylesheets or the
- * default font.
- */
-
-typedef struct _EekThemeContextClass EekThemeContextClass;
-
-#define EEK_TYPE_THEME_CONTEXT (eek_theme_context_get_type ())
-#define EEK_THEME_CONTEXT(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), EEK_TYPE_THEME_CONTEXT, EekThemeContext))
-#define EEK_THEME_CONTEXT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), EEK_TYPE_THEME_CONTEXT, EekThemeContextClass))
-#define EEK_IS_THEME_CONTEXT(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), EEK_TYPE_THEME_CONTEXT))
-#define EEK_IS_THEME_CONTEXT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), EEK_TYPE_THEME_CONTEXT))
-#define EEK_THEME_CONTEXT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), EEK_TYPE_THEME_CONTEXT, EekThemeContextClass))
-
-GType eek_theme_context_get_type
- (void) G_GNUC_CONST;
-
-EekThemeContext *eek_theme_context_new
- (void);
-
-void eek_theme_context_set_theme
- (EekThemeContext *context,
- EekTheme *theme);
-EekTheme * eek_theme_context_get_theme
- (EekThemeContext *context);
-
-void eek_theme_context_set_resolution
- (EekThemeContext *context,
- gdouble resolution);
-void eek_theme_context_set_default_resolution
- (EekThemeContext *context);
-double eek_theme_context_get_resolution
- (EekThemeContext *context);
-void eek_theme_context_set_font
- (EekThemeContext *context,
- const PangoFontDescription *font);
-const PangoFontDescription *eek_theme_context_get_font
- (EekThemeContext *context);
-
-EekThemeNode * eek_theme_context_get_root_node
- (EekThemeContext *context);
-
-G_END_DECLS
-
-#endif /* __EEK_THEME_CONTEXT_H__ */
diff --git a/eek/eek-theme-node.c b/eek/eek-theme-node.c
deleted file mode 100644
index a3bb3607..00000000
--- a/eek/eek-theme-node.c
+++ /dev/null
@@ -1,1864 +0,0 @@
-/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; c-basic-offset: 2; -*- */
-/*
- * eek-theme-node.c: style information for one node in a tree of themed objects
- *
- * Copyright 2008-2010 Red Hat, Inc.
- * Copyright 2009 Steve Frécinaux
- * Copyright 2009, 2010 Florian Müllner
- * Copyright 2010 Adel Gadllah
- * Copyright 2010 Giovanni Campagna
- * Copyright 2010-2011 Daiki Ueno
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation, either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT ANY
- * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
- * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
- * more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program. If not, see .
- */
-
-#include "config.h"
-
-#include
-#include
-#include
-
-#include "eek-theme-context.h"
-#include "eek-theme-node.h"
-#include "eek-theme-private.h"
-
-struct _EekThemeNode {
- GObject parent;
-
- EekThemeContext *context;
- EekThemeNode *parent_node;
- EekTheme *theme;
-
- PangoFontDescription *font_desc;
-
- EekGradientType background_gradient_type;
-
- EekColor background_color;
- EekColor background_gradient_end;
-
- EekColor foreground_color;
- EekColor border_color[4];
-
- int border_width[4];
- int border_radius[4];
-
- GType element_type;
- char *element_id;
- char *element_class;
- char *pseudo_class;
- char *inline_style;
-
- CRDeclaration **properties;
- int n_properties;
-
- /* We hold onto these separately so we can destroy them on finalize */
- CRDeclaration *inline_properties;
-
- guint properties_computed : 1;
- guint geometry_computed : 1;
- guint background_computed : 1;
- guint foreground_computed : 1;
-};
-
-struct _EekThemeNodeClass {
- GObjectClass parent_class;
-};
-
-G_DEFINE_TYPE (EekThemeNode, eek_theme_node, G_TYPE_OBJECT);
-
-#define EEK_THEME_NODE_GET_PRIVATE(obj) \
- (G_TYPE_INSTANCE_GET_PRIVATE ((obj), EEK_TYPE_THEME_NODE, EekThemeNodePrivate))
-
-static void eek_theme_node_init (EekThemeNode *node);
-static void eek_theme_node_class_init (EekThemeNodeClass *klass);
-static void eek_theme_node_dispose (GObject *object);
-static void eek_theme_node_finalize (GObject *object);
-
-static const EekColor BLACK_COLOR = { 0, 0, 0, 0xff };
-static const EekColor TRANSPARENT_COLOR = { 0, 0, 0, 0 };
-
-static void
-eek_theme_node_init (EekThemeNode *self)
-{
-}
-
-static void
-eek_theme_node_class_init (EekThemeNodeClass *klass)
-{
- GObjectClass *object_class = G_OBJECT_CLASS (klass);
-
- object_class->dispose = eek_theme_node_dispose;
- object_class->finalize = eek_theme_node_finalize;
-}
-
-static void
-eek_theme_node_dispose (GObject *gobject)
-{
- EekThemeNode *node = EEK_THEME_NODE (gobject);
-
- if (node->context)
- {
- g_object_unref (node->context);
- node->context = NULL;
- }
-
- if (node->theme)
- {
- g_object_unref (node->theme);
- node->theme = NULL;
- }
-
- if (node->parent_node)
- {
- g_object_unref (node->parent_node);
- node->parent_node = NULL;
- }
-
- G_OBJECT_CLASS (eek_theme_node_parent_class)->dispose (gobject);
-}
-
-static void
-eek_theme_node_finalize (GObject *object)
-{
- EekThemeNode *node = EEK_THEME_NODE (object);
-
- g_free (node->element_id);
- g_free (node->element_class);
- g_free (node->pseudo_class);
- g_free (node->inline_style);
-
- if (node->properties)
- {
- g_free (node->properties);
- node->properties = NULL;
- node->n_properties = 0;
- }
-
- if (node->inline_properties)
- {
- /* This destroys the list, not just the head of the list */
- cr_declaration_destroy (node->inline_properties);
- }
-
- if (node->font_desc)
- {
- pango_font_description_free (node->font_desc);
- node->font_desc = NULL;
- }
-
- G_OBJECT_CLASS (eek_theme_node_parent_class)->finalize (object);
-}
-
-/**
- * eek_theme_node_new:
- * @parent_node: (allow-none): the parent node of this node
- * @theme: (allow-none): a theme (stylesheet set) that overrides the
- * theme inherited from the parent node
- * @element_type: the type of the GObject represented by this node
- * in the tree (corresponding to an element if we were theming an XML
- * document. %G_TYPE_NONE means this style was created for the stage
- * actor and matches a selector element name of 'stage'.
- * @element_id: (allow-none): the ID to match CSS rules against
- * @element_class: (allow-none): a whitespace-separated list of classes
- * to match CSS rules against
- * @pseudo_class: (allow-none): a whitespace-separated list of pseudo-classes
- * (like 'hover' or 'visited') to match CSS rules against
- *
- * Creates a new #EekThemeNode. Once created, a node is immutable. Of any
- * of the attributes of the node (like the @element_class) change the node
- * and its child nodes must be destroyed and recreated.
- *
- * Return value: (transfer full): the theme node
- */
-EekThemeNode *
-eek_theme_node_new (EekThemeContext *context,
- EekThemeNode *parent_node,
- EekTheme *theme,
- GType element_type,
- const char *element_id,
- const char *element_class,
- const char *pseudo_class,
- const char *inline_style)
-{
- EekThemeNode *node;
-
- g_return_val_if_fail (EEK_IS_THEME_CONTEXT (context), NULL);
- g_return_val_if_fail (parent_node == NULL || EEK_IS_THEME_NODE (parent_node), NULL);
-
- node = g_object_new (EEK_TYPE_THEME_NODE, NULL);
-
- node->context = g_object_ref (context);
- if (parent_node != NULL)
- node->parent_node = g_object_ref (parent_node);
- else
- node->parent_node = NULL;
-
- if (theme == NULL && parent_node != NULL)
- theme = eek_theme_node_get_theme (parent_node);
-
- if (theme != NULL)
- node->theme = g_object_ref (theme);
-
- node->element_type = element_type;
- node->element_id = g_strdup (element_id);
- node->element_class = g_strdup (element_class);
- node->pseudo_class = g_strdup (pseudo_class);
- node->inline_style = g_strdup (inline_style);
-
- return node;
-}
-
-/**
- * eek_theme_node_get_parent:
- * @node: a #EekThemeNode
- *
- * Gets the parent themed element node.
- *
- * Return value: (transfer none): the parent #EekThemeNode, or %NULL if this
- * is the root node of the tree of theme elements.
- */
-EekThemeNode *
-eek_theme_node_get_parent (EekThemeNode *node)
-{
- g_return_val_if_fail (EEK_IS_THEME_NODE (node), NULL);
-
- return node->parent_node;
-}
-
-/**
- * eek_theme_node_get_theme:
- * @node: a #EekThemeNode
- *
- * Gets the theme stylesheet set that styles this node
- *
- * Return value: (transfer none): the theme stylesheet set
- */
-EekTheme *
-eek_theme_node_get_theme (EekThemeNode *node)
-{
- g_return_val_if_fail (EEK_IS_THEME_NODE (node), NULL);
-
- return node->theme;
-}
-
-GType
-eek_theme_node_get_element_type (EekThemeNode *node)
-{
- g_return_val_if_fail (EEK_IS_THEME_NODE (node), G_TYPE_NONE);
-
- return node->element_type;
-}
-
-const char *
-eek_theme_node_get_element_id (EekThemeNode *node)
-{
- g_return_val_if_fail (EEK_IS_THEME_NODE (node), NULL);
-
- return node->element_id;
-}
-
-const char *
-eek_theme_node_get_element_class (EekThemeNode *node)
-{
- g_return_val_if_fail (EEK_IS_THEME_NODE (node), NULL);
-
- return node->element_class;
-}
-
-const char *
-eek_theme_node_get_pseudo_class (EekThemeNode *node)
-{
- g_return_val_if_fail (EEK_IS_THEME_NODE (node), NULL);
-
- return node->pseudo_class;
-}
-
-static void
-ensure_properties (EekThemeNode *node)
-{
- if (!node->properties_computed)
- {
- GPtrArray *properties = NULL;
-
- node->properties_computed = TRUE;
-
- if (node->theme)
- properties = _eek_theme_get_matched_properties (node->theme, node);
-
- if (node->inline_style)
- {
- CRDeclaration *cur_decl;
-
- if (!properties)
- properties = g_ptr_array_new ();
-
- node->inline_properties =
- _eek_theme_parse_declaration_list (node->inline_style);
- for (cur_decl = node->inline_properties;
- cur_decl;
- cur_decl = cur_decl->next)
- g_ptr_array_add (properties, cur_decl);
- }
-
- if (properties)
- {
- node->n_properties = properties->len;
- node->properties = (CRDeclaration **)g_ptr_array_free (properties,
- FALSE);
- }
- }
-}
-
-typedef enum {
- VALUE_FOUND,
- VALUE_NOT_FOUND,
- VALUE_INHERIT
-} GetFromTermResult;
-
-static gboolean
-term_is_none (CRTerm *term)
-{
- return (term->type == TERM_IDENT &&
- strcmp (term->content.str->stryng->str, "none") == 0);
-}
-
-static gboolean
-term_is_transparent (CRTerm *term)
-{
- return (term->type == TERM_IDENT &&
- strcmp (term->content.str->stryng->str, "transparent") == 0);
-}
-
-static GetFromTermResult
-get_color_from_rgba_term (CRTerm *term,
- EekColor *color)
-{
- CRTerm *arg = term->ext_content.func_param;
- CRNum *num;
- double r = 0, g = 0, b = 0, a = 0;
- int i;
-
- for (i = 0; i < 4; i++)
- {
- double value;
-
- if (arg == NULL)
- return VALUE_NOT_FOUND;
-
- if ((i == 0 && arg->the_operator != NO_OP) ||
- (i > 0 && arg->the_operator != COMMA))
- return VALUE_NOT_FOUND;
-
- if (arg->type != TERM_NUMBER)
- return VALUE_NOT_FOUND;
-
- num = arg->content.num;
-
- /* For simplicity, we convert a,r,g,b to [0,1.0] floats and then
- * convert them back below. Then when we set them on a cairo content
- * we convert them back to floats, and then cairo converts them
- * back to integers to pass them to X, and so forth...
- */
- if (i < 3)
- {
- if (num->type == NUM_PERCENTAGE)
- value = num->val / 100;
- else if (num->type == NUM_GENERIC)
- value = num->val / 255;
- else
- return VALUE_NOT_FOUND;
- }
- else
- {
- if (num->type != NUM_GENERIC)
- return VALUE_NOT_FOUND;
-
- value = num->val;
- }
-
- value = CLAMP (value, 0, 1);
-
- switch (i)
- {
- case 0:
- r = value;
- break;
- case 1:
- g = value;
- break;
- case 2:
- b = value;
- break;
- case 3:
- a = value;
- break;
- }
-
- arg = arg->next;
- }
-
- color->red = CLAMP(r, 0.0, 1.0);
- color->green = CLAMP(g, 0.0, 1.0);
- color->blue = CLAMP(b, 0.0, 1.0);
- color->alpha = CLAMP(a, 0.0, 1.0);
-
- return VALUE_FOUND;
-}
-
-static GetFromTermResult
-get_color_from_term (EekThemeNode *node,
- CRTerm *term,
- EekColor *color)
-{
- CRRgb rgb;
- enum CRStatus status;
-
- /* Since libcroco doesn't know about rgba colors, it can't handle
- * the transparent keyword
- */
- if (term_is_transparent (term))
- {
- *color = TRANSPARENT_COLOR;
- return VALUE_FOUND;
- }
- /* rgba () colors - a CSS3 addition, are not supported by libcroco,
- * but they are parsed as a "function", so we can emulate the
- * functionality.
- *
- * libcroco < 0.6.2 has a bug where functions starting with 'r' are
- * misparsed. We workaround this by pre-converting 'rgba' to 'RGBA'
- * before parsing the stylesheet. Since libcroco isn't
- * case-insensitive (a bug), it's fine with functions starting with
- * 'R'. (In theory, we should be doing a case-insensitive compare
- * everywhere, not just here, but that doesn't make much sense when
- * the built-in parsing of libcroco is case-sensitive and things
- * like 10PX don't work.)
- */
- else if (term->type == TERM_FUNCTION &&
- term->content.str &&
- term->content.str->stryng &&
- term->content.str->stryng->str &&
- g_ascii_strcasecmp (term->content.str->stryng->str, "rgba") == 0)
- {
- return get_color_from_rgba_term (term, color);
- }
-
- status = cr_rgb_set_from_term (&rgb, term);
- if (status != CR_OK)
- return VALUE_NOT_FOUND;
-
- if (rgb.inherit)
- return VALUE_INHERIT;
-
- if (rgb.is_percentage)
- cr_rgb_compute_from_percentage (&rgb);
-
- color->red = rgb.red / (gdouble)0xff;
- color->green = rgb.green / (gdouble)0xff;
- color->blue = rgb.blue / (gdouble)0xff;
- color->alpha = 1.0;
-
- return VALUE_FOUND;
-}
-
-/**
- * eek_theme_node_lookup_color:
- * @node: a #EekThemeNode
- * @property_name: The name of the color property
- * @inherit: if %TRUE, if a value is not found for the property on the
- * node, then it will be looked up on the parent node, and then on the
- * parent's parent, and so forth. Note that if the property has a
- * value of 'inherit' it will be inherited even if %FALSE is passed
- * in for @inherit; this only affects the default behavior for inheritance.
- * @color: location to store the color that was determined.
- * If the property is not found, the value in this location
- * will not be changed.
- *
- * Generically looks up a property containing a single color value. When
- * specific getters (like eek_theme_node_get_background_color()) exist, they
- * should be used instead. They are cached, so more efficient, and have
- * handling for shortcut properties and other details of CSS.
- *
- * Return value: %TRUE if the property was found in the properties for this
- * theme node (or in the properties of parent nodes when inheriting.)
- */
-gboolean
-eek_theme_node_lookup_color (EekThemeNode *node,
- const char *property_name,
- gboolean inherit,
- EekColor *color)
-{
- int i;
-
- g_return_val_if_fail (EEK_IS_THEME_NODE(node), FALSE);
-
- ensure_properties (node);
-
- for (i = node->n_properties - 1; i >= 0; i--)
- {
- CRDeclaration *decl = node->properties[i];
-
- if (strcmp (decl->property->stryng->str, property_name) == 0)
- {
- GetFromTermResult result = get_color_from_term (node, decl->value, color);
- if (result == VALUE_FOUND)
- {
- return TRUE;
- }
- else if (result == VALUE_INHERIT)
- {
- if (node->parent_node)
- return eek_theme_node_lookup_color (node->parent_node, property_name, inherit, color);
- else
- break;
- }
- }
- }
-
- if (inherit && node->parent_node)
- return eek_theme_node_lookup_color (node->parent_node, property_name, inherit, color);
-
- return FALSE;
-}
-
-/**
- * eek_theme_node_get_color:
- * @node: a #EekThemeNode
- * @property_name: The name of the color property
- * @color: location to store the color that was determined.
- *
- * Generically looks up a property containing a single color value. When
- * specific getters (like eek_theme_node_get_background_color()) exist, they
- * should be used instead. They are cached, so more efficient, and have
- * handling for shortcut properties and other details of CSS.
- *
- * If @property_name is not found, a warning will be logged and a
- * default color returned.
- *
- * See also eek_theme_node_lookup_color(), which provides more options,
- * and lets you handle the case where the theme does not specify the
- * indicated color.
- */
-void
-eek_theme_node_get_color (EekThemeNode *node,
- const char *property_name,
- EekColor *color)
-{
- if (!eek_theme_node_lookup_color (node, property_name, FALSE, color))
- {
- g_warning ("Did not find color property '%s'", property_name);
- memset (color, 0, sizeof (EekColor));
- }
-}
-
-/**
- * eek_theme_node_lookup_double:
- * @node: a #EekThemeNode
- * @property_name: The name of the numeric property
- * @inherit: if %TRUE, if a value is not found for the property on the
- * node, then it will be looked up on the parent node, and then on the
- * parent's parent, and so forth. Note that if the property has a
- * value of 'inherit' it will be inherited even if %FALSE is passed
- * in for @inherit; this only affects the default behavior for inheritance.
- * @value: (out): location to store the value that was determined.
- * If the property is not found, the value in this location
- * will not be changed.
- *
- * Generically looks up a property containing a single numeric value
- * without units.
- *
- * See also eek_theme_node_get_double(), which provides a simpler API.
- *
- * Return value: %TRUE if the property was found in the properties for this
- * theme node (or in the properties of parent nodes when inheriting.)
- */
-gboolean
-eek_theme_node_lookup_double (EekThemeNode *node,
- const char *property_name,
- gboolean inherit,
- double *value)
-{
- gboolean result = FALSE;
- int i;
-
- g_return_val_if_fail (EEK_IS_THEME_NODE(node), FALSE);
-
- ensure_properties (node);
-
- for (i = node->n_properties - 1; i >= 0; i--)
- {
- CRDeclaration *decl = node->properties[i];
-
- if (strcmp (decl->property->stryng->str, property_name) == 0)
- {
- CRTerm *term = decl->value;
-
- if (term->type != TERM_NUMBER || term->content.num->type != NUM_GENERIC)
- continue;
-
- *value = term->content.num->val;
- result = TRUE;
- break;
- }
- }
-
- if (!result && inherit && node->parent_node)
- result = eek_theme_node_lookup_double (node->parent_node, property_name, inherit, value);
-
- return result;
-}
-
-/**
- * eek_theme_node_get_double:
- * @node: a #EekThemeNode
- * @property_name: The name of the numeric property
- *
- * Generically looks up a property containing a single numeric value
- * without units.
- *
- * See also eek_theme_node_lookup_double(), which provides more options,
- * and lets you handle the case where the theme does not specify the
- * indicated value.
- *
- * Return value: the value found. If @property_name is not
- * found, a warning will be logged and 0 will be returned.
- */
-gdouble
-eek_theme_node_get_double (EekThemeNode *node,
- const char *property_name)
-{
- gdouble value;
-
- if (eek_theme_node_lookup_double (node, property_name, FALSE, &value))
- return value;
- else
- {
- g_warning ("Did not find double property '%s'", property_name);
- return 0.0;
- }
-}
-
-static const PangoFontDescription *
-get_parent_font (EekThemeNode *node)
-{
- if (node->parent_node)
- return eek_theme_node_get_font (node->parent_node);
- else
- return eek_theme_context_get_font (node->context);
-}
-
-static GetFromTermResult
-get_length_from_term (EekThemeNode *node,
- CRTerm *term,
- gboolean use_parent_font,
- gdouble *length)
-{
- CRNum *num;
-
- enum {
- ABSOLUTE,
- POINTS,
- FONT_RELATIVE,
- } type = ABSOLUTE;
-
- double multiplier = 1.0;
-
- if (term->type != TERM_NUMBER)
- {
- g_warning ("Ignoring length property that isn't a number");
- return VALUE_NOT_FOUND;
- }
-
- num = term->content.num;
-
- switch (num->type)
- {
- case NUM_LENGTH_PX:
- type = ABSOLUTE;
- multiplier = 1;
- break;
- case NUM_LENGTH_PT:
- type = POINTS;
- multiplier = 1;
- break;
- case NUM_LENGTH_IN:
- type = POINTS;
- multiplier = 72;
- break;
- case NUM_LENGTH_CM:
- type = POINTS;
- multiplier = 72. / 2.54;
- break;
- case NUM_LENGTH_MM:
- type = POINTS;
- multiplier = 72. / 25.4;
- break;
- case NUM_LENGTH_PC:
- type = POINTS;
- multiplier = 12. / 25.4;
- break;
- case NUM_LENGTH_EM:
- {
- type = FONT_RELATIVE;
- multiplier = 1;
- break;
- }
- case NUM_LENGTH_EX:
- {
- /* Doing better would require actually resolving the font description
- * to a specific font, and Pango doesn't have an ex metric anyways,
- * so we'd have to try and synthesize it by complicated means.
- *
- * The 0.5em is the CSS spec suggested thing to use when nothing
- * better is available.
- */
- type = FONT_RELATIVE;
- multiplier = 0.5;
- break;
- }
-
- case NUM_INHERIT:
- return VALUE_INHERIT;
-
- case NUM_AUTO:
- g_warning ("'auto' not supported for lengths");
- return VALUE_NOT_FOUND;
-
- case NUM_GENERIC:
- {
- if (num->val != 0)
- {
- g_warning ("length values must specify a unit");
- return VALUE_NOT_FOUND;
- }
- else
- {
- type = ABSOLUTE;
- multiplier = 0;
- }
- break;
- }
-
- case NUM_PERCENTAGE:
- g_warning ("percentage lengths not currently supported");
- return VALUE_NOT_FOUND;
-
- case NUM_ANGLE_DEG:
- case NUM_ANGLE_RAD:
- case NUM_ANGLE_GRAD:
- case NUM_TIME_MS:
- case NUM_TIME_S:
- case NUM_FREQ_HZ:
- case NUM_FREQ_KHZ:
- case NUM_UNKNOWN_TYPE:
- case NB_NUM_TYPE:
- g_warning ("Ignoring invalid type of number of length property");
- return VALUE_NOT_FOUND;
- }
-
- switch (type)
- {
- case ABSOLUTE:
- *length = num->val * multiplier;
- break;
- case POINTS:
- {
- double resolution = eek_theme_context_get_resolution (node->context);
- *length = num->val * multiplier * (resolution / 72.);
- }
- break;
- case FONT_RELATIVE:
- {
- const PangoFontDescription *desc;
- double font_size;
-
- if (use_parent_font)
- desc = get_parent_font (node);
- else
- desc = eek_theme_node_get_font (node);
-
- font_size = (double)pango_font_description_get_size (desc) / PANGO_SCALE;
-
- if (pango_font_description_get_size_is_absolute (desc))
- {
- *length = num->val * multiplier * font_size;
- }
- else
- {
- double resolution = eek_theme_context_get_resolution (node->context);
- *length = num->val * multiplier * (resolution / 72.) * font_size;
- }
- }
- break;
-
- default:
- g_assert_not_reached ();
- }
-
- return VALUE_FOUND;
-}
-
-static GetFromTermResult
-get_length_from_term_int (EekThemeNode *node,
- CRTerm *term,
- gboolean use_parent_font,
- gint *length)
-{
- double value;
- GetFromTermResult result;
-
- result = get_length_from_term (node, term, use_parent_font, &value);
- if (result == VALUE_FOUND)
- *length = (int) (0.5 + value);
- return result;
-}
-
-static GetFromTermResult
-get_length_internal (EekThemeNode *node,
- const char *property_name,
- const char *suffixed,
- gdouble *length)
-{
- int i;
-
- g_return_val_if_fail (EEK_IS_THEME_NODE(node), FALSE);
-
- ensure_properties (node);
-
- for (i = node->n_properties - 1; i >= 0; i--)
- {
- CRDeclaration *decl = node->properties[i];
-
- if (strcmp (decl->property->stryng->str, property_name) == 0 ||
- (suffixed != NULL && strcmp (decl->property->stryng->str, suffixed) == 0))
- {
- GetFromTermResult result = get_length_from_term (node, decl->value, FALSE, length);
- if (result != VALUE_NOT_FOUND)
- return result;
- }
- }
-
- return VALUE_NOT_FOUND;
-}
-
-/**
- * eek_theme_node_lookup_length:
- * @node: a #EekThemeNode
- * @property_name: The name of the length property
- * @inherit: if %TRUE, if a value is not found for the property on the
- * node, then it will be looked up on the parent node, and then on the
- * parent's parent, and so forth. Note that if the property has a
- * value of 'inherit' it will be inherited even if %FALSE is passed
- * in for @inherit; this only affects the default behavior for inheritance.
- * @length: (out): location to store the length that was determined.
- * If the property is not found, the value in this location
- * will not be changed. The returned length is resolved
- * to pixels.
- *
- * Generically looks up a property containing a single length value. When
- * specific getters (like eek_theme_node_get_border_width()) exist, they
- * should be used instead. They are cached, so more efficient, and have
- * handling for shortcut properties and other details of CSS.
- *
- * See also eek_theme_node_get_length(), which provides a simpler API.
- *
- * Return value: %TRUE if the property was found in the properties for this
- * theme node (or in the properties of parent nodes when inheriting.)
- */
-gboolean
-eek_theme_node_lookup_length (EekThemeNode *node,
- const char *property_name,
- gboolean inherit,
- gdouble *length)
-{
- GetFromTermResult result;
-
- g_return_val_if_fail (EEK_IS_THEME_NODE(node), FALSE);
-
- result = get_length_internal (node, property_name, NULL, length);
- if (result == VALUE_FOUND)
- return TRUE;
- else if (result == VALUE_INHERIT)
- inherit = TRUE;
-
- if (inherit && node->parent_node &&
- eek_theme_node_lookup_length (node->parent_node, property_name, inherit, length))
- return TRUE;
- else
- return FALSE;
-}
-
-/**
- * eek_theme_node_get_length:
- * @node: a #EekThemeNode
- * @property_name: The name of the length property
- *
- * Generically looks up a property containing a single length value. When
- * specific getters (like eek_theme_node_get_border_width()) exist, they
- * should be used instead. They are cached, so more efficient, and have
- * handling for shortcut properties and other details of CSS.
- *
- * Unlike eek_theme_node_get_color() and eek_theme_node_get_double(),
- * this does not print a warning if the property is not found; it just
- * returns 0.
- *
- * See also eek_theme_node_lookup_length(), which provides more options.
- *
- * Return value: the length, in pixels, or 0 if the property was not found.
- */
-gdouble
-eek_theme_node_get_length (EekThemeNode *node,
- const char *property_name)
-{
- gdouble length;
-
- if (eek_theme_node_lookup_length (node, property_name, FALSE, &length))
- return length;
- else
- return 0.0;
-}
-
-static void
-do_border_radius_term (EekThemeNode *node,
- CRTerm *term,
- gboolean topleft,
- gboolean topright,
- gboolean bottomright,
- gboolean bottomleft)
-{
- int value;
-
- g_return_if_fail (EEK_IS_THEME_NODE (node));
-
- if (get_length_from_term_int (node, term, FALSE, &value) != VALUE_FOUND)
- return;
-
- if (topleft)
- node->border_radius[EEK_CORNER_TOPLEFT] = value;
- if (topright)
- node->border_radius[EEK_CORNER_TOPRIGHT] = value;
- if (bottomright)
- node->border_radius[EEK_CORNER_BOTTOMRIGHT] = value;
- if (bottomleft)
- node->border_radius[EEK_CORNER_BOTTOMLEFT] = value;
-}
-
-static void
-do_border_radius (EekThemeNode *node,
- CRDeclaration *decl)
-{
- const char *property_name = decl->property->stryng->str + 13; /* Skip 'border-radius' */
-
- if (strcmp (property_name, "") == 0)
- {
- /* Slight deviation ... if we don't understand some of the terms and understand others,
- * then we set the ones we understand and ignore the others instead of ignoring the
- * whole thing
- */
- if (decl->value == NULL) /* 0 values */
- return;
- else if (decl->value->next == NULL) /* 1 value */
- {
- do_border_radius_term (node, decl->value, TRUE, TRUE, TRUE, TRUE); /* all corners */
- return;
- }
- else if (decl->value->next->next == NULL) /* 2 values */
- {
- do_border_radius_term (node, decl->value, TRUE, FALSE, TRUE, FALSE); /* topleft/bottomright */
- do_border_radius_term (node, decl->value->next, FALSE, TRUE, FALSE, TRUE); /* topright/bottomleft */
- }
- else if (decl->value->next->next->next == NULL) /* 3 values */
- {
- do_border_radius_term (node, decl->value, TRUE, FALSE, FALSE, FALSE); /* topleft */
- do_border_radius_term (node, decl->value->next, FALSE, TRUE, FALSE, TRUE); /* topright/bottomleft */
- do_border_radius_term (node, decl->value->next->next, FALSE, FALSE, TRUE, FALSE); /* bottomright */
- }
- else if (decl->value->next->next->next->next == NULL) /* 4 values */
- {
- do_border_radius_term (node, decl->value, TRUE, FALSE, FALSE, FALSE); /* topleft */
- do_border_radius_term (node, decl->value->next, FALSE, TRUE, FALSE, FALSE); /* topright */
- do_border_radius_term (node, decl->value->next->next, FALSE, FALSE, TRUE, FALSE); /* bottomright */
- do_border_radius_term (node, decl->value->next->next->next, FALSE, FALSE, FALSE, TRUE); /* bottomleft */
- }
- else
- {
- g_warning ("Too many values for border-radius property");
- return;
- }
- }
- else
- {
- if (decl->value == NULL || decl->value->next != NULL)
- return;
-
- if (strcmp (property_name, "-topleft") == 0)
- do_border_radius_term (node, decl->value, TRUE, FALSE, FALSE, FALSE);
- else if (strcmp (property_name, "-topright") == 0)
- do_border_radius_term (node, decl->value, FALSE, TRUE, FALSE, FALSE);
- else if (strcmp (property_name, "-bottomright") == 0)
- do_border_radius_term (node, decl->value, FALSE, FALSE, TRUE, FALSE);
- else if (strcmp (property_name, "-bottomleft") == 0)
- do_border_radius_term (node, decl->value, FALSE, FALSE, FALSE, TRUE);
- }
-}
-
-static void
-do_border_property (EekThemeNode *node,
- CRDeclaration *decl)
-{
- const char *property_name = decl->property->stryng->str + 6; /* Skip 'border' */
- EekSide side = (EekSide)-1;
- EekColor color;
- gboolean color_set = FALSE;
- int width = 0; /* suppress warning */
- gboolean width_set = FALSE;
- int j;
-
- g_return_if_fail (EEK_IS_THEME_NODE (node));
-
- if (g_str_has_prefix (property_name, "-radius"))
- {
- do_border_radius (node, decl);
- return;
- }
-
- if (g_str_has_prefix (property_name, "-left"))
- {
- side = EEK_SIDE_LEFT;
- property_name += 5;
- }
- else if (g_str_has_prefix (property_name, "-right"))
- {
- side = EEK_SIDE_RIGHT;
- property_name += 6;
- }
- else if (g_str_has_prefix (property_name, "-top"))
- {
- side = EEK_SIDE_TOP;
- property_name += 4;
- }
- else if (g_str_has_prefix (property_name, "-bottom"))
- {
- side = EEK_SIDE_BOTTOM;
- property_name += 7;
- }
-
- if (strcmp (property_name, "") == 0)
- {
- /* Set value for width/color/style in any order */
- CRTerm *term;
-
- for (term = decl->value; term; term = term->next)
- {
- GetFromTermResult result;
-
- if (term->type == TERM_IDENT)
- {
- const char *ident = term->content.str->stryng->str;
- if (strcmp (ident, "none") == 0 || strcmp (ident, "hidden") == 0)
- {
- width = 0;
- width_set = TRUE;
- continue;
- }
- else if (strcmp (ident, "solid") == 0)
- {
- /* The only thing we support */
- continue;
- }
- else if (strcmp (ident, "dotted") == 0 ||
- strcmp (ident, "dashed") == 0 ||
- strcmp (ident, "double") == 0 ||
- strcmp (ident, "groove") == 0 ||
- strcmp (ident, "ridge") == 0 ||
- strcmp (ident, "inset") == 0 ||
- strcmp (ident, "outset") == 0)
- {
- /* Treat the same as solid */
- continue;
- }
-
- /* Presumably a color, fall through */
- }
-
- if (term->type == TERM_NUMBER)
- {
- result = get_length_from_term_int (node, term, FALSE, &width);
- if (result != VALUE_NOT_FOUND)
- {
- width_set = result == VALUE_FOUND;
- continue;
- }
- }
-
- result = get_color_from_term (node, term, &color);
- if (result != VALUE_NOT_FOUND)
- {
- color_set = result == VALUE_FOUND;
- continue;
- }
- }
-
- }
- else if (strcmp (property_name, "-color") == 0)
- {
- if (decl->value == NULL || decl->value->next != NULL)
- return;
-
- if (get_color_from_term (node, decl->value, &color) == VALUE_FOUND)
- /* Ignore inherit */
- color_set = TRUE;
- }
- else if (strcmp (property_name, "-width") == 0)
- {
- if (decl->value == NULL || decl->value->next != NULL)
- return;
-
- if (get_length_from_term_int (node, decl->value, FALSE, &width) == VALUE_FOUND)
- /* Ignore inherit */
- width_set = TRUE;
- }
-
- if (side == (EekSide)-1)
- {
- for (j = 0; j < 4; j++)
- {
- if (color_set)
- node->border_color[j] = color;
- if (width_set)
- node->border_width[j] = width;
- }
- }
- else
- {
- if (color_set)
- node->border_color[side] = color;
- if (width_set)
- node->border_width[side] = width;
- }
-}
-
-void
-_eek_theme_node_ensure_geometry (EekThemeNode *node)
-{
- int i, j;
-
- g_return_if_fail (EEK_IS_THEME_NODE (node));
-
- if (node->geometry_computed)
- return;
-
- node->geometry_computed = TRUE;
-
- ensure_properties (node);
-
- for (j = 0; j < 4; j++)
- {
- node->border_width[j] = 0;
- node->border_color[j] = TRANSPARENT_COLOR;
- }
-
- for (i = 0; i < node->n_properties; i++)
- {
- CRDeclaration *decl = node->properties[i];
- const char *property_name = decl->property->stryng->str;
-
- if (g_str_has_prefix (property_name, "border"))
- do_border_property (node, decl);
- }
-}
-
-int
-eek_theme_node_get_border_width (EekThemeNode *node,
- EekSide side)
-{
- g_return_val_if_fail (EEK_IS_THEME_NODE (node), 0.);
- g_return_val_if_fail (side >= EEK_SIDE_TOP && side <= EEK_SIDE_LEFT, 0.);
-
- _eek_theme_node_ensure_geometry (node);
-
- return node->border_width[side];
-}
-
-int
-eek_theme_node_get_border_radius (EekThemeNode *node,
- EekCorner corner)
-{
- g_return_val_if_fail (EEK_IS_THEME_NODE (node), 0.);
- g_return_val_if_fail (corner >= EEK_CORNER_TOPLEFT && corner <= EEK_CORNER_BOTTOMLEFT, 0.);
-
- _eek_theme_node_ensure_geometry (node);
-
- return node->border_radius[corner];
-}
-
-static GetFromTermResult
-get_background_color_from_term (EekThemeNode *node,
- CRTerm *term,
- EekColor *color)
-{
- GetFromTermResult result = get_color_from_term (node, term, color);
- if (result == VALUE_NOT_FOUND)
- {
- if (term_is_transparent (term))
- {
- *color = TRANSPARENT_COLOR;
- return VALUE_FOUND;
- }
- }
-
- return result;
-}
-
-void
-_eek_theme_node_ensure_background (EekThemeNode *node)
-{
- int i;
-
- if (node->background_computed)
- return;
-
- node->background_computed = TRUE;
- node->background_color = TRANSPARENT_COLOR;
- node->background_gradient_type = EEK_GRADIENT_NONE;
-
- ensure_properties (node);
-
- for (i = 0; i < node->n_properties; i++)
- {
- CRDeclaration *decl = node->properties[i];
- const char *property_name = decl->property->stryng->str;
-
- if (g_str_has_prefix (property_name, "background"))
- property_name += 10;
- else
- continue;
-
- if (strcmp (property_name, "") == 0)
- {
- /* We're very liberal here ... if we recognize any term in the expression we take it, and
- * we ignore the rest. The actual specification is:
- *
- * background: [<'background-color'> || <'background-image'> || <'background-repeat'> || <'background-attachment'> || <'background-position'>] | inherit
- */
-
- CRTerm *term;
- /* background: property sets all terms to specified or default values */
- node->background_color = TRANSPARENT_COLOR;
-
- for (term = decl->value; term; term = term->next)
- {
- GetFromTermResult result = get_background_color_from_term (node, term, &node->background_color);
- if (result == VALUE_FOUND)
- {
- /* color stored in node->background_color */
- }
- else if (result == VALUE_INHERIT)
- {
- if (node->parent_node)
- {
- eek_theme_node_get_background_color (node->parent_node, &node->background_color);
- }
- }
- else if (term_is_none (term))
- {
- /* leave node->background_color as transparent */
- }
- }
- }
- else if (strcmp (property_name, "-color") == 0)
- {
- GetFromTermResult result;
-
- if (decl->value == NULL || decl->value->next != NULL)
- continue;
-
- result = get_background_color_from_term (node, decl->value, &node->background_color);
- if (result == VALUE_FOUND)
- {
- /* color stored in node->background_color */
- }
- else if (result == VALUE_INHERIT)
- {
- if (node->parent_node)
- eek_theme_node_get_background_color (node->parent_node, &node->background_color);
- }
- }
- else if (strcmp (property_name, "-gradient-direction") == 0)
- {
- CRTerm *term = decl->value;
- if (strcmp (term->content.str->stryng->str, "vertical") == 0)
- {
- node->background_gradient_type = EEK_GRADIENT_VERTICAL;
- }
- else if (strcmp (term->content.str->stryng->str, "horizontal") == 0)
- {
- node->background_gradient_type = EEK_GRADIENT_HORIZONTAL;
- }
- else if (strcmp (term->content.str->stryng->str, "radial") == 0)
- {
- node->background_gradient_type = EEK_GRADIENT_RADIAL;
- }
- else if (strcmp (term->content.str->stryng->str, "none") == 0)
- {
- node->background_gradient_type = EEK_GRADIENT_NONE;
- }
- else
- {
- g_warning ("Unrecognized background-gradient-direction \"%s\"",
- term->content.str->stryng->str);
- }
- }
- else if (strcmp (property_name, "-gradient-start") == 0)
- {
- get_color_from_term (node, decl->value, &node->background_color);
- }
- else if (strcmp (property_name, "-gradient-end") == 0)
- {
- get_color_from_term (node, decl->value, &node->background_gradient_end);
- }
- }
-}
-
-void
-eek_theme_node_get_background_color (EekThemeNode *node,
- EekColor *color)
-{
- g_return_if_fail (EEK_IS_THEME_NODE (node));
-
- _eek_theme_node_ensure_background (node);
-
- *color = node->background_color;
-}
-
-void
-eek_theme_node_get_border_color (EekThemeNode *node,
- EekSide side,
- EekColor *color)
-{
- g_return_if_fail (EEK_IS_THEME_NODE (node));
- g_return_if_fail (side >= EEK_SIDE_TOP && side <= EEK_SIDE_LEFT);
-
- _eek_theme_node_ensure_geometry (node);
-
- *color = node->border_color[side];
-}
-
-void
-eek_theme_node_get_foreground_color (EekThemeNode *node,
- EekColor *color)
-{
- g_assert (EEK_IS_THEME_NODE (node));
-
- if (!node->foreground_computed)
- {
- int i;
-
- node->foreground_computed = TRUE;
-
- ensure_properties (node);
-
- for (i = node->n_properties - 1; i >= 0; i--)
- {
- CRDeclaration *decl = node->properties[i];
-
- if (strcmp (decl->property->stryng->str, "color") == 0)
- {
- GetFromTermResult result = get_color_from_term (node, decl->value, &node->foreground_color);
- if (result == VALUE_FOUND)
- goto out;
- else if (result == VALUE_INHERIT)
- break;
- }
- }
-
- if (node->parent_node)
- eek_theme_node_get_foreground_color (node->parent_node, &node->foreground_color);
- else
- node->foreground_color = BLACK_COLOR; /* default to black */
- }
-
- out:
- *color = node->foreground_color;
-}
-
-void
-eek_theme_node_get_background_gradient (EekThemeNode *node,
- EekGradientType *type,
- EekColor *start,
- EekColor *end)
-{
- g_assert (EEK_IS_THEME_NODE (node));
-
- _eek_theme_node_ensure_background (node);
-
- *type = node->background_gradient_type;
- if (*type != EEK_GRADIENT_NONE)
- {
- *start = node->background_color;
- *end = node->background_gradient_end;
- }
-}
-
-static gboolean
-font_family_from_terms (CRTerm *term,
- char **family)
-{
- GString *family_string;
- gboolean result = FALSE;
- gboolean last_was_quoted = FALSE;
-
- if (!term)
- return FALSE;
-
- family_string = g_string_new (NULL);
-
- while (term)
- {
- if (term->type != TERM_STRING && term->type != TERM_IDENT)
- {
- goto out;
- }
-
- if (family_string->len > 0)
- {
- if (term->the_operator != COMMA && term->the_operator != NO_OP)
- goto out;
- /* Can concatenate two bare words, but not two quoted strings */
- if ((term->the_operator == NO_OP && last_was_quoted) || term->type == TERM_STRING)
- goto out;
-
- if (term->the_operator == NO_OP)
- g_string_append (family_string, " ");
- else
- g_string_append (family_string, ", ");
- }
- else
- {
- if (term->the_operator != NO_OP)
- goto out;
- }
-
- g_string_append (family_string, term->content.str->stryng->str);
-
- term = term->next;
- }
-
- result = TRUE;
-
- out:
- if (result)
- {
- *family = g_string_free (family_string, FALSE);
- return TRUE;
- }
- else
- {
- *family = g_string_free (family_string, TRUE);
- return FALSE;
- }
-}
-
-/* In points */
-static int font_sizes[] = {
- 6 * 1024, /* xx-small */
- 8 * 1024, /* x-small */
- 10 * 1024, /* small */
- 12 * 1024, /* medium */
- 16 * 1024, /* large */
- 20 * 1024, /* x-large */
- 24 * 1024, /* xx-large */
-};
-
-static gboolean
-font_size_from_term (EekThemeNode *node,
- CRTerm *term,
- double *size)
-{
- if (term->type == TERM_IDENT)
- {
- double resolution = eek_theme_context_get_resolution (node->context);
- /* We work in integers to avoid double comparisons when converting back
- * from a size in pixels to a logical size.
- */
- int size_points = (int)(0.5 + *size * (72. / resolution));
-
- if (strcmp (term->content.str->stryng->str, "xx-small") == 0)
- size_points = font_sizes[0];
- else if (strcmp (term->content.str->stryng->str, "x-small") == 0)
- size_points = font_sizes[1];
- else if (strcmp (term->content.str->stryng->str, "small") == 0)
- size_points = font_sizes[2];
- else if (strcmp (term->content.str->stryng->str, "medium") == 0)
- size_points = font_sizes[3];
- else if (strcmp (term->content.str->stryng->str, "large") == 0)
- size_points = font_sizes[4];
- else if (strcmp (term->content.str->stryng->str, "x-large") == 0)
- size_points = font_sizes[5];
- else if (strcmp (term->content.str->stryng->str, "xx-large") == 0)
- size_points = font_sizes[6];
- else if (strcmp (term->content.str->stryng->str, "smaller") == 0)
- {
- /* Find the standard size equal to or smaller than the current size */
- int i = 0;
-
- while (i <= 6 && font_sizes[i] < size_points)
- i++;
-
- if (i > 6)
- {
- /* original size greater than any standard size */
- size_points = (int)(0.5 + size_points / 1.2);
- }
- else
- {
- /* Go one smaller than that, if possible */
- if (i > 0)
- i--;
-
- size_points = font_sizes[i];
- }
- }
- else if (strcmp (term->content.str->stryng->str, "larger") == 0)
- {
- /* Find the standard size equal to or larger than the current size */
- int i = 6;
-
- while (i >= 0 && font_sizes[i] > size_points)
- i--;
-
- if (i < 0) /* original size smaller than any standard size */
- i = 0;
-
- /* Go one larger than that, if possible */
- if (i < 6)
- i++;
-
- size_points = font_sizes[i];
- }
- else
- {
- return FALSE;
- }
-
- *size = size_points * (resolution / 72.);
- return TRUE;
-
- }
- else if (term->type == TERM_NUMBER && term->content.num->type == NUM_PERCENTAGE)
- {
- *size *= term->content.num->val / 100.;
- return TRUE;
- }
- else if (get_length_from_term (node, term, TRUE, size) == VALUE_FOUND)
- {
- /* Convert from pixels to Pango units */
- *size *= 1024;
- return TRUE;
- }
-
- return FALSE;
-}
-
-static gboolean
-font_weight_from_term (CRTerm *term,
- PangoWeight *weight,
- gboolean *weight_absolute)
-{
- if (term->type == TERM_NUMBER)
- {
- int weight_int;
-
- /* The spec only allows numeric weights from 100-900, though Pango
- * will handle any number. We just let anything through.
- */
- if (term->content.num->type != NUM_GENERIC)
- return FALSE;
-
- weight_int = (int)(0.5 + term->content.num->val);
-
- *weight = weight_int;
- *weight_absolute = TRUE;
-
- }
- else if (term->type == TERM_IDENT)
- {
- /* FIXME: handle INHERIT */
-
- if (strcmp (term->content.str->stryng->str, "bold") == 0)
- {
- *weight = PANGO_WEIGHT_BOLD;
- *weight_absolute = TRUE;
- }
- else if (strcmp (term->content.str->stryng->str, "normal") == 0)
- {
- *weight = PANGO_WEIGHT_NORMAL;
- *weight_absolute = TRUE;
- }
- else if (strcmp (term->content.str->stryng->str, "bolder") == 0)
- {
- *weight = PANGO_WEIGHT_BOLD;
- *weight_absolute = FALSE;
- }
- else if (strcmp (term->content.str->stryng->str, "lighter") == 0)
- {
- *weight = PANGO_WEIGHT_LIGHT;
- *weight_absolute = FALSE;
- }
- else
- {
- return FALSE;
- }
-
- }
- else
- {
- return FALSE;
- }
-
- return TRUE;
-}
-
-static gboolean
-font_style_from_term (CRTerm *term,
- PangoStyle *style)
-{
- if (term->type != TERM_IDENT)
- return FALSE;
-
- /* FIXME: handle INHERIT */
-
- if (strcmp (term->content.str->stryng->str, "normal") == 0)
- *style = PANGO_STYLE_NORMAL;
- else if (strcmp (term->content.str->stryng->str, "oblique") == 0)
- *style = PANGO_STYLE_OBLIQUE;
- else if (strcmp (term->content.str->stryng->str, "italic") == 0)
- *style = PANGO_STYLE_ITALIC;
- else
- return FALSE;
-
- return TRUE;
-}
-
-static gboolean
-font_variant_from_term (CRTerm *term,
- PangoVariant *variant)
-{
- if (term->type != TERM_IDENT)
- return FALSE;
-
- /* FIXME: handle INHERIT */
-
- if (strcmp (term->content.str->stryng->str, "normal") == 0)
- *variant = PANGO_VARIANT_NORMAL;
- else if (strcmp (term->content.str->stryng->str, "small-caps") == 0)
- *variant = PANGO_VARIANT_SMALL_CAPS;
- else
- return FALSE;
-
- return TRUE;
-}
-
-const PangoFontDescription *
-eek_theme_node_get_font (EekThemeNode *node)
-{
- /* Initialized despite _set flags to suppress compiler warnings */
- PangoStyle font_style = PANGO_STYLE_NORMAL;
- gboolean font_style_set = FALSE;
- PangoVariant variant = PANGO_VARIANT_NORMAL;
- gboolean variant_set = FALSE;
- PangoWeight weight = PANGO_WEIGHT_NORMAL;
- gboolean weight_absolute = TRUE;
- gboolean weight_set = FALSE;
- double size = 0.;
- gboolean size_set = FALSE;
-
- char *family = NULL;
- double parent_size;
- int i;
-
- if (node->font_desc)
- return node->font_desc;
-
- node->font_desc = pango_font_description_copy (get_parent_font (node));
- parent_size = pango_font_description_get_size (node->font_desc);
- if (!pango_font_description_get_size_is_absolute (node->font_desc))
- {
- double resolution = eek_theme_context_get_resolution (node->context);
- parent_size *= (resolution / 72.);
- }
-
- ensure_properties (node);
-
- for (i = 0; i < node->n_properties; i++)
- {
- CRDeclaration *decl = node->properties[i];
-
- if (strcmp (decl->property->stryng->str, "font") == 0)
- {
- PangoStyle tmp_style = PANGO_STYLE_NORMAL;
- PangoVariant tmp_variant = PANGO_VARIANT_NORMAL;
- PangoWeight tmp_weight = PANGO_WEIGHT_NORMAL;
- gboolean tmp_weight_absolute = TRUE;
- double tmp_size;
- CRTerm *term = decl->value;
-
- /* A font specification starts with node/variant/weight
- * in any order. Each is allowed to be specified only once,
- * but we don't enforce that.
- */
- for (; term; term = term->next)
- {
- if (font_style_from_term (term, &tmp_style))
- continue;
- if (font_variant_from_term (term, &tmp_variant))
- continue;
- if (font_weight_from_term (term, &tmp_weight, &tmp_weight_absolute))
- continue;
-
- break;
- }
-
- /* The size is mandatory */
-
- if (term == NULL || term->type != TERM_NUMBER)
- {
- g_warning ("Size missing from font property");
- continue;
- }
-
- tmp_size = parent_size;
- if (!font_size_from_term (node, term, &tmp_size))
- {
- g_warning ("Couldn't parse size in font property");
- continue;
- }
-
- term = term->next;
-
- if (term != NULL && term->type && TERM_NUMBER && term->the_operator == DIVIDE)
- {
- /* Ignore line-height specification */
- term = term->next;
- }
-
- /* the font family is mandatory - it is a comma-separated list of
- * names.
- */
- if (!font_family_from_terms (term, &family))
- {
- g_warning ("Couldn't parse family in font property");
- continue;
- }
-
- font_style = tmp_style;
- font_style_set = TRUE;
- weight = tmp_weight;
- weight_absolute = tmp_weight_absolute;
- weight_set = TRUE;
- variant = tmp_variant;
- variant_set = TRUE;
-
- size = tmp_size;
- size_set = TRUE;
-
- }
- else if (strcmp (decl->property->stryng->str, "font-family") == 0)
- {
- if (!font_family_from_terms (decl->value, &family))
- {
- g_warning ("Couldn't parse family in font property");
- continue;
- }
- }
- else if (strcmp (decl->property->stryng->str, "font-weight") == 0)
- {
- if (decl->value == NULL || decl->value->next != NULL)
- continue;
-
- if (font_weight_from_term (decl->value, &weight, &weight_absolute))
- weight_set = TRUE;
- }
- else if (strcmp (decl->property->stryng->str, "font-style") == 0)
- {
- if (decl->value == NULL || decl->value->next != NULL)
- continue;
-
- if (font_style_from_term (decl->value, &font_style))
- font_style_set = TRUE;
- }
- else if (strcmp (decl->property->stryng->str, "font-variant") == 0)
- {
- if (decl->value == NULL || decl->value->next != NULL)
- continue;
-
- if (font_variant_from_term (decl->value, &variant))
- variant_set = TRUE;
- }
- else if (strcmp (decl->property->stryng->str, "font-size") == 0)
- {
- gdouble tmp_size;
- if (decl->value == NULL || decl->value->next != NULL)
- continue;
-
- tmp_size = parent_size;
- if (font_size_from_term (node, decl->value, &tmp_size))
- {
- size = tmp_size;
- size_set = TRUE;
- }
- }
- }
-
- if (family)
- {
- pango_font_description_set_family (node->font_desc, family);
- g_free (family);
- }
-
- if (size_set)
- pango_font_description_set_absolute_size (node->font_desc, size);
-
- if (weight_set)
- {
- if (!weight_absolute)
- {
- /* bolder/lighter are supposed to switch between available styles, but with
- * font substitution, that gets to be a pretty fuzzy concept. So we use
- * a fixed step of 200. (The spec says 100, but that might not take us from
- * normal to bold.
- */
-
- PangoWeight old_weight = pango_font_description_get_weight (node->font_desc);
- if (weight == PANGO_WEIGHT_BOLD)
- weight = old_weight + 200;
- else
- weight = old_weight - 200;
-
- if (weight < 100)
- weight = 100;
- if (weight > 900)
- weight = 900;
- }
-
- pango_font_description_set_weight (node->font_desc, weight);
- }
-
- if (font_style_set)
- pango_font_description_set_style (node->font_desc, font_style);
- if (variant_set)
- pango_font_description_set_variant (node->font_desc, variant);
-
- return node->font_desc;
-}
diff --git a/eek/eek-theme-node.h b/eek/eek-theme-node.h
deleted file mode 100644
index 8662ccfd..00000000
--- a/eek/eek-theme-node.h
+++ /dev/null
@@ -1,141 +0,0 @@
-/*
- * Copyright (C) 2010-2011 Daiki Ueno
- * Copyright (C) 2010-2011 Red Hat, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public License
- * as published by the Free Software Foundation; either version 2 of
- * the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301 USA
- */
-#ifndef __EEK_THEME_NODE_H__
-#define __EEK_THEME_NODE_H__
-
-#include
-#include "eek-types.h"
-
-G_BEGIN_DECLS
-
-/**
- * SECTION:eek-theme-node
- * @short_description: style information for one node in a tree of
- * themed objects
- *
- * The #EekThemeNode class represents the CSS style information (the
- * set of CSS properties) for one node in a tree of themed objects. In
- * typical usage, it represents the style information for a single
- * #EekElement. A #EekThemeNode is immutable: attributes such as the
- * CSS classes for the node are passed in at construction. If the
- * attributes of the node or any parent node change, the node should
- * be discarded and a new node created. #EekThemeNode has generic
- * accessors to look up properties by name and specific accessors for
- * standard CSS properties that add caching and handling of various
- * details of the CSS specification. #EekThemeNode also has
- * convenience functions to help in implementing a #EekElement with
- * borders and padding.
- */
-
-typedef enum {
- EEK_SIDE_TOP,
- EEK_SIDE_RIGHT,
- EEK_SIDE_BOTTOM,
- EEK_SIDE_LEFT
-} EekSide;
-
-typedef enum {
- EEK_CORNER_TOPLEFT,
- EEK_CORNER_TOPRIGHT,
- EEK_CORNER_BOTTOMRIGHT,
- EEK_CORNER_BOTTOMLEFT
-} EekCorner;
-
-#define EEK_TYPE_THEME_NODE (eek_theme_node_get_type())
-#define EEK_THEME_NODE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EEK_TYPE_THEME_NODE, EekThemeNode))
-#define EEK_THEME_NODE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), EEK_TYPE_THEME_NODE, EekThemeNodeClass))
-#define EEK_IS_THEME_NODE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EEK_TYPE_THEME_NODE))
-#define EEK_IS_THEME_NODE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), EEK_TYPE_THEME_NODE))
-#define EEK_THEME_NODE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), EEK_TYPE_THEME_NODE, EekThemeNodeClass))
-
-typedef struct _EekThemeNodeClass EekThemeNodeClass;
-typedef struct _EekThemeNodePrivate EekThemeNodePrivate;
-
-GType eek_theme_node_get_type
- (void) G_GNUC_CONST;
-
-EekThemeNode *eek_theme_node_new (EekThemeContext *context,
- EekThemeNode *parent_node,
- /* can be null */ EekTheme *theme,
- /* can be null */ GType element_type,
- const char *element_id,
- const char *element_class,
- const char *pseudo_class,
- const char *inline_style);
-
-EekThemeNode *eek_theme_node_get_parent
- (EekThemeNode *node);
-
-EekTheme *eek_theme_node_get_theme
- (EekThemeNode *node);
-
-GType eek_theme_node_get_element_type
- (EekThemeNode *node);
-const char *eek_theme_node_get_element_id
- (EekThemeNode *node);
-const char *eek_theme_node_get_element_class
- (EekThemeNode *node);
-const char *eek_theme_node_get_pseudo_class
- (EekThemeNode *node);
-
-/* Generic getters ... these are not cached so are less efficient. The other
- * reason for adding the more specific version is that we can handle the
- * details of the actual CSS rules, which can be complicated, especially
- * for fonts
- */
-void eek_theme_node_get_color
- (EekThemeNode *node,
- const char *property_name,
- EekColor *color);
-
-/* Specific getters for particular properties: cached
- */
-void eek_theme_node_get_background_color
- (EekThemeNode *node,
- EekColor *color);
-void eek_theme_node_get_foreground_color
- (EekThemeNode *node,
- EekColor *color);
-void eek_theme_node_get_background_gradient
- (EekThemeNode *node,
- EekGradientType *type,
- EekColor *start,
- EekColor *end);
-int eek_theme_node_get_border_width
- (EekThemeNode *node,
- EekSide side);
-int eek_theme_node_get_border_radius
- (EekThemeNode *node,
- EekCorner corner);
-void eek_theme_node_get_border_color
- (EekThemeNode *node,
- EekSide side,
- EekColor *color);
-
-/* Font rule processing is pretty complicated, so we just hardcode it
- * under the standard font/font-family/font-size/etc names. This means
- * you can't have multiple separate styled fonts for a single item,
- * but that should be OK.
- */
-const PangoFontDescription *eek_theme_node_get_font (EekThemeNode *node);
-
-G_END_DECLS
-
-#endif /* __EEK_THEME_NODE_H__ */
diff --git a/eek/eek-theme-private.h b/eek/eek-theme-private.h
deleted file mode 100644
index ea17a747..00000000
--- a/eek/eek-theme-private.h
+++ /dev/null
@@ -1,22 +0,0 @@
-/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
-#ifndef __EEK_THEME_PRIVATE_H__
-#define __EEK_THEME_PRIVATE_H__
-
-#include
-#include "eek-theme.h"
-
-G_BEGIN_DECLS
-
-GPtrArray *_eek_theme_get_matched_properties (EekTheme *theme,
- EekThemeNode *node);
-
-/* Resolve an URL from the stylesheet to a filename */
-char *_eek_theme_resolve_url (EekTheme *theme,
- CRStyleSheet *base_stylesheet,
- const char *url);
-
-CRDeclaration *_eek_theme_parse_declaration_list (const char *str);
-
-G_END_DECLS
-
-#endif /* __EEK_THEME_PRIVATE_H__ */
diff --git a/eek/eek-theme.c b/eek/eek-theme.c
deleted file mode 100644
index 91d91783..00000000
--- a/eek/eek-theme.c
+++ /dev/null
@@ -1,1095 +0,0 @@
-/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
-
-/* This file started as a cut-and-paste of cr-sel-eng.c from libcroco.
- *
- * In moving it to hippo-canvas:
- * - Reformatted and otherwise edited to match our coding style
- * - Switched from handling xmlNode to handling HippoStyle
- * - Simplified by removing things that we don't need or that don't
- * make sense in our context.
- * - The code to get a list of matching properties works quite differently;
- * we order things in priority order, but we don't actually try to
- * coalesce properties with the same name.
- *
- * In moving it to GNOME Shell:
- * - Renamed again to StTheme
- * - Reformatted to match the gnome-shell coding style
- * - Removed notion of "theme engine" from hippo-canvas
- * - pseudo-class matching changed from link enum to strings
- * - Some code simplification
- *
- * In moving it to libeek:
- * - Renamed again to EekTheme
- */
-
-/*
- * This file is part of The Croco Library
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2.1 of the GNU Lesser General Public
- * License as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser
- * General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
- * USA
- *
- * Copyright (C) 2003-2004 Dodji Seketeli. All Rights Reserved.
- */
-
-#define G_LOG_DOMAIN "eek-theme"
-
-#include
-#include
-
-#include
-#include
-
-#include "eek-theme.h"
-#include "eek-theme-node.h"
-
-static GObject *eek_theme_constructor (GType type,
- guint n_construct_properties,
- GObjectConstructParam *construct_properties);
-
-static void eek_theme_finalize (GObject *object);
-static void eek_theme_set_property (GObject *object,
- guint prop_id,
- const GValue *value,
- GParamSpec *pspec);
-static void eek_theme_get_property (GObject *object,
- guint prop_id,
- GValue *value,
- GParamSpec *pspec);
-static char *eek_theme_resolve_url (EekTheme *theme,
- CRStyleSheet *base_stylesheet,
- const char *url);
-
-struct _EekTheme
-{
- GObject parent;
-
- char *application_stylesheet;
- char *default_stylesheet;
- char *theme_stylesheet;
- GSList *custom_stylesheets;
-
- GHashTable *stylesheets_by_filename;
- GHashTable *filenames_by_stylesheet;
-
- CRCascade *cascade;
-};
-
-struct _EekThemeClass
-{
- GObjectClass parent_class;
-};
-
-enum
-{
- PROP_0,
- PROP_APPLICATION_STYLESHEET,
- PROP_THEME_STYLESHEET,
- PROP_DEFAULT_STYLESHEET
-};
-
-G_DEFINE_TYPE (EekTheme, eek_theme, G_TYPE_OBJECT);
-
-/* Quick strcmp. Test only for == 0 or != 0, not < 0 or > 0. */
-#define strqcmp(str,lit,lit_len) \
- (strlen (str) != (lit_len) || memcmp (str, lit, lit_len))
-
-static void
-eek_theme_init (EekTheme *theme)
-{
- theme->stylesheets_by_filename = g_hash_table_new_full (g_str_hash, g_str_equal,
- (GDestroyNotify)g_free, (GDestroyNotify)cr_stylesheet_unref);
- theme->filenames_by_stylesheet = g_hash_table_new (g_direct_hash, g_direct_equal);
-}
-
-static void
-eek_theme_class_init (EekThemeClass *klass)
-{
- GObjectClass *object_class = G_OBJECT_CLASS (klass);
-
- object_class->constructor = eek_theme_constructor;
- object_class->finalize = eek_theme_finalize;
- object_class->set_property = eek_theme_set_property;
- object_class->get_property = eek_theme_get_property;
-
- /**
- * EekTheme:application-stylesheet:
- *
- * The highest priority stylesheet, representing application-specific
- * styling; this is associated with the CSS "author" stylesheet.
- */
- g_object_class_install_property (object_class,
- PROP_APPLICATION_STYLESHEET,
- g_param_spec_string ("application-stylesheet",
- "Application Stylesheet",
- "Stylesheet with application-specific styling",
- NULL,
- G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));
-
- /**
- * EekTheme:theme-stylesheet:
- *
- * The second priority stylesheet, representing theme-specific styling;
- * this is associated with the CSS "user" stylesheet.
- */
- g_object_class_install_property (object_class,
- PROP_THEME_STYLESHEET,
- g_param_spec_string ("theme-stylesheet",
- "Theme Stylesheet",
- "Stylesheet with theme-specific styling",
- NULL,
- G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));
-
- /**
- * EekTheme:default-stylesheet:
- *
- * The lowest priority stylesheet, representing global default
- * styling; this is associated with the CSS "user agent" stylesheet.
- */
- g_object_class_install_property (object_class,
- PROP_DEFAULT_STYLESHEET,
- g_param_spec_string ("default-stylesheet",
- "Default Stylesheet",
- "Stylesheet with global default styling",
- NULL,
- G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));
-
-}
-
-static CRStyleSheet *
-parse_stylesheet (const char *filename,
- GError **error)
-{
- enum CRStatus status;
- CRStyleSheet *stylesheet;
- g_autoptr (GFileInputStream) stream = NULL;
- g_autoptr (GFileInfo) info = NULL;
- g_autoptr (GFile) file = NULL;
- g_autofree guchar* contents = NULL;
- goffset size;
- gsize out = 0;
- GError *err = NULL;
-
- if (filename == NULL)
- return NULL;
-
- g_debug ("Parsing %s", filename);
- if (g_strcmp0 (filename, "resource://") > 0) {
- file = g_file_new_for_uri (filename);
- stream = g_file_read (file, NULL, &err);
- if (!stream) {
- g_warning ("Failed to open %s: %s", filename, err->message);
- g_clear_error (&err);
- return NULL;
- }
-
- info = g_file_input_stream_query_info (stream,
- G_FILE_ATTRIBUTE_STANDARD_SIZE,
- NULL,
- &err);
-
- if (!info) {
- g_warning ("Failed to stat %s: %s", filename, err->message);
- g_clear_error (&err);
- return NULL;
- }
-
- size = g_file_info_get_size (info);
- contents = g_malloc0 (size);
- if (!g_input_stream_read_all (G_INPUT_STREAM (stream),
- contents,
- size,
- &out,
- NULL,
- &err)) {
- g_warning ("Failed to read %s: %s", filename, err->message);
- g_clear_error (&err);
- return NULL;
- }
- status = cr_om_parser_simply_parse_buf (contents,
- size,
- CR_UTF_8,
- &stylesheet);
- } else {
- status = cr_om_parser_simply_parse_file ((const guchar *) filename,
- CR_UTF_8,
- &stylesheet);
- }
-
- if (status != CR_OK)
- {
- g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
- "Error parsing stylesheet '%s'; errcode:%d", filename, status);
- return NULL;
- }
-
- return stylesheet;
-}
-
-CRDeclaration *
-_eek_theme_parse_declaration_list (const char *str)
-{
- return cr_declaration_parse_list_from_buf ((const guchar *)str,
- CR_UTF_8);
-}
-
-/* Just g_warning for now until we have something nicer to do */
-static CRStyleSheet *
-parse_stylesheet_nofail (const char *filename)
-{
- GError *error = NULL;
- CRStyleSheet *result;
-
- result = parse_stylesheet (filename, &error);
- if (error)
- {
- g_warning ("%s", error->message);
- g_clear_error (&error);
- }
- return result;
-}
-
-static void
-insert_stylesheet (EekTheme *theme,
- const char *filename,
- CRStyleSheet *stylesheet)
-{
- char *filename_copy;
-
- if (stylesheet == NULL)
- return;
-
- filename_copy = g_strdup(filename);
- cr_stylesheet_ref (stylesheet);
-
- g_hash_table_insert (theme->stylesheets_by_filename, filename_copy, stylesheet);
- g_hash_table_insert (theme->filenames_by_stylesheet, stylesheet, filename_copy);
-}
-
-gboolean
-eek_theme_load_stylesheet (EekTheme *theme,
- const char *path,
- GError **error)
-{
- CRStyleSheet *stylesheet;
-
- stylesheet = parse_stylesheet (path, error);
- if (!stylesheet)
- return FALSE;
-
- insert_stylesheet (theme, path, stylesheet);
- theme->custom_stylesheets = g_slist_prepend (theme->custom_stylesheets, stylesheet);
-
- return TRUE;
-}
-
-void
-eek_theme_unload_stylesheet (EekTheme *theme,
- const char *path)
-{
- CRStyleSheet *stylesheet;
-
- stylesheet = g_hash_table_lookup (theme->stylesheets_by_filename, path);
- if (!stylesheet)
- return;
-
- if (!g_slist_find (theme->custom_stylesheets, stylesheet))
- return;
-
- theme->custom_stylesheets = g_slist_remove (theme->custom_stylesheets, stylesheet);
- g_hash_table_remove (theme->stylesheets_by_filename, path);
- g_hash_table_remove (theme->filenames_by_stylesheet, stylesheet);
- cr_stylesheet_unref (stylesheet);
-}
-
-static GObject *
-eek_theme_constructor (GType type,
- guint n_construct_properties,
- GObjectConstructParam *construct_properties)
-{
- GObject *object;
- EekTheme *theme;
- CRStyleSheet *application_stylesheet;
- CRStyleSheet *theme_stylesheet;
- CRStyleSheet *default_stylesheet;
-
- object = (*G_OBJECT_CLASS (eek_theme_parent_class)->constructor) (type,
- n_construct_properties,
- construct_properties);
- theme = EEK_THEME (object);
-
- application_stylesheet = parse_stylesheet_nofail (theme->application_stylesheet);
- theme_stylesheet = parse_stylesheet_nofail (theme->theme_stylesheet);
- default_stylesheet = parse_stylesheet_nofail (theme->default_stylesheet);
-
- theme->cascade = cr_cascade_new (application_stylesheet,
- theme_stylesheet,
- default_stylesheet);
-
- if (theme->cascade == NULL)
- g_error ("Out of memory when creating cascade object");
-
- insert_stylesheet (theme, theme->application_stylesheet, application_stylesheet);
- insert_stylesheet (theme, theme->theme_stylesheet, theme_stylesheet);
- insert_stylesheet (theme, theme->default_stylesheet, default_stylesheet);
-
- return object;
-}
-
-static void
-eek_theme_finalize (GObject * object)
-{
- EekTheme *theme = EEK_THEME (object);
-
- g_slist_foreach (theme->custom_stylesheets, (GFunc) cr_stylesheet_unref, NULL);
- g_slist_free (theme->custom_stylesheets);
- theme->custom_stylesheets = NULL;
-
- g_hash_table_destroy (theme->stylesheets_by_filename);
- g_hash_table_destroy (theme->filenames_by_stylesheet);
-
- g_free (theme->application_stylesheet);
- g_free (theme->theme_stylesheet);
- g_free (theme->default_stylesheet);
-
- if (theme->cascade)
- {
- cr_cascade_unref (theme->cascade);
- theme->cascade = NULL;
- }
-
- G_OBJECT_CLASS (eek_theme_parent_class)->finalize (object);
-}
-
-static void
-eek_theme_set_property (GObject *object,
- guint prop_id,
- const GValue *value,
- GParamSpec *pspec)
-{
- EekTheme *theme = EEK_THEME (object);
-
- switch (prop_id)
- {
- case PROP_APPLICATION_STYLESHEET:
- {
- const char *path = g_value_get_string (value);
-
- if (path != theme->application_stylesheet)
- {
- g_free (theme->application_stylesheet);
- theme->application_stylesheet = g_strdup (path);
- }
-
- break;
- }
- case PROP_THEME_STYLESHEET:
- {
- const char *path = g_value_get_string (value);
-
- if (path != theme->theme_stylesheet)
- {
- g_free (theme->theme_stylesheet);
- theme->theme_stylesheet = g_strdup (path);
- }
-
- break;
- }
- case PROP_DEFAULT_STYLESHEET:
- {
- const char *path = g_value_get_string (value);
-
- if (path != theme->default_stylesheet)
- {
- g_free (theme->default_stylesheet);
- theme->default_stylesheet = g_strdup (path);
- }
-
- break;
- }
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-}
-
-static void
-eek_theme_get_property (GObject *object,
- guint prop_id,
- GValue *value,
- GParamSpec *pspec)
-{
- EekTheme *theme = EEK_THEME (object);
-
- switch (prop_id)
- {
- case PROP_APPLICATION_STYLESHEET:
- g_value_set_string (value, theme->application_stylesheet);
- break;
- case PROP_THEME_STYLESHEET:
- g_value_set_string (value, theme->theme_stylesheet);
- break;
- case PROP_DEFAULT_STYLESHEET:
- g_value_set_string (value, theme->default_stylesheet);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-}
-
-/**
- * eek_theme_new:
- * @application_stylesheet: (allow-none): The highest priority stylesheet, representing application-specific
- * styling; this is associated with the CSS "author" stylesheet, may be %NULL
- * @theme_stylesheet: (allow-none): The second priority stylesheet, representing theme-specific styling ;
- * this is associated with the CSS "user" stylesheet, may be %NULL
- * @default_stylesheet: (allow-none): The lowest priority stylesheet, representing global default styling;
- * this is associated with the CSS "user agent" stylesheet, may be %NULL
- *
- * Return value: the newly created theme object
- **/
-EekTheme *
-eek_theme_new (const char *application_stylesheet,
- const char *theme_stylesheet,
- const char *default_stylesheet)
-{
- EekTheme *theme = g_object_new (EEK_TYPE_THEME,
- "application-stylesheet", application_stylesheet,
- "theme-stylesheet", theme_stylesheet,
- "default-stylesheet", default_stylesheet,
- NULL);
-
- return theme;
-}
-
-static gboolean
-string_in_list (GString *stryng,
- const char *list)
-{
- const char *cur;
-
- for (cur = list; *cur;)
- {
- while (*cur && cr_utils_is_white_space (*cur))
- cur++;
-
- if (strncmp (cur, stryng->str, stryng->len) == 0)
- {
- cur += stryng->len;
- if ((!*cur) || cr_utils_is_white_space (*cur))
- return TRUE;
- }
-
- /* skip to next whitespace character */
- while (*cur && !cr_utils_is_white_space (*cur))
- cur++;
- }
-
- return FALSE;
-}
-
-static gboolean
-pseudo_class_add_sel_matches_style (EekTheme *a_this,
- CRAdditionalSel *a_add_sel,
- EekThemeNode *a_node)
-{
- const char *node_pseudo_class;
-
- g_return_val_if_fail (a_this
- && a_add_sel
- && a_add_sel->content.pseudo
- && a_add_sel->content.pseudo->name
- && a_add_sel->content.pseudo->name->stryng
- && a_add_sel->content.pseudo->name->stryng->str
- && a_node, FALSE);
-
- node_pseudo_class = eek_theme_node_get_pseudo_class (a_node);
-
- if (node_pseudo_class == NULL)
- return FALSE;
-
- return string_in_list (a_add_sel->content.pseudo->name->stryng, node_pseudo_class);
-}
-
-/**
- *@param a_add_sel the class additional selector to consider.
- *@param a_node the style node to consider.
- *@return TRUE if the class additional selector matches
- *the style node given in argument, FALSE otherwise.
- */
-static gboolean
-class_add_sel_matches_style (CRAdditionalSel *a_add_sel,
- EekThemeNode *a_node)
-{
- const char *element_class;
-
- g_return_val_if_fail (a_add_sel
- && a_add_sel->type == CLASS_ADD_SELECTOR
- && a_add_sel->content.class_name
- && a_add_sel->content.class_name->stryng
- && a_add_sel->content.class_name->stryng->str
- && a_node, FALSE);
-
- element_class = eek_theme_node_get_element_class (a_node);
- if (element_class == NULL)
- return FALSE;
-
- return string_in_list (a_add_sel->content.class_name->stryng, element_class);
-}
-
-/**
- *@return TRUE if the additional attribute selector matches
- *the current style node given in argument, FALSE otherwise.
- *@param a_add_sel the additional attribute selector to consider.
- *@param a_node the style node to consider.
- */
-static gboolean
-id_add_sel_matches_style (CRAdditionalSel *a_add_sel,
- EekThemeNode *a_node)
-{
- gboolean result = FALSE;
- const char *id;
-
- g_return_val_if_fail (a_add_sel
- && a_add_sel->type == ID_ADD_SELECTOR
- && a_add_sel->content.id_name
- && a_add_sel->content.id_name->stryng
- && a_add_sel->content.id_name->stryng->str
- && a_node, FALSE);
- g_return_val_if_fail (a_add_sel
- && a_add_sel->type == ID_ADD_SELECTOR
- && a_node, FALSE);
-
- id = eek_theme_node_get_element_id (a_node);
-
- if (id != NULL)
- {
- if (!strqcmp (id, a_add_sel->content.id_name->stryng->str,
- a_add_sel->content.id_name->stryng->len))
- {
- result = TRUE;
- }
- }
-
- return result;
-}
-
-/**
- *additional_selector_matches_style:
- *Evaluates if a given additional selector matches an style node.
- *@param a_add_sel the additional selector to consider.
- *@param a_node the style node to consider.
- *@return TRUE is a_add_sel matches a_node, FALSE otherwise.
- */
-static gboolean
-additional_selector_matches_style (EekTheme *a_this,
- CRAdditionalSel *a_add_sel,
- EekThemeNode *a_node)
-{
- CRAdditionalSel *cur_add_sel = NULL;
-
- g_return_val_if_fail (a_add_sel, FALSE);
-
- for (cur_add_sel = a_add_sel; cur_add_sel; cur_add_sel = cur_add_sel->next)
- {
- switch (cur_add_sel->type)
- {
- case NO_ADD_SELECTOR:
- return FALSE;
- case CLASS_ADD_SELECTOR:
- if (!class_add_sel_matches_style (cur_add_sel, a_node))
- return FALSE;
- break;
- case ID_ADD_SELECTOR:
- if (!id_add_sel_matches_style (cur_add_sel, a_node))
- return FALSE;
- break;
- case ATTRIBUTE_ADD_SELECTOR:
- g_warning ("Attribute selectors not supported");
- return FALSE;
- case PSEUDO_CLASS_ADD_SELECTOR:
- if (!pseudo_class_add_sel_matches_style (a_this, cur_add_sel, a_node))
- return FALSE;
- break;
- }
- }
-
- return TRUE;
-}
-
-static gboolean
-element_name_matches_type (const char *element_name,
- GType element_type)
-{
- if (element_type == G_TYPE_NONE)
- {
- return strcmp (element_name, "stage") == 0;
- }
- else
- {
- GType match_type = g_type_from_name (element_name);
- if (match_type == G_TYPE_INVALID)
- return FALSE;
-
- return g_type_is_a (element_type, match_type);
- }
-}
-
-/**
- *Evaluate a selector (a simple selectors list) and says
- *if it matches the style node given in parameter.
- *The algorithm used here is the following:
- *Walk the combinator separated list of simple selectors backward, starting
- *from the end of the list. For each simple selector, looks if
- *if matches the current style.
- *
- *@param a_this the selection engine.
- *@param a_sel the simple selection list.
- *@param a_node the style node.
- *@param a_result out parameter. Set to true if the
- *selector matches the style node, FALSE otherwise.
- *@param a_recurse if set to TRUE, the function will walk to
- *the next simple selector (after the evaluation of the current one)
- *and recursively evaluate it. Must be usually set to TRUE unless you
- *know what you are doing.
- */
-static enum CRStatus
-sel_matches_style_real (EekTheme *a_this,
- CRSimpleSel *a_sel,
- EekThemeNode *a_node,
- gboolean *a_result,
- gboolean a_eval_sel_list_from_end,
- gboolean a_recurse)
-{
- CRSimpleSel *cur_sel = NULL;
- EekThemeNode *cur_node = NULL;
- GType cur_type;
-
- *a_result = FALSE;
-
- if (a_eval_sel_list_from_end)
- {
- /*go and get the last simple selector of the list */
- for (cur_sel = a_sel; cur_sel && cur_sel->next; cur_sel = cur_sel->next)
- ;
- }
- else
- {
- cur_sel = a_sel;
- }
-
- cur_node = a_node;
- cur_type = eek_theme_node_get_element_type (cur_node);
-
- while (cur_sel)
- {
- if (((cur_sel->type_mask & TYPE_SELECTOR)
- && (cur_sel->name
- && cur_sel->name->stryng
- && cur_sel->name->stryng->str)
- &&
- (element_name_matches_type (cur_sel->name->stryng->str, cur_type)))
- || (cur_sel->type_mask & UNIVERSAL_SELECTOR))
- {
- /*
- *this simple selector
- *matches the current style node
- *Let's see if the preceding
- *simple selectors also match
- *their style node counterpart.
- */
- if (cur_sel->add_sel)
- {
- if (additional_selector_matches_style (a_this, cur_sel->add_sel, cur_node))
- goto walk_a_step_in_expr;
- else
- goto done;
- }
- else
- goto walk_a_step_in_expr;
- }
- if (!(cur_sel->type_mask & TYPE_SELECTOR)
- && !(cur_sel->type_mask & UNIVERSAL_SELECTOR))
- {
- if (!cur_sel->add_sel)
- goto done;
- if (additional_selector_matches_style (a_this, cur_sel->add_sel, cur_node))
- goto walk_a_step_in_expr;
- else
- goto done;
- }
- else
- {
- goto done;
- }
-
- walk_a_step_in_expr:
- if (a_recurse == FALSE)
- {
- *a_result = TRUE;
- goto done;
- }
-
- /*
- *here, depending on the combinator of cur_sel
- *choose the axis of the element tree traversal
- *and walk one step in the element tree.
- */
- if (!cur_sel->prev)
- break;
-
- switch (cur_sel->combinator)
- {
- case NO_COMBINATOR:
- break;
-
- case COMB_WS: /*descendant selector */
- {
- EekThemeNode *n = NULL;
-
- /*
- *walk the element tree upward looking for a parent
- *style that matches the preceding selector.
- */
- for (n = eek_theme_node_get_parent (a_node); n; n = eek_theme_node_get_parent (n))
- {
- enum CRStatus status;
- gboolean matches = FALSE;
-
- status = sel_matches_style_real (a_this, cur_sel->prev, n, &matches, FALSE, TRUE);
-
- if (status != CR_OK)
- goto done;
-
- if (matches)
- {
- cur_node = n;
- cur_type = eek_theme_node_get_element_type (cur_node);
- break;
- }
- }
-
- if (!n)
- {
- /*
- *didn't find any ancestor that matches
- *the previous simple selector.
- */
- goto done;
- }
- /*
- *in this case, the preceding simple sel
- *will have been interpreted twice, which
- *is a cpu and mem waste ... I need to find
- *another way to do this. Anyway, this is
- *my first attempt to write this function and
- *I am a bit clueless.
- */
- break;
- }
-
- case COMB_PLUS:
- g_warning ("+ combinators are not supported");
- goto done;
-
- case COMB_GT:
- cur_node = eek_theme_node_get_parent (cur_node);
- if (!cur_node)
- goto done;
- cur_type = eek_theme_node_get_element_type (cur_node);
- break;
-
- default:
- goto done;
- }
-
- cur_sel = cur_sel->prev;
- }
-
- /*
- *if we reached this point, it means the selector matches
- *the style node.
- */
- *a_result = TRUE;
-
-done:
- return CR_OK;
-}
-
-static void
-add_matched_properties (EekTheme *a_this,
- CRStyleSheet *a_nodesheet,
- EekThemeNode *a_node,
- GPtrArray *props)
-{
- CRStatement *cur_stmt = NULL;
- CRSelector *sel_list = NULL;
- CRSelector *cur_sel = NULL;
- gboolean matches = FALSE;
- enum CRStatus status = CR_OK;
-
- /*
- *walk through the list of statements and,
- *get the selectors list inside the statements that
- *contain some, and try to match our style node in these
- *selectors lists.
- */
- for (cur_stmt = a_nodesheet->statements; cur_stmt; cur_stmt = cur_stmt->next)
- {
- /*
- *initialyze the selector list in which we will
- *really perform the search.
- */
- sel_list = NULL;
-
- /*
- *get the the damn selector list in
- *which we have to look
- */
- switch (cur_stmt->type)
- {
- case RULESET_STMT:
- if (cur_stmt->kind.ruleset && cur_stmt->kind.ruleset->sel_list)
- {
- sel_list = cur_stmt->kind.ruleset->sel_list;
- }
- break;
-
- case AT_MEDIA_RULE_STMT:
- if (cur_stmt->kind.media_rule
- && cur_stmt->kind.media_rule->rulesets
- && cur_stmt->kind.media_rule->rulesets->kind.ruleset
- && cur_stmt->kind.media_rule->rulesets->kind.ruleset->sel_list)
- {
- sel_list = cur_stmt->kind.media_rule->rulesets->kind.ruleset->sel_list;
- }
- break;
-
- case AT_IMPORT_RULE_STMT:
- {
- CRAtImportRule *import_rule = cur_stmt->kind.import_rule;
-
- if (import_rule->sheet == NULL)
- {
- char *filename = NULL;
-
- if (import_rule->url->stryng && import_rule->url->stryng->str)
- filename = eek_theme_resolve_url (a_this,
- a_nodesheet,
- import_rule->url->stryng->str);
-
- if (filename)
- import_rule->sheet = parse_stylesheet (filename, NULL);
-
- if (import_rule->sheet)
- {
- insert_stylesheet (a_this, filename, import_rule->sheet);
- /* refcount of stylesheets starts off at zero, so we don't need to unref! */
- }
- else
- {
- /* Set a marker to avoid repeatedly trying to parse a non-existent or
- * broken stylesheet
- */
- import_rule->sheet = (CRStyleSheet *) - 1;
- }
-
- if (filename)
- g_free (filename);
- }
-
- if (import_rule->sheet != (CRStyleSheet *) - 1)
- {
- add_matched_properties (a_this, import_rule->sheet,
- a_node, props);
- }
- }
- break;
- default:
- break;
- }
-
- if (!sel_list)
- continue;
-
- /*
- *now, we have a comma separated selector list to look in.
- *let's walk it and try to match the style node
- *on each item of the list.
- */
- for (cur_sel = sel_list; cur_sel; cur_sel = cur_sel->next)
- {
- if (!cur_sel->simple_sel)
- continue;
-
- status = sel_matches_style_real (a_this, cur_sel->simple_sel, a_node, &matches, TRUE, TRUE);
-
- if (status == CR_OK && matches)
- {
- CRDeclaration *cur_decl = NULL;
-
- /* In order to sort the matching properties, we need to compute the
- * specificity of the selector that actually matched this
- * element. In a non-thread-safe fashion, we store it in the
- * ruleset. (Fixing this would mean cut-and-pasting
- * cr_simple_sel_compute_specificity(), and have no need for
- * thread-safety anyways.)
- *
- * Once we've sorted the properties, the specificity no longer
- * matters and it can be safely overriden.
- */
- cr_simple_sel_compute_specificity (cur_sel->simple_sel);
-
- cur_stmt->specificity = cur_sel->simple_sel->specificity;
-
- for (cur_decl = cur_stmt->kind.ruleset->decl_list; cur_decl; cur_decl = cur_decl->next)
- g_ptr_array_add (props, cur_decl);
- }
- }
- }
-}
-
-#define ORIGIN_AUTHOR_IMPORTANT (ORIGIN_AUTHOR + 1)
-#define ORIGIN_USER_IMPORTANT (ORIGIN_AUTHOR + 2)
-
-static inline int
-get_origin (const CRDeclaration * decl)
-{
- enum CRStyleOrigin origin = decl->parent_statement->parent_sheet->origin;
-
- if (decl->important)
- {
- if (origin == ORIGIN_AUTHOR)
- return ORIGIN_AUTHOR_IMPORTANT;
- else if (origin == ORIGIN_USER)
- return ORIGIN_USER_IMPORTANT;
- }
-
- return origin;
-}
-
-/* Order of comparison is so that higher priority statements compare after
- * lower priority statements */
-static int
-compare_declarations (gconstpointer a,
- gconstpointer b)
-{
- /* g_ptr_array_sort() is broooken */
- CRDeclaration *decl_a = *(CRDeclaration **) a;
- CRDeclaration *decl_b = *(CRDeclaration **) b;
-
- int origin_a = get_origin (decl_a);
- int origin_b = get_origin (decl_b);
-
- if (origin_a != origin_b)
- return origin_a - origin_b;
-
- if (decl_a->parent_statement->specificity != decl_b->parent_statement->specificity)
- return decl_a->parent_statement->specificity - decl_b->parent_statement->specificity;
-
- return 0;
-}
-
-GPtrArray *
-_eek_theme_get_matched_properties (EekTheme *theme,
- EekThemeNode *node)
-{
- enum CRStyleOrigin origin = 0;
- CRStyleSheet *sheet = NULL;
- GPtrArray *props = g_ptr_array_new ();
- GSList *iter;
-
- g_return_val_if_fail (EEK_IS_THEME (theme), NULL);
- g_return_val_if_fail (EEK_IS_THEME_NODE (node), NULL);
-
- for (origin = ORIGIN_UA; origin < NB_ORIGINS; origin++)
- {
- sheet = cr_cascade_get_sheet (theme->cascade, origin);
- if (!sheet)
- continue;
-
- add_matched_properties (theme, sheet, node, props);
- }
-
- for (iter = theme->custom_stylesheets; iter; iter = iter->next)
- add_matched_properties (theme, iter->data, node, props);
-
- /* We count on a stable sort here so that later declarations come
- * after earlier declarations */
- g_ptr_array_sort (props, compare_declarations);
-
- return props;
-}
-
-/* Resolve an url from an url() reference in a stylesheet into an absolute
- * local filename, if possible. The resolution here is distinctly lame and
- * will fail on many examples.
- */
-static char *
-eek_theme_resolve_url (EekTheme *theme,
- CRStyleSheet *base_stylesheet,
- const char *url)
-{
- const char *base_filename = NULL;
- char *dirname;
- char *filename;
-
- /* Handle absolute file:/ URLs */
- if (g_str_has_prefix (url, "file:") ||
- g_str_has_prefix (url, "File:") ||
- g_str_has_prefix (url, "FILE:"))
- {
- GError *error = NULL;
- char *filename;
-
- filename = g_filename_from_uri (url, NULL, &error);
- if (filename == NULL)
- {
- g_warning ("%s", error->message);
- g_error_free (error);
- }
-
- return NULL;
- }
-
- /* Guard against http:/ URLs */
-
- if (g_str_has_prefix (url, "http:") ||
- g_str_has_prefix (url, "Http:") ||
- g_str_has_prefix (url, "HTTP:"))
- {
- g_warning ("Http URL '%s' in theme stylesheet is not supported", url);
- return NULL;
- }
-
- /* Assume anything else is a relative URL, and "resolve" it
- */
- if (url[0] == '/')
- return g_strdup (url);
-
- base_filename = g_hash_table_lookup (theme->filenames_by_stylesheet, base_stylesheet);
-
- if (base_filename == NULL)
- {
- g_warning ("Can't get base to resolve url '%s'", url);
- return NULL;
- }
-
- dirname = g_path_get_dirname (base_filename);
- filename = g_build_filename (dirname, url, NULL);
- g_free (dirname);
-
- return filename;
-}
diff --git a/eek/eek-theme.h b/eek/eek-theme.h
deleted file mode 100644
index 14fba423..00000000
--- a/eek/eek-theme.h
+++ /dev/null
@@ -1,49 +0,0 @@
-/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
-
-#if !defined(__EEK_H_INSIDE__) && !defined(EEK_COMPILATION)
-#error "Only can be included directly."
-#endif
-
-#ifndef __EEK_THEME_H__
-#define __EEK_THEME_H__
-
-#include
-
-#include "eek-types.h"
-
-G_BEGIN_DECLS
-
-/**
- * SECTION:EekTheme
- * @short_description: a set of stylesheets
- *
- * #EekTheme holds a set of stylesheets. (The "cascade" of the name
- * Cascading Stylesheets.) An #EekTheme can be set to apply to all the
- * keyboard elements.
- */
-
-typedef struct _EekThemeClass EekThemeClass;
-
-#define EEK_TYPE_THEME (eek_theme_get_type())
-#define EEK_THEME(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EEK_TYPE_THEME, EekTheme))
-#define EEK_THEME_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), EEK_TYPE_THEME, EekThemeClass))
-#define EEK_IS_THEME(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EEK_TYPE_THEME))
-#define EEK_IS_THEME_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), EEK_TYPE_THEME))
-#define EEK_THEME_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), EEK_TYPE_THEME, EekThemeClass))
-
-GType eek_theme_get_type (void) G_GNUC_CONST;
-
-EekTheme *eek_theme_new (const char *application_stylesheet,
- const char *theme_stylesheet,
- const char *default_stylesheet);
-
-gboolean eek_theme_load_stylesheet (EekTheme *theme,
- const char *path,
- GError **error);
-
-void eek_theme_unload_stylesheet (EekTheme *theme,
- const char *path);
-
-G_END_DECLS
-
-#endif /* __EEK_THEME_H__ */