From 71ad0bdf69a59891f22160718b1599945b900080 Mon Sep 17 00:00:00 2001 From: Richard Wilson Date: Sun, 16 Jan 2005 21:39:21 +0000 Subject: [project @ 2005-01-16 21:39:21 by rjw] Read content, counter-reset and counter-increment properties. svn path=/import/netsurf/; revision=1456 --- css/css.c | 84 ++++++++++++++++++++ css/css.h | 62 ++++++++++++++- css/ruleset.c | 251 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ render/list.c | 39 ++++++--- render/list.h | 20 +---- 5 files changed, 425 insertions(+), 31 deletions(-) diff --git a/css/css.c b/css/css.c index 009d71f94..d54f03229 100644 --- a/css/css.c +++ b/css/css.c @@ -133,6 +133,9 @@ const struct css_style css_base_style = { { CSS_CLIP_RECT_AUTO, { 0, CSS_UNIT_PX } }, { CSS_CLIP_RECT_AUTO, { 0, CSS_UNIT_PX } } } }, 0x000000, + { CSS_CONTENT_NORMAL, 0 }, + { CSS_COUNTER_RESET_NONE, 0 }, + { CSS_COUNTER_INCREMENT_NONE, 0 }, CSS_CURSOR_AUTO, CSS_DIRECTION_LTR, CSS_DISPLAY_BLOCK, @@ -215,6 +218,9 @@ const struct css_style css_empty_style = { { CSS_CLIP_RECT_AUTO, { 0, CSS_UNIT_PX } }, { CSS_CLIP_RECT_AUTO, { 0, CSS_UNIT_PX } } } }, CSS_COLOR_NOT_SET, + { CSS_CONTENT_NOT_SET, 0 }, + { CSS_COUNTER_RESET_NOT_SET, 0 }, + { CSS_COUNTER_INCREMENT_NOT_SET, 0 }, CSS_CURSOR_NOT_SET, CSS_DIRECTION_NOT_SET, CSS_DISPLAY_NOT_SET, @@ -298,6 +304,9 @@ const struct css_style css_blank_style = { { CSS_CLIP_RECT_AUTO, { 0, CSS_UNIT_PX } }, { CSS_CLIP_RECT_AUTO, { 0, CSS_UNIT_PX } } } }, CSS_COLOR_INHERIT, + { CSS_CONTENT_NORMAL, 0 }, + { CSS_COUNTER_RESET_NONE, 0 }, + { CSS_COUNTER_INCREMENT_NONE, 0 }, CSS_CURSOR_INHERIT, CSS_DIRECTION_INHERIT, CSS_DISPLAY_INLINE, @@ -516,9 +525,69 @@ void css_deep_free_style(struct css_style *style) if (style->list_style_image.type == CSS_LIST_STYLE_IMAGE_URI) free(style->list_style_image.uri); + if (style->content.type == CSS_CONTENT_INTERPRET) + css_deep_free_content(style->content.content); + + if (style->counter_reset.type == CSS_COUNTER_RESET_INTERPRET) + css_deep_free_counter_control(style->counter_reset.data); + + if (style->counter_increment.type == CSS_COUNTER_INCREMENT_INTERPRET) + css_deep_free_counter_control(style->counter_increment.data); + free(style); } +/** + * Free all auto-generated content data + * + * \param content the auto-generated content data to free + */ +void css_deep_free_content(struct css_content *content) { + struct css_content *next; + + while (content) { + next = content->next; + switch (content->type) { + case CSS_CONTENT_STRING: + free(content->data.string); + break; + case CSS_CONTENT_URI: + free(content->data.uri); + break; + case CSS_CONTENT_COUNTER: + free(content->data.counter.name); + free(content->data.counter.separator); + break; + case CSS_CONTENT_ATTR: + free(content->data.attr); + break; + case CSS_CONTENT_OPEN_QUOTE: + case CSS_CONTENT_CLOSE_QUOTE: + case CSS_CONTENT_NO_OPEN_QUOTE: + case CSS_CONTENT_NO_CLOSE_QUOTE: + break; + } + free(content); + content = next; + } +} + +/** + * Free all counter control data + * + * \param counter the counter control data to free + */ +void css_deep_free_counter_control(struct css_counter_control *control) { + struct css_counter_control *next; + + while (control) { + next = control->next; + free(control->name); + free(control); + control = next; + } +} + /** * Create a new struct css_node. * @@ -2340,6 +2409,15 @@ void css_cascade(struct css_style * const style, if (apply->color != CSS_COLOR_INHERIT && apply->color != CSS_COLOR_NOT_SET) style->color = apply->color; + if (apply->content.type != CSS_CONTENT_INHERIT && + apply->content.type != CSS_CONTENT_NOT_SET) + style->content = apply->content; + if (apply->counter_reset.type != CSS_COUNTER_RESET_INHERIT && + apply->counter_reset.type != CSS_COUNTER_RESET_NOT_SET) + style->counter_reset = apply->counter_reset; + if (apply->counter_increment.type != CSS_COUNTER_INCREMENT_INHERIT && + apply->counter_increment.type != CSS_COUNTER_INCREMENT_NOT_SET) + style->counter_increment = apply->counter_increment; if (apply->cursor != CSS_CURSOR_INHERIT && apply->cursor != CSS_CURSOR_NOT_SET) style->cursor = apply->cursor; @@ -2606,6 +2684,12 @@ void css_merge(struct css_style * const style, style->clear = apply->clear; if (apply->color != CSS_COLOR_NOT_SET) style->color = apply->color; + if (apply->content.type != CSS_CONTENT_NOT_SET) + style->content = apply->content; + if (apply->counter_reset.type != CSS_COUNTER_RESET_NOT_SET) + style->counter_reset = apply->counter_reset; + if (apply->counter_increment.type != CSS_COUNTER_INCREMENT_NOT_SET) + style->counter_increment = apply->counter_increment; if (apply->cursor != CSS_CURSOR_NOT_SET) style->cursor = apply->cursor; if (apply->direction != CSS_DIRECTION_NOT_SET) diff --git a/css/css.h b/css/css.h index 9c02cf26e..d795ff17a 100644 --- a/css/css.h +++ b/css/css.h @@ -84,6 +84,17 @@ struct css_border_width { struct css_length value; }; +typedef enum { + CSS_CONTENT_STRING, + CSS_CONTENT_URI, + CSS_CONTENT_COUNTER, + CSS_CONTENT_ATTR, + CSS_CONTENT_OPEN_QUOTE, + CSS_CONTENT_CLOSE_QUOTE, + CSS_CONTENT_NO_OPEN_QUOTE, + CSS_CONTENT_NO_CLOSE_QUOTE +} css_content_type_generated; + typedef enum { CSS_LIST_STYLE_IMAGE_INHERIT, CSS_LIST_STYLE_IMAGE_NONE, @@ -113,10 +124,27 @@ typedef enum { CSS_VERTICAL_ALIGN_NOT_SET } css_vertical_align_type; +struct css_counter_control { + char *name; + int value; + struct css_counter_control *next; +}; + struct css_counter { - const char *name; + char *name; css_list_style_type style; - const char *separator; /** NULL for counter() */ + char *separator; /** NULL for counter() */ +}; + +struct css_content { + css_content_type_generated type; + union { + char *string; + char *uri; + struct css_counter counter; + char *attr; + } data; + struct css_content *next; }; /** Representation of a complete CSS 2 style. */ @@ -166,7 +194,33 @@ struct css_style { colour color; - /** \todo content and counters */ + /* generated content */ + struct { + enum { + CSS_CONTENT_NORMAL, + CSS_CONTENT_INHERIT, + CSS_CONTENT_INTERPRET, + CSS_CONTENT_NOT_SET } type; + struct css_content *content; + } content; + + /* counter controls */ + struct { + enum { + CSS_COUNTER_RESET_NONE, + CSS_COUNTER_RESET_INHERIT, + CSS_COUNTER_RESET_INTERPRET, + CSS_COUNTER_RESET_NOT_SET } type; + struct css_counter_control *data; + } counter_reset; + struct { + enum { + CSS_COUNTER_INCREMENT_NONE, + CSS_COUNTER_INCREMENT_INHERIT, + CSS_COUNTER_INCREMENT_INTERPRET, + CSS_COUNTER_INCREMENT_NOT_SET } type; + struct css_counter_control *data; + } counter_increment; css_cursor cursor; css_direction direction; @@ -562,6 +616,8 @@ const char *css_parser_TokenName(int tokenType); void css_get_style(struct content *c, xmlNode *n, struct css_style * style); struct css_style *css_duplicate_style(const struct css_style * const style); void css_free_style(struct css_style *style); +void css_deep_free_content(struct css_content *content); +void css_deep_free_counter_control(struct css_counter_control *control); void css_cascade(struct css_style * const style, const struct css_style * const apply); void css_merge(struct css_style * const style, diff --git a/css/ruleset.c b/css/ruleset.c index 50ed75743..84074a06e 100644 --- a/css/ruleset.c +++ b/css/ruleset.c @@ -40,6 +40,11 @@ static int parse_length(struct css_length * const length, static colour parse_colour(const struct css_node * const v); static colour css_parse_rgb(struct css_node *v); static bool parse_uri(const struct css_node *v, char **uri); +static struct css_content *parse_content_new(struct css_content **current, css_content_type_generated generated); +static bool parse_content_counter(struct css_content **current, struct css_node *t, bool counters); +bool parse_counter_control_data(struct css_counter_control **current, const struct css_node * v, int empty); +struct css_counter_control *parse_counter_control_new(struct css_counter_control **current); + static void parse_background(struct css_style * const s, const struct css_node * v); static void parse_background_attachment(struct css_style * const s, const struct css_node * const v); @@ -91,6 +96,9 @@ static void parse_caption_side(struct css_style * const s, const struct css_node static void parse_clear(struct css_style * const s, const struct css_node * const v); static void parse_clip(struct css_style * const s, const struct css_node * v); static void parse_color(struct css_style * const s, const struct css_node * const v); +static void parse_content(struct css_style * const s, const struct css_node * v); +static void parse_counter_increment(struct css_style * const s, const struct css_node * v); +static void parse_counter_reset(struct css_style * const s, const struct css_node * v); static void parse_cursor(struct css_style * const s, const struct css_node * v); static void parse_direction(struct css_style * const s, const struct css_node * v); static void parse_display(struct css_style * const s, const struct css_node * const v); @@ -203,6 +211,9 @@ static const struct css_property_entry css_property_table[] = { { "clear", parse_clear }, { "clip", parse_clip }, { "color", parse_color }, + { "content", parse_content }, + { "counter-increment", parse_counter_increment }, + { "counter-reset", parse_counter_reset }, { "cursor", parse_cursor }, { "direction", parse_direction }, { "display", parse_display }, @@ -1614,6 +1625,246 @@ void parse_color(struct css_style * const s, const struct css_node * const v) s->color = c; } +void parse_content(struct css_style * const s, const struct css_node * v) +{ + struct css_content *new_content = NULL; + struct css_content *content; + struct css_node *t; + bool first = true; + + for (; v; v = v->next) { + switch (v->type) { + case CSS_NODE_STRING: + content = parse_content_new(&new_content, CSS_CONTENT_STRING); + if (!content) + return; + content->data.string = strndup(v->data, v->data_length); + if (!content->data.string) { + css_deep_free_content(new_content); + return; + } + break; + case CSS_NODE_URI: + content = parse_content_new(&new_content, CSS_CONTENT_URI); + if (!content) + return; + if (!parse_uri(v, &content->data.uri)) { + css_deep_free_content(new_content); + return; + } + break; + case CSS_NODE_IDENT: + if (v->data_length == 7 && + strncasecmp(v->data, "inherit", 7) == 0) { + if ((!first) || (v->next)) + return; + css_deep_free_content(s->content.content); + s->content.content = NULL; + s->content.type = CSS_CONTENT_INHERIT; + return; + } else if (v->data_length == 6 && + strncasecmp(v->data, "normal", 6) == 0) { + if ((!first) || (v->next)) + return; + css_deep_free_content(s->content.content); + s->content.content = NULL; + s->content.type = CSS_CONTENT_NORMAL; + return; + } else if (v->data_length == 10 && + strncasecmp(v->data, "open-quote", 10) == 0) { + if (!parse_content_new(&new_content, CSS_CONTENT_OPEN_QUOTE)) + return; + } else if (v->data_length == 11 && + strncasecmp(v->data, "close-quote", 11) == 0) { + if (!parse_content_new(&new_content, CSS_CONTENT_CLOSE_QUOTE)) + return; + } else if (v->data_length == 13 && + strncasecmp(v->data, "no-open-quote", 13) == 0) { + if (!parse_content_new(&new_content, CSS_CONTENT_NO_OPEN_QUOTE)) + return; + } else if (v->data_length == 14 && + strncasecmp(v->data, "no-close-quote", 14) == 0) { + if (!parse_content_new(&new_content, CSS_CONTENT_NO_CLOSE_QUOTE)) + return; + } else { + css_deep_free_content(new_content); + return; + } + break; + case CSS_NODE_FUNCTION: + if (v->data_length == 5 && + strncasecmp(v->data, "attr", 4) == 0) { + content = parse_content_new(&new_content, CSS_CONTENT_URI); + if (!content) + return; + t = v->value; + if ((t->type == CSS_NODE_STRING) && (!t->next)) { + content->data.string = strndup(t->data, t->data_length); + if (!content->data.string) { + css_deep_free_content(new_content); + return; + } + } else { + css_deep_free_content(new_content); + return; + } + } else if (v->data_length == 8 && + strncasecmp(v->data, "counter", 7) == 0) { + if (!parse_content_counter(&new_content, v->value, false)) + return; + } else if (v->data_length == 9 && + strncasecmp(v->data, "counters", 8) == 0) { + if (!parse_content_counter(&new_content, v->value, true)) + return; + } else { + css_deep_free_content(new_content); + return; + } + default: + css_deep_free_content(new_content); + return; + } + first = false; + } + + if (new_content) { + css_deep_free_content(s->content.content); + s->content.type = CSS_CONTENT_INTERPRET; + s->content.content = new_content; + } +} + +struct css_content *parse_content_new(struct css_content **current, css_content_type_generated generated) { + struct css_content *content; + struct css_content *link; + + content = (struct css_content *)calloc(1, sizeof(struct css_content)); + if (!content) { + css_deep_free_content(*current); + return NULL; + } + + content->type = generated; + if (!*current) { + *current = content; + } else { + for (link = *current; link->next; link = link->next); + link->next = content; + } + return content; +} + +bool parse_content_counter(struct css_content **current, struct css_node *t, bool counters) { + struct css_content *content; + css_list_style_type z; + + content = parse_content_new(current, CSS_CONTENT_COUNTER); + if ((!content) || (t->type != CSS_NODE_IDENT)) + return false; + + content->data.counter.name = strndup(t->data, t->data_length); + content->data.counter.style = CSS_LIST_STYLE_TYPE_DECIMAL; + t = t->next; + + if (counters) { + if ((!t) || (t->type != CSS_NODE_STRING)) { + css_deep_free_content(*current); + return false; + } + content->data.counter.separator = strndup(t->data, t->data_length); + t = t->next; + } + + if (!t) + return true; + + if ((t->type != CSS_NODE_IDENT) || (t->next)) { + css_deep_free_content(*current); + return false; + } + z = css_list_style_type_parse(t->data, t->data_length); + if (z != CSS_LIST_STYLE_TYPE_UNKNOWN) + content->data.counter.style = z; + return true; +} + +void parse_counter_reset(struct css_style * const s, const struct css_node * v) { + struct css_counter_control *counter = NULL; + + if (!parse_counter_control_data(&counter, v, 0)) + return; + + if (counter) { + css_deep_free_counter_control(s->counter_reset.data); + s->counter_reset.type = CSS_COUNTER_RESET_INTERPRET; + s->counter_reset.data = counter; + } +} + +void parse_counter_increment(struct css_style * const s, const struct css_node * v) { + struct css_counter_control *counter = NULL; + + if (!parse_counter_control_data(&counter, v, 1)) + return; + + if (counter) { + css_deep_free_counter_control(s->counter_increment.data); + s->counter_increment.type = CSS_COUNTER_INCREMENT_INTERPRET; + s->counter_increment.data = counter; + } +} + +bool parse_counter_control_data(struct css_counter_control **current, const struct css_node * v, int empty) { + struct css_counter_control *open = NULL; + + for (; v; v = v->next) { + switch (v->type) { + case CSS_NODE_IDENT: + open = parse_counter_control_new(current); + if (!open) + return false; + open->name = strndup(v->data, v->data_length); + open->value = empty; + if (!open->name) { + css_deep_free_counter_control(*current); + return false; + } + break; + case CSS_NODE_NUMBER: + if (!open) { + css_deep_free_counter_control(*current); + return false; + } + open->value = atoi(v->data); + open = NULL; + break; + default: + css_deep_free_counter_control(*current); + return false; + } + } + return true; +} + +struct css_counter_control *parse_counter_control_new(struct css_counter_control **current) { + struct css_counter_control *counter; + struct css_counter_control *link; + + counter = (struct css_counter_control *)calloc(1, sizeof(struct css_counter_control)); + if (!counter) { + css_deep_free_counter_control(*current); + return NULL; + } + + if (!*current) { + *current = counter; + } else { + for (link = *current; link->next; link = link->next); + link->next = counter; + } + return counter; +} + void parse_cursor(struct css_style * const s, const struct css_node * v) { css_cursor z; diff --git a/render/list.c b/render/list.c index fced6416c..432d31776 100644 --- a/render/list.c +++ b/render/list.c @@ -16,6 +16,20 @@ #include "netsurf/render/list.h" #include "netsurf/utils/log.h" + +struct list_counter { + char *name; /** Counter name */ + struct list_counter_state *first; /** First counter state */ + struct list_counter_state *state; /** Current counter state */ + struct list_counter *next; /** Next counter */ +}; + +struct list_counter_state { + int count; /** Current count */ + struct list_counter_state *parent; /** Parent counter, or NULL */ + struct list_counter_state *next; /** Next counter, or NULL */ +}; + static struct list_counter *list_counter_pool = NULL; static char list_counter_workspace[16]; @@ -31,13 +45,14 @@ static const int list_counter_decimal[] = { 1, 4, 5, 9, / sizeof(list_counter_decimal[0])) -static struct list_counter *render_list_find_counter(const char *name); +static struct list_counter *render_list_find_counter(char *name); static char *render_list_encode_counter(struct list_counter_state *state, css_list_style_type style); static char *render_list_encode_roman(int value); -static void render_list_counter_output(const char *name); - +/* +static void render_list_counter_output(char *name); +*/ /** * Finds a counter from the current pool, or adds a new one. @@ -45,13 +60,13 @@ static void render_list_counter_output(const char *name); * \param name the name of the counter to find * \return the counter, or NULL if it couldn't be found/created. */ -static struct list_counter *render_list_find_counter(const char *name) { +static struct list_counter *render_list_find_counter(char *name) { struct list_counter *counter; assert(name); /* find a current counter */ for (counter = list_counter_pool; counter; counter = counter->next) - if (!strcmp(name, counter->name)) + if (!strcasecmp(name, counter->name)) return counter; /* create a new counter */ @@ -104,7 +119,7 @@ void render_list_destroy_counters(void) { * \param value the value to reset the counter to * \return true on success, false on failure. */ -bool render_list_counter_reset(const char *name, int value) { +bool render_list_counter_reset(char *name, int value) { struct list_counter *counter; struct list_counter_state *state; struct list_counter_state *link; @@ -139,7 +154,7 @@ bool render_list_counter_reset(const char *name, int value) { * \param value the value to increment the counter by * \return true on success, false on failure. */ -bool render_list_counter_increment(const char *name, int value) { +bool render_list_counter_increment(char *name, int value) { struct list_counter *counter; assert(name); @@ -169,7 +184,7 @@ bool render_list_counter_increment(const char *name, int value) { * \param name the name of the counter to end the scope for * \return true on success, false on failure. */ -bool render_list_counter_end_scope(const char *name) { +bool render_list_counter_end_scope(char *name) { struct list_counter *counter; assert(name); @@ -387,7 +402,7 @@ static char *render_list_encode_roman(int value) { void render_list_test(void) { /* example given in CSS2.1/12.4.1 */ - render_list_counter_reset("item", 0); +/* render_list_counter_reset("item", 0); render_list_counter_increment("item", 1); render_list_counter_increment("item", 1); render_list_counter_reset("item", 0); @@ -409,9 +424,10 @@ void render_list_test(void) { render_list_counter_increment("item", 1); render_list_counter_increment("item", 1); render_list_counter_end_scope("item"); +*/ } - -static void render_list_counter_output(const char *name) { +/* +static void render_list_counter_output(char *name) { struct list_counter *counter; char *result; struct css_counter css_counter; @@ -442,3 +458,4 @@ static void render_list_counter_output(const char *name) { free(result); } } +*/ diff --git a/render/list.h b/render/list.h index f168bd043..0aa7d68ac 100644 --- a/render/list.h +++ b/render/list.h @@ -14,24 +14,10 @@ #include -struct list_counter { - char *name; /** Counter name */ - struct list_counter_state *first; /** First counter state */ - struct list_counter_state *state; /** Current counter state */ - struct list_counter *next; /** Next counter */ -}; - -struct list_counter_state { - int count; /** Current count */ - struct list_counter_state *parent; /** Parent counter, or NULL */ - struct list_counter_state *next; /** Next counter, or NULL */ -}; - - void render_list_destroy_counters(void); -bool render_list_counter_reset(const char *name, int value); -bool render_list_counter_increment(const char *name, int value); -bool render_list_counter_end_scope(const char *name); +bool render_list_counter_reset(char *name, int value); +bool render_list_counter_increment(char *name, int value); +bool render_list_counter_end_scope(char *name); char *render_list_counter(struct css_counter *css_counter); void render_list_test(void); -- cgit v1.2.3