diff --git a/content/html/document/src/nsHTMLContentSink.cpp b/content/html/document/src/nsHTMLContentSink.cpp index 04d6f1acdb57..8bed7559e85b 100644 --- a/content/html/document/src/nsHTMLContentSink.cpp +++ b/content/html/document/src/nsHTMLContentSink.cpp @@ -100,6 +100,7 @@ public: nsresult Init(nsIDocument* aDoc, nsIURL* aURL, nsIWebWidget* aWebWidget); nsIHTMLContent* GetCurrentContainer(eHTMLTags* aType); + nsIHTMLContent* GetTableParent(); virtual PRBool SetTitle(const nsString& aValue); @@ -187,6 +188,12 @@ protected: nsresult AddText(const nsString& aText, nsIHTMLContent** aContent); + void AppendToCorrectParent(nsHTMLTag aParentTag, + nsIHTMLContent* aParent, + nsHTMLTag aChildTag, + nsIHTMLContent* aChild, + PRBool aAllowReflow); + void GetAttributeValueAt(const nsIParserNode& aNode, PRInt32 aIndex, nsString& aResult); @@ -731,7 +738,9 @@ HTMLContentSink::CloseContainer(const nsIParserNode& aNode) } #endif - parent->AppendChild(container, allowReflow); + AppendToCorrectParent(parentType, parent, + (nsHTMLTag) aNode.GetNodeType(), container, + allowReflow); #ifdef NS_DEBUG if (allowReflow && (((PRInt32)gSinkLogModuleInfo->level) > 127)) { PRInt32 i, ns = mDocument->GetNumberOfShells(); @@ -1051,10 +1060,12 @@ PRInt32 HTMLContentSink::AddLeaf(const nsIParserNode& aNode) #ifdef NS_DEBUG if (allowReflow) { SINK_TRACE(SINK_TRACE_REFLOW, - ("HTMLContentSink::CloseContainer: reflow after append")); + ("HTMLContentSink::AddLeaf: reflow after append")); } #endif - parent->AppendChild(leaf, allowReflow); + AppendToCorrectParent(parentType, parent, + (nsHTMLTag) aNode.GetNodeType(), leaf, + allowReflow); } else { // XXX drop stuff on the floor that doesn't have a container! // Bad parser! @@ -1066,6 +1077,107 @@ PRInt32 HTMLContentSink::AddLeaf(const nsIParserNode& aNode) return 0; } +// Special handling code to push unexpected table content out of the +// table and into the table's parent, just before the table. Because +// the table is a container, it will not have been added to it's +// parent yet so we can just append the inappropriate content. +void +HTMLContentSink::AppendToCorrectParent(nsHTMLTag aParentTag, + nsIHTMLContent* aParent, + nsHTMLTag aChildTag, + nsIHTMLContent* aChild, + PRBool aAllowReflow) +{ + nsIHTMLContent* realParent = aParent; + + // These are the tags that are allowed in a table + static char tableTagSet[] = { + eHTMLTag_tbody, eHTMLTag_thead, eHTMLTag_tfoot, + eHTMLTag_tr, eHTMLTag_col, eHTMLTag_colgroup, + eHTMLTag_caption,/* XXX ok? */ + 0, + }; + + // These are the tags that are allowed in a tbody/thead/tfoot + static char tbodyTagSet[] = { + eHTMLTag_tr, + eHTMLTag_caption,/* XXX ok? */ + 0, + }; + + // These are the tags that are allowed in a colgroup + static char colgroupTagSet[] = { + eHTMLTag_col, + 0, + }; + + // These are the tags that are allowed in a tr + static char trTagSet[] = { + eHTMLTag_td, eHTMLTag_th, + 0, + }; + + switch (aParentTag) { + case eHTMLTag_table: + if (0 == strchr(tableTagSet, aChildTag)) { + realParent = GetTableParent(); + } + break; + + case eHTMLTag_tbody: + case eHTMLTag_thead: + case eHTMLTag_tfoot: + if (0 == strchr(tbodyTagSet, aChildTag)) { + realParent = GetTableParent(); + } + break; + + case eHTMLTag_col: + realParent = GetTableParent(); + break; + + case eHTMLTag_colgroup: + if (0 == strchr(colgroupTagSet, aChildTag)) { + realParent = GetTableParent(); + } + break; + + case eHTMLTag_tr: + if (0 == strchr(trTagSet, aChildTag)) { + realParent = GetTableParent(); + } + break; + + default: + break; + } + + realParent->AppendChild(aChild, aAllowReflow); +} + +// Find the parent of the currently open table +nsIHTMLContent* +HTMLContentSink::GetTableParent() +{ + PRInt32 sp = mStackPos - 1; + while (sp >= 0) { + switch (mNodeStack[sp]) { + case eHTMLTag_table: + case eHTMLTag_tr: + case eHTMLTag_tbody: + case eHTMLTag_thead: + case eHTMLTag_tfoot: + case eHTMLTag_col: + case eHTMLTag_colgroup: + break; + default: + return mContainerStack[sp]; + } + sp--; + } + return mBody; +} + nsresult HTMLContentSink::AddText(const nsString& aText, nsIHTMLContent** aContent) { diff --git a/layout/html/document/src/nsHTMLContentSink.cpp b/layout/html/document/src/nsHTMLContentSink.cpp index 04d6f1acdb57..8bed7559e85b 100644 --- a/layout/html/document/src/nsHTMLContentSink.cpp +++ b/layout/html/document/src/nsHTMLContentSink.cpp @@ -100,6 +100,7 @@ public: nsresult Init(nsIDocument* aDoc, nsIURL* aURL, nsIWebWidget* aWebWidget); nsIHTMLContent* GetCurrentContainer(eHTMLTags* aType); + nsIHTMLContent* GetTableParent(); virtual PRBool SetTitle(const nsString& aValue); @@ -187,6 +188,12 @@ protected: nsresult AddText(const nsString& aText, nsIHTMLContent** aContent); + void AppendToCorrectParent(nsHTMLTag aParentTag, + nsIHTMLContent* aParent, + nsHTMLTag aChildTag, + nsIHTMLContent* aChild, + PRBool aAllowReflow); + void GetAttributeValueAt(const nsIParserNode& aNode, PRInt32 aIndex, nsString& aResult); @@ -731,7 +738,9 @@ HTMLContentSink::CloseContainer(const nsIParserNode& aNode) } #endif - parent->AppendChild(container, allowReflow); + AppendToCorrectParent(parentType, parent, + (nsHTMLTag) aNode.GetNodeType(), container, + allowReflow); #ifdef NS_DEBUG if (allowReflow && (((PRInt32)gSinkLogModuleInfo->level) > 127)) { PRInt32 i, ns = mDocument->GetNumberOfShells(); @@ -1051,10 +1060,12 @@ PRInt32 HTMLContentSink::AddLeaf(const nsIParserNode& aNode) #ifdef NS_DEBUG if (allowReflow) { SINK_TRACE(SINK_TRACE_REFLOW, - ("HTMLContentSink::CloseContainer: reflow after append")); + ("HTMLContentSink::AddLeaf: reflow after append")); } #endif - parent->AppendChild(leaf, allowReflow); + AppendToCorrectParent(parentType, parent, + (nsHTMLTag) aNode.GetNodeType(), leaf, + allowReflow); } else { // XXX drop stuff on the floor that doesn't have a container! // Bad parser! @@ -1066,6 +1077,107 @@ PRInt32 HTMLContentSink::AddLeaf(const nsIParserNode& aNode) return 0; } +// Special handling code to push unexpected table content out of the +// table and into the table's parent, just before the table. Because +// the table is a container, it will not have been added to it's +// parent yet so we can just append the inappropriate content. +void +HTMLContentSink::AppendToCorrectParent(nsHTMLTag aParentTag, + nsIHTMLContent* aParent, + nsHTMLTag aChildTag, + nsIHTMLContent* aChild, + PRBool aAllowReflow) +{ + nsIHTMLContent* realParent = aParent; + + // These are the tags that are allowed in a table + static char tableTagSet[] = { + eHTMLTag_tbody, eHTMLTag_thead, eHTMLTag_tfoot, + eHTMLTag_tr, eHTMLTag_col, eHTMLTag_colgroup, + eHTMLTag_caption,/* XXX ok? */ + 0, + }; + + // These are the tags that are allowed in a tbody/thead/tfoot + static char tbodyTagSet[] = { + eHTMLTag_tr, + eHTMLTag_caption,/* XXX ok? */ + 0, + }; + + // These are the tags that are allowed in a colgroup + static char colgroupTagSet[] = { + eHTMLTag_col, + 0, + }; + + // These are the tags that are allowed in a tr + static char trTagSet[] = { + eHTMLTag_td, eHTMLTag_th, + 0, + }; + + switch (aParentTag) { + case eHTMLTag_table: + if (0 == strchr(tableTagSet, aChildTag)) { + realParent = GetTableParent(); + } + break; + + case eHTMLTag_tbody: + case eHTMLTag_thead: + case eHTMLTag_tfoot: + if (0 == strchr(tbodyTagSet, aChildTag)) { + realParent = GetTableParent(); + } + break; + + case eHTMLTag_col: + realParent = GetTableParent(); + break; + + case eHTMLTag_colgroup: + if (0 == strchr(colgroupTagSet, aChildTag)) { + realParent = GetTableParent(); + } + break; + + case eHTMLTag_tr: + if (0 == strchr(trTagSet, aChildTag)) { + realParent = GetTableParent(); + } + break; + + default: + break; + } + + realParent->AppendChild(aChild, aAllowReflow); +} + +// Find the parent of the currently open table +nsIHTMLContent* +HTMLContentSink::GetTableParent() +{ + PRInt32 sp = mStackPos - 1; + while (sp >= 0) { + switch (mNodeStack[sp]) { + case eHTMLTag_table: + case eHTMLTag_tr: + case eHTMLTag_tbody: + case eHTMLTag_thead: + case eHTMLTag_tfoot: + case eHTMLTag_col: + case eHTMLTag_colgroup: + break; + default: + return mContainerStack[sp]; + } + sp--; + } + return mBody; +} + nsresult HTMLContentSink::AddText(const nsString& aText, nsIHTMLContent** aContent) {