css: Add skeleton for new parsing infrastructure

This infrastructure will be based around the CSSOM and return a
GtkCssStyleSheet object as its result.

The initial intended use for this is as a syntax tree while editing in
the inspector, but we might even want to look into exporting the CSSOM
parts as public API at some point.
This commit is contained in:
Benjamin Otte
2016-03-09 19:44:50 +01:00
parent 25b2e2f3e5
commit 674ca8ae1c
15 changed files with 2038 additions and 31 deletions

View File

@@ -434,6 +434,8 @@ gtk_private_h_sources = \
gtkcssrbtreeprivate.h \
gtkcssrepeatvalueprivate.h \
gtkcssrgbavalueprivate.h \
gtkcssruleprivate.h \
gtkcssrulelistprivate.h \
gtkcsssectionprivate.h \
gtkcssselectorprivate.h \
gtkcssshadowsvalueprivate.h \
@@ -445,7 +447,11 @@ gtk_private_h_sources = \
gtkcssstylechangeprivate.h \
gtkcssstyleprivate.h \
gtkcssstylepropertyprivate.h \
gtkcssstyledeclarationprivate.h \
gtkcssstyleruleprivate.h \
gtkcssstylesheetprivate.h \
gtkcsstokenizerprivate.h \
gtkcsstokensourceprivate.h \
gtkcsstransformvalueprivate.h \
gtkcsstransientnodeprivate.h \
gtkcsstransitionprivate.h \
@@ -704,11 +710,15 @@ gtk_base_c_sources = \
gtkcssrbtree.c \
gtkcssrepeatvalue.c \
gtkcssrgbavalue.c \
gtkcssrule.c \
gtkcssrulelist.c \
gtkcsssection.c \
gtkcssselector.c \
gtkcssstringvalue.c \
gtkcssstyle.c \
gtkcssstylechange.c \
gtkcssstyledeclaration.c \
gtkcssstylerule.c \
gtkcssshadowsvalue.c \
gtkcssshadowvalue.c \
gtkcssshorthandproperty.c \
@@ -717,7 +727,9 @@ gtk_base_c_sources = \
gtkcssstylefuncs.c \
gtkcssstyleproperty.c \
gtkcssstylepropertyimpl.c \
gtkcssstylesheet.c \
gtkcsstokenizer.c \
gtkcsstokensource.c \
gtkcsstransformvalue.c \
gtkcsstransientnode.c \
gtkcsstransition.c \

215
gtk/gtkcssrule.c Normal file
View File

@@ -0,0 +1,215 @@
/*
* Copyright © 2016 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.1 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, see <http://www.gnu.org/licenses/>.
*
* Authors: Benjamin Otte <otte@gnome.org>
*/
#include "config.h"
#include "gtkcssruleprivate.h"
#include "gtkcssstylesheetprivate.h"
typedef struct _GtkCssRulePrivate GtkCssRulePrivate;
struct _GtkCssRulePrivate {
GtkCssRule *parent_rule;
GtkCssStyleSheet *parent_style_sheet;
};
typedef struct _GtkCssTokenSourceAt GtkCssTokenSourceAt;
struct _GtkCssTokenSourceAt {
GtkCssTokenSource parent;
GtkCssTokenSource *source;
guint inside_curly_block :1;
guint done :1;
};
static void
gtk_css_token_source_at_finalize (GtkCssTokenSource *source)
{
GtkCssTokenSourceAt *at = (GtkCssTokenSourceAt *) source;
gtk_css_token_source_unref (at->source);
}
static void
gtk_css_token_source_at_consume_token (GtkCssTokenSource *source)
{
GtkCssTokenSourceAt *at = (GtkCssTokenSourceAt *) source;
const GtkCssToken *token;
if (at->done)
return;
if (gtk_css_token_get_pending_block (source))
{
gtk_css_token_source_consume_token (at->source);
return;
}
token = gtk_css_token_source_get_token (at->source);
if (gtk_css_token_is (token, GTK_CSS_TOKEN_SEMICOLON))
at->done = TRUE;
else if (at->inside_curly_block && gtk_css_token_is (token, GTK_CSS_TOKEN_CLOSE_CURLY))
at->done = TRUE;
else if (gtk_css_token_is (token, GTK_CSS_TOKEN_OPEN_CURLY))
at->inside_curly_block = TRUE;
gtk_css_token_source_consume_token (at->source);
}
const GtkCssToken *
gtk_css_token_source_at_get_token (GtkCssTokenSource *source)
{
GtkCssTokenSourceAt *at = (GtkCssTokenSourceAt *) source;
static GtkCssToken eof_token = { GTK_CSS_TOKEN_EOF };
if (at->done)
return &eof_token;
return gtk_css_token_source_get_token (at->source);
}
static void
gtk_css_token_source_at_error (GtkCssTokenSource *source,
const GError *error)
{
GtkCssTokenSourceAt *at = (GtkCssTokenSourceAt *) source;
gtk_css_token_source_emit_error (at->source, error);
}
static const GtkCssTokenSourceClass GTK_CSS_TOKEN_SOURCE_AT = {
gtk_css_token_source_at_finalize,
gtk_css_token_source_at_consume_token,
gtk_css_token_source_at_get_token,
gtk_css_token_source_at_error
};
static GtkCssTokenSource *
gtk_css_token_source_new_at (GtkCssTokenSource *source)
{
GtkCssTokenSourceAt *at = gtk_css_token_source_new (GtkCssTokenSourceAt, &GTK_CSS_TOKEN_SOURCE_AT);
at->source = gtk_css_token_source_ref (source);
return &at->parent;
}
G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (GtkCssRule, gtk_css_rule, G_TYPE_OBJECT)
static void
gtk_css_rule_class_init (GtkCssRuleClass *klass)
{
}
static void
gtk_css_rule_init (GtkCssRule *rule)
{
}
GtkCssRule *
gtk_css_rule_new_from_at_rule (GtkCssTokenSource *source,
GtkCssRule *parent_rule,
GtkCssStyleSheet *parent_style_sheet)
{
GtkCssTokenSource *at_source;
const GtkCssToken *token;
g_return_val_if_fail (source != NULL, NULL);
g_return_val_if_fail (parent_rule == NULL || GTK_IS_CSS_RULE (parent_rule), NULL);
g_return_val_if_fail (GTK_IS_CSS_STYLE_SHEET (parent_style_sheet), NULL);
at_source = gtk_css_token_source_new_at (source);
token = gtk_css_token_source_get_token (at_source);
if (token->type != GTK_CSS_TOKEN_AT_KEYWORD)
{
gtk_css_token_source_error (at_source, "Expected an '@'");
gtk_css_token_source_unref (at_source);
return NULL;
}
else
{
const char *name = token->string.string;
if (g_ascii_strcasecmp (name, "import") == 0)
{
gtk_css_token_source_error (source, "Add code to parse @import here");
}
else
{
gtk_css_token_source_unknown (source, "Unknown rule @%s", name);
}
}
gtk_css_token_source_consume_all (at_source);
gtk_css_token_source_unref (at_source);
return NULL;
}
void
gtk_css_rule_print_css_text (GtkCssRule *rule,
GString *string)
{
GtkCssRuleClass *klass;
g_return_if_fail (GTK_IS_CSS_RULE (rule));
g_return_if_fail (string != NULL);
klass = GTK_CSS_RULE_GET_CLASS (rule);
klass->get_css_text (rule, string);
}
char *
gtk_css_rule_get_css_text (GtkCssRule *rule)
{
GString *string;
g_return_val_if_fail (GTK_IS_CSS_RULE (rule), NULL);
string = g_string_new (NULL);
gtk_css_rule_print_css_text (rule, string);
return g_string_free (string, FALSE);
}
GtkCssRule *
gtk_css_rule_get_parent_rule (GtkCssRule *rule)
{
GtkCssRulePrivate *priv;
g_return_val_if_fail (GTK_IS_CSS_RULE (rule), NULL);
priv = gtk_css_rule_get_instance_private (rule);
return priv->parent_rule;
}
GtkCssStyleSheet *
gtk_css_rule_get_parent_style_sheet (GtkCssRule *rule)
{
GtkCssRulePrivate *priv;
g_return_val_if_fail (GTK_IS_CSS_RULE (rule), NULL);
priv = gtk_css_rule_get_instance_private (rule);
return priv->parent_style_sheet;
}

166
gtk/gtkcssrulelist.c Normal file
View File

