diff --git a/editor/libeditor/base/nsEditor.cpp b/editor/libeditor/base/nsEditor.cpp index 0f8f08ec300..24ede4e6567 100644 --- a/editor/libeditor/base/nsEditor.cpp +++ b/editor/libeditor/base/nsEditor.cpp @@ -3839,23 +3839,7 @@ nsEditor::TagCanContain(const nsAString &aParentTag, nsIDOMNode* aChild) PRBool nsEditor::TagCanContainTag(const nsAString &aParentTag, const nsAString &aChildTag) { - // if we don't have a dtd then assume we can insert whatever want - if (!mDTD) return PR_TRUE; - - PRInt32 childTagEnum; - // XXX Should this handle #cdata-section too? - if (aChildTag.EqualsLiteral("#text")) { - childTagEnum = eHTMLTag_text; - } - else { - childTagEnum = sParserService->HTMLStringTagToId(aChildTag); - } - - PRInt32 parentTagEnum = sParserService->HTMLStringTagToId(aParentTag); - NS_ASSERTION(parentTagEnum < NS_HTML_TAG_MAX, - "Fix the caller, this type of node can never contain children."); - - return mDTD->CanContain(parentTagEnum, childTagEnum); + return PR_TRUE; } PRBool @@ -3896,13 +3880,7 @@ nsEditor::IsDescendantOfBody(nsIDOMNode *inNode) PRBool nsEditor::IsContainer(nsIDOMNode *aNode) { - if (!aNode) return PR_FALSE; - nsAutoString stringTag; - nsresult res = aNode->GetNodeName(stringTag); - if (NS_FAILED(res)) return PR_FALSE; - PRInt32 tagEnum = sParserService->HTMLStringTagToId(stringTag); - - return mDTD->IsContainer(tagEnum); + return aNode ? PR_TRUE : PR_FALSE; } PRBool diff --git a/editor/libeditor/base/nsEditor.h b/editor/libeditor/base/nsEditor.h index e4af6493db8..b05d6fb66f2 100644 --- a/editor/libeditor/base/nsEditor.h +++ b/editor/libeditor/base/nsEditor.h @@ -56,7 +56,6 @@ #include "nsIComponentManager.h" #include "nsISupportsArray.h" #include "nsICSSStyleSheet.h" -#include "nsIDTD.h" #include "nsIDOMElement.h" #include "nsSelectionState.h" #include "nsIEditorSpellCheck.h" @@ -489,7 +488,7 @@ public: PRBool IsDescendantOfBody(nsIDOMNode *inNode); /** returns PR_TRUE if aNode is a container */ - PRBool IsContainer(nsIDOMNode *aNode); + virtual PRBool IsContainer(nsIDOMNode *aNode); /** returns PR_TRUE if aNode is an editable node */ PRBool IsEditable(nsIDOMNode *aNode); @@ -626,7 +625,6 @@ protected: // receiver when we get it off anonymous content because during document // teardown the anonymous content can get unhooked before we get unhooked. nsCOMPtr mDOMEventReceiver; - nsCOMPtr mDTD; nsString* mPhonetic; diff --git a/editor/libeditor/html/nsHTMLEditUtils.cpp b/editor/libeditor/html/nsHTMLEditUtils.cpp index f36397cb638..6eb936e37d8 100644 --- a/editor/libeditor/html/nsHTMLEditUtils.cpp +++ b/editor/libeditor/html/nsHTMLEditUtils.cpp @@ -47,6 +47,7 @@ #include "nsIContent.h" #include "nsIDOMNodeList.h" #include "nsIDOMHTMLAnchorElement.h" +#include "nsHTMLTags.h" /////////////////////////////////////////////////////////////////////////// // @@ -455,3 +456,313 @@ nsHTMLEditUtils::SupportsAlignAttr(nsIDOMNode * aNode) || (nodeAtom == nsEditProperty::h5) || (nodeAtom == nsEditProperty::h6); } + +// We use bitmasks to test containment of elements. Elements are marked to be +// in certain groups by setting the mGroup member of the nsElementInfo struct +// to the corresponding GROUP_ values (OR'ed together). Similarly, elements are +// marked to allow containment of certain groups by setting the +// mCanContainGroups member of the nsElementInfo struct to the corresponding +// GROUP_ values (OR'ed together). +// Testing containment then simply consists of checking whether the +// mCanContainGroups bitmask of an element and the mGroup bitmask of a +// potential child overlap. + +#define GROUP_NONE 0 + +// body, head, html +#define GROUP_TOPLEVEL (1 << 1) + +// base, isindex, link, meta, script, style, title +#define GROUP_HEAD_CONTENT (1 << 2) + +// b, big, i, s, small, strike, tt, u +#define GROUP_FONTSTYLE (1 << 3) + +// abbr, acronym, cite, code, del, dfn, em, ins, kbd, samp, strong, var +#define GROUP_PHRASE (1 << 4) + +// a, applet, basefont, bdo, br, font, iframe, img, map, object, q, script, +// span, sub, sup +#define GROUP_SPECIAL (1 << 5) + +// button, form, input, label, select, textarea +#define GROUP_FORMCONTROL (1 << 6) + +// address, applet, blockquote, button, center, del, dir, div, dl, fieldset, +// form, h1, h2, h3, h4, h5, h6, hr, iframe, ins, isindex, map, menu, noframes, +// noscript, object, ol, p, pre, table, ul +#define GROUP_BLOCK (1 << 7) + +// frame, frameset +#define GROUP_FRAME (1 << 8) + +// col, tbody +#define GROUP_TABLE_CONTENT (1 << 9) + +// tr +#define GROUP_TBODY_CONTENT (1 << 10) + +// td, th +#define GROUP_TR_CONTENT (1 << 11) + +// col +#define GROUP_COLGROUP_CONTENT (1 << 12) + +// param +#define GROUP_OBJECT_CONTENT (1 << 13) + +// li +#define GROUP_LI (1 << 14) + +// area +#define GROUP_MAP_CONTENT (1 << 15) + +// optgroup, option +#define GROUP_SELECT_CONTENT (1 << 16) + +// option +#define GROUP_OPTGROUP_CONTENT (1 << 17) + +// dd, dt +#define GROUP_DL_CONTENT (1 << 18) + +// p +#define GROUP_P (1 << 19) + +// text, whitespace, newline, comment +#define GROUP_LEAF (1 << 20) + +// XXX This is because the editor does sublists illegally. +// ol, ul +#define GROUP_OL_UL (1 << 21) + +#define GROUP_INLINE_ELEMENT \ + (GROUP_FONTSTYLE | GROUP_PHRASE | GROUP_SPECIAL | GROUP_FORMCONTROL | \ + GROUP_LEAF) + +#define GROUP_FLOW_ELEMENT (GROUP_INLINE_ELEMENT | GROUP_BLOCK) + +struct nsElementInfo +{ +#ifdef DEBUG + eHTMLTags mTag; +#endif + PRUint32 mGroup; + PRUint32 mCanContainGroups; + PRPackedBool mIsContainer; + PRPackedBool mCanContainSelf; +}; + +#ifdef DEBUG +#define ELEM(_tag, _isContainer, _canContainSelf, _group, _canContainGroups) \ + { eHTMLTag_##_tag, _group, _canContainGroups, _isContainer, _canContainSelf } +#else +#define ELEM(_tag, _isContainer, _canContainSelf, _group, _canContainGroups) \ + { _group, _canContainGroups, _isContainer, _canContainSelf } +#endif + +static const nsElementInfo kElements[eHTMLTag_userdefined] = { + ELEM(a, PR_TRUE, PR_FALSE, GROUP_SPECIAL, GROUP_INLINE_ELEMENT), + ELEM(abbr, PR_TRUE, PR_TRUE, GROUP_PHRASE, GROUP_INLINE_ELEMENT), + ELEM(acronym, PR_TRUE, PR_TRUE, GROUP_PHRASE, GROUP_INLINE_ELEMENT), + ELEM(address, PR_TRUE, PR_TRUE, GROUP_BLOCK, + GROUP_INLINE_ELEMENT | GROUP_P), + ELEM(applet, PR_TRUE, PR_TRUE, GROUP_SPECIAL | GROUP_BLOCK, + GROUP_FLOW_ELEMENT | GROUP_OBJECT_CONTENT), + ELEM(area, PR_FALSE, PR_FALSE, GROUP_MAP_CONTENT, GROUP_NONE), + ELEM(b, PR_TRUE, PR_TRUE, GROUP_FONTSTYLE, GROUP_INLINE_ELEMENT), + ELEM(base, PR_FALSE, PR_FALSE, GROUP_HEAD_CONTENT, GROUP_NONE), + ELEM(basefont, PR_FALSE, PR_FALSE, GROUP_SPECIAL, GROUP_NONE), + ELEM(bdo, PR_TRUE, PR_TRUE, GROUP_SPECIAL, GROUP_INLINE_ELEMENT), + ELEM(bgsound, PR_FALSE, PR_FALSE, GROUP_NONE, GROUP_NONE), + ELEM(big, PR_TRUE, PR_TRUE, GROUP_FONTSTYLE, GROUP_INLINE_ELEMENT), + ELEM(blink, PR_FALSE, PR_FALSE, GROUP_NONE, GROUP_NONE), + ELEM(blockquote, PR_TRUE, PR_TRUE, GROUP_BLOCK, GROUP_FLOW_ELEMENT), + ELEM(body, PR_TRUE, PR_TRUE, GROUP_TOPLEVEL, GROUP_FLOW_ELEMENT), + ELEM(br, PR_FALSE, PR_FALSE, GROUP_SPECIAL, GROUP_NONE), + ELEM(button, PR_TRUE, PR_TRUE, GROUP_FORMCONTROL | GROUP_BLOCK, + GROUP_FLOW_ELEMENT), + ELEM(canvas, PR_FALSE, PR_FALSE, GROUP_NONE, GROUP_NONE), + ELEM(caption, PR_TRUE, PR_TRUE, GROUP_NONE, GROUP_INLINE_ELEMENT), + ELEM(center, PR_TRUE, PR_TRUE, GROUP_BLOCK, GROUP_FLOW_ELEMENT), + ELEM(cite, PR_TRUE, PR_TRUE, GROUP_PHRASE, GROUP_INLINE_ELEMENT), + ELEM(code, PR_TRUE, PR_TRUE, GROUP_PHRASE, GROUP_INLINE_ELEMENT), + ELEM(col, PR_FALSE, PR_FALSE, GROUP_TABLE_CONTENT | GROUP_COLGROUP_CONTENT, + GROUP_NONE), + ELEM(colgroup, PR_TRUE, PR_FALSE, GROUP_NONE, GROUP_COLGROUP_CONTENT), + ELEM(dd, PR_TRUE, PR_FALSE, GROUP_DL_CONTENT, GROUP_FLOW_ELEMENT), + ELEM(del, PR_TRUE, PR_TRUE, GROUP_PHRASE | GROUP_BLOCK, GROUP_FLOW_ELEMENT), + ELEM(dfn, PR_TRUE, PR_TRUE, GROUP_PHRASE, GROUP_INLINE_ELEMENT), + ELEM(dir, PR_TRUE, PR_FALSE, GROUP_BLOCK, GROUP_LI), + ELEM(div, PR_TRUE, PR_TRUE, GROUP_BLOCK, GROUP_FLOW_ELEMENT), + ELEM(dl, PR_TRUE, PR_FALSE, GROUP_BLOCK, GROUP_DL_CONTENT), + ELEM(dt, PR_TRUE, PR_TRUE, GROUP_DL_CONTENT, GROUP_INLINE_ELEMENT), + ELEM(em, PR_TRUE, PR_TRUE, GROUP_PHRASE, GROUP_INLINE_ELEMENT), + ELEM(embed, PR_FALSE, PR_FALSE, GROUP_NONE, GROUP_NONE), + ELEM(fieldset, PR_TRUE, PR_TRUE, GROUP_BLOCK, GROUP_FLOW_ELEMENT), + ELEM(font, PR_TRUE, PR_TRUE, GROUP_SPECIAL, GROUP_INLINE_ELEMENT), + ELEM(form, PR_TRUE, PR_TRUE, GROUP_BLOCK, GROUP_FLOW_ELEMENT), + ELEM(frame, PR_FALSE, PR_FALSE, GROUP_FRAME, GROUP_NONE), + ELEM(frameset, PR_TRUE, PR_TRUE, GROUP_FRAME, GROUP_FRAME), + ELEM(h1, PR_TRUE, PR_FALSE, GROUP_BLOCK, GROUP_INLINE_ELEMENT), + ELEM(h2, PR_TRUE, PR_FALSE, GROUP_BLOCK, GROUP_INLINE_ELEMENT), + ELEM(h3, PR_TRUE, PR_FALSE, GROUP_BLOCK, GROUP_INLINE_ELEMENT), + ELEM(h4, PR_TRUE, PR_FALSE, GROUP_BLOCK, GROUP_INLINE_ELEMENT), + ELEM(h5, PR_TRUE, PR_FALSE, GROUP_BLOCK, GROUP_INLINE_ELEMENT), + ELEM(h6, PR_TRUE, PR_FALSE, GROUP_BLOCK, GROUP_INLINE_ELEMENT), + ELEM(head, PR_TRUE, PR_FALSE, GROUP_TOPLEVEL, GROUP_HEAD_CONTENT), + ELEM(hr, PR_FALSE, PR_FALSE, GROUP_BLOCK, GROUP_NONE), + ELEM(html, PR_TRUE, PR_FALSE, GROUP_TOPLEVEL, GROUP_TOPLEVEL), + ELEM(i, PR_TRUE, PR_TRUE, GROUP_FONTSTYLE, GROUP_INLINE_ELEMENT), + ELEM(iframe, PR_TRUE, PR_TRUE, GROUP_SPECIAL | GROUP_BLOCK, + GROUP_FLOW_ELEMENT), + ELEM(image, PR_FALSE, PR_FALSE, GROUP_NONE, GROUP_NONE), + ELEM(img, PR_FALSE, PR_FALSE, GROUP_SPECIAL, GROUP_NONE), + ELEM(input, PR_FALSE, PR_FALSE, GROUP_FORMCONTROL, GROUP_NONE), + ELEM(ins, PR_TRUE, PR_TRUE, GROUP_PHRASE | GROUP_BLOCK, GROUP_FLOW_ELEMENT), + ELEM(isindex, PR_FALSE, PR_FALSE, GROUP_BLOCK | GROUP_HEAD_CONTENT, + GROUP_NONE), + ELEM(kbd, PR_TRUE, PR_TRUE, GROUP_PHRASE, GROUP_INLINE_ELEMENT), + ELEM(keygen, PR_FALSE, PR_FALSE, GROUP_NONE, GROUP_NONE), + ELEM(label, PR_TRUE, PR_FALSE, GROUP_FORMCONTROL, GROUP_INLINE_ELEMENT), + ELEM(legend, PR_TRUE, PR_TRUE, GROUP_NONE, GROUP_INLINE_ELEMENT), + ELEM(li, PR_TRUE, PR_FALSE, GROUP_LI, GROUP_FLOW_ELEMENT), + ELEM(link, PR_FALSE, PR_FALSE, GROUP_HEAD_CONTENT, GROUP_NONE), + ELEM(listing, PR_FALSE, PR_FALSE, GROUP_NONE, GROUP_NONE), + ELEM(map, PR_TRUE, PR_TRUE, GROUP_SPECIAL, GROUP_BLOCK | GROUP_MAP_CONTENT), + ELEM(marquee, PR_FALSE, PR_FALSE, GROUP_NONE, GROUP_NONE), + ELEM(menu, PR_TRUE, PR_FALSE, GROUP_BLOCK, GROUP_LI), + ELEM(meta, PR_FALSE, PR_FALSE, GROUP_HEAD_CONTENT, GROUP_NONE), + ELEM(multicol, PR_FALSE, PR_FALSE, GROUP_NONE, GROUP_NONE), + ELEM(nobr, PR_FALSE, PR_FALSE, GROUP_NONE, GROUP_NONE), + ELEM(noembed, PR_FALSE, PR_FALSE, GROUP_NONE, GROUP_NONE), + ELEM(noframes, PR_TRUE, PR_TRUE, GROUP_BLOCK, GROUP_FLOW_ELEMENT), + ELEM(noscript, PR_TRUE, PR_TRUE, GROUP_BLOCK, GROUP_FLOW_ELEMENT), + ELEM(object, PR_TRUE, PR_TRUE, GROUP_SPECIAL | GROUP_BLOCK, + GROUP_FLOW_ELEMENT | GROUP_OBJECT_CONTENT), + // XXX Can contain self and ul because editor does sublists illegally. + ELEM(ol, PR_TRUE, PR_TRUE, GROUP_BLOCK | GROUP_OL_UL, + GROUP_LI | GROUP_OL_UL), + ELEM(optgroup, PR_TRUE, PR_FALSE, GROUP_SELECT_CONTENT, + GROUP_OPTGROUP_CONTENT), + ELEM(option, PR_TRUE, PR_FALSE, + GROUP_SELECT_CONTENT | GROUP_OPTGROUP_CONTENT, GROUP_LEAF), + ELEM(p, PR_TRUE, PR_FALSE, GROUP_BLOCK | GROUP_P, GROUP_INLINE_ELEMENT), + ELEM(param, PR_FALSE, PR_FALSE, GROUP_OBJECT_CONTENT, GROUP_NONE), + ELEM(plaintext, PR_FALSE, PR_FALSE, GROUP_NONE, GROUP_NONE), + ELEM(pre, PR_TRUE, PR_TRUE, GROUP_BLOCK, GROUP_INLINE_ELEMENT), + ELEM(q, PR_TRUE, PR_TRUE, GROUP_SPECIAL, GROUP_INLINE_ELEMENT), + ELEM(s, PR_TRUE, PR_TRUE, GROUP_FONTSTYLE, GROUP_INLINE_ELEMENT), + ELEM(samp, PR_TRUE, PR_TRUE, GROUP_PHRASE, GROUP_INLINE_ELEMENT), + ELEM(script, PR_TRUE, PR_FALSE, GROUP_HEAD_CONTENT | GROUP_SPECIAL, + GROUP_LEAF), + ELEM(select, PR_TRUE, PR_FALSE, GROUP_FORMCONTROL, GROUP_SELECT_CONTENT), + ELEM(server, PR_FALSE, PR_FALSE, GROUP_NONE, GROUP_NONE), + ELEM(small, PR_TRUE, PR_TRUE, GROUP_FONTSTYLE, GROUP_INLINE_ELEMENT), + ELEM(sound, PR_FALSE, PR_FALSE, GROUP_NONE, GROUP_NONE), + ELEM(spacer, PR_FALSE, PR_FALSE, GROUP_NONE, GROUP_NONE), + ELEM(span, PR_TRUE, PR_TRUE, GROUP_SPECIAL, GROUP_INLINE_ELEMENT), + ELEM(strike, PR_TRUE, PR_TRUE, GROUP_FONTSTYLE, GROUP_INLINE_ELEMENT), + ELEM(strong, PR_TRUE, PR_TRUE, GROUP_PHRASE, GROUP_INLINE_ELEMENT), + ELEM(style, PR_TRUE, PR_FALSE, GROUP_HEAD_CONTENT, GROUP_LEAF), + ELEM(sub, PR_TRUE, PR_TRUE, GROUP_SPECIAL, GROUP_INLINE_ELEMENT), + ELEM(sup, PR_TRUE, PR_TRUE, GROUP_SPECIAL, GROUP_INLINE_ELEMENT), + ELEM(table, PR_TRUE, PR_FALSE, GROUP_BLOCK, GROUP_TABLE_CONTENT), + ELEM(tbody, PR_TRUE, PR_FALSE, GROUP_TABLE_CONTENT, GROUP_TBODY_CONTENT), + ELEM(td, PR_TRUE, PR_FALSE, GROUP_TR_CONTENT, GROUP_FLOW_ELEMENT), + ELEM(textarea, PR_TRUE, PR_FALSE, GROUP_FORMCONTROL, GROUP_LEAF), + ELEM(tfoot, PR_TRUE, PR_FALSE, GROUP_NONE, GROUP_TBODY_CONTENT), + ELEM(th, PR_TRUE, PR_FALSE, GROUP_TR_CONTENT, GROUP_FLOW_ELEMENT), + ELEM(thead, PR_TRUE, PR_FALSE, GROUP_NONE, GROUP_TBODY_CONTENT), + ELEM(title, PR_TRUE, PR_FALSE, GROUP_HEAD_CONTENT, GROUP_LEAF), + ELEM(tr, PR_TRUE, PR_FALSE, GROUP_TBODY_CONTENT, GROUP_TR_CONTENT), + ELEM(tt, PR_TRUE, PR_TRUE, GROUP_FONTSTYLE, GROUP_INLINE_ELEMENT), + ELEM(u, PR_TRUE, PR_TRUE, GROUP_FONTSTYLE, GROUP_INLINE_ELEMENT), + // XXX Can contain self and ol because editor does sublists illegally. + ELEM(ul, PR_TRUE, PR_TRUE, GROUP_BLOCK | GROUP_OL_UL, + GROUP_LI | GROUP_OL_UL), + ELEM(var, PR_TRUE, PR_TRUE, GROUP_PHRASE, GROUP_INLINE_ELEMENT), + ELEM(wbr, PR_FALSE, PR_FALSE, GROUP_NONE, GROUP_NONE), + ELEM(xmp, PR_FALSE, PR_FALSE, GROUP_NONE, GROUP_NONE), + + // These aren't elements. + ELEM(text, PR_FALSE, PR_FALSE, GROUP_LEAF, GROUP_NONE), + ELEM(whitespace, PR_FALSE, PR_FALSE, GROUP_LEAF, GROUP_NONE), + ELEM(newline, PR_FALSE, PR_FALSE, GROUP_LEAF, GROUP_NONE), + ELEM(comment, PR_FALSE, PR_FALSE, GROUP_LEAF, GROUP_NONE), + ELEM(entity, PR_FALSE, PR_FALSE, GROUP_NONE, GROUP_NONE), + ELEM(doctypeDecl, PR_FALSE, PR_FALSE, GROUP_NONE, GROUP_NONE), + ELEM(markupDecl, PR_FALSE, PR_FALSE, GROUP_NONE, GROUP_NONE), + ELEM(instruction, PR_FALSE, PR_FALSE, GROUP_NONE, GROUP_NONE), + + ELEM(userdefined, PR_TRUE, PR_FALSE, GROUP_NONE, GROUP_FLOW_ELEMENT) +}; + +PRBool +nsHTMLEditUtils::CanContain(PRInt32 aParent, PRInt32 aChild) +{ + NS_ASSERTION(aParent > eHTMLTag_unknown && aParent <= eHTMLTag_userdefined, + "aParent out of range!"); + NS_ASSERTION(aChild > eHTMLTag_unknown && aChild <= eHTMLTag_userdefined, + "aChild out of range!"); + +#ifdef DEBUG + static PRBool checked = PR_FALSE; + if (!checked) { + checked = PR_TRUE; + PRInt32 i; + for (i = 1; i <= eHTMLTag_userdefined; ++i) { + NS_ASSERTION(kElements[i - 1].mTag == i, + "You need to update kElements (missing tags)."); + } + } +#endif + + // Special-case button. + if (aParent == eHTMLTag_button) { + static const eHTMLTags kButtonExcludeKids[] = { + eHTMLTag_a, + eHTMLTag_fieldset, + eHTMLTag_form, + eHTMLTag_iframe, + eHTMLTag_input, + eHTMLTag_isindex, + eHTMLTag_select, + eHTMLTag_textarea + }; + + PRUint32 j; + for (j = 0; j < NS_ARRAY_LENGTH(kButtonExcludeKids); ++j) { + if (kButtonExcludeKids[j] == aChild) { + return PR_FALSE; + } + } + } + + // Deprecated elements. + if (aChild == eHTMLTag_bgsound || aChild == eHTMLTag_keygen) { + return PR_FALSE; + } + + // Bug #67007, dont strip userdefined tags. + if (aChild == eHTMLTag_userdefined) { + return PR_TRUE; + } + + const nsElementInfo& parent = kElements[aParent - 1]; + if (aParent == aChild) { + return parent.mCanContainSelf; + } + + const nsElementInfo& child = kElements[aChild - 1]; + return (parent.mCanContainGroups & child.mGroup) != 0; +} + +PRBool +nsHTMLEditUtils::IsContainer(PRInt32 aTag) +{ + NS_ASSERTION(aTag > eHTMLTag_unknown && aTag <= eHTMLTag_userdefined, + "aTag out of range!"); + + return kElements[aTag - 1].mIsContainer; +} diff --git a/editor/libeditor/html/nsHTMLEditUtils.h b/editor/libeditor/html/nsHTMLEditUtils.h index 9d3f8a72b70..eb57843d02d 100644 --- a/editor/libeditor/html/nsHTMLEditUtils.h +++ b/editor/libeditor/html/nsHTMLEditUtils.h @@ -79,7 +79,8 @@ public: static PRBool IsMailCite(nsIDOMNode *aNode); static PRBool IsFormWidget(nsIDOMNode *aNode); static PRBool SupportsAlignAttr(nsIDOMNode *aNode); - + static PRBool CanContain(PRInt32 aParent, PRInt32 aChild); + static PRBool IsContainer(PRInt32 aTag); }; #endif /* nsHTMLEditUtils_h__ */ diff --git a/editor/libeditor/html/nsHTMLEditor.cpp b/editor/libeditor/html/nsHTMLEditor.cpp index e62c38bf56c..561a36f65b0 100644 --- a/editor/libeditor/html/nsHTMLEditor.cpp +++ b/editor/libeditor/html/nsHTMLEditor.cpp @@ -96,7 +96,6 @@ #include "nsIDOMDocumentFragment.h" #include "nsIPresShell.h" #include "nsPresContext.h" -#include "nsParserCIID.h" #include "nsIImage.h" #include "nsAOLCiter.h" #include "nsInternetCiter.h" @@ -132,8 +131,6 @@ #include "nsIWidget.h" #include "nsIParserService.h" -static NS_DEFINE_CID(kCTransitionalDTDCID, NS_CTRANSITIONAL_DTD_CID); - // Some utilities to handle annoying overloading of "A" tag for link and named anchor static char hrefText[] = "href"; static char anchorTxt[] = "anchor"; @@ -284,10 +281,6 @@ nsHTMLEditor::Init(nsIDOMDocument *aDoc, nsIPresShell *aPresShell, // block to scope nsAutoEditInitRulesTrigger nsAutoEditInitRulesTrigger rulesTrigger(NS_STATIC_CAST(nsPlaintextEditor*,this), rulesRes); - // Set up a DTD - mDTD = do_CreateInstance(kCTransitionalDTDCID); - if (!mDTD) result = NS_ERROR_FAILURE; - // Init the plaintext editor result = nsPlaintextEditor::Init(aDoc, aPresShell, aRoot, aSelCon, aFlags); if (NS_FAILED(result)) { return result; } @@ -4266,40 +4259,37 @@ nsHTMLEditor::EndOperation() PRBool nsHTMLEditor::TagCanContainTag(const nsAString& aParentTag, const nsAString& aChildTag) { - // COtherDTD gives some unwanted results. We override them here. - if (aParentTag.LowerCaseEqualsLiteral("ol") || - aParentTag.LowerCaseEqualsLiteral("ul")) - { - // if parent is a list and tag is also a list, say "yes". - // This is because the editor does sublists illegally for now. - if (aChildTag.LowerCaseEqualsLiteral("ol") || - aChildTag.LowerCaseEqualsLiteral("ul")) - return PR_TRUE; + PRInt32 childTagEnum; + // XXX Should this handle #cdata-section too? + if (aChildTag.EqualsLiteral("#text")) { + childTagEnum = eHTMLTag_text; + } + else { + childTagEnum = sParserService->HTMLStringTagToId(aChildTag); } - if (aParentTag.LowerCaseEqualsLiteral("li")) - { - // list items cant contain list items - if (aChildTag.LowerCaseEqualsLiteral("li")) - return PR_FALSE; + PRInt32 parentTagEnum = sParserService->HTMLStringTagToId(aParentTag); + NS_ASSERTION(parentTagEnum < NS_HTML_TAG_MAX, + "Fix the caller, this type of node can never contain children."); + + return nsHTMLEditUtils::CanContain(parentTagEnum, childTagEnum); +} + +PRBool +nsHTMLEditor::IsContainer(nsIDOMNode *aNode) +{ + if (!aNode) { + return PR_FALSE; } -/* - // if parent is a pre, and child is not inline, say "no" - if ( aParentTag.EqualsLiteral("pre") ) - { - if (aChildTag.EqualsLiteral("#text")) - return PR_TRUE; + nsAutoString stringTag; - PRInt32 childTagEnum = sParserService->HTMLStringTagToId(aChildTag); - PRInt32 parentTagEnum = sParserService->HTMLStringTagToId(aParentTag); + nsresult rv = aNode->GetNodeName(stringTag); + NS_ENSURE_SUCCESS(rv, PR_FALSE); - if (!mDTD->IsInlineElement(childTagEnum, parentTagEnum)) - return PR_FALSE; - } -*/ - // else fall thru - return nsEditor::TagCanContainTag(aParentTag, aChildTag); + PRInt32 tagEnum = sParserService->HTMLStringTagToId(stringTag); + + return nsHTMLEditUtils::IsContainer(tagEnum); } diff --git a/editor/libeditor/html/nsHTMLEditor.h b/editor/libeditor/html/nsHTMLEditor.h index 2eb2506c938..ada3efcf2ef 100644 --- a/editor/libeditor/html/nsHTMLEditor.h +++ b/editor/libeditor/html/nsHTMLEditor.h @@ -346,6 +346,9 @@ public: /** returns PR_TRUE if aParentTag can contain a child of type aChildTag */ virtual PRBool TagCanContainTag(const nsAString& aParentTag, const nsAString& aChildTag); + /** returns PR_TRUE if aNode is a container */ + virtual PRBool IsContainer(nsIDOMNode *aNode); + /** make the given selection span the entire document */ NS_IMETHOD SelectEntireDocument(nsISelection *aSelection); diff --git a/parser/htmlparser/public/nsParserCIID.h b/parser/htmlparser/public/nsParserCIID.h index a3758cc6f9d..70461e7f2bf 100644 --- a/parser/htmlparser/public/nsParserCIID.h +++ b/parser/htmlparser/public/nsParserCIID.h @@ -60,10 +60,6 @@ #define NS_LOGGING_SINK_CID \ {0xa6cf9060, 0x15b3, 0x11d2,{0x93, 0x2e, 0x00, 0x80, 0x5f, 0x8a, 0xdd, 0x32}} -// {4611d482-960a-11d4-8eb0-b617661b6f7c} -#define NS_CTRANSITIONAL_DTD_CID \ -{ 0x4611d482, 0x960a, 0x11d4, { 0x8e, 0xb0, 0xb6, 0x17, 0x66, 0x1b, 0x6f, 0x7c } } - // {8323FAD0-2102-11d4-8142-000064657374} #define NS_VIEWSOURCE_DTD_CID \ { 0x8323fad0, 0x2102, 0x11d4, { 0x81, 0x42, 0x0, 0x0, 0x64, 0x65, 0x73, 0x74 } } diff --git a/parser/htmlparser/src/Makefile.in b/parser/htmlparser/src/Makefile.in index af7c02ea10e..420790651ac 100644 --- a/parser/htmlparser/src/Makefile.in +++ b/parser/htmlparser/src/Makefile.in @@ -82,7 +82,6 @@ CPPSRCS = \ nsElementTable.cpp \ nsExpatDriver.cpp \ CNavDTD.cpp \ - COtherDTD.cpp \ nsHTMLEntities.cpp \ nsHTMLTags.cpp \ nsHTMLTokens.cpp \ diff --git a/parser/htmlparser/src/nsParser.cpp b/parser/htmlparser/src/nsParser.cpp index a0133845d82..31aab84aa07 100644 --- a/parser/htmlparser/src/nsParser.cpp +++ b/parser/htmlparser/src/nsParser.cpp @@ -50,7 +50,6 @@ #include "nsICharsetAlias.h" #include "nsIInputStream.h" #include "CNavDTD.h" -#include "COtherDTD.h" #include "prenv.h" #include "nsParserCIID.h" #include "nsReadableUtils.h" diff --git a/parser/htmlparser/src/nsParserModule.cpp b/parser/htmlparser/src/nsParserModule.cpp index 4be865ca3c9..a5f8226c35f 100644 --- a/parser/htmlparser/src/nsParserModule.cpp +++ b/parser/htmlparser/src/nsParserModule.cpp @@ -45,7 +45,6 @@ #include "nsParserCIID.h" #include "nsParser.h" #include "CNavDTD.h" -#include "COtherDTD.h" #include "nsHTMLEntities.h" #include "nsHTMLTokenizer.h" //#include "nsTextTokenizer.h" @@ -70,7 +69,6 @@ NS_GENERIC_FACTORY_CONSTRUCTOR(nsExpatDriver) NS_GENERIC_FACTORY_CONSTRUCTOR(nsParser) NS_GENERIC_FACTORY_CONSTRUCTOR(CNavDTD) -NS_GENERIC_FACTORY_CONSTRUCTOR(CTransitionalDTD) NS_GENERIC_FACTORY_CONSTRUCTOR(nsParserService) #ifdef MOZ_VIEW_SOURCE @@ -86,8 +84,6 @@ static const nsModuleComponentInfo gComponents[] = { { "Parser", NS_PARSER_CID, NULL, nsParserConstructor }, { "Navigator HTML DTD", NS_CNAVDTD_CID, NULL, CNavDTDConstructor }, - { "Transitional DTD", NS_CTRANSITIONAL_DTD_CID, NULL, - CTransitionalDTDConstructor }, #ifdef MOZ_VIEW_SOURCE { "ViewSource DTD", NS_VIEWSOURCE_DTD_CID, NULL, CViewSourceHTMLConstructor }, #endif diff --git a/parser/htmlparser/src/nsViewSourceHTML.cpp b/parser/htmlparser/src/nsViewSourceHTML.cpp index 32cd11488bd..50876e2089d 100644 --- a/parser/htmlparser/src/nsViewSourceHTML.cpp +++ b/parser/htmlparser/src/nsViewSourceHTML.cpp @@ -84,7 +84,6 @@ #include "nsIServiceManager.h" -#include "COtherDTD.h" #include "nsElementTable.h" #include "prenv.h" //this is here for debug reasons...