diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/bytecode/bytecode.h | 5 | ||||
-rw-r--r-- | src/parse/css21.c | 16 | ||||
-rw-r--r-- | src/parse/css21props.c | 62 | ||||
-rw-r--r-- | src/stylesheet.c | 92 | ||||
-rw-r--r-- | src/stylesheet.h | 8 |
5 files changed, 175 insertions, 8 deletions
diff --git a/src/bytecode/bytecode.h b/src/bytecode/bytecode.h index c8d6215..2db3138 100644 --- a/src/bytecode/bytecode.h +++ b/src/bytecode/bytecode.h @@ -99,6 +99,11 @@ typedef enum opcode { OP_Z_INDEX = 0x053, } opcode; +enum flag { + FLAG_IMPORTANT = (1<<0), + FLAG_INHERIT = (1<<1), +}; + typedef enum unit { UNIT_PX = 0, UNIT_EX = 1, diff --git a/src/parse/css21.c b/src/parse/css21.c index 7f49490..7f16c8d 100644 --- a/src/parse/css21.c +++ b/src/parse/css21.c @@ -1067,7 +1067,7 @@ css_error parseProperty(css_css21 *c, const css_token *property, css_error error; css_prop_handler handler = NULL; int i = 0; - css_style *style; + css_style *style = NULL; /* Find property index */ /** \todo improve on this linear search */ @@ -1087,8 +1087,18 @@ css_error parseProperty(css_css21 *c, const css_token *property, if (error != CSS_OK) return error; - /** \todo append style to rule */ - UNUSED(rule); + /** \todo we should probably assert this, but until we've implemented + * all the property parsers, this will have to suffice. */ + if (style != NULL) { + /* Append style to rule */ + error = css_stylesheet_rule_append_style(c->sheet, rule, style); + if (error != CSS_OK) { + css_stylesheet_style_destroy(c->sheet, style); + return error; + } + } + + /* Style owned or destroyed by stylesheet, so forget about it */ return CSS_OK; } diff --git a/src/parse/css21props.c b/src/parse/css21props.c index 24c9ba1..c47ef99 100644 --- a/src/parse/css21props.c +++ b/src/parse/css21props.c @@ -690,10 +690,64 @@ css_error parse_clear(css_css21 *c, const parserutils_vector *vector, int *ctx, css_style **result) { - UNUSED(c); - UNUSED(vector); - UNUSED(ctx); - UNUSED(result); + const css_token *token, *ident; + uint8_t flags = 0; + uint16_t value = 0; + uint32_t opv; + + /* IDENT (left, right, both, none, inherit) */ + ident = parserutils_vector_iterate(vector, ctx); + if (ident == NULL || ident->type != CSS_TOKEN_IDENT) + return CSS_INVALID; + + /** \todo break this !important stuff into a utility function */ + consumeWhitespace(vector, ctx); + + token = parserutils_vector_iterate(vector, ctx); + if (token != NULL && tokenIsChar(token, '!')) { + consumeWhitespace(vector, ctx); + + token = parserutils_vector_iterate(vector, ctx); + if (token == NULL || token->type != CSS_TOKEN_IDENT) + return CSS_INVALID; + + /** \todo compare pointer to interned version. */ + if (token->lower.len == 9 && + strncmp((char *) token->lower.ptr, + "important", 9) == 0) + flags |= FLAG_IMPORTANT; + } else if (token != NULL) + return CSS_INVALID; + + + /** \todo ugh. compare pointers to interned versions, already */ + if (ident->lower.len == 7 && + strncmp((char *) ident->lower.ptr, "inherit", 7) == 0) { + flags |= FLAG_INHERIT; + } else if (ident->lower.len == 5 && + strncmp((char *) ident->lower.ptr, "right", 5) == 0) { + value = CLEAR_RIGHT; + } else if (ident->lower.len == 4 && + strncmp((char *) ident->lower.ptr, "left", 4) == 0) { + value = CLEAR_LEFT; + } else if (ident->lower.len == 4 && + strncmp((char *) ident->lower.ptr, "both", 4) == 0) { + value = CLEAR_BOTH; + } else if (ident->lower.len == 4 && + strncmp((char *) ident->lower.ptr, "none", 4) == 0) { + value = CLEAR_NONE; + } else + return CSS_INVALID; + + opv = buildOPV(OP_CLEAR, flags, value); + + /* Allocate result */ + *result = css_stylesheet_style_create(c->sheet, sizeof(opv)); + if (*result == NULL) + return CSS_NOMEM; + + /* Copy the bytecode to it */ + memcpy((*result)->bytecode, &opv, sizeof(opv)); return CSS_OK; } diff --git a/src/stylesheet.c b/src/stylesheet.c index 9d6f877..7a093f9 100644 --- a/src/stylesheet.c +++ b/src/stylesheet.c @@ -269,6 +269,45 @@ css_error css_stylesheet_set_disabled(css_stylesheet *sheet, bool disabled) ******************************************************************************/ /** + * Create a style + * + * \param sheet The stylesheet context + * \param len The required length of the style + * \return Pointer to style, or NULL on error + */ +css_style *css_stylesheet_style_create(css_stylesheet *sheet, uint32_t len) +{ + css_style *style; + + if (sheet == NULL || len == 0) + return NULL; + + style = sheet->alloc(NULL, sizeof(css_style) + len, sheet->pw); + if (style == NULL) + return NULL; + + /* DIY variable-sized data member */ + style->bytecode = ((uint8_t *) style + sizeof(css_style)); + style->length = len; + + return style; +} + +/** + * Destroy a style + * + * \param sheet The stylesheet context + * \param style The style to destroy + */ +void css_stylesheet_style_destroy(css_stylesheet *sheet, css_style *style) +{ + UNUSED(sheet); + UNUSED(style); + + /** \todo destroy style */ +} + +/** * Create a selector * * \param sheet The stylesheet context @@ -462,6 +501,59 @@ css_error css_stylesheet_rule_add_selector(css_stylesheet *sheet, } /** + * Append a style to a CSS rule + * + * \param sheet The stylesheet context + * \param rule The rule to add to (must be CSS_RULE_SELECTOR or CSS_RULE_PAGE) + * \param style The style to add + * \return CSS_OK on success, appropriate error otherwise + */ +css_error css_stylesheet_rule_append_style(css_stylesheet *sheet, + css_rule *rule, css_style *style) +{ + css_style *cur; + + if (sheet == NULL || rule == NULL || style == NULL) + return CSS_BADPARM; + + if (rule->type != CSS_RULE_SELECTOR && rule->type != CSS_RULE_PAGE) + return CSS_INVALID; + + if (rule->type == CSS_RULE_SELECTOR) + cur = rule->data.selector.style; + else + cur = rule->data.page.style; + + if (cur != NULL) { + /* Already have a style, so append to the end of the bytecode */ + css_style *temp = sheet->alloc(cur, + cur->length + style->length, sheet->pw); + if (temp == NULL) + return CSS_NOMEM; + + /** \todo Can we optimise the bytecode here? */ + memcpy((uint8_t *) temp->bytecode + temp->length, + style->bytecode, style->length); + + cur = temp; + cur->length += style->length; + + /* Done with style */ + css_stylesheet_style_destroy(sheet, style); + } else { + /* No current style, so use this one */ + cur = style; + } + + if (rule->type == CSS_RULE_SELECTOR) + rule->data.selector.style = cur; + else + rule->data.page.style = cur; + + return CSS_OK; +} + +/** * Add a rule to a stylesheet * * \param sheet The stylesheet to add to diff --git a/src/stylesheet.h b/src/stylesheet.h index 99af643..e23fbf3 100644 --- a/src/stylesheet.h +++ b/src/stylesheet.h @@ -21,6 +21,7 @@ typedef struct css_rule css_rule; typedef struct css_selector css_selector; +/** \todo would a parserutils_buffer be better here? */ typedef struct css_style { uint32_t length; /**< Length, in bytes, of bytecode */ void *bytecode; /**< Pointer to bytecode */ @@ -152,6 +153,9 @@ struct css_stylesheet { void *pw; /**< Private word */ }; +css_style *css_stylesheet_style_create(css_stylesheet *sheet, uint32_t len); +void css_stylesheet_style_destroy(css_stylesheet *sheet, css_style *style); + css_selector *css_stylesheet_selector_create(css_stylesheet *sheet, css_selector_type type, const css_string *name, const css_string *value); @@ -170,7 +174,9 @@ void css_stylesheet_rule_destroy(css_stylesheet *sheet, css_rule *rule); css_error css_stylesheet_rule_add_selector(css_stylesheet *sheet, css_rule *rule, css_selector *selector); -/** \todo something about adding style declarations to a rule */ +css_error css_stylesheet_rule_append_style(css_stylesheet *sheet, + css_rule *rule, css_style *style); + /** \todo registering other rule-type data with css_rules */ css_error css_stylesheet_add_rule(css_stylesheet *sheet, css_rule *rule); |