summaryrefslogtreecommitdiff
path: root/css
diff options
context:
space:
mode:
Diffstat (limited to 'css')
-rw-r--r--css/css.c33
-rw-r--r--css/css.h8
-rw-r--r--css/ruleset.c103
3 files changed, 98 insertions, 46 deletions
diff --git a/css/css.c b/css/css.c
index 205fd8a83..d9d0c9967 100644
--- a/css/css.c
+++ b/css/css.c
@@ -1,5 +1,5 @@
/**
- * $Id: css.c,v 1.1 2003/04/04 15:19:31 bursa Exp $
+ * $Id: css.c,v 1.2 2003/04/05 15:35:55 bursa Exp $
*/
#include <assert.h>
@@ -74,12 +74,13 @@ const struct css_style css_blank_style = {
void css_create(struct content *c)
{
+ unsigned int i;
LOG(("content %p", c));
c->data.css = xcalloc(1, sizeof(*c->data.css));
css_lex_init(&c->data.css->lexer);
c->data.css->parser = css_parser_Alloc(malloc);
- c->data.css->rule = 0;
- c->data.css->last_rule = 0;
+ for (i = 0; i != HASH_SIZE; i++)
+ c->data.css->rule[i] = 0;
}
@@ -168,11 +169,12 @@ void css_get_style(struct css_stylesheet * stylesheet, struct css_selector * sel
unsigned int selectors, struct css_style * style)
{
struct node *r, *n, *m;
- unsigned int i;
+ unsigned int hash, i;
LOG(("stylesheet %p, selectors %u", stylesheet, selectors));
-
- for (r = stylesheet->rule; r != 0; r = r->next) {
+
+ hash = css_hash(selector[selectors - 1].element);
+ for (r = stylesheet->rule[hash]; r != 0; r = r->next) {
i = selectors - 1;
n = r;
/* compare element */
@@ -218,14 +220,11 @@ void css_get_style(struct css_stylesheet * stylesheet, struct css_selector * sel
matched:
/* TODO: sort by specificity */
LOG(("matched rule %p", r));
- css_dump_style(r->style);
css_cascade(style, r->style);
not_matched:
}
-
- css_dump_style(style);
}
@@ -239,12 +238,6 @@ void css_parse_property_list(struct css_style * style, char * str)
* dump a style
*/
-static void dump_length(const struct css_length * const length)
-{
- LOG(("%g%s", length->value,
- css_unit_name[length->unit]));
-}
-
#define DUMP_LENGTH(pre, len, post) LOG((pre "%g%s" post, (len)->value, css_unit_name[(len)->unit]));
void css_dump_style(const struct css_style * const style)
@@ -389,6 +382,16 @@ void css_cascade(struct css_style * const style, const struct css_style * const
}
+unsigned int css_hash(const char *s)
+{
+ unsigned int z = 0;
+ for (; *s != 0; s++)
+ z += *s;
+ return z % HASH_SIZE;
+}
+
+
+
#ifdef DEBUG
int main()
diff --git a/css/css.h b/css/css.h
index 3b7844b5c..133f485eb 100644
--- a/css/css.h
+++ b/css/css.h
@@ -1,5 +1,5 @@
/**
- * $Id: css.h,v 1.1 2003/04/04 15:19:31 bursa Exp $
+ * $Id: css.h,v 1.2 2003/04/05 15:35:55 bursa Exp $
*/
#ifndef _NETSURF_CSS_CSS_H_
@@ -136,11 +136,12 @@ struct node {
#include "netsurf/css/scanner.h"
+#define HASH_SIZE 47
+
struct css_stylesheet {
yyscan_t lexer;
void *parser;
- struct node *rule;
- struct node *last_rule;
+ struct node *rule[HASH_SIZE];
};
#endif
@@ -166,6 +167,7 @@ void css_free_node(struct node *node);
void css_add_ruleset(struct css_stylesheet *stylesheet,
struct node *selector,
struct node *declaration);
+unsigned int css_hash(const char *s);
void css_parser_Trace(FILE *TraceFILE, char *zTracePrompt);
void *css_parser_Alloc(void *(*mallocProc)(int));
diff --git a/css/ruleset.c b/css/ruleset.c
index e22a188b8..32bb235a3 100644
--- a/css/ruleset.c
+++ b/css/ruleset.c
@@ -1,5 +1,5 @@
/**
- * $Id: ruleset.c,v 1.1 2003/04/04 15:19:31 bursa Exp $
+ * $Id: ruleset.c,v 1.2 2003/04/05 15:35:55 bursa Exp $
*/
#include <assert.h>
@@ -28,6 +28,7 @@ struct font_size_entry {
};
+static int compare_selectors(struct node *n0, struct node *n1);
static int parse_length(struct css_length * const length, const struct node * const v);
static colour parse_colour(const struct node * const v);
static void parse_background_color(struct css_style * const s, const struct node * const v);
@@ -102,40 +103,86 @@ void css_add_ruleset(struct css_stylesheet *stylesheet,
struct node *selector,
struct node *declaration)
{
- struct node *n, *last;
+ struct node *n, *sel, *next_sel;
struct css_style *style;
-
- /* construct the struct css_style */
- style = xcalloc(1, sizeof(*style));
- memcpy(style, &css_blank_style, sizeof(*style));
-
- for (n = declaration; n != 0; n = n->next) {
- struct property_entry *p;
- assert(n->type == NODE_DECLARATION && n->data != 0 && n->left != 0);
- p = bsearch(n->data, property_table,
- sizeof(property_table) / sizeof(property_table[0]),
- sizeof(property_table[0]), strcasecmp);
- if (p == 0)
- continue;
- p->parse(style, n->left);
+ unsigned int hash;
+
+ for (sel = selector; sel != 0; sel = next_sel) {
+ next_sel = sel->next;
+
+ /* check if this selector is already present */
+ hash = css_hash(sel->data);
+ for (n = stylesheet->rule[hash]; n != 0; n = n->next)
+ if (compare_selectors(sel, n))
+ break;
+ if (n == 0) {
+ /* not present: construct a new struct css_style */
+ style = xcalloc(1, sizeof(*style));
+ memcpy(style, &css_blank_style, sizeof(*style));
+ sel->style = style;
+ sel->next = stylesheet->rule[hash];
+ stylesheet->rule[hash] = sel;
+ } else {
+ /* already exists: augument existing style */
+ style = n->style;
+ sel->next = 0;
+ css_free_node(sel);
+ }
+
+ /* fill in the declarations */
+ for (n = declaration; n != 0; n = n->next) {
+ struct property_entry *p;
+ assert(n->type == NODE_DECLARATION && n->data != 0 && n->left != 0);
+ p = bsearch(n->data, property_table,
+ sizeof(property_table) / sizeof(property_table[0]),
+ sizeof(property_table[0]), strcasecmp);
+ if (p == 0)
+ continue;
+ p->parse(style, n->left);
+ }
}
+}
- /*css_dump_style(style);*/
- /* add selectors to the stylesheet */
- /* TODO: merge with identical selector */
- for (n = selector; n != 0; n = n->next) {
- n->style = style;
- last = n;
+int compare_selectors(struct node *n0, struct node *n1)
+{
+ struct node *m0, *m1;
+ unsigned int count0, count1;
+
+ /* compare element name */
+ if (!((n0->data == 0 && n1->data == 0) ||
+ (n0->data != 0 && n1->data != 0 && strcasecmp(n0->data, n1->data) == 0)))
+ return 0;
+
+ if (n0->comb != n1->comb)
+ return 0;
+
+ /* compare classes and ids */
+ for (m0 = n0->left; m0 != 0; m0 = m0->next)
+ count0++;
+ for (m1 = n1->left; m1 != 0; m1 = m1->next)
+ count1++;
+ if (count0 != count1)
+ return 0;
+ for (m0 = n0->left; m0 != 0; m0 = m0->next) {
+ int found = 0;
+ for (m1 = n1->left; m1 != 0; m1 = m1->next) {
+ /* TODO: should this be case sensitive for IDs? */
+ if (m0->type == m1->type && strcasecmp(m0->data, m1->data) == 0) {
+ found = 1;
+ break;
+ }
+ }
+ if (!found)
+ return 0;
}
- if (stylesheet->rule == 0)
- stylesheet->rule = selector;
- else
- stylesheet->last_rule->next = selector;
- stylesheet->last_rule = last;
-}
+ /* compare ancestors */
+ if (n0->comb == COMB_NONE)
+ return 1;
+ return compare_selectors(n0->right, n1->right);
+}