Gitweb links:
...log
http://git.netsurf-browser.org/libcss.git/shortlog/3a99f515f8b04f66ff73b51aa1ab8fa7e14acc88
...commit
http://git.netsurf-browser.org/libcss.git/commit/3a99f515f8b04f66ff73b51aa1ab8fa7e14acc88
...tree
http://git.netsurf-browser.org/libcss.git/tree/3a99f515f8b04f66ff73b51aa1ab8fa7e14acc88
The branch, tlsa/shared-styles has been updated
discards 3959f3c25347f32d33c35fdf31cb797948a8a5da (commit)
via 3a99f515f8b04f66ff73b51aa1ab8fa7e14acc88 (commit)
via ae8aa1c8254e373a74047015c0b53b9cf6026e1c (commit)
This update added new revisions after undoing existing revisions. That is
to say, the old revision is not a strict subset of the new revision. This
situation occurs when you --force push a change and generate a repository
containing something like this:
* -- * -- B -- O -- O -- O (3959f3c25347f32d33c35fdf31cb797948a8a5da)
\
N -- N -- N (3a99f515f8b04f66ff73b51aa1ab8fa7e14acc88)
When this happens we assume that you've already had alert emails for all
of the O revisions, and so we here report only the revisions in the N
branch from the common base, B.
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commitdiff
http://git.netsurf-browser.org/libcss.git/commit/?id=3a99f515f8b04f66ff73b51aa1ab8fa7e14acc88
commit 3a99f515f8b04f66ff73b51aa1ab8fa7e14acc88
Author: Michael Drake <[email protected]>
Commit: Michael Drake <[email protected]>
Make node data contain list of partial node styles.
diff --git a/src/select/computed.h b/src/select/computed.h
index 57981b2..f77bda2 100644
--- a/src/select/computed.h
+++ b/src/select/computed.h
@@ -338,6 +338,10 @@ static inline css_computed_style * css__computed_style_ref(
if (style == NULL)
return NULL;
+ if (style->i.uncommon != NULL) {
+ style->i.uncommon->count++;
+ }
+
style->count++;
return style;
}
diff --git a/src/select/select.c b/src/select/select.c
index 9f5f3a3..d9c8809 100644
--- a/src/select/select.c
+++ b/src/select/select.c
@@ -170,12 +170,21 @@ static css_error css__create_node_data(struct
css_node_data **node_data)
static void css__destroy_node_data(struct css_node_data *node_data)
{
+ int i;
+
assert(node_data != NULL);
if (node_data->bloom != NULL) {
free(node_data->bloom);
}
+ for (i = 0; i < CSS_PSEUDO_ELEMENT_COUNT; i++) {
+ if (node_data->partial.styles[i] != NULL) {
+ css_computed_style_destroy(
+ node_data->partial.styles[i]);
+ }
+ }
+
free(node_data);
}
@@ -660,18 +669,31 @@ cleanup:
static css_error css__set_node_data(void *node, css_select_state *state,
css_select_handler *handler, void *pw)
{
+ int i;
css_error error;
css_bloom *bloom;
+ css_select_results *results;
+
+ struct css_node_data *node_data = state->node_data;
/* Set node bloom filter */
error = css__create_node_bloom(&bloom, state);
if (error != CSS_OK) {
return error;
}
- state->node_data->bloom = bloom;
+ node_data->bloom = bloom;
- error = handler->set_libcss_node_data(pw, node, state->node_data);
+ /* Set selection results */
+ results = state->results;
+ for (i = 0; i < CSS_PSEUDO_ELEMENT_COUNT; i++) {
+ node_data->partial.styles[i] =
+ css__computed_style_ref(results->styles[i]);
+ }
+
+ error = handler->set_libcss_node_data(pw, node, node_data);
if (error != CSS_OK) {
+ css__destroy_node_data(node_data);
+ state->node_data = NULL;
return error;
}
diff --git a/src/select/select.h b/src/select/select.h
index 196914d..254b095 100644
--- a/src/select/select.h
+++ b/src/select/select.h
@@ -32,6 +32,7 @@ typedef struct prop_state {
} prop_state;
struct css_node_data {
+ css_select_results partial;
css_bloom *bloom;
};
commitdiff
http://git.netsurf-browser.org/libcss.git/commit/?id=ae8aa1c8254e373a74047015c0b53b9cf6026e1c
commit ae8aa1c8254e373a74047015c0b53b9cf6026e1c
Author: Michael Drake <[email protected]>
Commit: Michael Drake <[email protected]>
Remove option to support not storing data on DOM nodes.
It was complicating lifetimes and ownership.
diff --git a/test/INDEX b/test/INDEX
index cf1a3cb..d712157 100644
--- a/test/INDEX
+++ b/test/INDEX
@@ -10,8 +10,7 @@ number Conversion of numbers to fixed point
number
#css21 Parsing (CSS2.1 specifics) css
parse-auto Automated parser tests (bytecode) parse
parse2-auto Automated parser tests (om & invalid) parse2
-select-no-nd Automated selection engine tests (no node_data) select
-select-nd Automated selection engine tests (with node_data) select
+select Automated selection engine tests select
# Regression tests
diff --git a/test/Makefile b/test/Makefile
index 021d829..18124ce 100644
--- a/test/Makefile
+++ b/test/Makefile
@@ -2,6 +2,6 @@
DIR_TEST_ITEMS := csdetect:csdetect.c css21:css21.c lex:lex.c \
lex-auto:lex-auto.c number:number.c \
parse:parse.c parse-auto:parse-auto.c parse2-auto:parse2-auto.c \
- select-no-nd:select-no-nd.c select-nd:select-nd.c
+ select:select.c
include $(NSBUILD)/Makefile.subdir
diff --git a/test/select-common.c b/test/select-common.c
deleted file mode 100644
index b4f588a..0000000
--- a/test/select-common.c
+++ /dev/null
@@ -1,1681 +0,0 @@
-#include <ctype.h>
-#include <inttypes.h>
-#include <stdbool.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <libcss/libcss.h>
-#include <libcss/computed.h>
-#include <libcss/select.h>
-#include <libcss/stylesheet.h>
-
-#include "utils/utils.h"
-
-#include "dump_computed.h"
-#include "testutils.h"
-
-typedef struct attribute {
- lwc_string *name;
- lwc_string *value;
-} attribute;
-
-typedef struct node {
- lwc_string *name;
-
- uint32_t n_classes;
- lwc_string **classes;
-
- uint32_t n_attrs;
- attribute *attrs;
-
- css_select_results *sr;
- void *libcss_node_data;
-
- struct node *parent;
- struct node *next;
- struct node *prev;
- struct node *children;
- struct node *last_child;
-} node;
-
-typedef struct sheet_ctx {
- css_stylesheet *sheet;
- css_origin origin;
- uint64_t media;
-} sheet_ctx;
-
-typedef struct line_ctx {
- size_t explen;
- size_t expused;
- char *exp;
-
- bool intree;
- bool insheet;
- bool inerrors;
- bool inexp;
-
- node *tree;
- node *current;
- uint32_t depth;
-
- uint32_t n_sheets;
- sheet_ctx *sheets;
-
- uint64_t media;
- uint32_t pseudo_element;
- node *target;
-
- lwc_string *attr_class;
- lwc_string *attr_id;
-} line_ctx;
-
-
-
-
-static bool handle_line(const char *data, size_t datalen, void *pw);
-static void css__parse_tree(line_ctx *ctx, const char *data, size_t len);
-static void css__parse_tree_data(line_ctx *ctx, const char *data, size_t len);
-static void css__parse_sheet(line_ctx *ctx, const char *data, size_t len);
-static void css__parse_media_list(const char **data, size_t *len, uint64_t
*media);
-static void css__parse_pseudo_list(const char **data, size_t *len,
- uint32_t *element);
-static void css__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);
-
-static css_error node_name(void *pw, void *node,
- css_qname *qname);
-static css_error node_classes(void *pw, void *n,
- lwc_string ***classes, uint32_t *n_classes);
-static css_error node_id(void *pw, void *node,
- lwc_string **id);
-static css_error named_ancestor_node(void *pw, void *node,
- const css_qname *qname,
- void **ancestor);
-static css_error named_parent_node(void *pw, void *node,
- const css_qname *qname,
- void **parent);
-static css_error named_sibling_node(void *pw, void *node,
- const css_qname *qname,
- void **sibling);
-static css_error named_generic_sibling_node(void *pw, void *node,
- const css_qname *qname,
- void **sibling);
-static css_error parent_node(void *pw, void *node, void **parent);
-static css_error sibling_node(void *pw, void *node, void **sibling);
-static css_error node_has_name(void *pw, void *node,
- const css_qname *qname,
- bool *match);
-static css_error node_has_class(void *pw, void *node,
- lwc_string *name,
- bool *match);
-static css_error node_has_id(void *pw, void *node,
- lwc_string *name,
- bool *match);
-static css_error node_has_attribute(void *pw, void *node,
- const css_qname *qname,
- bool *match);
-static css_error node_has_attribute_equal(void *pw, void *node,
- const css_qname *qname,
- lwc_string *value,
- bool *match);
-static css_error node_has_attribute_dashmatch(void *pw, void *node,
- const css_qname *qname,
- lwc_string *value,
- bool *match);
-static css_error node_has_attribute_includes(void *pw, void *node,
- const css_qname *qname,
- lwc_string *value,
- bool *match);
-static css_error node_has_attribute_prefix(void *pw, void *node,
- const css_qname *qname,
- lwc_string *value,
- bool *match);
-static css_error node_has_attribute_suffix(void *pw, void *node,
- const css_qname *qname,
- lwc_string *value,
- bool *match);
-static css_error node_has_attribute_substring(void *pw, void *node,
- const css_qname *qname,
- lwc_string *value,
- bool *match);
-static css_error node_is_root(void *pw, void *node, bool *match);
-static css_error node_count_siblings(void *pw, void *node,
- bool same_name, bool after, int32_t *count);
-static css_error node_is_empty(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_enabled(void *pw, void *node, bool *match);
-static css_error node_is_disabled(void *pw, void *node, bool *match);
-static css_error node_is_checked(void *pw, void *node, bool *match);
-static css_error node_is_target(void *pw, void *node, bool *match);
-static css_error node_is_lang(void *pw, void *node,
- lwc_string *lang, bool *match);
-static css_error node_presentational_hint(void *pw, void *node,
- uint32_t *nhints, css_hint **hints);
-static css_error ua_default_for_property(void *pw, uint32_t property,
- css_hint *hints);
-static css_error compute_font_size(void *pw, const css_hint *parent,
- css_hint *size);
-static css_error set_libcss_node_data(void *pw, void *n,
- void *libcss_node_data);
-static css_error get_libcss_node_data(void *pw, void *n,
- void **libcss_node_data);
-
-static css_select_handler select_handler = {
- CSS_SELECT_HANDLER_VERSION_1,
-
- node_name,
- node_classes,
- node_id,
- named_ancestor_node,
- named_parent_node,
- named_sibling_node,
- named_generic_sibling_node,
- parent_node,
- sibling_node,
- node_has_name,
- node_has_class,
- node_has_id,
- node_has_attribute,
- node_has_attribute_equal,
- node_has_attribute_dashmatch,
- node_has_attribute_includes,
- node_has_attribute_prefix,
- node_has_attribute_suffix,
- node_has_attribute_substring,
- node_is_root,
- node_count_siblings,
- node_is_empty,
- node_is_link,
- node_is_visited,
- node_is_hover,
- node_is_active,
- node_is_focus,
- node_is_enabled,
- node_is_disabled,
- node_is_checked,
- node_is_target,
- node_is_lang,
- node_presentational_hint,
- ua_default_for_property,
- compute_font_size,
- set_libcss_node_data,
- get_libcss_node_data
-};
-
-static css_error resolve_url(void *pw,
- const char *base, lwc_string *rel, lwc_string **abs)
-{
- UNUSED(pw);
- UNUSED(base);
-
- /* About as useless as possible */
- *abs = lwc_string_ref(rel);
-
- return CSS_OK;
-}
-
-static bool fail_because_lwc_leaked = false;
-
-static void
-printing_lwc_iterator(lwc_string *str, void *pw)
-{
- UNUSED(pw);
-
- printf(" DICT: %*s\n", (int)(lwc_string_length(str)),
lwc_string_data(str));
- fail_because_lwc_leaked = true;
-}
-
-int main(int argc, char **argv)
-{
- line_ctx ctx;
-
- if (argc != 2) {
- printf("Usage: %s <filename>\n", argv[0]);
- return 1;
- }
-
- memset(&ctx, 0, sizeof(ctx));
-
-
- lwc_intern_string("class", SLEN("class"), &ctx.attr_class);
- lwc_intern_string("id", SLEN("id"), &ctx.attr_id);
-
- assert(css__parse_testfile(argv[1], handle_line, &ctx) == true);
-
- /* and run final test */
- if (ctx.tree != NULL)
- run_test(&ctx, ctx.exp, ctx.expused);
-
- free(ctx.exp);
-
- lwc_string_unref(ctx.attr_class);
- lwc_string_unref(ctx.attr_id);
-
- lwc_iterate_strings(printing_lwc_iterator, NULL);
-
- assert(fail_because_lwc_leaked == false);
-
- printf("PASS\n");
- return 0;
-}
-
-bool handle_line(const char *data, size_t datalen, void *pw)
-{
- line_ctx *ctx = (line_ctx *) pw;
- css_error error;
-
- if (data[0] == '#') {
- if (ctx->intree) {
- if (strncasecmp(data+1, "errors", 6) == 0) {
- ctx->intree = false;
- ctx->insheet = false;
- ctx->inerrors = true;
- ctx->inexp = false;
- } else {
- /* Assume start of stylesheet */
- css__parse_sheet(ctx, data + 1, datalen - 1);
-
- ctx->intree = false;
- ctx->insheet = true;
- ctx->inerrors = false;
- ctx->inexp = false;
- }
- } else if (ctx->insheet) {
- if (strncasecmp(data+1, "errors", 6) == 0) {
- assert(css_stylesheet_data_done(
- ctx->sheets[ctx->n_sheets - 1].sheet)
- == CSS_OK);
-
- ctx->intree = false;
- ctx->insheet = false;
- ctx->inerrors = true;
- ctx->inexp = false;
- } else if (strncasecmp(data+1, "ua", 2) == 0 ||
- strncasecmp(data+1, "user", 4) == 0 ||
- strncasecmp(data+1, "author", 6) == 0) {
- assert(css_stylesheet_data_done(
- ctx->sheets[ctx->n_sheets - 1].sheet)
- == CSS_OK);
-
- css__parse_sheet(ctx, data + 1, datalen - 1);
- } else {
- error = css_stylesheet_append_data(
- ctx->sheets[ctx->n_sheets - 1].sheet,
- (const uint8_t *) data,
- datalen);
- assert(error == CSS_OK ||
- error == CSS_NEEDDATA);
- }
- } else if (ctx->inerrors) {
- ctx->intree = false;
- ctx->insheet = false;
- ctx->inerrors = false;
- ctx->inexp = true;
- } else if (ctx->inexp) {
- /* This marks end of testcase, so run it */
- run_test(ctx, ctx->exp, ctx->expused);
-
- ctx->expused = 0;
-
- ctx->intree = false;
- ctx->insheet = false;
- ctx->inerrors = false;
- ctx->inexp = false;
- } else {
- /* Start state */
- if (strncasecmp(data+1, "tree", 4) == 0) {
- css__parse_tree(ctx, data + 5, datalen - 5);
-
- ctx->intree = true;
- ctx->insheet = false;
- ctx->inerrors = false;
- ctx->inexp = false;
- }
- }
- } else {
- if (ctx->intree) {
- /* Not interested in the '|' */
- css__parse_tree_data(ctx, data + 1, datalen - 1);
- } else if (ctx->insheet) {
- error = css_stylesheet_append_data(
- ctx->sheets[ctx->n_sheets - 1].sheet,
- (const uint8_t *) data, datalen);
- assert(error == CSS_OK || error == CSS_NEEDDATA);
- } else if (ctx->inexp) {
- css__parse_expected(ctx, data, datalen);
- }
- }
-
- return true;
-}
-
-void css__parse_tree(line_ctx *ctx, const char *data, size_t len)
-{
- const char *p = data;
- const char *end = data + len;
- size_t left;
-
- /* [ <media_list> <pseudo>? ] ? */
-
- ctx->media = CSS_MEDIA_ALL;
- ctx->pseudo_element = CSS_PSEUDO_ELEMENT_NONE;
-
- /* Consume any leading whitespace */
- while (p < end && isspace(*p))
- p++;
-
- if (p < end) {
- left = end - p;
-
- css__parse_media_list(&p, &left, &ctx->media);
-
- end = p + left;
- }
-
- if (p < end) {
- left = end - p;
-
- css__parse_pseudo_list(&p, &left, &ctx->pseudo_element);
- }
-}
-
-void css__parse_tree_data(line_ctx *ctx, const char *data, size_t len)
-{
- const char *p = data;
- const char *end = data + len;
- const char *name = NULL;
- const char *value = NULL;
- size_t namelen = 0;
- size_t valuelen = 0;
- uint32_t depth = 0;
- bool target = false;
-
- /* ' '{depth+1} [ <element> '*'? | <attr> ]
- *
- * <element> ::= [^=*[:space:]]+
- * <attr> ::= [^=*[:space:]]+ '=' [^[:space:]]*
- */
-
- while (p < end && isspace(*p)) {
- depth++;
- p++;
- }
- depth--;
-
- /* Get element/attribute name */
- name = p;
- while (p < end && *p != '=' && *p != '*' && isspace(*p) == false) {
- namelen++;
- p++;
- }
-
- /* Skip whitespace */
- while (p < end && isspace(*p))
- p++;
-
- if (p < end && *p == '=') {
- /* Attribute value */
- p++;
-
- value = p;
-
- while (p < end && isspace(*p) == false) {
- valuelen++;
- p++;
- }
- } else if (p < end && *p == '*') {
- /* Element is target node */
- target = true;
- }
-
- if (value == NULL) {
- /* We have an element, so create it */
- node *n = malloc(sizeof(node));
- assert(n != NULL);
-
- memset(n, 0, sizeof(node));
-
- lwc_intern_string(name, namelen, &n->name);
-
- /* Insert it into tree */
- if (ctx->tree == NULL) {
- ctx->tree = n;
- } else {
- assert(depth > 0);
- assert(depth <= ctx->depth + 1);
-
- /* Find node to insert into */
- while (depth <= ctx->depth) {
- ctx->depth--;
- ctx->current = ctx->current->parent;
- }
-
- /* Insert into current node */
- if (ctx->current->children == NULL) {
- ctx->current->children = n;
- ctx->current->last_child = n;
- } else {
- ctx->current->last_child->next = n;
- n->prev = ctx->current->last_child;
-
- ctx->current->last_child = n;
- }
- n->parent = ctx->current;
- }
-
- ctx->current = n;
- ctx->depth = depth;
-
- /* Mark the target, if it's us */
- if (target)
- ctx->target = n;
- } else {
- /* New attribute */
- bool amatch = false;
- attribute *attr;
- node *n = ctx->current;
-
- attribute *temp = realloc(n->attrs,
- (n->n_attrs + 1) * sizeof(attribute));
- assert(temp != NULL);
-
- n->attrs = temp;
-
- attr = &n->attrs[n->n_attrs];
-
- lwc_intern_string(name, namelen, &attr->name);
- lwc_intern_string(value, valuelen, &attr->value);
-
- assert(lwc_string_caseless_isequal(
- n->attrs[n->n_attrs].name,
- ctx->attr_class, &amatch) == lwc_error_ok);
- if (amatch == true) {
- n->classes = realloc(NULL, sizeof(lwc_string **));
- assert(n->classes != NULL);
-
- n->classes[0] = lwc_string_ref(
- n->attrs[n->n_attrs].
- value);
- n->n_classes = 1;
- }
-
- n->n_attrs++;
- }
-}
-
-void css__parse_sheet(line_ctx *ctx, const char *data, size_t len)
-{
- css_stylesheet_params params;
- const char *p;
- const char *end = data + len;
- css_origin origin = CSS_ORIGIN_AUTHOR;
- uint64_t media = CSS_MEDIA_ALL;
- css_stylesheet *sheet;
- sheet_ctx *temp;
-
- /* <origin> <media_list>? */
-
- /* Find end of origin */
- for (p = data; p < end; p++) {
- if (isspace(*p))
- break;
- }
-
- if (p - data == 6 && strncasecmp(data, "author", 6) == 0)
- origin = CSS_ORIGIN_AUTHOR;
- else if (p - data == 4 && strncasecmp(data, "user", 4) == 0)
- origin = CSS_ORIGIN_USER;
- else if (p - data == 2 && strncasecmp(data, "ua", 2) == 0)
- origin = CSS_ORIGIN_UA;
- else
- assert(0 && "Unknown stylesheet origin");
-
- /* Skip any whitespace */
- while (p < end && isspace(*p))
- p++;
-
- if (p < end) {
- size_t ignored = end - p;
-
- css__parse_media_list(&p, &ignored, &media);
- }
-
- params.params_version = CSS_STYLESHEET_PARAMS_VERSION_1;
- params.level = CSS_LEVEL_21;
- params.charset = "UTF-8";
- params.url = "foo";
- params.title = "foo";
- params.allow_quirks = false;
- params.inline_style = false;
- params.resolve = resolve_url;
- params.resolve_pw = NULL;
- params.import = NULL;
- params.import_pw = NULL;
- params.color = NULL;
- params.color_pw = NULL;
- params.font = NULL;
- params.font_pw = NULL;
-
- /** \todo How are we going to handle @import? */
- assert(css_stylesheet_create(¶ms, &sheet) == CSS_OK);
-
- /* Extend array of sheets and append new sheet to it */
- temp = realloc(ctx->sheets,
- (ctx->n_sheets + 1) * sizeof(sheet_ctx));
- assert(temp != NULL);
-
- ctx->sheets = temp;
-
- ctx->sheets[ctx->n_sheets].sheet = sheet;
- ctx->sheets[ctx->n_sheets].origin = origin;
- ctx->sheets[ctx->n_sheets].media = media;
-
- ctx->n_sheets++;
-}
-
-void css__parse_media_list(const char **data, size_t *len, uint64_t *media)
-{
- const char *p = *data;
- const char *end = p + *len;
- uint64_t result = 0;
-
- /* <medium> [ ',' <medium> ]* */
-
- while (p < end) {
- const char *start = p;
-
- /* consume a medium */
- while (isspace(*p) == false && *p != ',')
- p++;
-
- if (p - start == 10 &&
- strncasecmp(start, "projection", 10) == 0)
- result |= CSS_MEDIA_PROJECTION;
- else if (p - start == 8 &&
- strncasecmp(start, "handheld", 8) == 0)
- result |= CSS_MEDIA_HANDHELD;
- else if (p - start == 8 &&
- strncasecmp(start, "embossed", 8) == 0)
- result |= CSS_MEDIA_EMBOSSED;
- else if (p - start == 7 &&
- strncasecmp(start, "braille", 7) == 0)
- result |= CSS_MEDIA_BRAILLE;
- else if (p - start == 6 &&
- strncasecmp(start, "speech", 6) == 0)
- result |= CSS_MEDIA_SPEECH;
- else if (p - start == 6 &&
- strncasecmp(start, "screen", 6) == 0)
- result |= CSS_MEDIA_SCREEN;
- else if (p - start == 5 &&
- strncasecmp(start, "print", 5) == 0)
- result |= CSS_MEDIA_PRINT;
- else if (p - start == 5 &&
- strncasecmp(start, "aural", 5) == 0)
- result |= CSS_MEDIA_AURAL;
- else if (p - start == 3 &&
- strncasecmp(start, "tty", 3) == 0)
- result |= CSS_MEDIA_TTY;
- else if (p - start == 3 &&
- strncasecmp(start, "all", 3) == 0)
- result |= CSS_MEDIA_ALL;
- else if (p - start == 2 &&
- strncasecmp(start, "tv", 2) == 0)
- result |= CSS_MEDIA_TV;
- else
- assert(0 && "Unknown media type");
-
- /* Consume whitespace */
- while (p < end && isspace(*p))
- p++;
-
- /* Stop if we've reached the end */
- if (p == end || *p != ',')
- break;
-
- /* Consume comma */
- p++;
-
- /* Consume whitespace */
- while (p < end && isspace(*p))
- p++;
- }
-
- *media = result;
-
- *data = p;
- *len = end - p;
-}
-
-void css__parse_pseudo_list(const char **data, size_t *len, uint32_t *element)
-{
- const char *p = *data;
- const char *end = p + *len;
-
- /* <pseudo> [ ',' <pseudo> ]* */
-
- *element = CSS_PSEUDO_ELEMENT_NONE;
-
- while (p < end) {
- const char *start = p;
-
- /* consume a pseudo */
- while (isspace(*p) == false && *p != ',')
- p++;
-
- /* Pseudo elements */
- if (p - start == 12 &&
- strncasecmp(start, "first-letter", 12) == 0)
- *element = CSS_PSEUDO_ELEMENT_FIRST_LETTER;
- else if (p - start == 10 &&
- strncasecmp(start, "first-line", 10) == 0)
- *element = CSS_PSEUDO_ELEMENT_FIRST_LINE;
- else if (p - start == 6 &&
- strncasecmp(start, "before", 6) == 0)
- *element = CSS_PSEUDO_ELEMENT_BEFORE;
- else if (p - start == 5 &&
- strncasecmp(start, "after", 5) == 0)
- *element = CSS_PSEUDO_ELEMENT_AFTER;
- else
- assert(0 && "Unknown pseudo");
-
- /* Consume whitespace */
- while (p < end && isspace(*p))
- p++;
-
- /* Stop if we've reached the end */
- if (p == end || *p != ',')
- break;
-
- /* Consume comma */
- p++;
-
- /* Consume whitespace */
- while (p < end && isspace(*p))
- p++;
- }
-
- *data = p;
- *len = end - p;
-}
-
-void css__parse_expected(line_ctx *ctx, const char *data, size_t len)
-{
- while (ctx->expused + len >= ctx->explen) {
- size_t required = ctx->explen == 0 ? 64 : ctx->explen * 2;
- char *temp = realloc(ctx->exp, required);
- if (temp == NULL) {
- assert(0 && "No memory for expected output");
- }
-
- ctx->exp = temp;
- ctx->explen = required;
- }
-
- memcpy(ctx->exp + ctx->expused, data, len);
-
- ctx->expused += len;
-}
-
-static void show_differences(size_t len, const char *exp, const char *res)
-{
- const char *pos_exp, *opos_exp;
- const char *pos_res, *opos_res;
-
- opos_exp = pos_exp = exp;
- opos_res = pos_res = res;
-
- printf("Line differences:\n");
- while (pos_exp < exp + len && pos_res < res + len) {
- if (*pos_exp == '\n' && *pos_res == '\n') {
- if (pos_exp - opos_exp != pos_res - opos_res ||
- memcmp(opos_exp, opos_res,
- pos_exp - opos_exp) != 0) {
- printf("Expected:\t%.*s\n",
- (int)(pos_exp - opos_exp),
- opos_exp);
- printf(" Result:\t%.*s\n",
- (int)(pos_res - opos_res),
- opos_res);
- printf("\n");
- }
- opos_exp = ++pos_exp;
- opos_res = ++pos_res;
- } else if (*pos_exp == '\n') {
- pos_res++;
- } else if (*pos_res == '\n') {
- pos_exp++;
- } else {
- pos_exp++;
- pos_res++;
- }
- }
-}
-
-
-static void run_test_select_tree(css_select_ctx *select,
- node *node, line_ctx *ctx,
- char *buf, size_t *buflen)
-{
- css_select_results *sr;
- struct node *n = NULL;
-
- assert(css_select_style(select, node, ctx->media, NULL,
- &select_handler, ctx, &sr) == CSS_OK);
-
- if (node->parent != NULL) {
- css_computed_style *composed;
- assert(css_computed_style_compose(
- node->parent->sr->styles[ctx->pseudo_element],
- sr->styles[ctx->pseudo_element],
- compute_font_size, NULL,
- &composed) == CSS_OK);
- css_computed_style_destroy(sr->styles[ctx->pseudo_element]);
- sr->styles[ctx->pseudo_element] = composed;
- }
-
- node->sr = sr;
-
- if (node == ctx->target) {
- dump_computed_style(sr->styles[ctx->pseudo_element],
- buf, buflen);
- }
-
- for (n = node->children; n != NULL; n = n->next) {
- run_test_select_tree(select, n, ctx, buf, buflen);
- }
-}
-
-
-void run_test(line_ctx *ctx, const char *exp, size_t explen)
-{
- css_select_ctx *select;
- css_select_results *results;
- uint32_t i;
- char *buf;
- size_t buflen;
- static int testnum;
-
- UNUSED(exp);
-
- buf = malloc(8192);
- if (buf == NULL) {
- assert(0 && "No memory for result data");
- }
- buflen = 8192;
-
- assert(css_select_ctx_create(&select) == CSS_OK);
-
- for (i = 0; i < ctx->n_sheets; i++) {
- assert(css_select_ctx_append_sheet(select,
- ctx->sheets[i].sheet, ctx->sheets[i].origin,
- ctx->sheets[i].media) == CSS_OK);
- }
-
- testnum++;
-
- run_test_select_tree(select, ctx->tree, ctx, buf, &buflen);
-
- results = ctx->target->sr;
- assert(results->styles[ctx->pseudo_element] != NULL);
-
- if (8192 - buflen != explen || memcmp(buf, exp, explen) != 0) {
- size_t len = 8192 - buflen < explen ? 8192 - buflen : explen;
- printf("Expected (%u):\n%.*s\n",
- (int) explen, (int) explen, exp);
- printf("Result (%u):\n%.*s\n", (int) (8192 - buflen),
- (int) (8192 - buflen), buf);
-
- show_differences(len, exp, buf);
- assert(0 && "Result doesn't match expected");
- }
-
- /* Clean up */
- css_select_ctx_destroy(select);
- destroy_tree(ctx->tree);
-
- for (i = 0; i < ctx->n_sheets; i++) {
- css_stylesheet_destroy(ctx->sheets[i].sheet);
- }
-
- ctx->tree = NULL;
- ctx->current = NULL;
- ctx->depth = 0;
- ctx->n_sheets = 0;
- free(ctx->sheets);
- ctx->sheets = NULL;
- ctx->target = NULL;
-
- free(buf);
-
- printf("Test %d: PASS\n", testnum);
-}
-
-void destroy_tree(node *root)
-{
- node *n, *p;
- uint32_t i;
-
- for (n = root->children; n != NULL; n = p) {
- p = n->next;
-
- destroy_tree(n);
- }
-
- css_select_results_destroy(root->sr);
-
- for (i = 0; i < root->n_attrs; ++i) {
- lwc_string_unref(root->attrs[i].name);
- lwc_string_unref(root->attrs[i].value);
- }
- free(root->attrs);
-
- if (root->classes != NULL) {
- for (i = 0; i < root->n_classes; ++i) {
- lwc_string_unref(root->classes[i]);
- }
- free(root->classes);
- }
-
- if (root->libcss_node_data != NULL) {
- css_libcss_node_data_handler(&select_handler, CSS_NODE_DELETED,
- NULL, root, NULL, root->libcss_node_data);
- }
-
- lwc_string_unref(root->name);
- free(root);
-}
-
-
-css_error node_name(void *pw, void *n, css_qname *qname)
-{
- node *node = n;
-
- UNUSED(pw);
-
- qname->name = lwc_string_ref(node->name);
-
- return CSS_OK;
-}
-
-static css_error node_classes(void *pw, void *n,
- lwc_string ***classes, uint32_t *n_classes)
-{
- unsigned int i;
- node *node = n;
- UNUSED(pw);
-
- *classes = node->classes;
- *n_classes = node->n_classes;
-
- for (i = 0; i < *n_classes; i++)
- (*classes)[i] = lwc_string_ref(node->classes[i]);
-
- return CSS_OK;
-
-}
-
-css_error node_id(void *pw, void *n,
- lwc_string **id)
-{
- node *node = n;
- uint32_t i;
- line_ctx *lc = pw;
-
- for (i = 0; i < node->n_attrs; i++) {
- bool amatch = false;
- assert(lwc_string_caseless_isequal(
- node->attrs[i].name, lc->attr_id, &amatch) ==
- lwc_error_ok);
- if (amatch == true)
- break;
- }
-
- if (i != node->n_attrs)
- *id = lwc_string_ref(node->attrs[i].value);
- else
- *id = NULL;
-
- return CSS_OK;
-}
-
-css_error named_ancestor_node(void *pw, void *n,
- const css_qname *qname,
- void **ancestor)
-{
- node *node = n;
- UNUSED(pw);
-
- for (node = node->parent; node != NULL; node = node->parent) {
- bool match = false;
- assert(lwc_string_caseless_isequal(
- qname->name, node->name,
- &match) == lwc_error_ok);
- if (match == true)
- break;
- }
-
- *ancestor = (void *) node;
-
- return CSS_OK;
-}
-
-css_error named_parent_node(void *pw, void *n,
- const css_qname *qname,
- void **parent)
-{
- node *node = n;
- UNUSED(pw);
-
- *parent = NULL;
- if (node->parent != NULL) {
- bool match = false;
- assert(lwc_string_caseless_isequal(
- qname->name, node->parent->name, &match) ==
- lwc_error_ok);
- if (match == true)
- *parent = (void *) node->parent;
- }
-
- return CSS_OK;
-}
-
-css_error named_sibling_node(void *pw, void *n,
- const css_qname *qname,
- void **sibling)
-{
- node *node = n;
- UNUSED(pw);
-
- *sibling = NULL;
- if (node->prev != NULL) {
- bool match = false;
- assert(lwc_string_caseless_isequal(
- qname->name, node->prev->name, &match) ==
- lwc_error_ok);
- if (match == true)
- *sibling = (void *) node->prev;
- }
-
- return CSS_OK;
-}
-
-css_error named_generic_sibling_node(void *pw, void *n,
- const css_qname *qname,
- void **sibling)
-{
- node *node = n;
- UNUSED(pw);
-
- for (node = node->prev; node != NULL; node = node->prev) {
- bool match = false;
- assert(lwc_string_caseless_isequal(
- qname->name, node->name,
- &match) == lwc_error_ok);
- if (match == true)
- break;
- }
-
- *sibling = (void *) node;
-
- return CSS_OK;
-}
-
-css_error parent_node(void *pw, void *n, void **parent)
-{
- node *node = n;
-
- UNUSED(pw);
-
- *parent = (void *) node->parent;
-
- return CSS_OK;
-}
-
-css_error sibling_node(void *pw, void *n, void **sibling)
-{
- node *node = n;
-
- UNUSED(pw);
-
- *sibling = (void *) node->prev;
-
- return CSS_OK;
-}
-
-css_error node_has_name(void *pw, void *n,
- const css_qname *qname,
- bool *match)
-{
- node *node = n;
- UNUSED(pw);
-
- if (lwc_string_length(qname->name) == 1 &&
- lwc_string_data(qname->name)[0] == '*')
- *match = true;
- else
- assert(lwc_string_caseless_isequal(node->name,
- qname->name, match) == lwc_error_ok);
-
- return CSS_OK;
-}
-
-css_error node_has_class(void *pw, void *n,
- lwc_string *name,
- bool *match)
-{
- node *node = n;
- uint32_t i;
- line_ctx *ctx = pw;
-
- for (i = 0; i < node->n_attrs; i++) {
- bool amatch = false;
- assert(lwc_string_caseless_isequal(
- node->attrs[i].name, ctx->attr_class,
- &amatch) == lwc_error_ok);
- if (amatch == true)
- break;
- }
-
- /* Classes are case-sensitive in HTML */
- if (i != node->n_attrs && name == node->attrs[i].value)
- *match = true;
- else
- *match = false;
-
- return CSS_OK;
-}
-
-css_error node_has_id(void *pw, void *n,
- lwc_string *name,
- bool *match)
-{
- node *node = n;
- uint32_t i;
- line_ctx *ctx = pw;
-
- for (i = 0; i < node->n_attrs; i++) {
- bool amatch = false;
- assert(lwc_string_caseless_isequal(
- node->attrs[i].name, ctx->attr_id, &amatch) ==
- lwc_error_ok);
- if (amatch == true)
- break;
- }
-
- /* IDs are case-sensitive in HTML */
- if (i != node->n_attrs && name == node->attrs[i].value)
- *match = true;
- else
- *match = false;
-
- return CSS_OK;
-}
-
-css_error node_has_attribute(void *pw, void *n,
- const css_qname *qname,
- bool *match)
-{
- node *node = n;
- uint32_t i;
- UNUSED(pw);
-
- *match = false;
- for (i = 0; i < node->n_attrs; i++) {
- assert(lwc_string_caseless_isequal(
- node->attrs[i].name, qname->name, match) ==
- lwc_error_ok);
- if (*match == true)
- break;
- }
-
- return CSS_OK;
-}
-
-css_error node_has_attribute_equal(void *pw, void *n,
- const css_qname *qname,
- lwc_string *value,
- bool *match)
-{
- node *node = n;
- uint32_t i;
- UNUSED(pw);
-
- *match = false;
-
- for (i = 0; i < node->n_attrs; i++) {
- assert(lwc_string_caseless_isequal(
- node->attrs[i].name, qname->name, match) ==
- lwc_error_ok);
- if (*match == true)
- break;
- }
-
- if (*match == true) {
- assert(lwc_string_caseless_isequal(
- node->attrs[i].name, value, match) ==
- lwc_error_ok);
- }
-
- return CSS_OK;
-}
-
-css_error node_has_attribute_includes(void *pw, void *n,
- const css_qname *qname,
- lwc_string *value,
- bool *match)
-{
- node *node = n;
- uint32_t i;
- size_t vlen = lwc_string_length(value);
- UNUSED(pw);
-
- *match = false;
-
- for (i = 0; i < node->n_attrs; i++) {
- assert(lwc_string_caseless_isequal(
- node->attrs[i].name, qname->name, match) ==
- lwc_error_ok);
- if (*match == true)
- break;
- }
-
- if (*match == true) {
- const char *p;
- const char *start = lwc_string_data(node->attrs[i].value);
- const char *end = start +
- lwc_string_length(node->attrs[i].value);
-
- *match = false;
-
- for (p = start; p < end; p++) {
- if (*p == ' ') {
- if ((size_t) (p - start) == vlen &&
- strncasecmp(start,
- lwc_string_data(value),
- vlen) == 0) {
- *match = true;
- break;
- }
-
- start = p + 1;
- }
- }
- }
-
- return CSS_OK;
-}
-
-css_error node_has_attribute_dashmatch(void *pw, void *n,
- const css_qname *qname,
- lwc_string *value,
- bool *match)
-{
- node *node = n;
- uint32_t i;
- size_t vlen = lwc_string_length(value);
- UNUSED(pw);
-
- *match = false;
-
- for (i = 0; i < node->n_attrs; i++) {
- assert(lwc_string_caseless_isequal(
- node->attrs[i].name, qname->name, match) ==
- lwc_error_ok);
- if (*match == true)
- break;
- }
-
- if (*match == true) {
- const char *p;
- const char *start = lwc_string_data(node->attrs[i].value);
- const char *end = start +
- lwc_string_length(node->attrs[i].value);
-
- *match = false;
-
- for (p = start; p < end; p++) {
- if (*p == '-') {
- if ((size_t) (p - start) == vlen &&
- strncasecmp(start,
- lwc_string_data(value),
- vlen) == 0) {
- *match = true;
- break;
- }
-
- start = p + 1;
- }
- }
- }
-
- return CSS_OK;
-}
-
-css_error node_has_attribute_prefix(void *pw, void *n,
- const css_qname *qname,
- lwc_string *value,
- bool *match)
-{
- node *node = n;
- uint32_t i;
- UNUSED(pw);
-
- *match = false;
-
- for (i = 0; i < node->n_attrs; i++) {
- assert(lwc_string_caseless_isequal(
- node->attrs[i].name, qname->name, match) ==
- lwc_error_ok);
- if (*match == true)
- break;
- }
-
- if (*match == true) {
- size_t len = lwc_string_length(node->attrs[i].value);
- const char *data = lwc_string_data(node->attrs[i].value);
-
- size_t vlen = lwc_string_length(value);
- const char *vdata = lwc_string_data(value);
-
- if (len < vlen)
- *match = false;
- else
- *match = (strncasecmp(data, vdata, vlen) == 0);
- }
-
- return CSS_OK;
-}
-
-css_error node_has_attribute_suffix(void *pw, void *n,
- const css_qname *qname,
- lwc_string *value,
- bool *match)
-{
- node *node = n;
- uint32_t i;
- UNUSED(pw);
-
- *match = false;
-
- for (i = 0; i < node->n_attrs; i++) {
- assert(lwc_string_caseless_isequal(
- node->attrs[i].name, qname->name, match) ==
- lwc_error_ok);
- if (*match == true)
- break;
- }
-
- if (*match == true) {
- size_t len = lwc_string_length(node->attrs[i].value);
- const char *data = lwc_string_data(node->attrs[i].value);
-
- size_t vlen = lwc_string_length(value);
- const char *vdata = lwc_string_data(value);
-
- size_t suffix_start = len - vlen;
-
- if (len < vlen)
- *match = false;
- else {
- *match = (strncasecmp(data + suffix_start,
- vdata, vlen) == 0);
- }
- }
-
- return CSS_OK;
-}
-
-css_error node_has_attribute_substring(void *pw, void *n,
- const css_qname *qname,
- lwc_string *value,
- bool *match)
-{
- node *node = n;
- uint32_t i;
- UNUSED(pw);
-
- *match = false;
-
- for (i = 0; i < node->n_attrs; i++) {
- assert(lwc_string_caseless_isequal(
- node->attrs[i].name, qname->name, match) ==
- lwc_error_ok);
- if (*match == true)
- break;
- }
-
- if (*match == true) {
- size_t len = lwc_string_length(node->attrs[i].value);
- const char *data = lwc_string_data(node->attrs[i].value);
-
- size_t vlen = lwc_string_length(value);
- const char *vdata = lwc_string_data(value);
-
- const char *last_start = data + len - vlen;
-
- if (len < vlen)
- *match = false;
- else {
- while (data <= last_start) {
- if (strncasecmp(data, vdata, vlen) == 0) {
- *match = true;
- break;
- }
-
- data++;
- }
-
- if (data > last_start)
- *match = false;
- }
- }
-
- return CSS_OK;
-}
-
-css_error node_is_root(void *pw, void *n, bool *match)
-{
- node *node = n;
- UNUSED(pw);
-
- *match = (node->parent == NULL);
-
- return CSS_OK;
-}
-
-css_error node_count_siblings(void *pw, void *n,
- bool same_name, bool after, int32_t *count)
-{
- int32_t cnt = 0;
- bool match = false;
- node *node = n;
- lwc_string *name = node->name;
- UNUSED(pw);
-
- if (after) {
- while (node->next != NULL) {
- if (same_name) {
- assert(lwc_string_caseless_isequal(
- name, node->next->name, &match) ==
- lwc_error_ok);
-
- if (match)
- cnt++;
- } else {
- cnt++;
- }
-
- node = node->next;
- }
- } else {
- while (node->prev != NULL) {
- if (same_name) {
- assert(lwc_string_caseless_isequal(
- name, node->prev->name, &match) ==
- lwc_error_ok);
-
- if (match)
- cnt++;
- } else {
- cnt++;
- }
-
- node = node->prev;
- }
- }
-
- *count = cnt;
-
- return CSS_OK;
-}
-
-css_error node_is_empty(void *pw, void *n, bool *match)
-{
- node *node = n;
- UNUSED(pw);
-
- *match = (node->children == NULL);
-
- 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_enabled(void *pw, void *n, bool *match)
-{
- node *node = n;
-
- UNUSED(pw);
- UNUSED(node);
-
- *match = false;
-
- return CSS_OK;
-}
-
-css_error node_is_disabled(void *pw, void *n, bool *match)
-{
- node *node = n;
-
- UNUSED(pw);
- UNUSED(node);
-
- *match = false;
-
- return CSS_OK;
-}
-
-css_error node_is_checked(void *pw, void *n, bool *match)
-{
- node *node = n;
-
- UNUSED(pw);
- UNUSED(node);
-
- *match = false;
-
- return CSS_OK;
-}
-
-css_error node_is_target(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,
- lwc_string *lang,
- bool *match)
-{
- node *node = n;
-
- UNUSED(pw);
- UNUSED(node);
- UNUSED(lang);
-
- *match = false;
-
- return CSS_OK;
-}
-
-css_error node_presentational_hint(void *pw, void *node,
- uint32_t *nhints, css_hint **hints)
-{
- UNUSED(pw);
- UNUSED(node);
-
- *nhints = 0;
- *hints = NULL;
-
- return CSS_OK;
-}
-
-css_error ua_default_for_property(void *pw, uint32_t property, css_hint *hint)
-{
- UNUSED(pw);
-
- if (property == CSS_PROP_COLOR) {
- hint->data.color = 0xff000000;
- hint->status = CSS_COLOR_COLOR;
- } else if (property == CSS_PROP_FONT_FAMILY) {
- hint->data.strings = NULL;
- hint->status = CSS_FONT_FAMILY_SANS_SERIF;
- } else if (property == CSS_PROP_QUOTES) {
- /* Not exactly useful :) */
- hint->data.strings = NULL;
- hint->status = CSS_QUOTES_NONE;
- } else if (property == CSS_PROP_VOICE_FAMILY) {
- /** \todo Fix this when we have voice-family done */
- hint->data.strings = NULL;
- hint->status = 0;
- } else {
- return CSS_INVALID;
- }
-
- return CSS_OK;
-}
-
-css_error compute_font_size(void *pw, const css_hint *parent, css_hint *size)
-{
- static css_hint_length sizes[] = {
- { FLTTOFIX(6.75), CSS_UNIT_PT },
- { FLTTOFIX(7.50), CSS_UNIT_PT },
- { FLTTOFIX(9.75), CSS_UNIT_PT },
- { FLTTOFIX(12.0), CSS_UNIT_PT },
- { FLTTOFIX(13.5), CSS_UNIT_PT },
- { FLTTOFIX(18.0), CSS_UNIT_PT },
- { FLTTOFIX(24.0), CSS_UNIT_PT }
- };
- const css_hint_length *parent_size;
-
- UNUSED(pw);
-
- /* Grab parent size, defaulting to medium if none */
- if (parent == NULL) {
- parent_size = &sizes[CSS_FONT_SIZE_MEDIUM - 1];
- } else {
- assert(parent->status == CSS_FONT_SIZE_DIMENSION);
- assert(parent->data.length.unit != CSS_UNIT_EM);
- assert(parent->data.length.unit != CSS_UNIT_EX);
- parent_size = &parent->data.length;
- }
-
- assert(size->status != CSS_FONT_SIZE_INHERIT);
-
- if (size->status < CSS_FONT_SIZE_LARGER) {
- /* Keyword -- simple */
- size->data.length = sizes[size->status - 1];
- } else if (size->status == CSS_FONT_SIZE_LARGER) {
- /** \todo Step within table, if appropriate */
- size->data.length.value =
- FMUL(parent_size->value, FLTTOFIX(1.2));
- size->data.length.unit = parent_size->unit;
- } else if (size->status == CSS_FONT_SIZE_SMALLER) {
- /** \todo Step within table, if appropriate */
- size->data.length.value =
- FMUL(parent_size->value, FLTTOFIX(1.2));
- size->data.length.unit = parent_size->unit;
- } else if (size->data.length.unit == CSS_UNIT_EM ||
- size->data.length.unit == CSS_UNIT_EX) {
- size->data.length.value =
- FMUL(size->data.length.value, parent_size->value);
-
- if (size->data.length.unit == CSS_UNIT_EX) {
- size->data.length.value = FMUL(size->data.length.value,
- FLTTOFIX(0.6));
- }
-
- size->data.length.unit = parent_size->unit;
- } else if (size->data.length.unit == CSS_UNIT_PCT) {
- size->data.length.value = FDIV(FMUL(size->data.length.value,
- parent_size->value), FLTTOFIX(100));
- size->data.length.unit = parent_size->unit;
- }
-
- size->status = CSS_FONT_SIZE_DIMENSION;
-
- return CSS_OK;
-}
-
-static css_error set_libcss_node_data(void *pw, void *n,
- void *libcss_node_data)
-{
- node *node = n;
- UNUSED(pw);
-
- node->libcss_node_data = libcss_node_data;
-
- return CSS_OK;
-}
-
-
diff --git a/test/select-nd.c b/test/select-nd.c
deleted file mode 100644
index 6469267..0000000
--- a/test/select-nd.c
+++ /dev/null
@@ -1,14 +0,0 @@
-
-#include "select-common.c"
-
-static css_error get_libcss_node_data(void *pw, void *n,
- void **libcss_node_data)
-{
- node *node = n;
- UNUSED(pw);
-
- /* Pass any node data back to libcss */
- *libcss_node_data = node->libcss_node_data;
-
- return CSS_OK;
-}
diff --git a/test/select-no-nd.c b/test/select-no-nd.c
deleted file mode 100644
index 8eb3735..0000000
--- a/test/select-no-nd.c
+++ /dev/null
@@ -1,14 +0,0 @@
-
-#include "select-common.c"
-
-static css_error get_libcss_node_data(void *pw, void *n,
- void **libcss_node_data)
-{
- UNUSED(pw);
- UNUSED(n);
-
- /* Test case were node data is deleted, by not passing any node data */
- *libcss_node_data = NULL;
-
- return CSS_OK;
-}
diff --git a/test/select.c b/test/select.c
new file mode 100644
index 0000000..4146355
--- /dev/null
+++ b/test/select.c
@@ -0,0 +1,1693 @@
+#include <ctype.h>
+#include <inttypes.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <libcss/libcss.h>
+#include <libcss/computed.h>
+#include <libcss/select.h>
+#include <libcss/stylesheet.h>
+
+#include "utils/utils.h"
+
+#include "dump_computed.h"
+#include "testutils.h"
+
+typedef struct attribute {
+ lwc_string *name;
+ lwc_string *value;
+} attribute;
+
+typedef struct node {
+ lwc_string *name;
+
+ uint32_t n_classes;
+ lwc_string **classes;
+
+ uint32_t n_attrs;
+ attribute *attrs;
+
+ css_select_results *sr;
+ void *libcss_node_data;
+
+ struct node *parent;
+ struct node *next;
+ struct node *prev;
+ struct node *children;
+ struct node *last_child;
+} node;
+
+typedef struct sheet_ctx {
+ css_stylesheet *sheet;
+ css_origin origin;
+ uint64_t media;
+} sheet_ctx;
+
+typedef struct line_ctx {
+ size_t explen;
+ size_t expused;
+ char *exp;
+
+ bool intree;
+ bool insheet;
+ bool inerrors;
+ bool inexp;
+
+ node *tree;
+ node *current;
+ uint32_t depth;
+
+ uint32_t n_sheets;
+ sheet_ctx *sheets;
+
+ uint64_t media;
+ uint32_t pseudo_element;
+ node *target;
+
+ lwc_string *attr_class;
+ lwc_string *attr_id;
+} line_ctx;
+
+
+
+
+static bool handle_line(const char *data, size_t datalen, void *pw);
+static void css__parse_tree(line_ctx *ctx, const char *data, size_t len);
+static void css__parse_tree_data(line_ctx *ctx, const char *data, size_t len);
+static void css__parse_sheet(line_ctx *ctx, const char *data, size_t len);
+static void css__parse_media_list(const char **data, size_t *len, uint64_t
*media);
+static void css__parse_pseudo_list(const char **data, size_t *len,
+ uint32_t *element);
+static void css__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);
+
+static css_error node_name(void *pw, void *node,
+ css_qname *qname);
+static css_error node_classes(void *pw, void *n,
+ lwc_string ***classes, uint32_t *n_classes);
+static css_error node_id(void *pw, void *node,
+ lwc_string **id);
+static css_error named_ancestor_node(void *pw, void *node,
+ const css_qname *qname,
+ void **ancestor);
+static css_error named_parent_node(void *pw, void *node,
+ const css_qname *qname,
+ void **parent);
+static css_error named_sibling_node(void *pw, void *node,
+ const css_qname *qname,
+ void **sibling);
+static css_error named_generic_sibling_node(void *pw, void *node,
+ const css_qname *qname,
+ void **sibling);
+static css_error parent_node(void *pw, void *node, void **parent);
+static css_error sibling_node(void *pw, void *node, void **sibling);
+static css_error node_has_name(void *pw, void *node,
+ const css_qname *qname,
+ bool *match);
+static css_error node_has_class(void *pw, void *node,
+ lwc_string *name,
+ bool *match);
+static css_error node_has_id(void *pw, void *node,
+ lwc_string *name,
+ bool *match);
+static css_error node_has_attribute(void *pw, void *node,
+ const css_qname *qname,
+ bool *match);
+static css_error node_has_attribute_equal(void *pw, void *node,
+ const css_qname *qname,
+ lwc_string *value,
+ bool *match);
+static css_error node_has_attribute_dashmatch(void *pw, void *node,
+ const css_qname *qname,
+ lwc_string *value,
+ bool *match);
+static css_error node_has_attribute_includes(void *pw, void *node,
+ const css_qname *qname,
+ lwc_string *value,
+ bool *match);
+static css_error node_has_attribute_prefix(void *pw, void *node,
+ const css_qname *qname,
+ lwc_string *value,
+ bool *match);
+static css_error node_has_attribute_suffix(void *pw, void *node,
+ const css_qname *qname,
+ lwc_string *value,
+ bool *match);
+static css_error node_has_attribute_substring(void *pw, void *node,
+ const css_qname *qname,
+ lwc_string *value,
+ bool *match);
+static css_error node_is_root(void *pw, void *node, bool *match);
+static css_error node_count_siblings(void *pw, void *node,
+ bool same_name, bool after, int32_t *count);
+static css_error node_is_empty(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_enabled(void *pw, void *node, bool *match);
+static css_error node_is_disabled(void *pw, void *node, bool *match);
+static css_error node_is_checked(void *pw, void *node, bool *match);
+static css_error node_is_target(void *pw, void *node, bool *match);
+static css_error node_is_lang(void *pw, void *node,
+ lwc_string *lang, bool *match);
+static css_error node_presentational_hint(void *pw, void *node,
+ uint32_t *nhints, css_hint **hints);
+static css_error ua_default_for_property(void *pw, uint32_t property,
+ css_hint *hints);
+static css_error compute_font_size(void *pw, const css_hint *parent,
+ css_hint *size);
+static css_error set_libcss_node_data(void *pw, void *n,
+ void *libcss_node_data);
+static css_error get_libcss_node_data(void *pw, void *n,
+ void **libcss_node_data);
+
+static css_select_handler select_handler = {
+ CSS_SELECT_HANDLER_VERSION_1,
+
+ node_name,
+ node_classes,
+ node_id,
+ named_ancestor_node,
+ named_parent_node,
+ named_sibling_node,
+ named_generic_sibling_node,
+ parent_node,
+ sibling_node,
+ node_has_name,
+ node_has_class,
+ node_has_id,
+ node_has_attribute,
+ node_has_attribute_equal,
+ node_has_attribute_dashmatch,
+ node_has_attribute_includes,
+ node_has_attribute_prefix,
+ node_has_attribute_suffix,
+ node_has_attribute_substring,
+ node_is_root,
+ node_count_siblings,
+ node_is_empty,
+ node_is_link,
+ node_is_visited,
+ node_is_hover,
+ node_is_active,
+ node_is_focus,
+ node_is_enabled,
+ node_is_disabled,
+ node_is_checked,
+ node_is_target,
+ node_is_lang,
+ node_presentational_hint,
+ ua_default_for_property,
+ compute_font_size,
+ set_libcss_node_data,
+ get_libcss_node_data
+};
+
+static css_error resolve_url(void *pw,
+ const char *base, lwc_string *rel, lwc_string **abs)
+{
+ UNUSED(pw);
+ UNUSED(base);
+
+ /* About as useless as possible */
+ *abs = lwc_string_ref(rel);
+
+ return CSS_OK;
+}
+
+static bool fail_because_lwc_leaked = false;
+
+static void
+printing_lwc_iterator(lwc_string *str, void *pw)
+{
+ UNUSED(pw);
+
+ printf(" DICT: %*s\n", (int)(lwc_string_length(str)),
lwc_string_data(str));
+ fail_because_lwc_leaked = true;
+}
+
+int main(int argc, char **argv)
+{
+ line_ctx ctx;
+
+ if (argc != 2) {
+ printf("Usage: %s <filename>\n", argv[0]);
+ return 1;
+ }
+
+ memset(&ctx, 0, sizeof(ctx));
+
+
+ lwc_intern_string("class", SLEN("class"), &ctx.attr_class);
+ lwc_intern_string("id", SLEN("id"), &ctx.attr_id);
+
+ assert(css__parse_testfile(argv[1], handle_line, &ctx) == true);
+
+ /* and run final test */
+ if (ctx.tree != NULL)
+ run_test(&ctx, ctx.exp, ctx.expused);
+
+ free(ctx.exp);
+
+ lwc_string_unref(ctx.attr_class);
+ lwc_string_unref(ctx.attr_id);
+
+ lwc_iterate_strings(printing_lwc_iterator, NULL);
+
+ assert(fail_because_lwc_leaked == false);
+
+ printf("PASS\n");
+ return 0;
+}
+
+bool handle_line(const char *data, size_t datalen, void *pw)
+{
+ line_ctx *ctx = (line_ctx *) pw;
+ css_error error;
+
+ if (data[0] == '#') {
+ if (ctx->intree) {
+ if (strncasecmp(data+1, "errors", 6) == 0) {
+ ctx->intree = false;
+ ctx->insheet = false;
+ ctx->inerrors = true;
+ ctx->inexp = false;
+ } else {
+ /* Assume start of stylesheet */
+ css__parse_sheet(ctx, data + 1, datalen - 1);
+
+ ctx->intree = false;
+ ctx->insheet = true;
+ ctx->inerrors = false;
+ ctx->inexp = false;
+ }
+ } else if (ctx->insheet) {
+ if (strncasecmp(data+1, "errors", 6) == 0) {
+ assert(css_stylesheet_data_done(
+ ctx->sheets[ctx->n_sheets - 1].sheet)
+ == CSS_OK);
+
+ ctx->intree = false;
+ ctx->insheet = false;
+ ctx->inerrors = true;
+ ctx->inexp = false;
+ } else if (strncasecmp(data+1, "ua", 2) == 0 ||
+ strncasecmp(data+1, "user", 4) == 0 ||
+ strncasecmp(data+1, "author", 6) == 0) {
+ assert(css_stylesheet_data_done(
+ ctx->sheets[ctx->n_sheets - 1].sheet)
+ == CSS_OK);
+
+ css__parse_sheet(ctx, data + 1, datalen - 1);
+ } else {
+ error = css_stylesheet_append_data(
+ ctx->sheets[ctx->n_sheets - 1].sheet,
+ (const uint8_t *) data,
+ datalen);
+ assert(error == CSS_OK ||
+ error == CSS_NEEDDATA);
+ }
+ } else if (ctx->inerrors) {
+ ctx->intree = false;
+ ctx->insheet = false;
+ ctx->inerrors = false;
+ ctx->inexp = true;
+ } else if (ctx->inexp) {
+ /* This marks end of testcase, so run it */
+ run_test(ctx, ctx->exp, ctx->expused);
+
+ ctx->expused = 0;
+
+ ctx->intree = false;
+ ctx->insheet = false;
+ ctx->inerrors = false;
+ ctx->inexp = false;
+ } else {
+ /* Start state */
+ if (strncasecmp(data+1, "tree", 4) == 0) {
+ css__parse_tree(ctx, data + 5, datalen - 5);
+
+ ctx->intree = true;
+ ctx->insheet = false;
+ ctx->inerrors = false;
+ ctx->inexp = false;
+ }
+ }
+ } else {
+ if (ctx->intree) {
+ /* Not interested in the '|' */
+ css__parse_tree_data(ctx, data + 1, datalen - 1);
+ } else if (ctx->insheet) {
+ error = css_stylesheet_append_data(
+ ctx->sheets[ctx->n_sheets - 1].sheet,
+ (const uint8_t *) data, datalen);
+ assert(error == CSS_OK || error == CSS_NEEDDATA);
+ } else if (ctx->inexp) {
+ css__parse_expected(ctx, data, datalen);
+ }
+ }
+
+ return true;
+}
+
+void css__parse_tree(line_ctx *ctx, const char *data, size_t len)
+{
+ const char *p = data;
+ const char *end = data + len;
+ size_t left;
+
+ /* [ <media_list> <pseudo>? ] ? */
+
+ ctx->media = CSS_MEDIA_ALL;
+ ctx->pseudo_element = CSS_PSEUDO_ELEMENT_NONE;
+
+ /* Consume any leading whitespace */
+ while (p < end && isspace(*p))
+ p++;
+
+ if (p < end) {
+ left = end - p;
+
+ css__parse_media_list(&p, &left, &ctx->media);
+
+ end = p + left;
+ }
+
+ if (p < end) {
+ left = end - p;
+
+ css__parse_pseudo_list(&p, &left, &ctx->pseudo_element);
+ }
+}
+
+void css__parse_tree_data(line_ctx *ctx, const char *data, size_t len)
+{
+ const char *p = data;
+ const char *end = data + len;
+ const char *name = NULL;
+ const char *value = NULL;
+ size_t namelen = 0;
+ size_t valuelen = 0;
+ uint32_t depth = 0;
+ bool target = false;
+
+ /* ' '{depth+1} [ <element> '*'? | <attr> ]
+ *
+ * <element> ::= [^=*[:space:]]+
+ * <attr> ::= [^=*[:space:]]+ '=' [^[:space:]]*
+ */
+
+ while (p < end && isspace(*p)) {
+ depth++;
+ p++;
+ }
+ depth--;
+
+ /* Get element/attribute name */
+ name = p;
+ while (p < end && *p != '=' && *p != '*' && isspace(*p) == false) {
+ namelen++;
+ p++;
+ }
+
+ /* Skip whitespace */
+ while (p < end && isspace(*p))
+ p++;
+
+ if (p < end && *p == '=') {
+ /* Attribute value */
+ p++;
+
+ value = p;
+
+ while (p < end && isspace(*p) == false) {
+ valuelen++;
+ p++;
+ }
+ } else if (p < end && *p == '*') {
+ /* Element is target node */
+ target = true;
+ }
+
+ if (value == NULL) {
+ /* We have an element, so create it */
+ node *n = malloc(sizeof(node));
+ assert(n != NULL);
+
+ memset(n, 0, sizeof(node));
+
+ lwc_intern_string(name, namelen, &n->name);
+
+ /* Insert it into tree */
+ if (ctx->tree == NULL) {
+ ctx->tree = n;
+ } else {
+ assert(depth > 0);
+ assert(depth <= ctx->depth + 1);
+
+ /* Find node to insert into */
+ while (depth <= ctx->depth) {
+ ctx->depth--;
+ ctx->current = ctx->current->parent;
+ }
+
+ /* Insert into current node */
+ if (ctx->current->children == NULL) {
+ ctx->current->children = n;
+ ctx->current->last_child = n;
+ } else {
+ ctx->current->last_child->next = n;
+ n->prev = ctx->current->last_child;
+
+ ctx->current->last_child = n;
+ }
+ n->parent = ctx->current;
+ }
+
+ ctx->current = n;
+ ctx->depth = depth;
+
+ /* Mark the target, if it's us */
+ if (target)
+ ctx->target = n;
+ } else {
+ /* New attribute */
+ bool amatch = false;
+ attribute *attr;
+ node *n = ctx->current;
+
+ attribute *temp = realloc(n->attrs,
+ (n->n_attrs + 1) * sizeof(attribute));
+ assert(temp != NULL);
+
+ n->attrs = temp;
+
+ attr = &n->attrs[n->n_attrs];
+
+ lwc_intern_string(name, namelen, &attr->name);
+ lwc_intern_string(value, valuelen, &attr->value);
+
+ assert(lwc_string_caseless_isequal(
+ n->attrs[n->n_attrs].name,
+ ctx->attr_class, &amatch) == lwc_error_ok);
+ if (amatch == true) {
+ n->classes = realloc(NULL, sizeof(lwc_string **));
+ assert(n->classes != NULL);
+
+ n->classes[0] = lwc_string_ref(
+ n->attrs[n->n_attrs].
+ value);
+ n->n_classes = 1;
+ }
+
+ n->n_attrs++;
+ }
+}
+
+void css__parse_sheet(line_ctx *ctx, const char *data, size_t len)
+{
+ css_stylesheet_params params;
+ const char *p;
+ const char *end = data + len;
+ css_origin origin = CSS_ORIGIN_AUTHOR;
+ uint64_t media = CSS_MEDIA_ALL;
+ css_stylesheet *sheet;
+ sheet_ctx *temp;
+
+ /* <origin> <media_list>? */
+
+ /* Find end of origin */
+ for (p = data; p < end; p++) {
+ if (isspace(*p))
+ break;
+ }
+
+ if (p - data == 6 && strncasecmp(data, "author", 6) == 0)
+ origin = CSS_ORIGIN_AUTHOR;
+ else if (p - data == 4 && strncasecmp(data, "user", 4) == 0)
+ origin = CSS_ORIGIN_USER;
+ else if (p - data == 2 && strncasecmp(data, "ua", 2) == 0)
+ origin = CSS_ORIGIN_UA;
+ else
+ assert(0 && "Unknown stylesheet origin");
+
+ /* Skip any whitespace */
+ while (p < end && isspace(*p))
+ p++;
+
+ if (p < end) {
+ size_t ignored = end - p;
+
+ css__parse_media_list(&p, &ignored, &media);
+ }
+
+ params.params_version = CSS_STYLESHEET_PARAMS_VERSION_1;
+ params.level = CSS_LEVEL_21;
+ params.charset = "UTF-8";
+ params.url = "foo";
+ params.title = "foo";
+ params.allow_quirks = false;
+ params.inline_style = false;
+ params.resolve = resolve_url;
+ params.resolve_pw = NULL;
+ params.import = NULL;
+ params.import_pw = NULL;
+ params.color = NULL;
+ params.color_pw = NULL;
+ params.font = NULL;
+ params.font_pw = NULL;
+
+ /** \todo How are we going to handle @import? */
+ assert(css_stylesheet_create(¶ms, &sheet) == CSS_OK);
+
+ /* Extend array of sheets and append new sheet to it */
+ temp = realloc(ctx->sheets,
+ (ctx->n_sheets + 1) * sizeof(sheet_ctx));
+ assert(temp != NULL);
+
+ ctx->sheets = temp;
+
+ ctx->sheets[ctx->n_sheets].sheet = sheet;
+ ctx->sheets[ctx->n_sheets].origin = origin;
+ ctx->sheets[ctx->n_sheets].media = media;
+
+ ctx->n_sheets++;
+}
+
+void css__parse_media_list(const char **data, size_t *len, uint64_t *media)
+{
+ const char *p = *data;
+ const char *end = p + *len;
+ uint64_t result = 0;
+
+ /* <medium> [ ',' <medium> ]* */
+
+ while (p < end) {
+ const char *start = p;
+
+ /* consume a medium */
+ while (isspace(*p) == false && *p != ',')
+ p++;
+
+ if (p - start == 10 &&
+ strncasecmp(start, "projection", 10) == 0)
+ result |= CSS_MEDIA_PROJECTION;
+ else if (p - start == 8 &&
+ strncasecmp(start, "handheld", 8) == 0)
+ result |= CSS_MEDIA_HANDHELD;
+ else if (p - start == 8 &&
+ strncasecmp(start, "embossed", 8) == 0)
+ result |= CSS_MEDIA_EMBOSSED;
+ else if (p - start == 7 &&
+ strncasecmp(start, "braille", 7) == 0)
+ result |= CSS_MEDIA_BRAILLE;
+ else if (p - start == 6 &&
+ strncasecmp(start, "speech", 6) == 0)
+ result |= CSS_MEDIA_SPEECH;
+ else if (p - start == 6 &&
+ strncasecmp(start, "screen", 6) == 0)
+ result |= CSS_MEDIA_SCREEN;
+ else if (p - start == 5 &&
+ strncasecmp(start, "print", 5) == 0)
+ result |= CSS_MEDIA_PRINT;
+ else if (p - start == 5 &&
+ strncasecmp(start, "aural", 5) == 0)
+ result |= CSS_MEDIA_AURAL;
+ else if (p - start == 3 &&
+ strncasecmp(start, "tty", 3) == 0)
+ result |= CSS_MEDIA_TTY;
+ else if (p - start == 3 &&
+ strncasecmp(start, "all", 3) == 0)
+ result |= CSS_MEDIA_ALL;
+ else if (p - start == 2 &&
+ strncasecmp(start, "tv", 2) == 0)
+ result |= CSS_MEDIA_TV;
+ else
+ assert(0 && "Unknown media type");
+
+ /* Consume whitespace */
+ while (p < end && isspace(*p))
+ p++;
+
+ /* Stop if we've reached the end */
+ if (p == end || *p != ',')
+ break;
+
+ /* Consume comma */
+ p++;
+
+ /* Consume whitespace */
+ while (p < end && isspace(*p))
+ p++;
+ }
+
+ *media = result;
+
+ *data = p;
+ *len = end - p;
+}
+
+void css__parse_pseudo_list(const char **data, size_t *len, uint32_t *element)
+{
+ const char *p = *data;
+ const char *end = p + *len;
+
+ /* <pseudo> [ ',' <pseudo> ]* */
+
+ *element = CSS_PSEUDO_ELEMENT_NONE;
+
+ while (p < end) {
+ const char *start = p;
+
+ /* consume a pseudo */
+ while (isspace(*p) == false && *p != ',')
+ p++;
+
+ /* Pseudo elements */
+ if (p - start == 12 &&
+ strncasecmp(start, "first-letter", 12) == 0)
+ *element = CSS_PSEUDO_ELEMENT_FIRST_LETTER;
+ else if (p - start == 10 &&
+ strncasecmp(start, "first-line", 10) == 0)
+ *element = CSS_PSEUDO_ELEMENT_FIRST_LINE;
+ else if (p - start == 6 &&
+ strncasecmp(start, "before", 6) == 0)
+ *element = CSS_PSEUDO_ELEMENT_BEFORE;
+ else if (p - start == 5 &&
+ strncasecmp(start, "after", 5) == 0)
+ *element = CSS_PSEUDO_ELEMENT_AFTER;
+ else
+ assert(0 && "Unknown pseudo");
+
+ /* Consume whitespace */
+ while (p < end && isspace(*p))
+ p++;
+
+ /* Stop if we've reached the end */
+ if (p == end || *p != ',')
+ break;
+
+ /* Consume comma */
+ p++;
+
+ /* Consume whitespace */
+ while (p < end && isspace(*p))
+ p++;
+ }
+
+ *data = p;
+ *len = end - p;
+}
+
+void css__parse_expected(line_ctx *ctx, const char *data, size_t len)
+{
+ while (ctx->expused + len >= ctx->explen) {
+ size_t required = ctx->explen == 0 ? 64 : ctx->explen * 2;
+ char *temp = realloc(ctx->exp, required);
+ if (temp == NULL) {
+ assert(0 && "No memory for expected output");
+ }
+
+ ctx->exp = temp;
+ ctx->explen = required;
+ }
+
+ memcpy(ctx->exp + ctx->expused, data, len);
+
+ ctx->expused += len;
+}
+
+static void show_differences(size_t len, const char *exp, const char *res)
+{
+ const char *pos_exp, *opos_exp;
+ const char *pos_res, *opos_res;
+
+ opos_exp = pos_exp = exp;
+ opos_res = pos_res = res;
+
+ printf("Line differences:\n");
+ while (pos_exp < exp + len && pos_res < res + len) {
+ if (*pos_exp == '\n' && *pos_res == '\n') {
+ if (pos_exp - opos_exp != pos_res - opos_res ||
+ memcmp(opos_exp, opos_res,
+ pos_exp - opos_exp) != 0) {
+ printf("Expected:\t%.*s\n",
+ (int)(pos_exp - opos_exp),
+ opos_exp);
+ printf(" Result:\t%.*s\n",
+ (int)(pos_res - opos_res),
+ opos_res);
+ printf("\n");
+ }
+ opos_exp = ++pos_exp;
+ opos_res = ++pos_res;
+ } else if (*pos_exp == '\n') {
+ pos_res++;
+ } else if (*pos_res == '\n') {
+ pos_exp++;
+ } else {
+ pos_exp++;
+ pos_res++;
+ }
+ }
+}
+
+
+static void run_test_select_tree(css_select_ctx *select,
+ node *node, line_ctx *ctx,
+ char *buf, size_t *buflen)
+{
+ css_select_results *sr;
+ struct node *n = NULL;
+
+ assert(css_select_style(select, node, ctx->media, NULL,
+ &select_handler, ctx, &sr) == CSS_OK);
+
+ if (node->parent != NULL) {
+ css_computed_style *composed;
+ assert(css_computed_style_compose(
+ node->parent->sr->styles[ctx->pseudo_element],
+ sr->styles[ctx->pseudo_element],
+ compute_font_size, NULL,
+ &composed) == CSS_OK);
+ css_computed_style_destroy(sr->styles[ctx->pseudo_element]);
+ sr->styles[ctx->pseudo_element] = composed;
+ }
+
+ node->sr = sr;
+
+ if (node == ctx->target) {
+ dump_computed_style(sr->styles[ctx->pseudo_element],
+ buf, buflen);
+ }
+
+ for (n = node->children; n != NULL; n = n->next) {
+ run_test_select_tree(select, n, ctx, buf, buflen);
+ }
+}
+
+
+void run_test(line_ctx *ctx, const char *exp, size_t explen)
+{
+ css_select_ctx *select;
+ css_select_results *results;
+ uint32_t i;
+ char *buf;
+ size_t buflen;
+ static int testnum;
+
+ UNUSED(exp);
+
+ buf = malloc(8192);
+ if (buf == NULL) {
+ assert(0 && "No memory for result data");
+ }
+ buflen = 8192;
+
+ assert(css_select_ctx_create(&select) == CSS_OK);
+
+ for (i = 0; i < ctx->n_sheets; i++) {
+ assert(css_select_ctx_append_sheet(select,
+ ctx->sheets[i].sheet, ctx->sheets[i].origin,
+ ctx->sheets[i].media) == CSS_OK);
+ }
+
+ testnum++;
+
+ run_test_select_tree(select, ctx->tree, ctx, buf, &buflen);
+
+ results = ctx->target->sr;
+ assert(results->styles[ctx->pseudo_element] != NULL);
+
+ if (8192 - buflen != explen || memcmp(buf, exp, explen) != 0) {
+ size_t len = 8192 - buflen < explen ? 8192 - buflen : explen;
+ printf("Expected (%u):\n%.*s\n",
+ (int) explen, (int) explen, exp);
+ printf("Result (%u):\n%.*s\n", (int) (8192 - buflen),
+ (int) (8192 - buflen), buf);
+
+ show_differences(len, exp, buf);
+ assert(0 && "Result doesn't match expected");
+ }
+
+ /* Clean up */
+ css_select_ctx_destroy(select);
+ destroy_tree(ctx->tree);
+
+ for (i = 0; i < ctx->n_sheets; i++) {
+ css_stylesheet_destroy(ctx->sheets[i].sheet);
+ }
+
+ ctx->tree = NULL;
+ ctx->current = NULL;
+ ctx->depth = 0;
+ ctx->n_sheets = 0;
+ free(ctx->sheets);
+ ctx->sheets = NULL;
+ ctx->target = NULL;
+
+ free(buf);
+
+ printf("Test %d: PASS\n", testnum);
+}
+
+void destroy_tree(node *root)
+{
+ node *n, *p;
+ uint32_t i;
+
+ for (n = root->children; n != NULL; n = p) {
+ p = n->next;
+
+ destroy_tree(n);
+ }
+
+ css_select_results_destroy(root->sr);
+
+ for (i = 0; i < root->n_attrs; ++i) {
+ lwc_string_unref(root->attrs[i].name);
+ lwc_string_unref(root->attrs[i].value);
+ }
+ free(root->attrs);
+
+ if (root->classes != NULL) {
+ for (i = 0; i < root->n_classes; ++i) {
+ lwc_string_unref(root->classes[i]);
+ }
+ free(root->classes);
+ }
+
+ if (root->libcss_node_data != NULL) {
+ css_libcss_node_data_handler(&select_handler, CSS_NODE_DELETED,
+ NULL, root, NULL, root->libcss_node_data);
+ }
+
+ lwc_string_unref(root->name);
+ free(root);
+}
+
+
+css_error node_name(void *pw, void *n, css_qname *qname)
+{
+ node *node = n;
+
+ UNUSED(pw);
+
+ qname->name = lwc_string_ref(node->name);
+
+ return CSS_OK;
+}
+
+static css_error node_classes(void *pw, void *n,
+ lwc_string ***classes, uint32_t *n_classes)
+{
+ unsigned int i;
+ node *node = n;
+ UNUSED(pw);
+
+ *classes = node->classes;
+ *n_classes = node->n_classes;
+
+ for (i = 0; i < *n_classes; i++)
+ (*classes)[i] = lwc_string_ref(node->classes[i]);
+
+ return CSS_OK;
+
+}
+
+css_error node_id(void *pw, void *n,
+ lwc_string **id)
+{
+ node *node = n;
+ uint32_t i;
+ line_ctx *lc = pw;
+
+ for (i = 0; i < node->n_attrs; i++) {
+ bool amatch = false;
+ assert(lwc_string_caseless_isequal(
+ node->attrs[i].name, lc->attr_id, &amatch) ==
+ lwc_error_ok);
+ if (amatch == true)
+ break;
+ }
+
+ if (i != node->n_attrs)
+ *id = lwc_string_ref(node->attrs[i].value);
+ else
+ *id = NULL;
+
+ return CSS_OK;
+}
+
+css_error named_ancestor_node(void *pw, void *n,
+ const css_qname *qname,
+ void **ancestor)
+{
+ node *node = n;
+ UNUSED(pw);
+
+ for (node = node->parent; node != NULL; node = node->parent) {
+ bool match = false;
+ assert(lwc_string_caseless_isequal(
+ qname->name, node->name,
+ &match) == lwc_error_ok);
+ if (match == true)
+ break;
+ }
+
+ *ancestor = (void *) node;
+
+ return CSS_OK;
+}
+
+css_error named_parent_node(void *pw, void *n,
+ const css_qname *qname,
+ void **parent)
+{
+ node *node = n;
+ UNUSED(pw);
+
+ *parent = NULL;
+ if (node->parent != NULL) {
+ bool match = false;
+ assert(lwc_string_caseless_isequal(
+ qname->name, node->parent->name, &match) ==
+ lwc_error_ok);
+ if (match == true)
+ *parent = (void *) node->parent;
+ }
+
+ return CSS_OK;
+}
+
+css_error named_sibling_node(void *pw, void *n,
+ const css_qname *qname,
+ void **sibling)
+{
+ node *node = n;
+ UNUSED(pw);
+
+ *sibling = NULL;
+ if (node->prev != NULL) {
+ bool match = false;
+ assert(lwc_string_caseless_isequal(
+ qname->name, node->prev->name, &match) ==
+ lwc_error_ok);
+ if (match == true)
+ *sibling = (void *) node->prev;
+ }
+
+ return CSS_OK;
+}
+
+css_error named_generic_sibling_node(void *pw, void *n,
+ const css_qname *qname,
+ void **sibling)
+{
+ node *node = n;
+ UNUSED(pw);
+
+ for (node = node->prev; node != NULL; node = node->prev) {
+ bool match = false;
+ assert(lwc_string_caseless_isequal(
+ qname->name, node->name,
+ &match) == lwc_error_ok);
+ if (match == true)
+ break;
+ }
+
+ *sibling = (void *) node;
+
+ return CSS_OK;
+}
+
+css_error parent_node(void *pw, void *n, void **parent)
+{
+ node *node = n;
+
+ UNUSED(pw);
+
+ *parent = (void *) node->parent;
+
+ return CSS_OK;
+}
+
+css_error sibling_node(void *pw, void *n, void **sibling)
+{
+ node *node = n;
+
+ UNUSED(pw);
+
+ *sibling = (void *) node->prev;
+
+ return CSS_OK;
+}
+
+css_error node_has_name(void *pw, void *n,
+ const css_qname *qname,
+ bool *match)
+{
+ node *node = n;
+ UNUSED(pw);
+
+ if (lwc_string_length(qname->name) == 1 &&
+ lwc_string_data(qname->name)[0] == '*')
+ *match = true;
+ else
+ assert(lwc_string_caseless_isequal(node->name,
+ qname->name, match) == lwc_error_ok);
+
+ return CSS_OK;
+}
+
+css_error node_has_class(void *pw, void *n,
+ lwc_string *name,
+ bool *match)
+{
+ node *node = n;
+ uint32_t i;
+ line_ctx *ctx = pw;
+
+ for (i = 0; i < node->n_attrs; i++) {
+ bool amatch = false;
+ assert(lwc_string_caseless_isequal(
+ node->attrs[i].name, ctx->attr_class,
+ &amatch) == lwc_error_ok);
+ if (amatch == true)
+ break;
+ }
+
+ /* Classes are case-sensitive in HTML */
+ if (i != node->n_attrs && name == node->attrs[i].value)
+ *match = true;
+ else
+ *match = false;
+
+ return CSS_OK;
+}
+
+css_error node_has_id(void *pw, void *n,
+ lwc_string *name,
+ bool *match)
+{
+ node *node = n;
+ uint32_t i;
+ line_ctx *ctx = pw;
+
+ for (i = 0; i < node->n_attrs; i++) {
+ bool amatch = false;
+ assert(lwc_string_caseless_isequal(
+ node->attrs[i].name, ctx->attr_id, &amatch) ==
+ lwc_error_ok);
+ if (amatch == true)
+ break;
+ }
+
+ /* IDs are case-sensitive in HTML */
+ if (i != node->n_attrs && name == node->attrs[i].value)
+ *match = true;
+ else
+ *match = false;
+
+ return CSS_OK;
+}
+
+css_error node_has_attribute(void *pw, void *n,
+ const css_qname *qname,
+ bool *match)
+{
+ node *node = n;
+ uint32_t i;
+ UNUSED(pw);
+
+ *match = false;
+ for (i = 0; i < node->n_attrs; i++) {
+ assert(lwc_string_caseless_isequal(
+ node->attrs[i].name, qname->name, match) ==
+ lwc_error_ok);
+ if (*match == true)
+ break;
+ }
+
+ return CSS_OK;
+}
+
+css_error node_has_attribute_equal(void *pw, void *n,
+ const css_qname *qname,
+ lwc_string *value,
+ bool *match)
+{
+ node *node = n;
+ uint32_t i;
+ UNUSED(pw);
+
+ *match = false;
+
+ for (i = 0; i < node->n_attrs; i++) {
+ assert(lwc_string_caseless_isequal(
+ node->attrs[i].name, qname->name, match) ==
+ lwc_error_ok);
+ if (*match == true)
+ break;
+ }
+
+ if (*match == true) {
+ assert(lwc_string_caseless_isequal(
+ node->attrs[i].name, value, match) ==
+ lwc_error_ok);
+ }
+
+ return CSS_OK;
+}
+
+css_error node_has_attribute_includes(void *pw, void *n,
+ const css_qname *qname,
+ lwc_string *value,
+ bool *match)
+{
+ node *node = n;
+ uint32_t i;
+ size_t vlen = lwc_string_length(value);
+ UNUSED(pw);
+
+ *match = false;
+
+ for (i = 0; i < node->n_attrs; i++) {
+ assert(lwc_string_caseless_isequal(
+ node->attrs[i].name, qname->name, match) ==
+ lwc_error_ok);
+ if (*match == true)
+ break;
+ }
+
+ if (*match == true) {
+ const char *p;
+ const char *start = lwc_string_data(node->attrs[i].value);
+ const char *end = start +
+ lwc_string_length(node->attrs[i].value);
+
+ *match = false;
+
+ for (p = start; p < end; p++) {
+ if (*p == ' ') {
+ if ((size_t) (p - start) == vlen &&
+ strncasecmp(start,
+ lwc_string_data(value),
+ vlen) == 0) {
+ *match = true;
+ break;
+ }
+
+ start = p + 1;
+ }
+ }
+ }
+
+ return CSS_OK;
+}
+
+css_error node_has_attribute_dashmatch(void *pw, void *n,
+ const css_qname *qname,
+ lwc_string *value,
+ bool *match)
+{
+ node *node = n;
+ uint32_t i;
+ size_t vlen = lwc_string_length(value);
+ UNUSED(pw);
+
+ *match = false;
+
+ for (i = 0; i < node->n_attrs; i++) {
+ assert(lwc_string_caseless_isequal(
+ node->attrs[i].name, qname->name, match) ==
+ lwc_error_ok);
+ if (*match == true)
+ break;
+ }
+
+ if (*match == true) {
+ const char *p;
+ const char *start = lwc_string_data(node->attrs[i].value);
+ const char *end = start +
+ lwc_string_length(node->attrs[i].value);
+
+ *match = false;
+
+ for (p = start; p < end; p++) {
+ if (*p == '-') {
+ if ((size_t) (p - start) == vlen &&
+ strncasecmp(start,
+ lwc_string_data(value),
+ vlen) == 0) {
+ *match = true;
+ break;
+ }
+
+ start = p + 1;
+ }
+ }
+ }
+
+ return CSS_OK;
+}
+
+css_error node_has_attribute_prefix(void *pw, void *n,
+ const css_qname *qname,
+ lwc_string *value,
+ bool *match)
+{
+ node *node = n;
+ uint32_t i;
+ UNUSED(pw);
+
+ *match = false;
+
+ for (i = 0; i < node->n_attrs; i++) {
+ assert(lwc_string_caseless_isequal(
+ node->attrs[i].name, qname->name, match) ==
+ lwc_error_ok);
+ if (*match == true)
+ break;
+ }
+
+ if (*match == true) {
+ size_t len = lwc_string_length(node->attrs[i].value);
+ const char *data = lwc_string_data(node->attrs[i].value);
+
+ size_t vlen = lwc_string_length(value);
+ const char *vdata = lwc_string_data(value);
+
+ if (len < vlen)
+ *match = false;
+ else
+ *match = (strncasecmp(data, vdata, vlen) == 0);
+ }
+
+ return CSS_OK;
+}
+
+css_error node_has_attribute_suffix(void *pw, void *n,
+ const css_qname *qname,
+ lwc_string *value,
+ bool *match)
+{
+ node *node = n;
+ uint32_t i;
+ UNUSED(pw);
+
+ *match = false;
+
+ for (i = 0; i < node->n_attrs; i++) {
+ assert(lwc_string_caseless_isequal(
+ node->attrs[i].name, qname->name, match) ==
+ lwc_error_ok);
+ if (*match == true)
+ break;
+ }
+
+ if (*match == true) {
+ size_t len = lwc_string_length(node->attrs[i].value);
+ const char *data = lwc_string_data(node->attrs[i].value);
+
+ size_t vlen = lwc_string_length(value);
+ const char *vdata = lwc_string_data(value);
+
+ size_t suffix_start = len - vlen;
+
+ if (len < vlen)
+ *match = false;
+ else {
+ *match = (strncasecmp(data + suffix_start,
+ vdata, vlen) == 0);
+ }
+ }
+
+ return CSS_OK;
+}
+
+css_error node_has_attribute_substring(void *pw, void *n,
+ const css_qname *qname,
+ lwc_string *value,
+ bool *match)
+{
+ node *node = n;
+ uint32_t i;
+ UNUSED(pw);
+
+ *match = false;
+
+ for (i = 0; i < node->n_attrs; i++) {
+ assert(lwc_string_caseless_isequal(
+ node->attrs[i].name, qname->name, match) ==
+ lwc_error_ok);
+ if (*match == true)
+ break;
+ }
+
+ if (*match == true) {
+ size_t len = lwc_string_length(node->attrs[i].value);
+ const char *data = lwc_string_data(node->attrs[i].value);
+
+ size_t vlen = lwc_string_length(value);
+ const char *vdata = lwc_string_data(value);
+
+ const char *last_start = data + len - vlen;
+
+ if (len < vlen)
+ *match = false;
+ else {
+ while (data <= last_start) {
+ if (strncasecmp(data, vdata, vlen) == 0) {
+ *match = true;
+ break;
+ }
+
+ data++;
+ }
+
+ if (data > last_start)
+ *match = false;
+ }
+ }
+
+ return CSS_OK;
+}
+
+css_error node_is_root(void *pw, void *n, bool *match)
+{
+ node *node = n;
+ UNUSED(pw);
+
+ *match = (node->parent == NULL);
+
+ return CSS_OK;
+}
+
+css_error node_count_siblings(void *pw, void *n,
+ bool same_name, bool after, int32_t *count)
+{
+ int32_t cnt = 0;
+ bool match = false;
+ node *node = n;
+ lwc_string *name = node->name;
+ UNUSED(pw);
+
+ if (after) {
+ while (node->next != NULL) {
+ if (same_name) {
+ assert(lwc_string_caseless_isequal(
+ name, node->next->name, &match) ==
+ lwc_error_ok);
+
+ if (match)
+ cnt++;
+ } else {
+ cnt++;
+ }
+
+ node = node->next;
+ }
+ } else {
+ while (node->prev != NULL) {
+ if (same_name) {
+ assert(lwc_string_caseless_isequal(
+ name, node->prev->name, &match) ==
+ lwc_error_ok);
+
+ if (match)
+ cnt++;
+ } else {
+ cnt++;
+ }
+
+ node = node->prev;
+ }
+ }
+
+ *count = cnt;
+
+ return CSS_OK;
+}
+
+css_error node_is_empty(void *pw, void *n, bool *match)
+{
+ node *node = n;
+ UNUSED(pw);
+
+ *match = (node->children == NULL);
+
+ 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_enabled(void *pw, void *n, bool *match)
+{
+ node *node = n;
+
+ UNUSED(pw);
+ UNUSED(node);
+
+ *match = false;
+
+ return CSS_OK;
+}
+
+css_error node_is_disabled(void *pw, void *n, bool *match)
+{
+ node *node = n;
+
+ UNUSED(pw);
+ UNUSED(node);
+
+ *match = false;
+
+ return CSS_OK;
+}
+
+css_error node_is_checked(void *pw, void *n, bool *match)
+{
+ node *node = n;
+
+ UNUSED(pw);
+ UNUSED(node);
+
+ *match = false;
+
+ return CSS_OK;
+}
+
+css_error node_is_target(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,
+ lwc_string *lang,
+ bool *match)
+{
+ node *node = n;
+
+ UNUSED(pw);
+ UNUSED(node);
+ UNUSED(lang);
+
+ *match = false;
+
+ return CSS_OK;
+}
+
+css_error node_presentational_hint(void *pw, void *node,
+ uint32_t *nhints, css_hint **hints)
+{
+ UNUSED(pw);
+ UNUSED(node);
+
+ *nhints = 0;
+ *hints = NULL;
+
+ return CSS_OK;
+}
+
+css_error ua_default_for_property(void *pw, uint32_t property, css_hint *hint)
+{
+ UNUSED(pw);
+
+ if (property == CSS_PROP_COLOR) {
+ hint->data.color = 0xff000000;
+ hint->status = CSS_COLOR_COLOR;
+ } else if (property == CSS_PROP_FONT_FAMILY) {
+ hint->data.strings = NULL;
+ hint->status = CSS_FONT_FAMILY_SANS_SERIF;
+ } else if (property == CSS_PROP_QUOTES) {
+ /* Not exactly useful :) */
+ hint->data.strings = NULL;
+ hint->status = CSS_QUOTES_NONE;
+ } else if (property == CSS_PROP_VOICE_FAMILY) {
+ /** \todo Fix this when we have voice-family done */
+ hint->data.strings = NULL;
+ hint->status = 0;
+ } else {
+ return CSS_INVALID;
+ }
+
+ return CSS_OK;
+}
+
+css_error compute_font_size(void *pw, const css_hint *parent, css_hint *size)
+{
+ static css_hint_length sizes[] = {
+ { FLTTOFIX(6.75), CSS_UNIT_PT },
+ { FLTTOFIX(7.50), CSS_UNIT_PT },
+ { FLTTOFIX(9.75), CSS_UNIT_PT },
+ { FLTTOFIX(12.0), CSS_UNIT_PT },
+ { FLTTOFIX(13.5), CSS_UNIT_PT },
+ { FLTTOFIX(18.0), CSS_UNIT_PT },
+ { FLTTOFIX(24.0), CSS_UNIT_PT }
+ };
+ const css_hint_length *parent_size;
+
+ UNUSED(pw);
+
+ /* Grab parent size, defaulting to medium if none */
+ if (parent == NULL) {
+ parent_size = &sizes[CSS_FONT_SIZE_MEDIUM - 1];
+ } else {
+ assert(parent->status == CSS_FONT_SIZE_DIMENSION);
+ assert(parent->data.length.unit != CSS_UNIT_EM);
+ assert(parent->data.length.unit != CSS_UNIT_EX);
+ parent_size = &parent->data.length;
+ }
+
+ assert(size->status != CSS_FONT_SIZE_INHERIT);
+
+ if (size->status < CSS_FONT_SIZE_LARGER) {
+ /* Keyword -- simple */
+ size->data.length = sizes[size->status - 1];
+ } else if (size->status == CSS_FONT_SIZE_LARGER) {
+ /** \todo Step within table, if appropriate */
+ size->data.length.value =
+ FMUL(parent_size->value, FLTTOFIX(1.2));
+ size->data.length.unit = parent_size->unit;
+ } else if (size->status == CSS_FONT_SIZE_SMALLER) {
+ /** \todo Step within table, if appropriate */
+ size->data.length.value =
+ FMUL(parent_size->value, FLTTOFIX(1.2));
+ size->data.length.unit = parent_size->unit;
+ } else if (size->data.length.unit == CSS_UNIT_EM ||
+ size->data.length.unit == CSS_UNIT_EX) {
+ size->data.length.value =
+ FMUL(size->data.length.value, parent_size->value);
+
+ if (size->data.length.unit == CSS_UNIT_EX) {
+ size->data.length.value = FMUL(size->data.length.value,
+ FLTTOFIX(0.6));
+ }
+
+ size->data.length.unit = parent_size->unit;
+ } else if (size->data.length.unit == CSS_UNIT_PCT) {
+ size->data.length.value = FDIV(FMUL(size->data.length.value,
+ parent_size->value), FLTTOFIX(100));
+ size->data.length.unit = parent_size->unit;
+ }
+
+ size->status = CSS_FONT_SIZE_DIMENSION;
+
+ return CSS_OK;
+}
+
+static css_error set_libcss_node_data(void *pw, void *n,
+ void *libcss_node_data)
+{
+ node *node = n;
+ UNUSED(pw);
+
+ node->libcss_node_data = libcss_node_data;
+
+ return CSS_OK;
+}
+
+static css_error get_libcss_node_data(void *pw, void *n,
+ void **libcss_node_data)
+{
+ node *node = n;
+ UNUSED(pw);
+
+ /* Pass any node data back to libcss */
+ *libcss_node_data = node->libcss_node_data;
+
+ return CSS_OK;
+}
+
+
-----------------------------------------------------------------------
Summary of changes:
src/select/select.c | 6 +++---
test/INDEX | 3 +--
test/Makefile | 2 +-
test/select-nd.c | 25 -------------------------
test/select-no-nd.c | 25 -------------------------
test/{select-common.c => select.c} | 23 +++++++++++++++++++++++
6 files changed, 28 insertions(+), 56 deletions(-)
delete mode 100644 test/select-nd.c
delete mode 100644 test/select-no-nd.c
rename test/{select-common.c => select.c} (98%)
diff --git a/src/select/select.c b/src/select/select.c
index 955370b..d9c8809 100644
--- a/src/select/select.c
+++ b/src/select/select.c
@@ -683,7 +683,7 @@ static css_error css__set_node_data(void *node,
css_select_state *state,
}
node_data->bloom = bloom;
- /* Set selection results */
+ /* Set selection results */
results = state->results;
for (i = 0; i < CSS_PSEUDO_ELEMENT_COUNT; i++) {
node_data->partial.styles[i] =
@@ -692,9 +692,9 @@ static css_error css__set_node_data(void *node,
css_select_state *state,
error = handler->set_libcss_node_data(pw, node, node_data);
if (error != CSS_OK) {
- //css__destroy_node_data(node_data);
+ css__destroy_node_data(node_data);
state->node_data = NULL;
- return CSS_OK;
+ return error;
}
state->node_data = NULL;
diff --git a/test/INDEX b/test/INDEX
index cf1a3cb..d712157 100644
--- a/test/INDEX
+++ b/test/INDEX
@@ -10,8 +10,7 @@ number Conversion of numbers to fixed point
number
#css21 Parsing (CSS2.1 specifics) css
parse-auto Automated parser tests (bytecode) parse
parse2-auto Automated parser tests (om & invalid) parse2
-select-no-nd Automated selection engine tests (no node_data) select
-select-nd Automated selection engine tests (with node_data) select
+select Automated selection engine tests select
# Regression tests
diff --git a/test/Makefile b/test/Makefile
index 021d829..18124ce 100644
--- a/test/Makefile
+++ b/test/Makefile
@@ -2,6 +2,6 @@
DIR_TEST_ITEMS := csdetect:csdetect.c css21:css21.c lex:lex.c \
lex-auto:lex-auto.c number:number.c \
parse:parse.c parse-auto:parse-auto.c parse2-auto:parse2-auto.c \
- select-no-nd:select-no-nd.c select-nd:select-nd.c
+ select:select.c
include $(NSBUILD)/Makefile.subdir
diff --git a/test/select-nd.c b/test/select-nd.c
deleted file mode 100644
index 3c236a6..0000000
--- a/test/select-nd.c
+++ /dev/null
@@ -1,25 +0,0 @@
-
-#include "select-common.c"
-
-static css_error set_libcss_node_data(void *pw, void *n,
- void *libcss_node_data)
-{
- node *node = n;
- UNUSED(pw);
-
- node->libcss_node_data = libcss_node_data;
-
- return CSS_OK;
-}
-
-static css_error get_libcss_node_data(void *pw, void *n,
- void **libcss_node_data)
-{
- node *node = n;
- UNUSED(pw);
-
- /* Pass any node data back to libcss */
- *libcss_node_data = node->libcss_node_data;
-
- return CSS_OK;
-}
diff --git a/test/select-no-nd.c b/test/select-no-nd.c
deleted file mode 100644
index c035126..0000000
--- a/test/select-no-nd.c
+++ /dev/null
@@ -1,25 +0,0 @@
-
-#include "select-common.c"
-
-static css_error set_libcss_node_data(void *pw, void *n,
- void *libcss_node_data)
-{
- UNUSED(n);
- UNUSED(pw);
- UNUSED(libcss_node_data);
-
- return CSS_PROPERTY_NOT_SET;
-}
-
-static css_error get_libcss_node_data(void *pw, void *n,
- void **libcss_node_data)
-{
- UNUSED(pw);
- UNUSED(n);
-
- /* Test case were node data is deleted, by not passing any node data */
- *libcss_node_data = NULL;
-
- return CSS_OK;
-}
-
diff --git a/test/select-common.c b/test/select.c
similarity index 98%
rename from test/select-common.c
rename to test/select.c
index ef96efd..4146355 100644
--- a/test/select-common.c
+++ b/test/select.c
@@ -1667,4 +1667,27 @@ css_error compute_font_size(void *pw, const css_hint
*parent, css_hint *size)
return CSS_OK;
}
+static css_error set_libcss_node_data(void *pw, void *n,
+ void *libcss_node_data)
+{
+ node *node = n;
+ UNUSED(pw);
+
+ node->libcss_node_data = libcss_node_data;
+
+ return CSS_OK;
+}
+
+static css_error get_libcss_node_data(void *pw, void *n,
+ void **libcss_node_data)
+{
+ node *node = n;
+ UNUSED(pw);
+
+ /* Pass any node data back to libcss */
+ *libcss_node_data = node->libcss_node_data;
+
+ return CSS_OK;
+}
+
--
Cascading Style Sheets library
_______________________________________________
netsurf-commits mailing list
[email protected]
http://listmaster.pepperfish.net/cgi-bin/mailman/listinfo/netsurf-commits-netsurf-browser.org