@@ -0,0 +1,166 @@
/*
* Copyright © 2016 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.1 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, see <http://www.gnu.org/licenses/>.
*
* Authors: Benjamin Otte <otte@gnome.org>
*/
#include "config.h"
#include "gtkcssrulelistprivate.h"
#include "gtkcssstyleruleprivate.h"
#include "gtkcssstylesheetprivate.h"
typedef struct _GtkCssRuleListPrivate GtkCssRuleListPrivate;
struct _GtkCssRuleListPrivate {
GPtrArray *items;
};
G_DEFINE_TYPE_WITH_PRIVATE (GtkCssRuleList, gtk_css_rule_list, G_TYPE_OBJECT)
static void
gtk_css_rule_list_finalize (GObject *object)
{
GtkCssRuleList *rule_list = GTK_CSS_RULE_LIST (object);
GtkCssRuleListPrivate *priv = gtk_css_rule_list_get_instance_private (rule_list);
g_ptr_array_unref (priv->items);
G_OBJECT_CLASS (gtk_css_rule_list_parent_class)->finalize (object);
}
static void
gtk_css_rule_list_class_init (GtkCssRuleListClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->finalize = gtk_css_rule_list_finalize;
}
static void
gtk_css_rule_list_init (GtkCssRuleList *rule_list)
{
GtkCssRuleListPrivate *priv = gtk_css_rule_list_get_instance_private (rule_list);
priv->items = g_ptr_array_new_with_free_func (g_object_unref);
}
GtkCssRuleList *
gtk_css_rule_list_new (void)
{
return g_object_new (GTK_TYPE_CSS_RULE_LIST, NULL);
}
void
gtk_css_rule_list_parse (GtkCssRuleList *rule_list,
GtkCssTokenSource *source,
GtkCssRule *parent_rule,
GtkCssStyleSheet *parent_style_sheet)
{
GtkCssRule *rule;
const GtkCssToken *token;
g_return_if_fail (GTK_IS_CSS_RULE_LIST (rule_list));
g_return_if_fail (source != NULL);
g_return_if_fail (parent_rule == NULL || GTK_IS_CSS_RULE (parent_rule));
g_return_if_fail (GTK_IS_CSS_STYLE_SHEET (parent_style_sheet));
for (token = gtk_css_token_source_get_token (source);
token->type != GTK_CSS_TOKEN_EOF;
token = gtk_css_token_source_get_token (source))
{
switch (token->type)
{
case GTK_CSS_TOKEN_WHITESPACE:
gtk_css_token_source_consume_token (source);
break;
case GTK_CSS_TOKEN_AT_KEYWORD:
rule = gtk_css_rule_new_from_at_rule (source, parent_rule, parent_style_sheet);
if (rule)
gtk_css_rule_list_append (rule_list, rule);
break;
case GTK_CSS_TOKEN_CDO:
case GTK_CSS_TOKEN_CDC:
if (parent_rule == NULL)
{
gtk_css_token_source_consume_token (source);
break;
}
/* else fall through */
default:
rule = gtk_css_style_rule_new_parse (source, parent_rule, parent_style_sheet);
if (rule)
gtk_css_rule_list_append (rule_list, rule);
break;
}
}
}
void
gtk_css_rule_list_insert (GtkCssRuleList *rule_list,
gsize id,
GtkCssRule *rule)
{
GtkCssRuleListPrivate *priv;
g_return_if_fail (GTK_IS_CSS_RULE_LIST (rule_list));
g_return_if_fail (GTK_IS_CSS_RULE (rule));
priv = gtk_css_rule_list_get_instance_private (rule_list);
g_ptr_array_insert (priv->items, id, g_object_ref (rule));
}
void
gtk_css_rule_list_append (GtkCssRuleList *rule_list,
GtkCssRule *rule)
{
GtkCssRuleListPrivate *priv;
g_return_if_fail (GTK_IS_CSS_RULE_LIST (rule_list));
g_return_if_fail (GTK_IS_CSS_RULE (rule));
priv = gtk_css_rule_list_get_instance_private (rule_list);
g_ptr_array_add (priv->items, g_object_ref (rule));
}
GtkCssRule *
gtk_css_rule_list_get_item (GtkCssRuleList *rule_list,
gsize id)
{
GtkCssRuleListPrivate *priv;
g_return_val_if_fail (GTK_IS_CSS_RULE_LIST (rule_list), NULL);
priv = gtk_css_rule_list_get_instance_private (rule_list);
g_return_val_if_fail (id < priv->items->len, NULL);
return g_ptr_array_index (priv->items, id);
}
gsize
gtk_css_rule_list_get_length (GtkCssRuleList *rule_list)
{
GtkCssRuleListPrivate *priv;
g_return_val_if_fail (GTK_IS_CSS_RULE_LIST (rule_list), 0);
priv = gtk_css_rule_list_get_instance_private (rule_list);
return priv->items->len;
}

View File

@@ -0,0 +1,69 @@
/*
* Copyright © 2016 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.1 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, see <http://www.gnu.org/licenses/>.
*
* Authors: Benjamin Otte <otte@gnome.org>
*/
#ifndef __GTK_CSS_RULE_LIST_PRIVATE_H__
#define __GTK_CSS_RULE_LIST_PRIVATE_H__
#include "gtk/gtkcssruleprivate.h"
G_BEGIN_DECLS
#define GTK_TYPE_CSS_RULE_LIST (gtk_css_rule_list_get_type ())
#define GTK_CSS_RULE_LIST(obj) (G_TYPE_CHECK_INSTANCE_CAST (obj, GTK_TYPE_CSS_RULE_LIST, GtkCssRuleList))
#define GTK_CSS_RULE_LIST_CLASS(cls) (G_TYPE_CHECK_CLASS_CAST (cls, GTK_TYPE_CSS_RULE_LIST, GtkCssRuleListClass))
#define GTK_IS_CSS_RULE_LIST(obj) (G_TYPE_CHECK_INSTANCE_TYPE (obj, GTK_TYPE_CSS_RULE_LIST))
#define GTK_IS_CSS_RULE_LIST_CLASS(obj) (G_TYPE_CHECK_CLASS_TYPE (obj, GTK_TYPE_CSS_RULE_LIST))
#define GTK_CSS_RULE_LIST_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_CSS_RULE_LIST, GtkCssRuleListClass))
typedef struct _GtkCssRuleList GtkCssRuleList;
typedef struct _GtkCssRuleListClass GtkCssRuleListClass;
struct _GtkCssRuleList
{
GObject parent;
};
struct _GtkCssRuleListClass
{
GObjectClass parent_class;
};
GType gtk_css_rule_list_get_type (void) G_GNUC_CONST;
GtkCssRuleList * gtk_css_rule_list_new (void);
void gtk_css_rule_list_parse (GtkCssRuleList *rule_list,
GtkCssTokenSource *source,
GtkCssRule *parent_rule,
GtkCssStyleSheet *parent_style_sheet);
void gtk_css_rule_list_insert (GtkCssRuleList *rule_list,
gsize id,
GtkCssRule *rule);
void gtk_css_rule_list_append (GtkCssRuleList *rule_list,
GtkCssRule *rule);
/* GtkCSSRule DOM */
GtkCssRule * gtk_css_rule_list_get_item (GtkCssRuleList *rule_list,
gsize id);
gsize gtk_css_rule_list_get_length (GtkCssRuleList *rule_list);
G_END_DECLS
#endif /* __GTK_CSS_RULE_LIST_PRIVATE_H__ */

70
gtk/gtkcssruleprivate.h Normal file
View File

@@ -0,0 +1,70 @@
/*
* Copyright © 2016 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.1 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, see <http://www.gnu.org/licenses/>.
*
* Authors: Benjamin Otte <otte@gnome.org>
*/
#ifndef __GTK_CSS_RULE_PRIVATE_H__
#define __GTK_CSS_RULE_PRIVATE_H__
#include "gtk/gtkcsstokensourceprivate.h"
G_BEGIN_DECLS
#define GTK_TYPE_CSS_RULE (gtk_css_rule_get_type ())
#define GTK_CSS_RULE(obj) (G_TYPE_CHECK_INSTANCE_CAST (obj, GTK_TYPE_CSS_RULE, GtkCssRule))
#define GTK_CSS_RULE_CLASS(cls) (G_TYPE_CHECK_CLASS_CAST (cls, GTK_TYPE_CSS_RULE, GtkCssRuleClass))
#define GTK_IS_CSS_RULE(obj) (G_TYPE_CHECK_INSTANCE_TYPE (obj, GTK_TYPE_CSS_RULE))
#define GTK_IS_CSS_RULE_CLASS(obj) (G_TYPE_CHECK_CLASS_TYPE (obj, GTK_TYPE_CSS_RULE))
#define GTK_CSS_RULE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_CSS_RULE, GtkCssRuleClass))
/* forward declaration */
typedef struct _GtkCssStyleSheet GtkCssStyleSheet;
typedef struct _GtkCssRule GtkCssRule;
typedef struct _GtkCssRuleClass GtkCssRuleClass;
struct _GtkCssRule
{
GObject parent;
};
struct _GtkCssRuleClass
{
GObjectClass parent_class;
/* gets the cssText for this rule */
void (* get_css_text) (GtkCssRule *rule,
GString *string);
};
GType gtk_css_rule_get_type (void) G_GNUC_CONST;
GtkCssRule * gtk_css_rule_new_from_at_rule (GtkCssTokenSource *source,
GtkCssRule *parent_rule,
GtkCssStyleSheet *parent_style_sheet);
void gtk_css_rule_print_css_text (GtkCssRule *rule,
GString *string);
char * gtk_css_rule_get_css_text (GtkCssRule *rule);
GtkCssRule * gtk_css_rule_get_parent_rule (GtkCssRule *rule);
GtkCssStyleSheet * gtk_css_rule_get_parent_style_sheet (GtkCssRule *rule);
G_END_DECLS
#endif /* __GTK_CSS_RULE_PRIVATE_H__ */

