[project @ 2005-01-16 21:39:21 by rjw]

Read content, counter-reset and counter-increment properties.

svn path=/import/netsurf/; revision=1456
This commit is contained in:
Richard Wilson 2005-01-16 21:39:21 +00:00
parent 7ab8b2c1ba
commit 71ad0bdf69
5 changed files with 425 additions and 31 deletions

View File

@ -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)

View File

@ -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,

View File

@ -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;

View File

@ -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);
}
}
*/

View File

@ -14,24 +14,10 @@
#include <stdbool.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 */
};
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);