summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJohn Mark Bell <jmb@netsurf-browser.org>2008-10-23 00:28:20 +0000
committerJohn Mark Bell <jmb@netsurf-browser.org>2008-10-23 00:28:20 +0000
commitc8e73871f9006987983fd1010d97b6168c13f6a3 (patch)
tree2fb79379af6643828fb93bd6c855a6e0a5e6dc7b /src
parent5d9507591d83b48be8c76421b602500c196e3785 (diff)
downloadlibcss-c8e73871f9006987983fd1010d97b6168c13f6a3.tar.gz
libcss-c8e73871f9006987983fd1010d97b6168c13f6a3.tar.bz2
Something approximating a parser for clear.
Provide API to create/destroy css_styles and append them to css_rules. svn path=/trunk/libcss/; revision=5625
Diffstat (limited to 'src')
-rw-r--r--src/bytecode/bytecode.h5
-rw-r--r--src/parse/css21.c16
-rw-r--r--src/parse/css21props.c62
-rw-r--r--src/stylesheet.c92
-rw-r--r--src/stylesheet.h8
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);