From cab0809536f6523273bb9d74b2f22ff57351f8a9 Mon Sep 17 00:00:00 2001 From: "shaver%netscape.com" Date: Thu, 10 Sep 1998 22:14:52 +0000 Subject: [PATCH] perignon grows (and throbs) git-svn-id: svn://10.0.0.236/trunk@9773 18797224-902f-48f8-a5cc-f745e15eee43 --- mozilla/lib/libdom/domstyle.c | 115 +++++++++++++++++++++++++++++++++- mozilla/lib/libdom/domstyle.h | 67 ++++++++++---------- 2 files changed, 146 insertions(+), 36 deletions(-) diff --git a/mozilla/lib/libdom/domstyle.c b/mozilla/lib/libdom/domstyle.c index e234ee7eb0b..83d860cebec 100644 --- a/mozilla/lib/libdom/domstyle.c +++ b/mozilla/lib/libdom/domstyle.c @@ -19,13 +19,68 @@ #include "domstyle.h" static DOM_StyleSelector * -GetBaseSelector(DOM_StyleDatabase *db, DOM_StyleToken type) +GetBaseSelector(JSContext *cx, DOM_StyleDatabase *db, DOM_StyleToken type, + DOM_StyleToken pseudo) { DOM_StyleSelector *sel = NULL; /* sel = HASH_LOOKUP(db->hashtable, type); */ return sel; } +static void +DestroySelector(JSContext *cx, DOM_StyleSelector *sel) +{ + XP_FREE(sel->selector); + if (sel->pseudo) + XP_FREE(sel->pseudo); + if (sel->rules) { + DOM_StyleRule *iter, *next; + iter = sel->rules; + do { + next = iter->next; + XP_FREE(iter->entry.name); + XP_FREE(iter->entry.value); + XP_FREE(iter); + iter = next; + } while (iter); + } + XP_FREE(sel); +} + +static DOM_StyleSelector * +NewSelector(JSContext *cx, DOM_StyleToken selector, DOM_StyleToken pseudo) +{ + DOM_StyleSelector *sel; + sel = XP_NEW_ZAP(DOM_StyleSelector); + if (!sel) + return NULL; + if (selector[0] == '.') { + sel->type = SELECTOR_CLASS; + selector++; + } else if (selector[0] == '#') { + sel->type = SELECTOR_ID; + selector++; + } else { + sel->type = SELECTOR_TAG; + } + + sel->selector = XP_STRDUP(selector); + if (!sel->selector) { + DestroySelector(cx, sel); + return NULL; + } + + if (pseudo) { + sel->pseudo = XP_STRDUP(pseudo); + if (!sel->pseudo) { + DestroySelector(cx, sel); + return NULL; + } + } + + return sel; +} + /* the pseudoclass, if any, is stored in a magic attribute */ static DOM_StyleToken GetPseudo(JSContext *cx, DOM_Element *element) @@ -57,6 +112,14 @@ GetPseudo(JSContext *cx, DOM_Element *element) element->tagName); \ #endif +static JSBool +SelectorMatchesToken(JSContext *cx, DOM_StyleSelector *sel, + DOM_StyleToken token, DOM_StyleToken pseudo) +{ + /* XXX handle #ID and .class */ + return !XPSTRCMP(sel->type, token); +} + static JSBool SelectorMatchesElement(JSContext *cx, DOM_Element *element, DOM_StyleSelector *sel) @@ -177,6 +240,52 @@ DOM_StyleGetProperty(JSContext *cx, DOM_StyleDatabase *db, if (!sel) return JS_TRUE; - return CheckSelector(cx, element, sel, property, entryp, &best, - 1); + /* + * CheckSelector will recursively find the best match for a given + * property. + */ + return CheckSelector(cx, element, sel, property, entryp, &best, 1); +} + +DOM_StyleSelector * +DOM_StyleFindSelector(JSContext *cx, DOM_StyleDatabase *db, + DOM_StyleSelector *base, DOM_StyleToken enclosing, + DOM_StyleToken pseudo) +{ + DOM_StyleSelector *sel; + + /* looking for the base one */ + if (!base) { + sel = GetBaseSelector(cx, db, enclosing, pseudo); + if (!sel) + sel = NewSelector(cx, enclosing, pseudo); + if (sel) + InsertBaseSelector(cx, db, sel); + return sel; + } + + if (!base->enclosing) { + sel = NewSelector(cx, enclosing, pseudo); + if (!sel) + return NULL; + base->enclosing = sel; + return sel; + } + + /* check existing enclosing selectors */ + sel = base->enclosing; + do { + if (SelectorMatchesToken(cx, sel, enclosing, pseudo)) + return sel; + sel = sel->sibling; + } while (sel); + + /* nothing found that matches, so create a new one */ + sel = NewSelector(cx, enclosing, pseudo); + if (!sel) + return NULL; + sel->sibling = base->enclosing; + base->enclosing = sel; + + return sel; } diff --git a/mozilla/lib/libdom/domstyle.h b/mozilla/lib/libdom/domstyle.h index 418c0dc6a43..ecbeb95ed8a 100644 --- a/mozilla/lib/libdom/domstyle.h +++ b/mozilla/lib/libdom/domstyle.h @@ -33,7 +33,7 @@ typedef struct DOM_StyleRule DOM_StyleRule; /* * DOM_StyleTokens are used for identification of elements ("H1"), style - * properties ("color"), style values ("blue") and pseudo-classes (":visited"). + * properties ("color"), style values ("blue") and pseudo-classes ("visited"). */ /* this may become int or something later, for speed */ @@ -44,19 +44,22 @@ typedef const char *DOM_StyleToken; #define DOM_STYLE_SELECTOR_TYPE(sel) ((sel) & ~DOM_STYLE_PSEUDO_TAG) #define DOM_PSEUDOIZE(sel) ((sel) | DOM_STYLE_PSEUDO_TAG) -typedef enum { +enum { SELECTOR_UNKNOWN = 0 SELECTOR_ID, SELECTOR_CLASS, SELECTOR_TAG -} - -struct DOM_StyleDatabase { - void *hashtable; /* PRHash, from js/ref or nsprpub, depending? */ }; +struct DOM_StyleDatabase { + PRHashTable *hashtable; /* PRHash, from js/ref or nsprpub, depending? */ +}; + +DOM_StyleDatabase * +DOM_NewStyleDatabase(JSContext *cx); + struct DOM_StyleSelector { - int8 selectorType; + int8 type; DOM_StyleToken selector; DOM_StyleToken pseudo; DOM_StyleSelector *enclosing; @@ -64,6 +67,26 @@ struct DOM_StyleSelector { DOM_StyleRule *rules; }; +/* + * Find or create a selector for the given enclosing element type, starting + * from the provided (optional) base selector. + * + * Usage examples: + * + * Find/create a selector for "B" + * sel = DOM_StyleFindSelector(cx, db, NULL, "B", NULL); + * + * Now find/create a selector for "CODE B": + * sel2 = DOM_StyleFindSelector(cx, db, sel, "CODE", NULL); + * + * And for "A:visited CODE B": + * sel3 = DOM_StyleFindSelector(cx, db, sel2, "A", "visited"); + */ +DOM_StyleSelector * +DOM_StyleFindSelector(JSContext *cx, DOM_StyleDatabase *db, + DOM_StyleSelector *base, DOM_StyleToken enclosing, + DOM_StyleToken pseudo); + struct DOM_StyleRule { DOM_AttributeEntry entry; int16 weight; @@ -106,30 +129,8 @@ DOM_StyleAddRule(JSContext *cx, DOM_StyleDatabase *db, const char *rule, JSBool DOM_StyleGetProperty(JSContext *cx, DOM_StyleDatabase *db, DOM_Node *node, - DOM_StyleToken property, DOM_StyleToken psuedo, - DOM_AttributeEntry **entryp); - -/* - * Find or create a selector for the given enclosing element type, starting - * from the provided (optional) base selector. - * - * Usage examples: - * - * Find/create a selector for "B" - * sel = DOM_StyleFindSelector(cx, db, NULL, "B"); - * - * Now find/create a selector for "CODE B": - * sel2 = DOM_StyleFindSelector(cx, db, sel, "CODE"); - * - * And for "H1 CODE B": - * sel3 = DOM_StyleFindSelector(cx, db, sel2, "H1"); - * - * Pseudo-classes are prefixed with ":": - * visited = DOM_StyleFindSelector(cx, db, hrefSel, ":visited"); - */ -DOM_StyleSelector * -DOM_StyleFindSelector(JSContext *cx, DOM_StyleDatabase *db, - DOM_StyleSelector *base, DOM_StyleToken enclosing); + DOM_StyleToken property, DOM_StyleToken psuedo, + DOM_AttributeEntry **entryp); /* * Add a property to the provided selector. @@ -137,7 +138,7 @@ DOM_StyleFindSelector(JSContext *cx, DOM_StyleDatabase *db, * DOM_StyleAddRule(cx, db, sel, "color", "blue"); */ JSBool -DOM_StyleAddRule(JSContext *cx, DOM_StyleDatabase *db, DOM_StyleToken name, - const char *value); +DOM_StyleAddRule(JSContext *cx, DOM_StyleDatabase *db, DOM_StyleSelector *sel, + DOM_StyleToken name, const char *value); #endif /* DOM_STYLE_H */