From b740ed09f1f1a9319a6ffa1d99d0dc8849f75173 Mon Sep 17 00:00:00 2001 From: John Mark Bell Date: Sat, 14 Feb 2009 09:35:32 +0000 Subject: Pseudo classes are now matched by callbacks to the client. This is far saner, as any node may match a pseudo class, not just the immediate target of the selection. Munge test data to no longer expect :active to match -- there's currently no way to specify which node(s) in the tree have which pseudo classes applying to them. The pseudo classes on @page are no longer supported (namely, :left, :right, :first). These, and @page itself, probably want a dedicated API, as they are nothing to do with normal selection. Probably something like css_error css_select_page_margins(ctx, CSS_PAGE_LEFT, &computed); svn path=/trunk/libcss/; revision=6476 --- include/libcss/select.h | 33 +++++----- src/select/select.c | 95 ++++++++------------------- test/data/select/tests1.dat | 4 +- test/select-auto.c | 152 ++++++++++++++++++++++++++++++-------------- 4 files changed, 150 insertions(+), 134 deletions(-) diff --git a/include/libcss/select.h b/include/libcss/select.h index cb12b76..2dec80f 100644 --- a/include/libcss/select.h +++ b/include/libcss/select.h @@ -12,23 +12,12 @@ #include #include -enum css_pseudo_class { - CSS_PSEUDO_CLASS_LINK = (1<<0), - CSS_PSEUDO_CLASS_VISITED = (1<<1), - CSS_PSEUDO_CLASS_HOVER = (1<<2), - CSS_PSEUDO_CLASS_ACTIVE = (1<<3), - CSS_PSEUDO_CLASS_FOCUS = (1<<4), - /** \todo CSS_PSEUDO_CLASS_LANG = (1<<5), */ - CSS_PSEUDO_CLASS_LEFT = (1<<6), - CSS_PSEUDO_CLASS_RIGHT = (1<<7), - CSS_PSEUDO_CLASS_FIRST = (1<<8) -}; - enum css_pseudo_element { - CSS_PSEUDO_ELEMENT_FIRST_LINE = (1<<0), - CSS_PSEUDO_ELEMENT_FIRST_LETTER = (1<<1), - CSS_PSEUDO_ELEMENT_BEFORE = (1<<2), - CSS_PSEUDO_ELEMENT_AFTER = (1<<3) + CSS_PSEUDO_ELEMENT_NONE = 0, + CSS_PSEUDO_ELEMENT_FIRST_LINE = 1, + CSS_PSEUDO_ELEMENT_FIRST_LETTER = 2, + CSS_PSEUDO_ELEMENT_BEFORE = 3, + CSS_PSEUDO_ELEMENT_AFTER = 4 }; typedef struct css_select_handler { @@ -71,6 +60,14 @@ typedef struct css_select_handler { bool *match); css_error (*node_is_first_child)(void *pw, void *node, bool *match); + css_error (*node_is_link)(void *pw, void *node, bool *match); + css_error (*node_is_visited)(void *pw, void *node, bool *match); + css_error (*node_is_hover)(void *pw, void *node, bool *match); + css_error (*node_is_active)(void *pw, void *node, bool *match); + css_error (*node_is_focus)(void *pw, void *node, bool *match); + css_error (*node_is_lang)(void *pw, void *node, + const uint8_t *lang, size_t len, + bool *match); } css_select_handler; css_error css_select_ctx_create(css_alloc alloc, void *pw, @@ -89,8 +86,8 @@ css_error css_select_ctx_get_sheet(css_select_ctx *ctx, uint32_t index, const css_stylesheet **sheet); css_error css_select_style(css_select_ctx *ctx, void *node, - uint64_t pseudo_element, uint64_t pseudo_classes, - uint64_t media, css_computed_style *result, + uint32_t pseudo_element, uint64_t media, + css_computed_style *result, css_select_handler *handler, void *pw); #endif diff --git a/src/select/select.c b/src/select/select.c index 542f82d..19b544e 100644 --- a/src/select/select.c +++ b/src/select/select.c @@ -45,8 +45,7 @@ typedef struct prop_state { */ typedef struct css_select_state { void *node; /* Node we're selecting for */ - uint64_t pseudo_element; /* Pseudo element to select for */ - uint64_t pseudo_classes; /* Currently active pseudo classes */ + uint32_t pseudo_element; /* Pseudo element to select for */ uint64_t media; /* Currently active media types */ css_computed_style *result; /* Style to populate */ @@ -66,9 +65,6 @@ typedef struct css_select_state { const parserutils_hash_entry *hover; const parserutils_hash_entry *active; const parserutils_hash_entry *focus; - const parserutils_hash_entry *left; - const parserutils_hash_entry *right; - const parserutils_hash_entry *first; const parserutils_hash_entry *first_line; const parserutils_hash_entry *first_letter; const parserutils_hash_entry *before; @@ -411,7 +407,6 @@ css_error css_select_ctx_get_sheet(css_select_ctx *ctx, uint32_t index, * \param ctx Selection context to use * \param node Node to select style for * \param pseudo_element Pseudo element to select for, instead - * \param pseudo_classes Currently active pseudo classes * \param media Currently active media types * \param result Pointer to style to populate (assumed clean) * \param handler Dispatch table of handler functions @@ -428,8 +423,8 @@ css_error css_select_ctx_get_sheet(css_select_ctx *ctx, uint32_t index, * update the fully computed style for a node when layout changes. */ css_error css_select_style(css_select_ctx *ctx, void *node, - uint64_t pseudo_element, uint64_t pseudo_classes, - uint64_t media, css_computed_style *result, + uint32_t pseudo_element, uint64_t media, + css_computed_style *result, css_select_handler *handler, void *pw) { uint32_t i; @@ -443,7 +438,6 @@ css_error css_select_style(css_select_ctx *ctx, void *node, memset(&state, 0, sizeof(css_select_state)); state.node = node; state.pseudo_element = pseudo_element; - state.pseudo_classes = pseudo_classes; state.media = media; state.result = result; state.handler = handler; @@ -619,24 +613,6 @@ css_error intern_strings_for_sheet(css_select_ctx *ctx, if (perror != PARSERUTILS_OK) return css_error_from_parserutils_error(perror); - perror = parserutils_hash_insert(sheet->dictionary, - (const uint8_t *) "left", SLEN("left"), - &state->left); - if (perror != PARSERUTILS_OK) - return css_error_from_parserutils_error(perror); - - perror = parserutils_hash_insert(sheet->dictionary, - (const uint8_t *) "right", SLEN("right"), - &state->right); - if (perror != PARSERUTILS_OK) - return css_error_from_parserutils_error(perror); - - perror = parserutils_hash_insert(sheet->dictionary, - (const uint8_t *) "first", SLEN("first"), - &state->first); - if (perror != PARSERUTILS_OK) - return css_error_from_parserutils_error(perror); - /* Pseudo elements */ perror = parserutils_hash_insert(sheet->dictionary, (const uint8_t *) "first-line", SLEN("first-line"), @@ -928,57 +904,40 @@ css_error match_detail(css_select_ctx *ctx, void *node, if (detail->name == state->first_child) { error = state->handler->node_is_first_child(state->pw, node, match); - } else if (detail->name == state->link && - (state->pseudo_classes & - CSS_PSEUDO_CLASS_LINK)) - *match = true; - else if (detail->name == state->visited && - (state->pseudo_classes & - CSS_PSEUDO_CLASS_VISITED)) - *match = true; - else if (detail->name == state->hover && - (state->pseudo_classes & - CSS_PSEUDO_CLASS_HOVER)) - *match = true; - else if (detail->name == state->active && - (state->pseudo_classes & - CSS_PSEUDO_CLASS_ACTIVE)) - *match = true; - else if (detail->name == state->focus && - (state->pseudo_classes & - CSS_PSEUDO_CLASS_FOCUS)) - *match = true; - else if (detail->name == state->left && - (state->pseudo_classes & - CSS_PSEUDO_CLASS_LEFT)) - *match = true; - else if (detail->name == state->right && - (state->pseudo_classes & - CSS_PSEUDO_CLASS_RIGHT)) - *match = true; - else if (detail->name == state->first && - (state->pseudo_classes & - CSS_PSEUDO_CLASS_FIRST)) - *match = true; - else + } else if (detail->name == state->link) { + error = state->handler->node_is_link(state->pw, + node, match); + } else if (detail->name == state->visited) { + error = state->handler->node_is_visited(state->pw, + node, match); + } else if (detail->name == state->hover) { + error = state->handler->node_is_hover(state->pw, + node, match); + } else if (detail->name == state->active) { + error = state->handler->node_is_active(state->pw, + node, match); + } else if (detail->name == state->focus) { + error = state->handler->node_is_focus(state->pw, + node, match); + } else *match = false; break; case CSS_SELECTOR_PSEUDO_ELEMENT: if (detail->name == state->first_line && - (state->pseudo_element & - CSS_PSEUDO_ELEMENT_FIRST_LINE)) + state->pseudo_element == + CSS_PSEUDO_ELEMENT_FIRST_LINE) *match = true; else if (detail->name == state->first_letter && - (state->pseudo_element & - CSS_PSEUDO_ELEMENT_FIRST_LETTER)) + state->pseudo_element == + CSS_PSEUDO_ELEMENT_FIRST_LETTER) *match = true; else if (detail->name == state->before && - (state->pseudo_element & - CSS_PSEUDO_ELEMENT_BEFORE)) + state->pseudo_element == + CSS_PSEUDO_ELEMENT_BEFORE) *match = true; else if (detail->name == state->after && - (state->pseudo_element & - CSS_PSEUDO_ELEMENT_AFTER)) + state->pseudo_element == + CSS_PSEUDO_ELEMENT_AFTER) *match = true; else *match = false; diff --git a/test/data/select/tests1.dat b/test/data/select/tests1.dat index dc9f3c7..64f87b1 100644 --- a/test/data/select/tests1.dat +++ b/test/data/select/tests1.dat @@ -45,7 +45,7 @@ border-left-color: #00000000 display: block #reset -#tree all active +#tree all | div* #author div { background-color: #000; } @@ -53,7 +53,7 @@ div:active { background-color: #bbc; } #errors #expected background-attachment: scroll -background-color: #bbbbcc00 +background-color: #00000000 background-image: none background-position: 0% 0% background-repeat: repeat diff --git a/test/select-auto.c b/test/select-auto.c index f07b5c9..3f859a0 100644 --- a/test/select-auto.c +++ b/test/select-auto.c @@ -51,8 +51,7 @@ typedef struct line_ctx { css_stylesheet **sheets; uint64_t media; - uint64_t pseudo_elements; - uint64_t pseudo_classes; + uint32_t pseudo_element; node *target; } line_ctx; @@ -61,8 +60,8 @@ static void parse_tree(line_ctx *ctx, const char *data, size_t len); static void parse_tree_data(line_ctx *ctx, const char *data, size_t len); static void parse_sheet(line_ctx *ctx, const char *data, size_t len); static void parse_media_list(const char **data, size_t *len, uint64_t *media); -static void parse_pseudo_list(const char **data, size_t *len, - uint64_t *elements, uint64_t *classes); +static void parse_pseudo_list(const char **data, size_t *len, + uint32_t *element); static void parse_expected(line_ctx *ctx, const char *data, size_t len); static void run_test(line_ctx *ctx, const char *exp, size_t explen); static void destroy_tree(node *root); @@ -102,6 +101,14 @@ static css_error node_has_attribute_includes(void *pw, void *node, const uint8_t *value, size_t vlen, bool *match); static css_error node_is_first_child(void *pw, void *node, bool *match); +static css_error node_is_link(void *pw, void *node, bool *match); +static css_error node_is_visited(void *pw, void *node, bool *match); +static css_error node_is_hover(void *pw, void *node, bool *match); +static css_error node_is_active(void *pw, void *node, bool *match); +static css_error node_is_focus(void *pw, void *node, bool *match); +static css_error node_is_lang(void *pw, void *node, + const uint8_t *lang, size_t len, + bool *match); static css_select_handler select_handler = { node_name, @@ -116,7 +123,13 @@ static css_select_handler select_handler = { node_has_attribute_equal, node_has_attribute_dashmatch, node_has_attribute_includes, - node_is_first_child + node_is_first_child, + node_is_link, + node_is_visited, + node_is_hover, + node_is_active, + node_is_focus, + node_is_lang }; static void *myrealloc(void *data, size_t len, void *pw) @@ -254,8 +267,7 @@ void parse_tree(line_ctx *ctx, const char *data, size_t len) /* [ ? ] ? */ ctx->media = CSS_MEDIA_ALL; - ctx->pseudo_elements = 0; - ctx->pseudo_classes = 0; + ctx->pseudo_element = CSS_PSEUDO_ELEMENT_NONE; /* Consume any leading whitespace */ while (p < end && isspace(*p)) @@ -272,8 +284,7 @@ void parse_tree(line_ctx *ctx, const char *data, size_t len) if (p < end) { left = end - p; - parse_pseudo_list(&p, &left, &ctx->pseudo_elements, - &ctx->pseudo_classes); + parse_pseudo_list(&p, &left, &ctx->pseudo_element); } } @@ -516,16 +527,14 @@ void parse_media_list(const char **data, size_t *len, uint64_t *media) *len = end - p; } -void parse_pseudo_list(const char **data, size_t *len, uint64_t *elements, - uint64_t *classes) +void parse_pseudo_list(const char **data, size_t *len, uint32_t *element) { const char *p = *data; const char *end = p + *len; /* [ ',' ]* */ - *elements = 0; - *classes = 0; + *element = CSS_PSEUDO_ELEMENT_NONE; while (p < end) { const char *start = p; @@ -534,44 +543,19 @@ void parse_pseudo_list(const char **data, size_t *len, uint64_t *elements, while (isspace(*p) == false && *p != ',') p++; - /* Pseudo classes */ - if (p - start == 7 && - strncasecmp(start, "visited", 7) == 0) - *classes |= CSS_PSEUDO_CLASS_VISITED; - else if (p - start == 6 && - strncasecmp(start, "active", 6) == 0) - *classes |= CSS_PSEUDO_CLASS_ACTIVE; - else if (p - start == 5 && - strncasecmp(start, "first", 5) == 0) - *classes |= CSS_PSEUDO_CLASS_FIRST; - else if (p - start == 5 && - strncasecmp(start, "right", 5) == 0) - *classes |= CSS_PSEUDO_CLASS_RIGHT; - else if (p - start == 5 && - strncasecmp(start, "focus", 5) == 0) - *classes |= CSS_PSEUDO_CLASS_FOCUS; - else if (p - start == 5 && - strncasecmp(start, "hover", 5) == 0) - *classes |= CSS_PSEUDO_CLASS_HOVER; - else if (p - start == 4 && - strncasecmp(start, "left", 4) == 0) - *classes |= CSS_PSEUDO_CLASS_LEFT; - else if (p - start == 4 && - strncasecmp(start, "link", 4) == 0) - *classes |= CSS_PSEUDO_CLASS_LINK; /* Pseudo elements */ - else if (p - start == 12 && + if (p - start == 12 && strncasecmp(start, "first-letter", 12) == 0) - *elements |= CSS_PSEUDO_ELEMENT_FIRST_LETTER; + *element = CSS_PSEUDO_ELEMENT_FIRST_LETTER; else if (p - start == 10 && strncasecmp(start, "first-line", 10) == 0) - *elements |= CSS_PSEUDO_ELEMENT_FIRST_LINE; + *element = CSS_PSEUDO_ELEMENT_FIRST_LINE; else if (p - start == 6 && strncasecmp(start, "before", 6) == 0) - *elements |= CSS_PSEUDO_ELEMENT_BEFORE; + *element = CSS_PSEUDO_ELEMENT_BEFORE; else if (p - start == 5 && strncasecmp(start, "after", 5) == 0) - *elements |= CSS_PSEUDO_ELEMENT_AFTER; + *element = CSS_PSEUDO_ELEMENT_AFTER; else assert(0 && "Unknown pseudo"); @@ -641,9 +625,8 @@ void run_test(line_ctx *ctx, const char *exp, size_t explen) testnum++; - assert(css_select_style(select, ctx->target, ctx->pseudo_elements, - ctx->pseudo_classes, ctx->media, computed, - &select_handler, NULL) == CSS_OK); + assert(css_select_style(select, ctx->target, ctx->pseudo_element, + ctx->media, computed, &select_handler, NULL) == CSS_OK); dump_computed_style(computed, buf, &buflen); @@ -968,3 +951,80 @@ css_error node_is_first_child(void *pw, void *n, bool *match) return CSS_OK; } + +css_error node_is_link(void *pw, void *n, bool *match) +{ + node *node = n; + + UNUSED(pw); + UNUSED(node); + + *match = false; + + return CSS_OK; +} + +css_error node_is_visited(void *pw, void *n, bool *match) +{ + node *node = n; + + UNUSED(pw); + UNUSED(node); + + *match = false; + + return CSS_OK; +} + +css_error node_is_hover(void *pw, void *n, bool *match) +{ + node *node = n; + + UNUSED(pw); + UNUSED(node); + + *match = false; + + return CSS_OK; +} + +css_error node_is_active(void *pw, void *n, bool *match) +{ + node *node = n; + + UNUSED(pw); + UNUSED(node); + + *match = false; + + return CSS_OK; +} + +css_error node_is_focus(void *pw, void *n, bool *match) +{ + node *node = n; + + UNUSED(pw); + UNUSED(node); + + *match = false; + + return CSS_OK; +} + +css_error node_is_lang(void *pw, void *n, + const uint8_t *lang, size_t len, + bool *match) +{ + node *node = n; + + UNUSED(pw); + UNUSED(node); + UNUSED(lang); + UNUSED(len); + + *match = false; + + return CSS_OK; +} + -- cgit v1.2.3