зеркало из https://github.com/mozilla/pjs.git
perignon grows (and throbs)
This commit is contained in:
Родитель
dc36bb18e6
Коммит
8803a12976
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
@ -109,35 +132,13 @@ 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);
|
||||
|
||||
/*
|
||||
* Add a property to the provided selector.
|
||||
*
|
||||
* 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 */
|
||||
|
|
Загрузка…
Ссылка в новой задаче