summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/libcss/select.h10
-rw-r--r--src/select/select.c113
2 files changed, 116 insertions, 7 deletions
diff --git a/include/libcss/select.h b/include/libcss/select.h
index ab28b3b..90f72a9 100644
--- a/include/libcss/select.h
+++ b/include/libcss/select.h
@@ -16,7 +16,15 @@ typedef struct css_select_handler {
css_error (*node_name)(void *pw, void *node, const uint8_t **name,
size_t *len);
-
+ css_error (*ancestor_node)(void *pw, void *node,
+ const uint8_t *name, size_t len,
+ void **ancestor);
+ css_error (*parent_node)(void *pw, void *node,
+ const uint8_t *name, size_t len,
+ void **parent);
+ css_error (*sibling_node)(void *pw, void *node,
+ const uint8_t *name, size_t len,
+ void **sibling);
} css_select_handler;
css_error css_select_ctx_create(css_alloc alloc, void *pw,
diff --git a/src/select/select.c b/src/select/select.c
index 90f916c..261c67b 100644
--- a/src/select/select.c
+++ b/src/select/select.c
@@ -68,8 +68,15 @@ static css_error select_from_sheet(css_select_ctx *ctx,
const css_stylesheet *sheet, css_select_state *state);
static css_error match_selectors_in_sheet(css_select_ctx *ctx,
const css_stylesheet *sheet, css_select_state *state);
-static css_error match_selector(css_select_ctx *ctx,
- const css_selector *selector, css_select_state *state);
+static css_error match_selector_chain(css_select_ctx *ctx,
+ const css_selector *selector, css_origin origin,
+ css_select_state *state);
+static css_error match_detail(css_select_ctx *ctx, void *node,
+ const css_selector_detail *detail, css_select_state *state,
+ bool *match);
+static css_error cascade_style(css_select_ctx *ctx, css_style *style,
+ uint32_t specificity, css_origin origin, uint32_t rule_index,
+ css_select_state *state);
/**
* Create a selection context
@@ -404,7 +411,8 @@ css_error match_selectors_in_sheet(css_select_ctx *ctx,
/* Process any matching selectors */
while (*selectors != NULL) {
- error = match_selector(ctx, *selectors, state);
+ error = match_selector_chain(ctx, *selectors,
+ sheet->origin, state);
if (error != CSS_OK)
return error;
@@ -421,7 +429,8 @@ css_error match_selectors_in_sheet(css_select_ctx *ctx,
/* Process any matching selectors */
while (*selectors != NULL) {
- error = match_selector(ctx, *selectors, state);
+ error = match_selector_chain(ctx, *selectors,
+ sheet->origin, state);
if (error != CSS_OK)
return error;
@@ -434,11 +443,103 @@ css_error match_selectors_in_sheet(css_select_ctx *ctx,
return CSS_OK;
}
-css_error match_selector(css_select_ctx *ctx, const css_selector *selector,
+css_error match_selector_chain(css_select_ctx *ctx,
+ const css_selector *selector, css_origin origin,
+ css_select_state *state)
+{
+ const css_selector *s = selector;
+ void *node = state->node;
+ css_error error;
+
+ do {
+ void *next_node = NULL;
+ const css_selector_detail *detail = &s->data;
+
+ /* First, consider any combinator on this selector */
+ if (s->data.comb != CSS_COMBINATOR_NONE) {
+ const uint8_t *name = s->combinator->data.name->data;
+ size_t len = s->combinator->data.name->len;
+
+ switch (s->data.comb) {
+ case CSS_COMBINATOR_ANCESTOR:
+ error = state->handler->ancestor_node(
+ state->pw, node, name, len,
+ &next_node);
+ if (error != CSS_OK)
+ return error;
+ break;
+ case CSS_COMBINATOR_PARENT:
+ error = state->handler->parent_node(
+ state->pw, node, name, len,
+ &next_node);
+ if (error != CSS_OK)
+ return error;
+ break;
+ case CSS_COMBINATOR_SIBLING:
+ error = state->handler->sibling_node(
+ state->pw, node, name, len,
+ &next_node);
+ if (error != CSS_OK)
+ return error;
+ break;
+ }
+
+ /* No match for combinator, so reject selector chain */
+ if (next_node == NULL)
+ return CSS_OK;
+ }
+
+ /* Now match details on this selector */
+ while (detail->next != 0) {
+ bool match = false;
+
+ /* Don't bother with the first detail, as it's the
+ * element selector */
+ detail++;
+
+ error = match_detail(ctx, node, detail, state, &match);
+ if (error != CSS_OK)
+ return error;
+
+ /* Detail doesn't match, so reject selector chain */
+ if (match == false)
+ return CSS_OK;
+ }
+
+ /* Details matched, so progress to combining selector */
+ s = s->combinator;
+ node = next_node;
+ } while (s != NULL);
+
+ /* If we got here, then the entire selector chain matched, so cascade */
+ return cascade_style(ctx,
+ ((css_rule_selector *) selector->rule)->style,
+ selector->specificity, origin, selector->rule->index,
+ state);
+}
+
+css_error match_detail(css_select_ctx *ctx, void *node,
+ const css_selector_detail *detail, css_select_state *state,
+ bool *match)
+{
+ UNUSED(ctx);
+ UNUSED(node);
+ UNUSED(detail);
+ UNUSED(state);
+ UNUSED(match);
+
+ return CSS_OK;
+}
+
+css_error cascade_style(css_select_ctx *ctx, css_style *style,
+ uint32_t specificity, css_origin origin, uint32_t rule_index,
css_select_state *state)
{
UNUSED(ctx);
- UNUSED(selector);
+ UNUSED(style);
+ UNUSED(specificity);
+ UNUSED(origin);
+ UNUSED(rule_index);
UNUSED(state);
return CSS_OK;