View File

@@ -25,6 +25,8 @@
#include "gtkcssprovider.h"
#include "gtkstylecontextprivate.h"
#include <errno.h>
#include <stdlib.h>
#if defined(_MSC_VER) && _MSC_VER >= 1500
# include <intrin.h>
#endif
@@ -1102,42 +1104,42 @@ parse_selector_pseudo_class_nth_child (GtkCssParser *parser,
return selector;
}
static const struct {
const char *name;
gboolean deprecated;
GtkStateFlags state_flag;
PositionType position_type;
int position_a;
int position_b;
} pseudo_classes[] = {
{ "first-child", 0, 0, POSITION_FORWARD, 0, 1 },
{ "last-child", 0, 0, POSITION_BACKWARD, 0, 1 },
{ "only-child", 0, 0, POSITION_ONLY, 0, 0 },
{ "sorted", 1, 0, POSITION_SORTED, 0, 0 },
{ "active", 0, GTK_STATE_FLAG_ACTIVE, },
{ "prelight", 1, GTK_STATE_FLAG_PRELIGHT, },
{ "hover", 0, GTK_STATE_FLAG_PRELIGHT, },
{ "selected", 0, GTK_STATE_FLAG_SELECTED, },
{ "insensitive", 1, GTK_STATE_FLAG_INSENSITIVE, },
{ "disabled", 0, GTK_STATE_FLAG_INSENSITIVE, },
{ "inconsistent", 1, GTK_STATE_FLAG_INCONSISTENT, },
{ "indeterminate", 0, GTK_STATE_FLAG_INCONSISTENT, },
{ "focused", 1, GTK_STATE_FLAG_FOCUSED, },
{ "focus", 0, GTK_STATE_FLAG_FOCUSED, },
{ "backdrop", 0, GTK_STATE_FLAG_BACKDROP, },
{ "dir(ltr)", 0, GTK_STATE_FLAG_DIR_LTR, },
{ "dir(rtl)", 0, GTK_STATE_FLAG_DIR_RTL, },
{ "link", 0, GTK_STATE_FLAG_LINK, },
{ "visited", 0, GTK_STATE_FLAG_VISITED, },
{ "checked", 0, GTK_STATE_FLAG_CHECKED, },
{ "drop(active)", 0, GTK_STATE_FLAG_DROP_ACTIVE, }
};
static GtkCssSelector *
parse_selector_pseudo_class (GtkCssParser *parser,
GtkCssSelector *selector,
gboolean negate)
{
static const struct {
const char *name;
gboolean deprecated;
GtkStateFlags state_flag;
PositionType position_type;
int position_a;
int position_b;
} pseudo_classes[] = {
{ "first-child", 0, 0, POSITION_FORWARD, 0, 1 },
{ "last-child", 0, 0, POSITION_BACKWARD, 0, 1 },
{ "only-child", 0, 0, POSITION_ONLY, 0, 0 },
{ "sorted", 1, 0, POSITION_SORTED, 0, 0 },
{ "active", 0, GTK_STATE_FLAG_ACTIVE, },
{ "prelight", 1, GTK_STATE_FLAG_PRELIGHT, },
{ "hover", 0, GTK_STATE_FLAG_PRELIGHT, },
{ "selected", 0, GTK_STATE_FLAG_SELECTED, },
{ "insensitive", 1, GTK_STATE_FLAG_INSENSITIVE, },
{ "disabled", 0, GTK_STATE_FLAG_INSENSITIVE, },
{ "inconsistent", 1, GTK_STATE_FLAG_INCONSISTENT, },
{ "indeterminate", 0, GTK_STATE_FLAG_INCONSISTENT, },
{ "focused", 1, GTK_STATE_FLAG_FOCUSED, },
{ "focus", 0, GTK_STATE_FLAG_FOCUSED, },
{ "backdrop", 0, GTK_STATE_FLAG_BACKDROP, },
{ "dir(ltr)", 0, GTK_STATE_FLAG_DIR_LTR, },
{ "dir(rtl)", 0, GTK_STATE_FLAG_DIR_RTL, },
{ "link", 0, GTK_STATE_FLAG_LINK, },
{ "visited", 0, GTK_STATE_FLAG_VISITED, },
{ "checked", 0, GTK_STATE_FLAG_CHECKED, },
{ "drop(active)", 0, GTK_STATE_FLAG_DROP_ACTIVE, }
};
guint i;
if (_gtk_css_parser_try (parser, "nth-child", FALSE))
@@ -1305,6 +1307,539 @@ _gtk_css_selector_parse (GtkCssParser *parser)
return selector;
}
GtkCssSelector *
token_parse_selector_class (GtkCssTokenSource *source,
GtkCssSelector *selector,
gboolean negate)
{
const GtkCssToken *token;
gtk_css_token_source_consume_token (source);
token = gtk_css_token_source_get_token (source);
if (gtk_css_token_is (token, GTK_CSS_TOKEN_IDENT))
{
selector = gtk_css_selector_new (negate ? &GTK_CSS_SELECTOR_NOT_CLASS
: &GTK_CSS_SELECTOR_CLASS,
selector);
selector->style_class.style_class = g_quark_from_string (token->string.string);
gtk_css_token_source_consume_token (source);
return selector;
}
else
{
gtk_css_token_source_error (source, "No class name after '.' in selector");
if (selector)
_gtk_css_selector_free (selector);
return NULL;
}
}
static gboolean
parse_plus_b (GtkCssTokenSource *source,
gboolean negate,
gint *b)
{
const GtkCssToken *token;
gboolean has_seen_sign;
gtk_css_token_source_consume_whitespace (source);
token = gtk_css_token_source_get_token (source);
if (negate)
{
has_seen_sign = TRUE;
}
else
{
if (gtk_css_token_is_delim (token, '+'))
{
gtk_css_token_source_consume_token (source);
gtk_css_token_source_consume_whitespace (source);
has_seen_sign = TRUE;
}
else if (gtk_css_token_is_delim (token, '-'))
{
gtk_css_token_source_consume_token (source);
gtk_css_token_source_consume_whitespace (source);
negate = TRUE;
has_seen_sign = TRUE;
}
}
token = gtk_css_token_source_get_token (source);
if (gtk_css_token_is (token, GTK_CSS_TOKEN_INTEGER))
{
if (has_seen_sign && token->number.number >= 0)
{
*b = token->number.number;
if (negate)
*b = - *b;
return TRUE;
}
}
gtk_css_token_source_error (source, "Not a valid an+b type");
return FALSE;
}
gboolean
parse_a_n_plus_b (GtkCssTokenSource *source,
gint *a,
gint *b)
{
const GtkCssToken *token;
token = gtk_css_token_source_get_token (source);
if (gtk_css_token_is_ident (token, "even"))
{
*a = 2;
*b = 0;
gtk_css_token_source_consume_token (source);
return TRUE;
}
else if (gtk_css_token_is_ident (token, "odd"))
{
*a = 2;
*b = 1;
gtk_css_token_source_consume_token (source);
return TRUE;
}
else if (gtk_css_token_is (token, GTK_CSS_TOKEN_INTEGER))
{
*a = 0;
*b = token->number.number;
gtk_css_token_source_consume_token (source);
return TRUE;
}
else if (gtk_css_token_is (token, GTK_CSS_TOKEN_INTEGER_DIMENSION) &&
g_ascii_strcasecmp (token->dimension.dimension, "n") == 0)
{
*a = token->dimension.value;
gtk_css_token_source_consume_token (source);
return parse_plus_b (source, FALSE, b);
}
else if (gtk_css_token_is (token, GTK_CSS_TOKEN_INTEGER_DIMENSION) &&
g_ascii_strcasecmp (token->dimension.dimension, "n-") == 0)
{
*a = token->dimension.value;
gtk_css_token_source_consume_token (source);
return parse_plus_b (source, TRUE, b);
}
else if (gtk_css_token_is (token, GTK_CSS_TOKEN_INTEGER_DIMENSION) &&
g_ascii_strncasecmp (token->dimension.dimension, "n-", 2) == 0)
{
char *end;
*a = token->dimension.value;
errno = 0;
*b = strtoul (token->dimension.dimension + 2, &end, 10);
if (*end == '\0' && errno == 0)
{
gtk_css_token_source_consume_token (source);
return TRUE;
}
}
else if (gtk_css_token_is_ident (token, "-n"))
{
*a = -1;
gtk_css_token_source_consume_token (source);
return parse_plus_b (source, FALSE, b);
}
else if (gtk_css_token_is_ident (token, "-n-"))
{
*a = -1;
gtk_css_token_source_consume_token (source);
return parse_plus_b (source, TRUE, b);
}
gtk_css_token_source_error (source, "Not a valid an+b type");
return FALSE;
}
GtkCssSelector *
token_parse_selector_pseudo_class (GtkCssTokenSource *source,
GtkCssSelector *selector,
gboolean negate)
{
const GtkCssToken *token;
gtk_css_token_source_consume_token (source);
token = gtk_css_token_source_get_token (source);
if (gtk_css_token_is (token, GTK_CSS_TOKEN_IDENT))
{
guint i;
for (i = 0; i < G_N_ELEMENTS (pseudo_classes); i++)
{
if (g_ascii_strcasecmp (pseudo_classes[i].name, token->string.string) == 0)
{
if (pseudo_classes[i].state_flag)
{
selector = gtk_css_selector_new (negate ? &GTK_CSS_SELECTOR_NOT_PSEUDOCLASS_STATE
: &GTK_CSS_SELECTOR_PSEUDOCLASS_STATE,
selector);
selector->state.state = pseudo_classes[i].state_flag;
if (pseudo_classes[i].deprecated)
{
if (pseudo_classes[i + 1].state_flag == pseudo_classes[i].state_flag)
gtk_css_token_source_deprecated (source,
"The :%s pseudo-class is deprecated. Use :%s instead.",
pseudo_classes[i].name,
pseudo_classes[i + 1].name);
else
gtk_css_token_source_deprecated (source,
"The :%s pseudo-class is deprecated.",
pseudo_classes[i].name);
}
}
else
{
selector = gtk_css_selector_new (negate ? &GTK_CSS_SELECTOR_NOT_PSEUDOCLASS_POSITION
: &GTK_CSS_SELECTOR_PSEUDOCLASS_POSITION,
selector);
selector->position.type = pseudo_classes[i].position_type;
selector->position.a = pseudo_classes[i].position_a;
selector->position.b = pseudo_classes[i].position_b;
}
gtk_css_token_source_consume_token (source);
return selector;
}
}
gtk_css_token_source_unknown (source, "Unknown name of pseudo-class");
if (selector)
_gtk_css_selector_free (selector);
return NULL;
}
else if (gtk_css_token_is (token, GTK_CSS_TOKEN_FUNCTION))
{
gint a, b;
if (gtk_css_token_is_function (token, "nth-child"))
{
gtk_css_token_source_consume_token (source);
if (parse_a_n_plus_b (source, &a, &b))
{
selector = gtk_css_selector_new (negate ? &GTK_CSS_SELECTOR_NOT_PSEUDOCLASS_POSITION
: &GTK_CSS_SELECTOR_PSEUDOCLASS_POSITION,
selector);
selector->position.type = POSITION_FORWARD;
selector->position.a = a;
selector->position.b = b;
}
else
{
if (selector)
_gtk_css_selector_free (selector);
return NULL;
}
gtk_css_token_source_consume_whitespace (source);
token = gtk_css_token_source_get_token (source);
if (!gtk_css_token_is (token, GTK_CSS_TOKEN_CLOSE_PARENS))
{
gtk_css_token_source_error (source, "Expected ')' at end of :nth-child()");
if (selector)
_gtk_css_selector_free (selector);
return NULL;
}
gtk_css_token_source_consume_token (source);
}
else if (gtk_css_token_is_function (token, "nth-last-child"))
{
gtk_css_token_source_consume_token (source);
if (parse_a_n_plus_b (source, &a, &b))
{
selector = gtk_css_selector_new (negate ? &GTK_CSS_SELECTOR_NOT_PSEUDOCLASS_POSITION
: &GTK_CSS_SELECTOR_PSEUDOCLASS_POSITION,
selector);
selector->position.type = POSITION_BACKWARD;
selector->position.a = a;
selector->position.b = b;
}
else
{
if (selector)
_gtk_css_selector_free (selector);
return NULL;
}
gtk_css_token_source_consume_whitespace (source);
token = gtk_css_token_source_get_token (source);
if (!gtk_css_token_is (token, GTK_CSS_TOKEN_CLOSE_PARENS))
{
gtk_css_token_source_error (source, "Expected ')' at end of :nth-last-child()");
if (selector)
_gtk_css_selector_free (selector);
return NULL;
}
gtk_css_token_source_consume_token (source);
}
else if (gtk_css_token_is_function (token, "not"))
{
if (negate)
{
gtk_css_token_source_error (source, "Nesting of :not() not allowed");
if (selector)
_gtk_css_selector_free (selector);
return NULL;
}
else
{
gtk_css_token_source_consume_token (source);
token = gtk_css_token_source_get_token (source);
if (gtk_css_token_is_delim (token, '*'))
{
selector = gtk_css_selector_new (&GTK_CSS_SELECTOR_ANY, selector);
gtk_css_token_source_consume_token (source);
}
else if (gtk_css_token_is (token, GTK_CSS_TOKEN_IDENT))
{
selector = gtk_css_selector_new (&GTK_CSS_SELECTOR_NOT_NAME, selector);
selector->name.name = g_intern_string (token->string.string);
gtk_css_token_source_consume_token (source);
}
else if (gtk_css_token_is (token, GTK_CSS_TOKEN_HASH_ID))
{
selector = gtk_css_selector_new (&GTK_CSS_SELECTOR_NOT_ID, selector);
selector->id.name = g_intern_string (token->string.string);
gtk_css_token_source_consume_token (source);
}
else if (gtk_css_token_is_delim (token, '.'))
{
selector = token_parse_selector_class (source, selector, TRUE);
}
else if (gtk_css_token_is (token, GTK_CSS_TOKEN_COLON))
{
selector = token_parse_selector_pseudo_class (source, selector, TRUE);
}
else
{
gtk_css_token_source_error (source, "Invalid contents of :not() selector");
if (selector)
_gtk_css_selector_free (selector);
selector = NULL;
return NULL;
}
gtk_css_token_source_consume_whitespace (source);
token = gtk_css_token_source_get_token (source);
if (gtk_css_token_is (token, GTK_CSS_TOKEN_CLOSE_PARENS))
{
gtk_css_token_source_consume_token (source);
}
else
{
gtk_css_token_source_error (source, "Invalid contents of :not() selector");
if (selector)
_gtk_css_selector_free (selector);
selector = NULL;
return NULL;
}
}
}
else if (gtk_css_token_is_function (token, "dir"))
{
gtk_css_token_source_consume_token (source);
gtk_css_token_source_consume_whitespace (source);
token = gtk_css_token_source_get_token (source);
if (gtk_css_token_is_ident (token, "ltr"))
{
selector = gtk_css_selector_new (negate ? &GTK_CSS_SELECTOR_NOT_PSEUDOCLASS_STATE
: &GTK_CSS_SELECTOR_PSEUDOCLASS_STATE,
selector);
selector->state.state = GTK_STATE_FLAG_DIR_LTR;
gtk_css_token_source_consume_token (source);
}
else if (gtk_css_token_is_ident (token, "rtl"))
{
selector = gtk_css_selector_new (negate ? &GTK_CSS_SELECTOR_NOT_PSEUDOCLASS_STATE
: &GTK_CSS_SELECTOR_PSEUDOCLASS_STATE,
selector);
selector->state.state = GTK_STATE_FLAG_DIR_LTR;
gtk_css_token_source_consume_token (source);
}
else
{
gtk_css_token_source_error (source, "Expected :dir(ltr) or :dir(rtl)");
if (selector)
_gtk_css_selector_free (selector);
selector = NULL;
return NULL;
}
gtk_css_token_source_consume_whitespace (source);
token = gtk_css_token_source_get_token (source);
if (!gtk_css_token_is (token, GTK_CSS_TOKEN_CLOSE_PARENS))
{
gtk_css_token_source_error (source, "Expected ')' at end of :dir()");
if (selector)
_gtk_css_selector_free (selector);
return NULL;
}
gtk_css_token_source_consume_token (source);
}
else if (gtk_css_token_is_function (token, "drop"))
{
gtk_css_token_source_consume_token (source);
gtk_css_token_source_consume_whitespace (source);
token = gtk_css_token_source_get_token (source);
if (gtk_css_token_is_ident (token, "active"))
{
selector = gtk_css_selector_new (negate ? &GTK_CSS_SELECTOR_NOT_PSEUDOCLASS_STATE
: &GTK_CSS_SELECTOR_PSEUDOCLASS_STATE,
selector);
selector->state.state = GTK_STATE_FLAG_DROP_ACTIVE;
gtk_css_token_source_consume_token (source);
}
else
{
gtk_css_token_source_error (source, "Expected :drop(active)");
if (selector)
_gtk_css_selector_free (selector);
selector = NULL;
return NULL;
}
gtk_css_token_source_consume_whitespace (source);
token = gtk_css_token_source_get_token (source);
if (!gtk_css_token_is (token, GTK_CSS_TOKEN_CLOSE_PARENS))
{
gtk_css_token_source_error (source, "Expected ')' at end of :drop()");
if (selector)
_gtk_css_selector_free (selector);
return NULL;
}
gtk_css_token_source_consume_token (source);
}
else
{
gtk_css_token_source_unknown (source, "Unknown pseudoclass");
if (selector)
_gtk_css_selector_free (selector);
return NULL;
}
}
else
{
gtk_css_token_source_error (source, "Unknown pseudoclass");
if (selector)
_gtk_css_selector_free (selector);
return NULL;
}
return selector;
}
GtkCssSelector *
token_parse_simple_selector (GtkCssTokenSource *source,
GtkCssSelector *selector)
{
gboolean parsed_something = FALSE;
const GtkCssToken *token;
do {
token = gtk_css_token_source_get_token (source);
if (!parsed_something && gtk_css_token_is_delim (token, '*'))
{
selector = gtk_css_selector_new (&GTK_CSS_SELECTOR_ANY, selector);
gtk_css_token_source_consume_token (source);
}
else if (!parsed_something && gtk_css_token_is (token, GTK_CSS_TOKEN_IDENT))
{
selector = gtk_css_selector_new (&GTK_CSS_SELECTOR_NAME, selector);
selector->name.name = g_intern_string (token->string.string);
gtk_css_token_source_consume_token (source);
}
else if (gtk_css_token_is (token, GTK_CSS_TOKEN_HASH_ID))
{
selector = gtk_css_selector_new (&GTK_CSS_SELECTOR_ID, selector);
selector->id.name = g_intern_string (token->string.string);
gtk_css_token_source_consume_token (source);
}
else if (gtk_css_token_is_delim (token, '.'))
{
selector = token_parse_selector_class (source, selector, FALSE);
}
else if (gtk_css_token_is (token, GTK_CSS_TOKEN_COLON))
{
selector = token_parse_selector_pseudo_class (source, selector, FALSE);
}
else
{
if (!parsed_something)
{
gtk_css_token_source_error (source, "Expected a valid selector");
if (selector)
_gtk_css_selector_free (selector);
selector = NULL;
}
break;
}
parsed_something = TRUE;
}
while (TRUE);
return selector;
}
GtkCssSelector *
gtk_css_selector_token_parse (GtkCssTokenSource *source)
{
GtkCssSelector *selector = NULL;
const GtkCssToken *token;
while (TRUE)
{
gboolean seen_whitespace = FALSE;
selector = token_parse_simple_selector (source, selector);
if (selector == NULL)
{
gtk_css_token_source_consume_all (source);
return NULL;
}
seen_whitespace = gtk_css_token_source_consume_whitespace (source);
token = gtk_css_token_source_get_token (source);
if (gtk_css_token_is_delim (token, '+'))
{
selector = gtk_css_selector_new (&GTK_CSS_SELECTOR_ADJACENT, selector);
gtk_css_token_source_consume_token (source);
}
else if (gtk_css_token_is_delim (token, '~'))
{
selector = gtk_css_selector_new (&GTK_CSS_SELECTOR_SIBLING, selector);
gtk_css_token_source_consume_token (source);
}
else if (gtk_css_token_is_delim (token, '>'))
{
selector = gtk_css_selector_new (&GTK_CSS_SELECTOR_CHILD, selector);
gtk_css_token_source_consume_token (source);
}
else if (gtk_css_token_is (token, GTK_CSS_TOKEN_EOF))
{
break;
}
else if (seen_whitespace)
{
selector = gtk_css_selector_new (&GTK_CSS_SELECTOR_DESCENDANT, selector);
}
else
{
gtk_css_token_source_error (source, "Expected a valid selector");
_gtk_css_selector_free (selector);
gtk_css_token_source_consume_all (source);
return NULL;
}
gtk_css_token_source_consume_whitespace (source);
}
return selector;
}
void
_gtk_css_selector_free (GtkCssSelector *selector)
{

View File

@@ -20,6 +20,7 @@
#include "gtk/gtkcssmatcherprivate.h"
#include "gtk/gtkcssparserprivate.h"
#include "gtk/gtkcsstokensourceprivate.h"
G_BEGIN_DECLS
@@ -28,6 +29,7 @@ typedef struct _GtkCssSelectorTree GtkCssSelectorTree;
typedef struct _GtkCssSelectorTreeBuilder GtkCssSelectorTreeBuilder;
GtkCssSelector * _gtk_css_selector_parse (GtkCssParser *parser);
GtkCssSelector * gtk_css_selector_token_parse (GtkCssTokenSource *parser);
void _gtk_css_selector_free (GtkCssSelector *selector);
char * _gtk_css_selector_to_string (const GtkCssSelector *selector);

View File

@@ -0,0 +1,66 @@
/*
* Copyright © 2016 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.1 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, see <http://www.gnu.org/licenses/>.
*
* Authors: Benjamin Otte <otte@gnome.org>
*/
#include "config.h"
#include "gtkcssstyledeclarationprivate.h"
#include "gtkcssselectorprivate.h"
#include "gtkcssstylesheetprivate.h"
typedef struct _GtkCssStyleDeclarationPrivate GtkCssStyleDeclarationPrivate;
struct _GtkCssStyleDeclarationPrivate {
GPtrArray *declarations;
};
G_DEFINE_TYPE_WITH_PRIVATE (GtkCssStyleDeclaration, gtk_css_style_declaration, G_TYPE_OBJECT)
static void
gtk_css_style_declaration_finalize (GObject *object)
{
GtkCssStyleDeclaration *style_declaration = GTK_CSS_STYLE_DECLARATION (object);
GtkCssStyleDeclarationPrivate *priv = gtk_css_style_declaration_get_instance_private (style_declaration);
g_ptr_array_unref (priv->declarations);
G_OBJECT_CLASS (gtk_css_style_declaration_parent_class)->finalize (object);
}
static void
gtk_css_style_declaration_class_init (GtkCssStyleDeclarationClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->finalize = gtk_css_style_declaration_finalize;
}
static void
gtk_css_style_declaration_init (GtkCssStyleDeclaration *style_declaration)
{
GtkCssStyleDeclarationPrivate *priv = gtk_css_style_declaration_get_instance_private (style_declaration);
priv->declarations = g_ptr_array_new_with_free_func (g_object_unref);
}
GtkCssStyleDeclaration *
gtk_css_style_declaration_new (GtkCssRule *parent_rule)
{
return g_object_new (GTK_TYPE_CSS_STYLE_DECLARATION, NULL);
}

View File

@@ -0,0 +1,61 @@
/*
* Copyright © 2016 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.1 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, see <http://www.gnu.org/licenses/>.
*
* Authors: Benjamin Otte <otte@gnome.org>
*/
#ifndef __GTK_CSS_STYLE_DECLARATION_PRIVATE_H__
#define __GTK_CSS_STYLE_DECLARATION_PRIVATE_H__
#include "gtk/gtkcssruleprivate.h"
G_BEGIN_DECLS
#define GTK_TYPE_CSS_STYLE_DECLARATION (gtk_css_style_declaration_get_type ())
#define GTK_CSS_STYLE_DECLARATION(obj) (G_TYPE_CHECK_INSTANCE_CAST (obj, GTK_TYPE_CSS_STYLE_DECLARATION, GtkCssStyleDeclaration))
#define GTK_CSS_STYLE_DECLARATION_CLASS(cls) (G_TYPE_CHECK_CLASS_CAST (cls, GTK_TYPE_CSS_STYLE_DECLARATION, GtkCssStyleDeclarationClass))
#define GTK_IS_CSS_STYLE_DECLARATION(obj) (G_TYPE_CHECK_INSTANCE_TYPE (obj, GTK_TYPE_CSS_STYLE_DECLARATION))
#define GTK_IS_CSS_STYLE_DECLARATION_CLASS(obj) (G_TYPE_CHECK_CLASS_TYPE (obj, GTK_TYPE_CSS_STYLE_DECLARATION))
#define GTK_CSS_STYLE_DECLARATION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_CSS_STYLE_DECLARATION, GtkCssStyleDeclarationClass))
typedef struct _GtkCssStyleDeclaration GtkCssStyleDeclaration;
typedef struct _GtkCssStyleDeclarationClass GtkCssStyleDeclarationClass;
struct _GtkCssStyleDeclaration
{
GObject parent;
};
struct _GtkCssStyleDeclarationClass
{
GObjectClass parent_class;
};
GType gtk_css_style_declaration_get_type (void) G_GNUC_CONST;
GtkCssStyleDeclaration *gtk_css_style_declaration_new (GtkCssRule *parent_rule);
void gtk_css_style_declaration_print_css_text (GtkCssStyleDeclaration *declaration,
GString *string);
char * gtk_css_style_declaration_get_css_text (GtkCssStyleDeclaration *declaration);
/* GtkCssStyleDeclaration DOM */
gsize gtk_css_style_declaration_get_length (GtkCssStyleDeclaration *declaration);
G_END_DECLS
#endif /* __GTK_CSS_STYLE_DECLARATION_PRIVATE_H__ */

124
gtk/gtkcssstylerule.c Normal file
View File

@@ -0,0 +1,124 @@
/*
* Copyright © 2016 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.1 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, see <http://www.gnu.org/licenses/>.
*
* Authors: Benjamin Otte <otte@gnome.org>
*/
#include "config.h"
#include "gtkcssstyleruleprivate.h"
#include "gtkcssselectorprivate.h"
#include "gtkcssstylesheetprivate.h"
typedef struct _GtkCssStyleRulePrivate GtkCssStyleRulePrivate;
struct _GtkCssStyleRulePrivate {
GPtrArray *selectors;
//GtkCssStyleDeclaration *declaration;
};
G_DEFINE_TYPE_WITH_PRIVATE (GtkCssStyleRule, gtk_css_style_rule, GTK_TYPE_CSS_RULE)
static void
gtk_css_style_rule_finalize (GObject *object)
{
GtkCssStyleRule *style_rule = GTK_CSS_STYLE_RULE (object);
GtkCssStyleRulePrivate *priv = gtk_css_style_rule_get_instance_private (style_rule);
g_ptr_array_unref (priv->selectors);
G_OBJECT_CLASS (gtk_css_style_rule_parent_class)->finalize (object);
}
static void
gtk_css_style_rule_class_init (GtkCssStyleRuleClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->finalize = gtk_css_style_rule_finalize;
}
static void
gtk_css_style_rule_init (GtkCssStyleRule *style_rule)
{
GtkCssStyleRulePrivate *priv = gtk_css_style_rule_get_instance_private (style_rule);
priv->selectors = g_ptr_array_new_with_free_func ((GDestroyNotify) _gtk_css_selector_free);
}
static GtkCssRule *
gtk_css_style_rule_new (GtkCssRule *parent_rule,
GtkCssStyleSheet *parent_style_sheet)
{
return g_object_new (GTK_TYPE_CSS_STYLE_RULE, NULL);
}
static GtkCssStyleRule *
gtk_css_style_rule_parse_selectors (GtkCssStyleRule *rule,
GtkCssTokenSource *source)
{
GtkCssStyleRulePrivate *priv = gtk_css_style_rule_get_instance_private (rule);
GtkCssTokenSource *child_source;
GtkCssSelector *selector;
const GtkCssToken *token;
for (token = gtk_css_token_source_get_token (source);
!gtk_css_token_is (token, GTK_CSS_TOKEN_EOF);
token = gtk_css_token_source_get_token (source))
{
gtk_css_token_source_consume_whitespace (source);
child_source = gtk_css_token_source_new_for_part (source, GTK_CSS_TOKEN_COMMA);
selector = gtk_css_selector_token_parse (child_source);
gtk_css_token_source_unref (child_source);
if (selector == NULL)
{
g_object_unref (rule);
return NULL;
}
g_ptr_array_add (priv->selectors, selector);
gtk_css_token_source_consume_token (source);
}
return rule;
}
GtkCssRule *
gtk_css_style_rule_new_parse (GtkCssTokenSource *source,
GtkCssRule *parent_rule,
GtkCssStyleSheet *parent_style_sheet)
{
GtkCssTokenSource *child_source;
GtkCssStyleRule *rule;
g_return_val_if_fail (source != NULL, NULL);
g_return_val_if_fail (parent_rule == NULL || GTK_IS_CSS_RULE (parent_rule), NULL);
g_return_val_if_fail (GTK_IS_CSS_STYLE_SHEET (parent_style_sheet), NULL);
rule = GTK_CSS_STYLE_RULE (gtk_css_style_rule_new (parent_rule, parent_style_sheet));
child_source = gtk_css_token_source_new_for_part (source, GTK_CSS_TOKEN_OPEN_CURLY);
rule = gtk_css_style_rule_parse_selectors (rule, child_source);
gtk_css_token_source_unref (child_source);
gtk_css_token_source_consume_token (source);
child_source = gtk_css_token_source_new_for_part (source, GTK_CSS_TOKEN_CLOSE_CURLY);
gtk_css_token_source_consume_all (child_source);
gtk_css_token_source_unref (child_source);
gtk_css_token_source_consume_token (source);
return GTK_CSS_RULE (rule);
}

View File

@@ -0,0 +1,56 @@
/*
* Copyright © 2016 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.1 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, see <http://www.gnu.org/licenses/>.
*
* Authors: Benjamin Otte <otte@gnome.org>
*/
#ifndef __GTK_CSS_STYLE_RULE_PRIVATE_H__
#define __GTK_CSS_STYLE_RULE_PRIVATE_H__
#include "gtk/gtkcssruleprivate.h"
G_BEGIN_DECLS
#define GTK_TYPE_CSS_STYLE_RULE (gtk_css_style_rule_get_type ())
#define GTK_CSS_STYLE_RULE(obj) (G_TYPE_CHECK_INSTANCE_CAST (obj, GTK_TYPE_CSS_STYLE_RULE, GtkCssStyleRule))
#define GTK_CSS_STYLE_RULE_CLASS(cls) (G_TYPE_CHECK_CLASS_CAST (cls, GTK_TYPE_CSS_STYLE_RULE, GtkCssStyleRuleClass))
#define GTK_IS_CSS_STYLE_RULE(obj) (G_TYPE_CHECK_INSTANCE_TYPE (obj, GTK_TYPE_CSS_STYLE_RULE))
#define GTK_IS_CSS_STYLE_RULE_CLASS(obj) (G_TYPE_CHECK_CLASS_TYPE (obj, GTK_TYPE_CSS_STYLE_RULE))
#define GTK_CSS_STYLE_RULE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_CSS_STYLE_RULE, GtkCssStyleRuleClass))
typedef struct _GtkCssStyleRule GtkCssStyleRule;
typedef struct _GtkCssStyleRuleClass GtkCssStyleRuleClass;
struct _GtkCssStyleRule
{
GtkCssRule parent;
};
struct _GtkCssStyleRuleClass
{
GtkCssRuleClass parent_class;
};
GType gtk_css_style_rule_get_type (void) G_GNUC_CONST;
GtkCssRule * gtk_css_style_rule_new_parse (GtkCssTokenSource *source,
GtkCssRule *parent_rule,
GtkCssStyleSheet *parent_style_sheet);
G_END_DECLS
#endif /* __GTK_CSS_STYLE_RULE_PRIVATE_H__ */

114
gtk/gtkcssstylesheet.c Normal file
View File

@@ -0,0 +1,114 @@
/*
* Copyright © 2016 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.1 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, see <http://www.gnu.org/licenses/>.
*
* Authors: Benjamin Otte <otte@gnome.org>
*/
#include "config.h"
#include "gtkcssstylesheetprivate.h"
typedef struct _GtkCssStyleSheetPrivate GtkCssStyleSheetPrivate;
struct _GtkCssStyleSheetPrivate {
GtkCssRule *parent_rule;
GtkCssRuleList *css_rules;
};
G_DEFINE_TYPE_WITH_PRIVATE (GtkCssStyleSheet, gtk_css_style_sheet, G_TYPE_OBJECT)
static void
gtk_css_style_sheet_finalize (GObject *object)
{
GtkCssStyleSheet *style_sheet = GTK_CSS_STYLE_SHEET (object);
GtkCssStyleSheetPrivate *priv = gtk_css_style_sheet_get_instance_private (style_sheet);
g_object_unref (priv->css_rules);
G_OBJECT_CLASS (gtk_css_style_sheet_parent_class)->finalize (object);
}
static void
gtk_css_style_sheet_class_init (GtkCssStyleSheetClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->finalize = gtk_css_style_sheet_finalize;
}
static void
gtk_css_style_sheet_init (GtkCssStyleSheet *style_sheet)
{
GtkCssStyleSheetPrivate *priv = gtk_css_style_sheet_get_instance_private (style_sheet);
priv->css_rules = gtk_css_rule_list_new ();
}
GtkCssStyleSheet *
gtk_css_style_sheet_new (void)
{
return g_object_new (GTK_TYPE_CSS_STYLE_SHEET, NULL);
}
void
gtk_css_style_sheet_parse (GtkCssStyleSheet *style_sheet,
GtkCssTokenSource *source)
{
GtkCssStyleSheetPrivate *priv;
g_return_if_fail (GTK_IS_CSS_STYLE_SHEET (style_sheet));
g_return_if_fail (source != NULL);
priv = gtk_css_style_sheet_get_instance_private (style_sheet);
gtk_css_rule_list_parse (priv->css_rules, source, NULL, style_sheet);
}
GtkCssStyleSheet *
gtk_css_style_sheet_get_parent_style_sheet (GtkCssStyleSheet *style_sheet)
{
GtkCssStyleSheetPrivate *priv;
g_return_val_if_fail (GTK_IS_CSS_STYLE_SHEET (style_sheet), NULL);
priv = gtk_css_style_sheet_get_instance_private (style_sheet);
return gtk_css_rule_get_parent_style_sheet (priv->parent_rule);
}
GtkCssRule *
gtk_css_style_sheet_get_parent_rule (GtkCssStyleSheet *style_sheet)
{
GtkCssStyleSheetPrivate *priv;
g_return_val_if_fail (GTK_IS_CSS_STYLE_SHEET (style_sheet), NULL);
priv = gtk_css_style_sheet_get_instance_private (style_sheet);
return priv->parent_rule;
}
GtkCssRuleList *
gtk_css_style_sheet_get_css_rules (GtkCssStyleSheet *style_sheet)
{
GtkCssStyleSheetPrivate *priv;
g_return_val_if_fail (GTK_IS_CSS_STYLE_SHEET (style_sheet), NULL);
priv = gtk_css_style_sheet_get_instance_private (style_sheet);
return priv->css_rules;
}

View File

@@ -0,0 +1,67 @@
/*
* Copyright © 2016 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.1 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, see <http://www.gnu.org/licenses/>.
*
* Authors: Benjamin Otte <otte@gnome.org>
*/
#ifndef __GTK_CSS_STYLE_SHEET_PRIVATE_H__
#define __GTK_CSS_STYLE_SHEET_PRIVATE_H__
#include "gtk/gtkcssruleprivate.h"
#include "gtk/gtkcssrulelistprivate.h"
#include "gtk/gtkcsstokensourceprivate.h"
G_BEGIN_DECLS
#define GTK_TYPE_CSS_STYLE_SHEET (gtk_css_style_sheet_get_type ())
#define GTK_CSS_STYLE_SHEET(obj) (G_TYPE_CHECK_INSTANCE_CAST (obj, GTK_TYPE_CSS_STYLE_SHEET, GtkCssStyleSheet))
#define GTK_CSS_STYLE_SHEET_CLASS(cls) (G_TYPE_CHECK_CLASS_CAST (cls, GTK_TYPE_CSS_STYLE_SHEET, GtkCssStyleSheetClass))
#define GTK_IS_CSS_STYLE_SHEET(obj) (G_TYPE_CHECK_INSTANCE_TYPE (obj, GTK_TYPE_CSS_STYLE_SHEET))
#define GTK_IS_CSS_STYLE_SHEET_CLASS(obj) (G_TYPE_CHECK_CLASS_TYPE (obj, GTK_TYPE_CSS_STYLE_SHEET))
#define GTK_CSS_STYLE_SHEET_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_CSS_STYLE_SHEET, GtkCssStyleSheetClass))
/* declared with GtkCssRule */
/* typedef struct _GtkCssStyleSheet GtkCssStyleSheet; */
typedef struct _GtkCssStyleSheetClass GtkCssStyleSheetClass;
struct _GtkCssStyleSheet
{
GObject parent;
};
struct _GtkCssStyleSheetClass
{
GObjectClass parent_class;
};
GType gtk_css_style_sheet_get_type (void) G_GNUC_CONST;
GtkCssStyleSheet * gtk_css_style_sheet_new (void);
void gtk_css_style_sheet_parse (GtkCssStyleSheet *style_sheet,
GtkCssTokenSource *source);
/* StyleSheet interface */
GtkCssStyleSheet * gtk_css_style_sheet_get_parent_style_sheet (GtkCssStyleSheet *style_sheet);
/* CSSStyleSheet interface */
GtkCssRule * gtk_css_style_sheet_get_parent_rule (GtkCssStyleSheet *style_sheet);
GtkCssRuleList * gtk_css_style_sheet_get_css_rules (GtkCssStyleSheet *style_sheet);
G_END_DECLS
#endif /* __GTK_CSS_STYLE_SHEET_PRIVATE_H__ */

369
gtk/gtkcsstokensource.c Normal file
View File

@@ -0,0 +1,369 @@
/*
* Copyright © 2016 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.1 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, see <http://www.gnu.org/licenses/>.
*
* Authors: Benjamin Otte <otte@gnome.org>
*/
#include "config.h"
#include "gtkcsstokensourceprivate.h"
#include "gtkcssprovider.h"
typedef struct _GtkCssTokenSourceTokenizer GtkCssTokenSourceTokenizer;
struct _GtkCssTokenSourceTokenizer {
GtkCssTokenSource parent;
GtkCssTokenizer *tokenizer;
GtkCssToken current_token;
};
static void
gtk_css_token_source_tokenizer_finalize (GtkCssTokenSource *source)
{
GtkCssTokenSourceTokenizer *tok = (GtkCssTokenSourceTokenizer *) source;
gtk_css_token_clear (&tok->current_token);
gtk_css_tokenizer_unref (tok->tokenizer);
}
static void
gtk_css_token_source_tokenizer_consume_token (GtkCssTokenSource *source)
{
GtkCssTokenSourceTokenizer *tok = (GtkCssTokenSourceTokenizer *) source;
gtk_css_token_clear (&tok->current_token);
}
static const GtkCssToken *
gtk_css_token_source_tokenizer_get_token (GtkCssTokenSource *source)
{
GtkCssTokenSourceTokenizer *tok = (GtkCssTokenSourceTokenizer *) source;
if (gtk_css_token_is (&tok->current_token, GTK_CSS_TOKEN_EOF))
{
do {
gtk_css_tokenizer_read_token (tok->tokenizer, &tok->current_token);
} while (gtk_css_token_is (&tok->current_token, GTK_CSS_TOKEN_COMMENT));
#if 0
if (!gtk_css_token_is (&tok->current_token, GTK_CSS_TOKEN_EOF)) {
char *s = gtk_css_token_to_string (&tok->current_token);
g_print ("%3zu:%02zu %2d %s\n",
gtk_css_tokenizer_get_line (tok->tokenizer), gtk_css_tokenizer_get_line_char (tok->tokenizer),
tok->current_token.type, s);
g_free (s);
}
#endif
}
return &tok->current_token;
}
static void
gtk_css_token_source_tokenizer_error (GtkCssTokenSource *source,
const GError *error)
{
GtkCssTokenSourceTokenizer *tok = (GtkCssTokenSourceTokenizer *) source;
/* XXX */
g_print ("ERROR: %zu:%zu: %s\n",
gtk_css_tokenizer_get_line (tok->tokenizer),
gtk_css_tokenizer_get_line_char (tok->tokenizer),
error->message);
}
const GtkCssTokenSourceClass GTK_CSS_TOKEN_SOURCE_TOKENIZER = {
gtk_css_token_source_tokenizer_finalize,
gtk_css_token_source_tokenizer_consume_token,
gtk_css_token_source_tokenizer_get_token,
gtk_css_token_source_tokenizer_error,
};
GtkCssTokenSource *
gtk_css_token_source_new_for_tokenizer (GtkCssTokenizer *tokenizer)
{
GtkCssTokenSourceTokenizer *source;
g_return_val_if_fail (tokenizer != NULL, NULL);
source = gtk_css_token_source_new (GtkCssTokenSourceTokenizer, &GTK_CSS_TOKEN_SOURCE_TOKENIZER);
source->tokenizer = gtk_css_tokenizer_ref (tokenizer);
return &source->parent;
}
typedef struct _GtkCssTokenSourcePart GtkCssTokenSourcePart;
struct _GtkCssTokenSourcePart {
GtkCssTokenSource parent;
GtkCssTokenSource *source;
GtkCssTokenType end_type;
};
static void
gtk_css_token_source_part_finalize (GtkCssTokenSource *source)
{
GtkCssTokenSourcePart *part = (GtkCssTokenSourcePart *) source;
gtk_css_token_source_unref (part->source);
}
static void
gtk_css_token_source_part_consume_token (GtkCssTokenSource *source)
{
GtkCssTokenSourcePart *part = (GtkCssTokenSourcePart *) source;
const GtkCssToken *token;
if (!gtk_css_token_get_pending_block (source))
{
token = gtk_css_token_source_get_token (part->source);
if (gtk_css_token_is (token, part->end_type))
return;
}
gtk_css_token_source_consume_token (part->source);
}
static const GtkCssToken *
gtk_css_token_source_part_get_token (GtkCssTokenSource *source)
{
GtkCssTokenSourcePart *part = (GtkCssTokenSourcePart *) source;
static const GtkCssToken eof_token = { GTK_CSS_TOKEN_EOF };
const GtkCssToken *token;
token = gtk_css_token_source_get_token (part->source);
if (!gtk_css_token_get_pending_block (source) &&
gtk_css_token_is (token, part->end_type))
return &eof_token;
return token;
}
static void
gtk_css_token_source_part_error (GtkCssTokenSource *source,
const GError *error)
{
GtkCssTokenSourcePart *part = (GtkCssTokenSourcePart *) source;
gtk_css_token_source_emit_error (part->source, error);
}
const GtkCssTokenSourceClass GTK_CSS_TOKEN_SOURCE_PART = {
gtk_css_token_source_part_finalize,
gtk_css_token_source_part_consume_token,
gtk_css_token_source_part_get_token,
gtk_css_token_source_part_error,
};
GtkCssTokenSource *
gtk_css_token_source_new_for_part (GtkCssTokenSource *source,
GtkCssTokenType end_type)
{
GtkCssTokenSourcePart *part;
g_return_val_if_fail (source != NULL, NULL);
g_return_val_if_fail (end_type != GTK_CSS_TOKEN_EOF, NULL);
part = gtk_css_token_source_new (GtkCssTokenSourcePart, &GTK_CSS_TOKEN_SOURCE_PART);
part->source = gtk_css_token_source_ref (source);
part->end_type = end_type;
return &part->parent;
}
GtkCssTokenSource *
gtk_css_token_source_alloc (gsize struct_size,
const GtkCssTokenSourceClass *klass)
{
GtkCssTokenSource *source;
source = g_malloc0 (struct_size);
source->klass = klass;
source->ref_count = 1;
return source;
}
GtkCssTokenSource *
gtk_css_token_source_ref (GtkCssTokenSource *source)
{
source->ref_count++;
return source;
}
void
gtk_css_token_source_unref (GtkCssTokenSource *source)
{
source->ref_count--;
if (source->ref_count > 0)
return;
source->klass->finalize (source);
g_free (source);
}
void
gtk_css_token_source_consume_token (GtkCssTokenSource *source)
{
gtk_css_token_source_consume_token_as (source, source->consumer);
}
void
gtk_css_token_source_consume_token_as (GtkCssTokenSource *source,
GObject *consumer)
{
const GtkCssToken *token;
if (source->blocks)
{
token = gtk_css_token_source_get_token (source);
if (gtk_css_token_is (token, GPOINTER_TO_UINT (source->blocks->data)))
source->blocks = g_slist_remove (source->blocks, source->blocks->data);
}
source->klass->consume_token (source);
token = gtk_css_token_source_get_token (source);
switch (token->type)
{
case GTK_CSS_TOKEN_FUNCTION:
case GTK_CSS_TOKEN_OPEN_PARENS:
source->blocks = g_slist_prepend (source->blocks, GUINT_TO_POINTER (GTK_CSS_TOKEN_CLOSE_PARENS));
break;
case GTK_CSS_TOKEN_OPEN_SQUARE:
source->blocks = g_slist_prepend (source->blocks, GUINT_TO_POINTER (GTK_CSS_TOKEN_CLOSE_SQUARE));
break;
case GTK_CSS_TOKEN_OPEN_CURLY:
source->blocks = g_slist_prepend (source->blocks, GUINT_TO_POINTER (GTK_CSS_TOKEN_CLOSE_CURLY));
break;
default:
break;
}
source->klass->consume_token (source, consumer);
if (source->blocks)
{
if (token_type == GPOINTER_TO_UINT (source->blocks->data))
source->blocks = g_slist_remove (source->blocks, source->blocks->data);
}
}
const GtkCssToken *
gtk_css_token_source_get_token (GtkCssTokenSource *source)
{
return source->klass->get_token (source);
}
void
gtk_css_token_source_consume_all (GtkCssTokenSource *source)
{
const GtkCssToken *token;
for (token = gtk_css_token_source_get_token (source);
!gtk_css_token_is (token, GTK_CSS_TOKEN_EOF);
token = gtk_css_token_source_get_token (source))
{
gtk_css_token_source_consume_token (source);
}
}
gboolean
gtk_css_token_source_consume_whitespace (GtkCssTokenSource *source)
{
const GtkCssToken *token;
gboolean seen_whitespace = FALSE;
for (token = gtk_css_token_source_get_token (source);
gtk_css_token_is (token, GTK_CSS_TOKEN_WHITESPACE);
token = gtk_css_token_source_get_token (source))
{
seen_whitespace = TRUE;
gtk_css_token_source_consume_token (source);
}
return seen_whitespace;
}
GtkCssTokenType
gtk_css_token_get_pending_block (GtkCssTokenSource *source)
{
if (!source->blocks)
return GTK_CSS_TOKEN_EOF;
return GPOINTER_TO_UINT(source->blocks->data);
}
void
gtk_css_token_source_emit_error (GtkCssTokenSource *source,
const GError *error)
{
source->klass->error (source, error);
}
void
gtk_css_token_source_error (GtkCssTokenSource *source,
const char *format,
...)
{
va_list args;
GError *error;
va_start (args, format);
error = g_error_new_valist (GTK_CSS_PROVIDER_ERROR,
GTK_CSS_PROVIDER_ERROR_SYNTAX,
format, args);
gtk_css_token_source_emit_error (source, error);
g_error_free (error);
va_end (args);
}
void
gtk_css_token_source_unknown (GtkCssTokenSource *source,
const char *format,
...)
{
va_list args;
GError *error;
va_start (args, format);
error = g_error_new_valist (GTK_CSS_PROVIDER_ERROR,
GTK_CSS_PROVIDER_ERROR_UNKNOWN_VALUE,
format, args);
gtk_css_token_source_emit_error (source, error);
g_error_free (error);
va_end (args);
}
void
gtk_css_token_source_deprecated (GtkCssTokenSource *source,
const char *format,
...)
{
va_list args;
GError *error;
va_start (args, format);
error = g_error_new_valist (GTK_CSS_PROVIDER_ERROR,
GTK_CSS_PROVIDER_ERROR_DEPRECATED,
format, args);
gtk_css_token_source_emit_error (source, error);
g_error_free (error);
va_end (args);
}

View File

@@ -0,0 +1,81 @@
/*
* Copyright © 2016 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.1 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, see <http://www.gnu.org/licenses/>.
*
* Authors: Benjamin Otte <otte@gnome.org>
*/
#ifndef __GTK_CSS_TOKEN_SOURCE_PRIVATE_H__
#define __GTK_CSS_TOKEN_SOURCE_PRIVATE_H__
#include <glib-object.h>
#include "gtk/gtkcsstokenizerprivate.h"
G_BEGIN_DECLS
typedef struct _GtkCssTokenSource GtkCssTokenSource;
typedef struct _GtkCssTokenSourceClass GtkCssTokenSourceClass;
struct _GtkCssTokenSource
{
const GtkCssTokenSourceClass *klass;
gint ref_count;
GSList *blocks; /* of GPOINTER_TO_UINT(GtkCssTokenType) */
};
struct _GtkCssTokenSourceClass
{
void (* finalize) (GtkCssTokenSource *source);
void (* consume_token) (GtkCssTokenSource *source);
const GtkCssToken * (* get_token) (GtkCssTokenSource *source);
void (* error) (GtkCssTokenSource *source,
const GError *error);
};
GtkCssTokenSource * gtk_css_token_source_new_for_tokenizer (GtkCssTokenizer *tokenizer);
GtkCssTokenSource * gtk_css_token_source_new_for_part (GtkCssTokenSource *source,
GtkCssTokenType end_type);
GtkCssTokenSource * gtk_css_token_source_ref (GtkCssTokenSource *source);
void gtk_css_token_source_unref (GtkCssTokenSource *source);
#define gtk_css_token_source_new(type,klass) ((type *) gtk_css_token_source_alloc (sizeof (type), (klass)))
GtkCssTokenSource * gtk_css_token_source_alloc (gsize struct_size,
const GtkCssTokenSourceClass *klass);
void gtk_css_token_source_consume_token (GtkCssTokenSource *source);
const GtkCssToken * gtk_css_token_source_get_token (GtkCssTokenSource *source);
GtkCssTokenType gtk_css_token_get_pending_block (GtkCssTokenSource *source);
void gtk_css_token_source_consume_all (GtkCssTokenSource *source);
gboolean gtk_css_token_source_consume_whitespace (GtkCssTokenSource *source);
void gtk_css_token_source_emit_error (GtkCssTokenSource *source,
const GError *error);
void gtk_css_token_source_error (GtkCssTokenSource *source,
const char *format,
...) G_GNUC_PRINTF(2, 3);
void gtk_css_token_source_unknown (GtkCssTokenSource *source,
const char *format,
...) G_GNUC_PRINTF(2, 3);
void gtk_css_token_source_deprecated (GtkCssTokenSource *source,
const char *format,
...) G_GNUC_PRINTF(2, 3);
G_END_DECLS
#endif /* __GTK_CSS_TOKEN_SOURCE_PRIVATE_H__ */