summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Mark Bell <jmb@netsurf-browser.org>2009-02-14 09:35:32 +0000
committerJohn Mark Bell <jmb@netsurf-browser.org>2009-02-14 09:35:32 +0000
commitb740ed09f1f1a9319a6ffa1d99d0dc8849f75173 (patch)
tree8c3dfa143f1df2405a4d3bd64320f7eedc9e0be9
parente12825e094f3bb40336e92ea208050fe001f78ba (diff)
downloadlibcss-b740ed09f1f1a9319a6ffa1d99d0dc8849f75173.tar.gz
libcss-b740ed09f1f1a9319a6ffa1d99d0dc8849f75173.tar.bz2
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
-rw-r--r--include/libcss/select.h33
-rw-r--r--src/select/select.c95
-rw-r--r--test/data/select/tests1.dat4
-rw-r--r--test/select-auto.c152
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 <libcss/functypes.h>
#include <libcss/types.h>
-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)
/* [ <media_list> <pseudo>? ] ? */
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;
/* <pseudo> [ ',' <pseudo> ]* */
- *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;
+}
+