[gtk+] css: Move selector parsing code into a custom function
- From: Benjamin Otte <otte src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk+] css: Move selector parsing code into a custom function
- Date: Fri, 2 Mar 2012 01:24:48 +0000 (UTC)
commit 67d0b8195d3659e1080b52457826c105b8200939
Author: Benjamin Otte <otte redhat com>
Date: Wed Feb 15 15:42:00 2012 +0100
css: Move selector parsing code into a custom function
gtk/gtkcssprovider.c | 279 +------------------------------------------
gtk/gtkcssselector.c | 269 ++++++++++++++++++++++++++++++++++++++++--
gtk/gtkcssselectorprivate.h | 14 +--
3 files changed, 264 insertions(+), 298 deletions(-)
---
diff --git a/gtk/gtkcssprovider.c b/gtk/gtkcssprovider.c
index 4811c01..2da4073 100644
--- a/gtk/gtkcssprovider.c
+++ b/gtk/gtkcssprovider.c
@@ -2075,283 +2075,6 @@ parse_at_keyword (GtkCssScanner *scanner)
}
}
-static gboolean
-parse_selector_class (GtkCssScanner *scanner, GArray *classes)
-{
- GQuark qname;
- char *name;
-
- name = _gtk_css_parser_try_name (scanner->parser, FALSE);
-
- if (name == NULL)
- {
- gtk_css_provider_error_literal (scanner->provider,
- scanner,
- GTK_CSS_PROVIDER_ERROR,
- GTK_CSS_PROVIDER_ERROR_SYNTAX,
- "Expected a valid name for class");
- return FALSE;
- }
-
- qname = g_quark_from_string (name);
- g_array_append_val (classes, qname);
- g_free (name);
- return TRUE;
-}
-
-static gboolean
-parse_selector_name (GtkCssScanner *scanner, GArray *names)
-{
- GQuark qname;
- char *name;
-
- name = _gtk_css_parser_try_name (scanner->parser, FALSE);
-
- if (name == NULL)
- {
- gtk_css_provider_error_literal (scanner->provider,
- scanner,
- GTK_CSS_PROVIDER_ERROR,
- GTK_CSS_PROVIDER_ERROR_SYNTAX,
- "Expected a valid name for id");
- return FALSE;
- }
-
- qname = g_quark_from_string (name);
- g_array_append_val (names, qname);
- g_free (name);
- return TRUE;
-}
-
-static gboolean
-parse_selector_pseudo_class (GtkCssScanner *scanner,
- GtkRegionFlags *region_to_modify,
- GtkStateFlags *state_to_modify)
-{
- struct {
- const char *name;
- GtkRegionFlags region_flag;
- GtkStateFlags state_flag;
- } pseudo_classes[] = {
- { "first-child", GTK_REGION_FIRST, 0 },
- { "last-child", GTK_REGION_LAST, 0 },
- { "only-child", GTK_REGION_ONLY, 0 },
- { "sorted", GTK_REGION_SORTED, 0 },
- { "active", 0, GTK_STATE_FLAG_ACTIVE },
- { "prelight", 0, GTK_STATE_FLAG_PRELIGHT },
- { "hover", 0, GTK_STATE_FLAG_PRELIGHT },
- { "selected", 0, GTK_STATE_FLAG_SELECTED },
- { "insensitive", 0, GTK_STATE_FLAG_INSENSITIVE },
- { "inconsistent", 0, GTK_STATE_FLAG_INCONSISTENT },
- { "focused", 0, GTK_STATE_FLAG_FOCUSED },
- { "focus", 0, GTK_STATE_FLAG_FOCUSED },
- { "backdrop", 0, GTK_STATE_FLAG_BACKDROP },
- { NULL, }
- }, nth_child_classes[] = {
- { "first", GTK_REGION_FIRST, 0 },
- { "last", GTK_REGION_LAST, 0 },
- { "even", GTK_REGION_EVEN, 0 },
- { "odd", GTK_REGION_ODD, 0 },
- { NULL, }
- }, *classes;
- guint i;
- char *name;
-
- name = _gtk_css_parser_try_ident (scanner->parser, FALSE);
- if (name == NULL)
- {
- gtk_css_provider_error_literal (scanner->provider,
- scanner,
- GTK_CSS_PROVIDER_ERROR,
- GTK_CSS_PROVIDER_ERROR_SYNTAX,
- "Missing name of pseudo-class");
- return FALSE;
- }
-
- if (_gtk_css_parser_try (scanner->parser, "(", TRUE))
- {
- char *function = name;
-
- name = _gtk_css_parser_try_ident (scanner->parser, TRUE);
- if (!_gtk_css_parser_try (scanner->parser, ")", FALSE))
- {
- gtk_css_provider_error_literal (scanner->provider,
- scanner,
- GTK_CSS_PROVIDER_ERROR,
- GTK_CSS_PROVIDER_ERROR_SYNTAX,
- "Missing closing bracket for pseudo-class");
- return FALSE;
- }
-
- if (g_ascii_strcasecmp (function, "nth-child") != 0)
- {
- gtk_css_provider_error (scanner->provider,
- scanner,
- GTK_CSS_PROVIDER_ERROR,
- GTK_CSS_PROVIDER_ERROR_UNKNOWN_VALUE,
- "Unknown pseudo-class '%s(%s)'", function, name ? name : "");
- g_free (function);
- g_free (name);
- return FALSE;
- }
-
- g_free (function);
-
- if (name == NULL)
- {
- gtk_css_provider_error (scanner->provider,
- scanner,
- GTK_CSS_PROVIDER_ERROR,
- GTK_CSS_PROVIDER_ERROR_UNKNOWN_VALUE,
- "nth-child() requires an argument");
- return FALSE;
- }
-
- classes = nth_child_classes;
- }
- else
- classes = pseudo_classes;
-
- for (i = 0; classes[i].name != NULL; i++)
- {
- if (g_ascii_strcasecmp (name, classes[i].name) == 0)
- {
- if ((*region_to_modify & classes[i].region_flag) ||
- (*state_to_modify & classes[i].state_flag))
- {
- if (classes == nth_child_classes)
- gtk_css_provider_error (scanner->provider,
- scanner,
- GTK_CSS_PROVIDER_ERROR,
- GTK_CSS_PROVIDER_ERROR_SYNTAX,
- "Duplicate pseudo-class 'nth-child(%s)'", name);
- else
- gtk_css_provider_error (scanner->provider,
- scanner,
- GTK_CSS_PROVIDER_ERROR,
- GTK_CSS_PROVIDER_ERROR_SYNTAX,
- "Duplicate pseudo-class '%s'", name);
- }
- *region_to_modify |= classes[i].region_flag;
- *state_to_modify |= classes[i].state_flag;
-
- g_free (name);
- return TRUE;
- }
- }
-
- if (classes == nth_child_classes)
- gtk_css_provider_error (scanner->provider,
- scanner,
- GTK_CSS_PROVIDER_ERROR,
- GTK_CSS_PROVIDER_ERROR_UNKNOWN_VALUE,
- "Unknown pseudo-class 'nth-child(%s)'", name);
- else
- gtk_css_provider_error (scanner->provider,
- scanner,
- GTK_CSS_PROVIDER_ERROR,
- GTK_CSS_PROVIDER_ERROR_UNKNOWN_VALUE,
- "Unknown pseudo-class '%s'", name);
- g_free (name);
- return FALSE;
-}
-
-static gboolean
-parse_simple_selector (GtkCssScanner *scanner,
- char **name,
- GArray *ids,
- GArray *classes,
- GtkRegionFlags *pseudo_classes,
- GtkStateFlags *state)
-{
- gboolean parsed_something;
-
- *name = _gtk_css_parser_try_ident (scanner->parser, FALSE);
- if (*name)
- parsed_something = TRUE;
- else
- parsed_something = _gtk_css_parser_try (scanner->parser, "*", FALSE);
-
- do {
- if (_gtk_css_parser_try (scanner->parser, "#", FALSE))
- {
- if (!parse_selector_name (scanner, ids))
- return FALSE;
- }
- else if (_gtk_css_parser_try (scanner->parser, ".", FALSE))
- {
- if (!parse_selector_class (scanner, classes))
- return FALSE;
- }
- else if (_gtk_css_parser_try (scanner->parser, ":", FALSE))
- {
- if (!parse_selector_pseudo_class (scanner, pseudo_classes, state))
- return FALSE;
- }
- else if (!parsed_something)
- {
- gtk_css_provider_error_literal (scanner->provider,
- scanner,
- GTK_CSS_PROVIDER_ERROR,
- GTK_CSS_PROVIDER_ERROR_SYNTAX,
- "Expected a valid selector");
- return FALSE;
- }
- else
- break;
-
- parsed_something = TRUE;
- }
- while (!_gtk_css_parser_is_eof (scanner->parser));
-
- _gtk_css_parser_skip_whitespace (scanner->parser);
- return TRUE;
-}
-
-static GtkCssSelector *
-parse_selector (GtkCssScanner *scanner)
-{
- GtkCssSelector *selector = NULL;
-
- do {
- char *name = NULL;
- GArray *ids = g_array_new (TRUE, FALSE, sizeof (GQuark));
- GArray *classes = g_array_new (TRUE, FALSE, sizeof (GQuark));
- GtkRegionFlags pseudo_classes = 0;
- GtkStateFlags state = 0;
- GtkCssCombinator combine = GTK_CSS_COMBINE_DESCANDANT;
-
- if (selector)
- {
- if (_gtk_css_parser_try (scanner->parser, ">", TRUE))
- combine = GTK_CSS_COMBINE_CHILD;
- }
-
- if (!parse_simple_selector (scanner, &name, ids, classes, &pseudo_classes, &state))
- {
- g_array_free (ids, TRUE);
- g_array_free (classes, TRUE);
- if (selector)
- _gtk_css_selector_free (selector);
- return NULL;
- }
-
- selector = _gtk_css_selector_new (selector,
- combine,
- name,
- (GQuark *) g_array_free (ids, ids->len == 0),
- (GQuark *) g_array_free (classes, classes->len == 0),
- pseudo_classes,
- state);
- g_free (name);
- }
- while (!_gtk_css_parser_is_eof (scanner->parser) &&
- !_gtk_css_parser_begins_with (scanner->parser, ',') &&
- !_gtk_css_parser_begins_with (scanner->parser, '{'));
-
- return selector;
-}
-
static GSList *
parse_selector_list (GtkCssScanner *scanner)
{
@@ -2360,7 +2083,7 @@ parse_selector_list (GtkCssScanner *scanner)
gtk_css_scanner_push_section (scanner, GTK_CSS_SECTION_SELECTOR);
do {
- GtkCssSelector *select = parse_selector (scanner);
+ GtkCssSelector *select = _gtk_css_selector_parse (scanner->parser);
if (select == NULL)
{
diff --git a/gtk/gtkcssselector.c b/gtk/gtkcssselector.c
index d67880f..71247c0 100644
--- a/gtk/gtkcssselector.c
+++ b/gtk/gtkcssselector.c
@@ -19,8 +19,14 @@
#include "gtkcssselectorprivate.h"
+#include "gtkcssprovider.h"
#include "gtkstylecontextprivate.h"
+typedef enum {
+ GTK_CSS_COMBINE_DESCANDANT,
+ GTK_CSS_COMBINE_CHILD
+} GtkCssCombinator;
+
struct _GtkCssSelector
{
GtkCssSelector * previous; /* link to next element in selector or NULL if last */
@@ -33,14 +39,14 @@ struct _GtkCssSelector
GtkStateFlags state; /* required state flags (currently not checked when matching) */
};
-GtkCssSelector *
-_gtk_css_selector_new (GtkCssSelector *previous,
- GtkCssCombinator combine,
- const char * name,
- GQuark * ids,
- GQuark * classes,
- GtkRegionFlags pseudo_classes,
- GtkStateFlags state)
+static GtkCssSelector *
+gtk_css_selector_new (GtkCssSelector *previous,
+ GtkCssCombinator combine,
+ const char * name,
+ GQuark * ids,
+ GQuark * classes,
+ GtkRegionFlags pseudo_classes,
+ GtkStateFlags state)
{
GtkCssSelector *selector;
@@ -57,6 +63,253 @@ _gtk_css_selector_new (GtkCssSelector *previous,
return selector;
}
+static gboolean
+parse_selector_class (GtkCssParser *parser, GArray *classes)
+{
+ GQuark qname;
+ char *name;
+
+ name = _gtk_css_parser_try_name (parser, FALSE);
+
+ if (name == NULL)
+ {
+ _gtk_css_parser_error (parser, "Expected a valid name for class");
+ return FALSE;
+ }
+
+ qname = g_quark_from_string (name);
+ g_array_append_val (classes, qname);
+ g_free (name);
+ return TRUE;
+}
+
+static gboolean
+parse_selector_name (GtkCssParser *parser, GArray *names)
+{
+ GQuark qname;
+ char *name;
+
+ name = _gtk_css_parser_try_name (parser, FALSE);
+
+ if (name == NULL)
+ {
+ _gtk_css_parser_error (parser, "Expected a valid name for id");
+ return FALSE;
+ }
+
+ qname = g_quark_from_string (name);
+ g_array_append_val (names, qname);
+ g_free (name);
+ return TRUE;
+}
+
+static gboolean
+parse_selector_pseudo_class (GtkCssParser *parser,
+ GtkRegionFlags *region_to_modify,
+ GtkStateFlags *state_to_modify)
+{
+ struct {
+ const char *name;
+ GtkRegionFlags region_flag;
+ GtkStateFlags state_flag;
+ } pseudo_classes[] = {
+ { "first-child", GTK_REGION_FIRST, 0 },
+ { "last-child", GTK_REGION_LAST, 0 },
+ { "only-child", GTK_REGION_ONLY, 0 },
+ { "sorted", GTK_REGION_SORTED, 0 },
+ { "active", 0, GTK_STATE_FLAG_ACTIVE },
+ { "prelight", 0, GTK_STATE_FLAG_PRELIGHT },
+ { "hover", 0, GTK_STATE_FLAG_PRELIGHT },
+ { "selected", 0, GTK_STATE_FLAG_SELECTED },
+ { "insensitive", 0, GTK_STATE_FLAG_INSENSITIVE },
+ { "inconsistent", 0, GTK_STATE_FLAG_INCONSISTENT },
+ { "focused", 0, GTK_STATE_FLAG_FOCUSED },
+ { "focus", 0, GTK_STATE_FLAG_FOCUSED },
+ { "backdrop", 0, GTK_STATE_FLAG_BACKDROP },
+ { NULL, }
+ }, nth_child_classes[] = {
+ { "first", GTK_REGION_FIRST, 0 },
+ { "last", GTK_REGION_LAST, 0 },
+ { "even", GTK_REGION_EVEN, 0 },
+ { "odd", GTK_REGION_ODD, 0 },
+ { NULL, }
+ }, *classes;
+ guint i;
+ char *name;
+ GError *error;
+
+ name = _gtk_css_parser_try_ident (parser, FALSE);
+ if (name == NULL)
+ {
+ _gtk_css_parser_error (parser, "Missing name of pseudo-class");
+ return FALSE;
+ }
+
+ if (_gtk_css_parser_try (parser, "(", TRUE))
+ {
+ char *function = name;
+
+ name = _gtk_css_parser_try_ident (parser, TRUE);
+ if (!_gtk_css_parser_try (parser, ")", FALSE))
+ {
+ _gtk_css_parser_error (parser, "Missing closing bracket for pseudo-class");
+ return FALSE;
+ }
+
+ if (g_ascii_strcasecmp (function, "nth-child") != 0)
+ {
+ error = g_error_new (GTK_CSS_PROVIDER_ERROR,
+ GTK_CSS_PROVIDER_ERROR_UNKNOWN_VALUE,
+ "Unknown pseudo-class '%s(%s)'", function, name ? name : "");
+ _gtk_css_parser_take_error (parser, error);
+ g_free (function);
+ g_free (name);
+ return FALSE;
+ }
+
+ g_free (function);
+
+ if (name == NULL)
+ {
+ error = g_error_new (GTK_CSS_PROVIDER_ERROR,
+ GTK_CSS_PROVIDER_ERROR_UNKNOWN_VALUE,
+ "Unknown pseudo-class 'nth-child(%s)'", name);
+ _gtk_css_parser_take_error (parser, error);
+ return FALSE;
+ }
+
+ classes = nth_child_classes;
+ }
+ else
+ classes = pseudo_classes;
+
+ for (i = 0; classes[i].name != NULL; i++)
+ {
+ if (g_ascii_strcasecmp (name, classes[i].name) == 0)
+ {
+ if ((*region_to_modify & classes[i].region_flag) ||
+ (*state_to_modify & classes[i].state_flag))
+ {
+ if (classes == nth_child_classes)
+ _gtk_css_parser_error (parser, "Duplicate pseudo-class 'nth-child(%s)'", name);
+ else
+ _gtk_css_parser_error (parser, "Duplicate pseudo-class '%s'", name);
+ }
+ *region_to_modify |= classes[i].region_flag;
+ *state_to_modify |= classes[i].state_flag;
+
+ g_free (name);
+ return TRUE;
+ }
+ }
+
+ if (classes == nth_child_classes)
+ error = g_error_new (GTK_CSS_PROVIDER_ERROR,
+ GTK_CSS_PROVIDER_ERROR_UNKNOWN_VALUE,
+ "Unknown pseudo-class 'nth-child(%s)'", name);
+ else
+ error = g_error_new (GTK_CSS_PROVIDER_ERROR,
+ GTK_CSS_PROVIDER_ERROR_UNKNOWN_VALUE,
+ "Unknown pseudo-class '%s'", name);
+
+ g_free (name);
+ _gtk_css_parser_take_error (parser, error);
+
+ return FALSE;
+}
+
+static gboolean
+parse_simple_selector (GtkCssParser *parser,
+ char **name,
+ GArray *ids,
+ GArray *classes,
+ GtkRegionFlags *pseudo_classes,
+ GtkStateFlags *state)
+{
+ gboolean parsed_something;
+
+ *name = _gtk_css_parser_try_ident (parser, FALSE);
+ if (*name)
+ parsed_something = TRUE;
+ else
+ parsed_something = _gtk_css_parser_try (parser, "*", FALSE);
+
+ do {
+ if (_gtk_css_parser_try (parser, "#", FALSE))
+ {
+ if (!parse_selector_name (parser, ids))
+ return FALSE;
+ }
+ else if (_gtk_css_parser_try (parser, ".", FALSE))
+ {
+ if (!parse_selector_class (parser, classes))
+ return FALSE;
+ }
+ else if (_gtk_css_parser_try (parser, ":", FALSE))
+ {
+ if (!parse_selector_pseudo_class (parser, pseudo_classes, state))
+ return FALSE;
+ }
+ else if (!parsed_something)
+ {
+ _gtk_css_parser_error (parser, "Expected a valid selector");
+ return FALSE;
+ }
+ else
+ break;
+
+ parsed_something = TRUE;
+ }
+ while (!_gtk_css_parser_is_eof (parser));
+
+ _gtk_css_parser_skip_whitespace (parser);
+ return TRUE;
+}
+
+GtkCssSelector *
+_gtk_css_selector_parse (GtkCssParser *parser)
+{
+ GtkCssSelector *selector = NULL;
+
+ do {
+ char *name = NULL;
+ GArray *ids = g_array_new (TRUE, FALSE, sizeof (GQuark));
+ GArray *classes = g_array_new (TRUE, FALSE, sizeof (GQuark));
+ GtkRegionFlags pseudo_classes = 0;
+ GtkStateFlags state = 0;
+ GtkCssCombinator combine = GTK_CSS_COMBINE_DESCANDANT;
+
+ if (selector)
+ {
+ if (_gtk_css_parser_try (parser, ">", TRUE))
+ combine = GTK_CSS_COMBINE_CHILD;
+ }
+
+ if (!parse_simple_selector (parser, &name, ids, classes, &pseudo_classes, &state))
+ {
+ g_array_free (ids, TRUE);
+ g_array_free (classes, TRUE);
+ if (selector)
+ _gtk_css_selector_free (selector);
+ return NULL;
+ }
+
+ selector = gtk_css_selector_new (selector,
+ combine,
+ name,
+ (GQuark *) g_array_free (ids, ids->len == 0),
+ (GQuark *) g_array_free (classes, classes->len == 0),
+ pseudo_classes,
+ state);
+ g_free (name);
+ }
+ while (!_gtk_css_parser_is_eof (parser) &&
+ !_gtk_css_parser_begins_with (parser, ',') &&
+ !_gtk_css_parser_begins_with (parser, '{'));
+
+ return selector;
+}
+
void
_gtk_css_selector_free (GtkCssSelector *selector)
{
diff --git a/gtk/gtkcssselectorprivate.h b/gtk/gtkcssselectorprivate.h
index 8601381..b74dfc5 100644
--- a/gtk/gtkcssselectorprivate.h
+++ b/gtk/gtkcssselectorprivate.h
@@ -20,23 +20,13 @@
#include <gtk/gtkenums.h>
#include <gtk/gtkwidgetpath.h>
+#include "gtk/gtkcssparserprivate.h"
G_BEGIN_DECLS
-typedef enum {
- GTK_CSS_COMBINE_DESCANDANT,
- GTK_CSS_COMBINE_CHILD
-} GtkCssCombinator;
-
typedef struct _GtkCssSelector GtkCssSelector;
-GtkCssSelector * _gtk_css_selector_new (GtkCssSelector *previous,
- GtkCssCombinator combine,
- const char * name,
- GQuark * ids,
- GQuark * classes,
- GtkRegionFlags pseudo_classes,
- GtkStateFlags state);
+GtkCssSelector * _gtk_css_selector_parse (GtkCssParser *parser);
void _gtk_css_selector_free (GtkCssSelector *selector);
char * _gtk_css_selector_to_string (const GtkCssSelector *selector);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]