- Update Unix make goo to handle our new MOZILLA_CLIENT dependencies.
- Added TODO and STYLE_NOTES - Added style data to DOM_Element - Added GetCleanEntryData convenience function - Added internal dom_SetElementAttribute with optional suppressing of callback invocation - Added style init code - Style support (everything) - Fix text initialization thinko git-svn-id: svn://10.0.0.236/trunk@11289 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
@@ -20,9 +20,16 @@ DEPTH = ../..
|
||||
MODULE = dom
|
||||
LIBRARY_NAME = dom
|
||||
|
||||
REQUIRES = js
|
||||
REQUIRES = js dom
|
||||
|
||||
EXPORTS = dom.h
|
||||
ifdef MOZILLA_CLIENT
|
||||
REQUIRES += lay img layer util
|
||||
|
||||
# hack until PERIGNON takes over the world
|
||||
REQUIRES += style
|
||||
endif
|
||||
|
||||
EXPORTS = dom.h domstyle.h
|
||||
|
||||
CSRCS = domattr.c \
|
||||
domcore.c \
|
||||
@@ -34,3 +41,5 @@ CSRCS = domattr.c \
|
||||
$(NULL)
|
||||
|
||||
include $(DEPTH)/config/rules.mk
|
||||
|
||||
DEFINES += -DDOM
|
||||
|
||||
@@ -26,8 +26,14 @@ MODULE = dom
|
||||
LIBRARY_NAME = dom
|
||||
|
||||
REQUIRES = js
|
||||
#ifdef MOZILLA_CLIENT
|
||||
REQUIRES += lay img layer util
|
||||
|
||||
EXPORTS = $(srcdir)/dom.h
|
||||
# hack until PERIGNON takes over the world
|
||||
REQUIRES += style
|
||||
#endif
|
||||
|
||||
EXPORTS = $(srcdir)/dom.h $(srcdir)/domstyle.h
|
||||
|
||||
CSRCS = domattr.c \
|
||||
domcore.c \
|
||||
@@ -39,3 +45,5 @@ CSRCS = domattr.c \
|
||||
$(NULL)
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
DEFINES += -DDOM
|
||||
|
||||
65
mozilla/lib/libdom/STYLE_NOTES
Normal file
65
mozilla/lib/libdom/STYLE_NOTES
Normal file
@@ -0,0 +1,65 @@
|
||||
Notes on DOM style support, or: Everything you ever wanted to know
|
||||
about Perignon, but managed to avoid asking.
|
||||
|
||||
Data Structures:
|
||||
----------------
|
||||
Style data is represented by sets of disjoint trees, rooted on the
|
||||
innermost element type (simple selector). The sets are stored in a
|
||||
hash table. It's easier to understand with a picture, so here goes.
|
||||
|
||||
Legend:
|
||||
-- ``enclosing''
|
||||
| ``sibling''
|
||||
(=...) ``rule''
|
||||
|
||||
Style data:
|
||||
H1 { color:blue }
|
||||
H1 A { color:red }
|
||||
H1 B A { color:green }
|
||||
B A { color:purple }
|
||||
A:link { color:orange }
|
||||
.A { color:forclassA }
|
||||
|
||||
A -- B (=color:purple) -- H1 (=color:green)
|
||||
| |
|
||||
| H1 (=color:red)
|
||||
|
|
||||
A:link (=color:orange)
|
||||
|
|
||||
|
|
||||
.A (=color:forclassA)
|
||||
|
||||
H1 (=color:blue)
|
||||
|
||||
Note that there are no rules on the ``A'' selector. If the only rule
|
||||
in the sheet for ``A'' was the ``A:visited'' one, a dummy selector
|
||||
would be added, since the hash table is keyed on the pseudo-less
|
||||
selector.
|
||||
|
||||
Classes (".H1") and IDs ("#H1") are chained in the sibling list with
|
||||
their like-named tags.
|
||||
|
||||
A selector can correspond to a tag, class or id, depending on the
|
||||
value of the type field. If a class selector applies to the magic
|
||||
``all'' class, it will have no extra field. Otherwise, the extra
|
||||
field will be the tag selector. If a tag selector has an ID as well,
|
||||
it will be found in the extra field.
|
||||
|
||||
JSSS:
|
||||
-----
|
||||
|
||||
Perignon currently depends on JSSS to populate it, but someday I should
|
||||
implement DOM_StyleParseRule for the heathens that just use CSS.
|
||||
|
||||
CSS2:
|
||||
-----
|
||||
|
||||
I don't do CSS2 selectors yet. I don't yet know how much I care about
|
||||
that, because I don't yet know what CSS2 selectors are. =)
|
||||
|
||||
Questions:
|
||||
----------
|
||||
|
||||
- Do visited links get A:link properties as well? They don't appear to in
|
||||
the current implementation, but to my mind they should (unless, of course,
|
||||
such properties are overridden by A:visited rules).
|
||||
27
mozilla/lib/libdom/TODO
Normal file
27
mozilla/lib/libdom/TODO
Normal file
@@ -0,0 +1,27 @@
|
||||
General:
|
||||
- document.create*
|
||||
- escape HTML entities (JS entities?) coming into the text functions
|
||||
|
||||
Style:
|
||||
- add a CSS-parsing input API, or extract CSS->JS conversion from
|
||||
libstyle
|
||||
- DOM_StyleIsDirty/DOM_LockStyle/DOM_UnlockStyle to allow global
|
||||
caching of style data during document layout without racing with
|
||||
alterations from mocha thread.
|
||||
|
||||
Layout:
|
||||
- make proper LO_Elements for table stuff (pollmann)
|
||||
- stick the DOM_StyleGetElementProperty stuff in all the right places
|
||||
(reflow?)
|
||||
- make <HR> honour inherited style (colour, etc.)
|
||||
|
||||
libmocha:
|
||||
- move destruction into LM_ReleaseDocument
|
||||
- add destruction of style db
|
||||
- look closely at the implicit pop stuff in DOM_HTMLPushNode
|
||||
- wire up node reordering
|
||||
- put single <HTML> element child on #document at creation (and never
|
||||
pop it off)
|
||||
|
||||
XML:
|
||||
- everything, really
|
||||
@@ -224,8 +224,9 @@ struct DOM_Element {
|
||||
DOM_ElementOps *ops;
|
||||
const char *tagName;
|
||||
uintN nattrs;
|
||||
DOM_AttributeEntry *attrs;
|
||||
void *style; /* later, later... */
|
||||
DOM_AttributeEntry *attrs;
|
||||
char *styleClass;
|
||||
char *styleID;
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -235,7 +236,7 @@ struct DOM_Element {
|
||||
|
||||
DOM_Element *
|
||||
DOM_NewElement(const char *tagName, DOM_ElementOps *eleops, char *name,
|
||||
DOM_NodeOps *nodeops);
|
||||
char *styleClass, char *styleID, DOM_NodeOps *nodeops);
|
||||
|
||||
JSObject *
|
||||
DOM_NewElementObject(JSContext *cx, DOM_Element *element);
|
||||
@@ -251,6 +252,12 @@ JSBool
|
||||
DOM_SetElementAttribute(JSContext *cx, DOM_Element *element, const char *name,
|
||||
const char *value);
|
||||
|
||||
typedef JSBool(*DOM_DataParser)(const char *str, uint32 *data, void *closure);
|
||||
|
||||
JSBool
|
||||
DOM_GetCleanEntryData(JSContext *cx, DOM_AttributeEntry *entry,
|
||||
DOM_DataParser parser, uint32 *data, void *closure);
|
||||
|
||||
/*
|
||||
* Set the attributes from a pair of synchronized lists.
|
||||
* (This is what PA_FetchAllNameValues provides, handily enough.)
|
||||
|
||||
@@ -43,6 +43,10 @@ dom_NodeInit(JSContext *cx, JSObject *obj);
|
||||
JSObject *
|
||||
dom_ElementInit(JSContext *cx, JSObject *obj, JSObject *node_proto);
|
||||
|
||||
JSBool
|
||||
dom_SetElementAttribute(JSContext *cx, DOM_Element *element, const char *name,
|
||||
const char *value, JSBool runCallback);
|
||||
|
||||
JSObject *
|
||||
dom_AttributeInit(JSContext *cx, JSObject *scope, JSObject *node_proto);
|
||||
|
||||
|
||||
@@ -25,12 +25,17 @@
|
||||
JSBool
|
||||
DOM_Init(JSContext *cx, JSObject *scope) {
|
||||
JSObject *node, *cdata;
|
||||
return (( node = dom_NodeInit(cx, scope)) &&
|
||||
dom_AttributeInit(cx, scope, node) &&
|
||||
dom_ElementInit(cx, scope, node) &&
|
||||
( cdata = dom_CharacterDataInit(cx, scope, node)) &&
|
||||
dom_TextInit(cx, scope, cdata) &&
|
||||
dom_CommentInit(cx, scope, cdata));
|
||||
JSBool ok = (( node = dom_NodeInit(cx, scope)) &&
|
||||
dom_AttributeInit(cx, scope, node) &&
|
||||
dom_ElementInit(cx, scope, node) &&
|
||||
( cdata = dom_CharacterDataInit(cx, scope, node)) &&
|
||||
dom_TextInit(cx, scope, cdata) &&
|
||||
dom_CommentInit(cx, scope, cdata));
|
||||
#ifdef PERIGNON
|
||||
ok &= (dom_StyleSelectorInit(cx, scope) &&
|
||||
dom_TagsObjectInit(cx, scope));
|
||||
#endif
|
||||
return ok;
|
||||
}
|
||||
|
||||
static char *exception_names[] = {
|
||||
|
||||
@@ -188,7 +188,7 @@ static JSFunctionSpec element_methods[] = {
|
||||
|
||||
DOM_Element *
|
||||
DOM_NewElement(const char *tagName, DOM_ElementOps *eleops, char *name,
|
||||
DOM_NodeOps *nodeops)
|
||||
char *styleClass, char *styleID, DOM_NodeOps *nodeops)
|
||||
{
|
||||
DOM_Node *node;
|
||||
DOM_Element *element = XP_NEW_ZAP(DOM_Element);
|
||||
@@ -201,7 +201,10 @@ DOM_NewElement(const char *tagName, DOM_ElementOps *eleops, char *name,
|
||||
node->ops = nodeops;
|
||||
|
||||
element->tagName = tagName;
|
||||
element->styleClass = styleClass;
|
||||
element->styleID = styleID;
|
||||
element->ops = eleops;
|
||||
|
||||
return element;
|
||||
}
|
||||
|
||||
@@ -290,7 +293,22 @@ DOM_GetElementAttribute(JSContext *cx, DOM_Element *element, const char *name,
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
static JSBool
|
||||
JSBool
|
||||
DOM_GetCleanEntryData(JSContext *cx, DOM_AttributeEntry *entry,
|
||||
DOM_DataParser parser, uint32 *data, void *closure)
|
||||
{
|
||||
if (entry->dirty) {
|
||||
uint32 newdata;
|
||||
if (!parser(entry->value, &newdata, closure))
|
||||
return JS_FALSE;
|
||||
entry->data = newdata;
|
||||
entry->dirty = JS_FALSE;
|
||||
}
|
||||
*data = entry->data;
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
static DOM_AttributeEntry *
|
||||
AddAttribute(JSContext *cx, DOM_Element *element, const char *name,
|
||||
const char *value)
|
||||
{
|
||||
@@ -299,29 +317,31 @@ AddAttribute(JSContext *cx, DOM_Element *element, const char *name,
|
||||
if (!element->attrs) {
|
||||
element->attrs = JS_malloc(cx, sizeof(DOM_AttributeEntry));
|
||||
if (!element->attrs)
|
||||
return JS_FALSE;
|
||||
return NULL;
|
||||
element->nattrs = 1;
|
||||
} else {
|
||||
element->attrs = XP_REALLOC(element->attrs,
|
||||
(element->nattrs++) * sizeof(DOM_AttributeEntry));
|
||||
if (!element->attrs)
|
||||
return JS_FALSE;
|
||||
return NULL;
|
||||
}
|
||||
entry = element->attrs + element->nattrs - 1;
|
||||
entry->name = name;
|
||||
entry->value = value;
|
||||
return JS_TRUE;
|
||||
|
||||
return entry;
|
||||
}
|
||||
|
||||
JSBool
|
||||
DOM_SetElementAttribute(JSContext *cx, DOM_Element *element, const char *name,
|
||||
const char *value)
|
||||
dom_SetElementAttribute(JSContext *cx, DOM_Element *element, const char *name,
|
||||
const char *value, JSBool runCallback)
|
||||
{
|
||||
DOM_AttributeEntry *entry;
|
||||
if (!DOM_GetElementAttribute(cx, element, name, &entry))
|
||||
return JS_FALSE;
|
||||
if (!entry) {
|
||||
if (!AddAttribute(cx, element, name, value))
|
||||
entry = AddAttribute(cx, element, name, value);
|
||||
if (!entry)
|
||||
return JS_FALSE;
|
||||
} else {
|
||||
if (entry->value)
|
||||
@@ -330,9 +350,18 @@ DOM_SetElementAttribute(JSContext *cx, DOM_Element *element, const char *name,
|
||||
}
|
||||
entry->dirty = JS_TRUE;
|
||||
|
||||
if (!runCallback)
|
||||
return JS_TRUE;
|
||||
return element->ops->setAttribute(cx, element, name, value);
|
||||
}
|
||||
|
||||
JSBool
|
||||
DOM_SetElementAttribute(JSContext *cx, DOM_Element *element, const char *name,
|
||||
const char *value)
|
||||
{
|
||||
return dom_SetElementAttribute(cx, element, name, value, JS_TRUE);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
Element(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *vp)
|
||||
{
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -17,8 +17,7 @@
|
||||
*/
|
||||
|
||||
/*
|
||||
* Style things for the DOM.
|
||||
* Very purty. Makes it all go.
|
||||
* Perignon: store style information in the DOM, using CSS-1 selectors.
|
||||
*/
|
||||
|
||||
#include "jsapi.h"
|
||||
@@ -40,11 +39,6 @@ typedef struct DOM_StyleRule DOM_StyleRule;
|
||||
/* this may become int or something later, for speed */
|
||||
typedef const char *DOM_StyleToken;
|
||||
|
||||
#define DOM_STYLE_PSEUDO_TAG (1 << 7)
|
||||
#define DOM_SELECTOR_IS_PSEUDO(sel) ((sel) & DOM_STYLE_PSEUDO_TAG)
|
||||
#define DOM_STYLE_SELECTOR_TYPE(sel) ((sel) & ~DOM_STYLE_PSEUDO_TAG)
|
||||
#define DOM_PSEUDOIZE(sel) ((sel) | DOM_STYLE_PSEUDO_TAG)
|
||||
|
||||
enum {
|
||||
SELECTOR_UNKNOWN = 0,
|
||||
SELECTOR_ID,
|
||||
@@ -53,19 +47,33 @@ enum {
|
||||
};
|
||||
|
||||
struct DOM_StyleDatabase {
|
||||
PLHashTable *ht; /* PRHash, from js/ref or nsprpub, depending? */
|
||||
PLHashTable *ht;
|
||||
};
|
||||
|
||||
DOM_StyleDatabase *
|
||||
DOM_NewStyleDatabase(JSContext *cx);
|
||||
|
||||
void
|
||||
DOM_DestroyStyleDatabase(JSContext *cx, DOM_StyleDatabase *db);
|
||||
|
||||
/*
|
||||
* Find or create the StyleDatabase for the given JSContext.
|
||||
* The embedder must provide an implementation, or #define MOZILLA_CLIENT
|
||||
* to get the Mozilla-specific one which depends on MochaDecoder and
|
||||
* MWContext and lo_TopState and stuff.
|
||||
*/
|
||||
DOM_StyleDatabase *
|
||||
DOM_StyleDatabaseFromContext(JSContext *cx);
|
||||
|
||||
struct DOM_StyleSelector {
|
||||
int8 type;
|
||||
DOM_StyleToken selector;
|
||||
DOM_StyleToken pseudo;
|
||||
DOM_StyleToken extra;
|
||||
DOM_StyleSelector *enclosing;
|
||||
DOM_StyleSelector *sibling;
|
||||
DOM_StyleRule *rules;
|
||||
JSObject *mocha_object; /* reflection for this selector's rules */
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -80,14 +88,25 @@ struct DOM_StyleSelector {
|
||||
* 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");
|
||||
* And ".myclass CODE B":
|
||||
* sel3 = DOM_StyleFindSelector(cx, db, sel2, ".myclass", NULL);
|
||||
*/
|
||||
DOM_StyleSelector *
|
||||
DOM_StyleFindSelector(JSContext *cx, DOM_StyleDatabase *db,
|
||||
DOM_StyleSelector *base, DOM_StyleToken enclosing,
|
||||
DOM_StyleToken pseudo);
|
||||
|
||||
/*
|
||||
* As above, but take type explicitly rather than parsing leading # or . for
|
||||
* ID or class. For classes or extra is a tag or NULL. For tags, extra is an
|
||||
* ID or NULL. (For ID, extra is ignored.)
|
||||
*/
|
||||
DOM_StyleSelector *
|
||||
DOM_StyleFindSelectorFull(JSContext *cx, DOM_StyleDatabase *db,
|
||||
DOM_StyleSelector *base, uint8 type,
|
||||
DOM_StyleToken enclosing, DOM_StyleToken extra,
|
||||
DOM_StyleToken pseudo);
|
||||
|
||||
struct DOM_StyleRule {
|
||||
DOM_AttributeEntry entry;
|
||||
int16 weight;
|
||||
@@ -96,7 +115,7 @@ struct DOM_StyleRule {
|
||||
|
||||
/*
|
||||
* Parses a style rule and adds it to the style database.
|
||||
* If len is 0, rule is presumed to be NUL-terminated.
|
||||
* If len is 0, rule is presumed to be NUL-terminated. (XXX NYI)
|
||||
*
|
||||
* Usage example:
|
||||
*
|
||||
@@ -119,6 +138,8 @@ DOM_StyleParseRule(JSContext *cx, DOM_StyleDatabase *db, const char *rule,
|
||||
* enclosing Element is used for finding matches. The implementation is
|
||||
* necessarily somewhat hairy. See domstyle.c for details.
|
||||
*
|
||||
* If db is NULL, DOM_StyleDatabaseFromContext is used to find it.
|
||||
*
|
||||
* Usage examples:
|
||||
*
|
||||
* Get the color for a section of text:
|
||||
@@ -130,16 +151,38 @@ DOM_StyleParseRule(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);
|
||||
DOM_StyleToken property, DOM_AttributeEntry **entryp);
|
||||
|
||||
/*
|
||||
* Get/set the pseudoclass for an element
|
||||
*/
|
||||
DOM_StyleToken
|
||||
DOM_GetElementPseudo(JSContext *cx, DOM_Element *element);
|
||||
|
||||
JSBool
|
||||
DOM_SetElementPseudo(JSContext *cx, DOM_Element *element,
|
||||
DOM_StyleToken pseudo);
|
||||
|
||||
/*
|
||||
* Add a property to the provided selector.
|
||||
*
|
||||
* DOM_StyleAddRule(cx, db, sel, "color", "blue");
|
||||
*/
|
||||
JSBool
|
||||
DOM_AttributeEntry *
|
||||
DOM_StyleAddRule(JSContext *cx, DOM_StyleDatabase *db, DOM_StyleSelector *sel,
|
||||
DOM_StyleToken name, const char *value);
|
||||
|
||||
/*
|
||||
* Resolve classes, tags, ids, contextual on the given object.
|
||||
*/
|
||||
JSBool
|
||||
DOM_DocObjectResolveStyleProps(JSContext *cx, JSObject *obj, jsval id);
|
||||
|
||||
/*
|
||||
* The contextual selector JS function: contextual("H1", "EM");
|
||||
*/
|
||||
JSBool
|
||||
DOM_JSContextual(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
|
||||
jsval *rval);
|
||||
|
||||
#endif /* DOM_STYLE_H */
|
||||
|
||||
@@ -373,6 +373,7 @@ DOM_NewText(const char *data, int64 length, DOM_CDataOp notify,
|
||||
|
||||
LL_L2I(nbytes, length);
|
||||
cdata = (DOM_CharacterData *)text;
|
||||
cdata->len = length;
|
||||
cdata->data = XP_ALLOC(nbytes);
|
||||
cdata->notify = notify;
|
||||
if (!cdata->data) {
|
||||
|
||||
Reference in New Issue
Block a user