diff --git a/mozilla/content/html/document/src/nsHTMLContentSink.cpp b/mozilla/content/html/document/src/nsHTMLContentSink.cpp index 1df482f564c..b1d88192d3e 100644 --- a/mozilla/content/html/document/src/nsHTMLContentSink.cpp +++ b/mozilla/content/html/document/src/nsHTMLContentSink.cpp @@ -45,6 +45,10 @@ #include "nsIWebShell.h" extern nsresult NS_NewHTMLIFrame(nsIHTMLContent** aInstancePtrResult, nsIAtom* aTag, nsIWebShell* aWebShell); // XXX move +extern nsresult NS_NewHTMLFrame(nsIHTMLContent** aInstancePtrResult, + nsIAtom* aTag, nsIWebShell* aWebShell); // XXX move +extern nsresult NS_NewHTMLFrameset(nsIHTMLContent** aInstancePtrResult, + nsIAtom* aTag, nsIWebShell* aWebShell); // XXX move // XXX attribute values have entities in them - use the parsers expander! @@ -129,10 +133,10 @@ public: NS_IMETHOD CloseBody(const nsIParserNode& aNode); NS_IMETHOD OpenForm(const nsIParserNode& aNode); NS_IMETHOD CloseForm(const nsIParserNode& aNode); - NS_IMETHOD OpenMap(const nsIParserNode& aNode); - NS_IMETHOD CloseMap(const nsIParserNode& aNode); NS_IMETHOD OpenFrameset(const nsIParserNode& aNode); NS_IMETHOD CloseFrameset(const nsIParserNode& aNode); + NS_IMETHOD OpenMap(const nsIParserNode& aNode); + NS_IMETHOD CloseMap(const nsIParserNode& aNode); NS_IMETHOD OpenContainer(const nsIParserNode& aNode); NS_IMETHOD CloseContainer(const nsIParserNode& aNode); NS_IMETHOD AddLeaf(const nsIParserNode& aNode); @@ -157,6 +161,8 @@ protected: const nsIParserNode& aNode); nsresult ProcessEMBEDTag(nsIHTMLContent** aInstancePtrResult, const nsIParserNode& aNode); + nsresult ProcessFrameTag(nsIHTMLContent** aInstancePtrResult, + const nsIParserNode& aNode); nsresult ProcessHRTag(nsIHTMLContent** aInstancePtrResult, const nsIParserNode& aNode); nsresult ProcessINPUTTag(nsIHTMLContent** aInstancePtrResult, @@ -182,6 +188,8 @@ protected: nsresult ProcessIFRAMETag(nsIHTMLContent** aInstancePtrResult, const nsIParserNode& aNode); + nsresult ProcessFRAMESETTag(nsIHTMLContent** aInstancePtrResult, + const nsIParserNode& aNode); //---------------------------------------------------------------------- void FlushText(); @@ -205,6 +213,8 @@ protected: nsresult AddAttributes(const nsIParserNode& aNode, nsIHTMLContent* aInstancePtrResult); + nsIHTMLContent* GetBodyOrFrameset() { if (mBody) return mBody; else return mFrameset; } + nsresult LoadStyleSheet(nsIURL* aURL, nsIUnicharInputStream* aUIN); @@ -226,6 +236,7 @@ protected: nsIHTMLContent* mRoot; nsIHTMLContent* mBody; + nsIHTMLContent* mFrameset; nsIHTMLContent* mHead; PRTime mLastUpdateTime; @@ -233,6 +244,11 @@ protected: PRBool mLayoutStarted; PRInt32 mInMonolithicContainer; nsIWebShell* mWebShell; + + // XXX The parser needs to keep track of body tags and frameset tags + // and tell the content sink if they are to be ignored. For example, in nav4 + // ignores the frameset and + // ignores the body }; // Note: operator new zeros our memory @@ -252,6 +268,7 @@ HTMLContentSink::~HTMLContentSink() { NS_IF_RELEASE(mHead); NS_IF_RELEASE(mBody); + NS_IF_RELEASE(mFrameset); NS_IF_RELEASE(mRoot); NS_IF_RELEASE(mDocument); NS_IF_RELEASE(mDocumentURL); @@ -304,21 +321,6 @@ HTMLContentSink::Init(nsIDocument* aDoc, } mRoot->AppendChild(mHead, PR_FALSE); - // Make body container - NS_IF_RELEASE(mBody); - atom = NS_NewAtom("BODY"); - if (nsnull == atom) { - return NS_ERROR_OUT_OF_MEMORY; - } - rv = NS_NewBodyPart(&mBody, atom); - NS_RELEASE(atom); - if (NS_OK != rv) { - return rv; - } - - // Note: Can't do this here; see the comment in OpenBody - //XXX mRoot->AppendChild(mBody, PR_FALSE); - return rv; } @@ -348,8 +350,12 @@ HTMLContentSink::CloseHTML(const nsIParserNode& aNode) SINK_TRACE_NODE(SINK_TRACE_CALLS, "HTMLContentSink::CloseHTML", aNode); - NS_ASSERTION(mStackPos > 0, "bad bad"); - mNodeStack[--mStackPos] = eHTMLTag_unknown; + // XXX this is the way it used to be + //NS_ASSERTION(mStackPos > 0, "bad bad"); + //mNodeStack[--mStackPos] = eHTMLTag_unknown; + if (mStackPos > 0) { + mNodeStack[--mStackPos] = eHTMLTag_unknown; + } NS_IF_RELEASE(mCurrentForm); @@ -422,6 +428,19 @@ HTMLContentSink::OpenBody(const nsIParserNode& aNode) "HTMLContentSink::OpenBody", aNode); mNodeStack[mStackPos] = (eHTMLTags)aNode.GetNodeType(); + + // Make body container + NS_IF_RELEASE(mBody); + nsIAtom* atom = NS_NewAtom("BODY"); + if (nsnull == atom) { + return NS_ERROR_OUT_OF_MEMORY; + } + nsresult rv = NS_NewBodyPart(&mBody, atom); + NS_RELEASE(atom); + if (NS_OK != rv) { + return rv; + } + mContainerStack[mStackPos] = mBody; mStackPos++; @@ -558,6 +577,60 @@ HTMLContentSink::CloseForm(const nsIParserNode& aNode) return NS_OK; } +// XXX this is a copy of OpenBody, consolidate! +NS_IMETHODIMP +HTMLContentSink::OpenFrameset(const nsIParserNode& aNode) +{ + FlushText(); + + SINK_TRACE_NODE(SINK_TRACE_CALLS, + "HTMLContentSink::OpenFrameset", aNode); + + mNodeStack[mStackPos] = (eHTMLTags)aNode.GetNodeType(); + + // Make frameset container + NS_IF_RELEASE(mFrameset); + nsIAtom* atom = NS_NewAtom("FRAMESET"); + if (nsnull == atom) { + return NS_ERROR_OUT_OF_MEMORY; + } + nsresult rv = NS_NewHTMLFrameset(&mFrameset, atom, nsnull); + NS_RELEASE(atom); + if (NS_OK != rv) { + return rv; + } + + mContainerStack[mStackPos] = mFrameset; + mStackPos++; + + // Add attributes to the frameset content object + AddAttributes(aNode, mFrameset); + // XXX If the frameset already existed and has been reflowed somewhat + // then we need to trigger a style change + mRoot->AppendChild(mFrameset, PR_TRUE); + + return NS_OK; +} + +NS_IMETHODIMP +HTMLContentSink::CloseFrameset(const nsIParserNode& aNode) +{ + FlushText(); + + SINK_TRACE_NODE(SINK_TRACE_CALLS, + "HTMLContentSink::CloseFrameset", aNode); + + NS_ASSERTION(mStackPos > 0, "bad bad"); + mNodeStack[--mStackPos] = eHTMLTag_unknown; + + // Reflow any lingering content + if (!mLayoutStarted) { + StartLayout(); + } + + return NS_OK; +} + NS_IMETHODIMP HTMLContentSink::OpenMap(const nsIParserNode& aNode) { @@ -605,29 +678,6 @@ HTMLContentSink::CloseMap(const nsIParserNode& aNode) return NS_OK; } -NS_IMETHODIMP -HTMLContentSink::OpenFrameset(const nsIParserNode& aNode) -{ - FlushText(); - - SINK_TRACE_NODE(SINK_TRACE_CALLS, - "HTMLContentSink::OpenFrameset", aNode); - - mNodeStack[mStackPos++] = (eHTMLTags)aNode.GetNodeType(); - return NS_OK; -} - -NS_IMETHODIMP -HTMLContentSink::CloseFrameset(const nsIParserNode& aNode) -{ - FlushText(); - - SINK_TRACE_NODE(SINK_TRACE_CALLS, - "HTMLContentSink::CloseFrameset", aNode); - - mNodeStack[--mStackPos] = eHTMLTag_unknown; - return NS_OK; -} NS_IMETHODIMP HTMLContentSink::OpenContainer(const nsIParserNode& aNode) @@ -716,6 +766,14 @@ HTMLContentSink::OpenContainer(const nsIParserNode& aNode) rv = ProcessIFRAMETag(&container, aNode); break; + case eHTMLTag_frameset: + if (!mFrameset) { + rv = OpenFrameset(aNode); // top level frameset + } else { + rv = ProcessFRAMESETTag(&container, aNode); + } + break; + default: rv = NS_NewHTMLContainer(&container, atom); break; @@ -783,9 +841,15 @@ HTMLContentSink::CloseContainer(const nsIParserNode& aNode) eHTMLTags parentType; parent = GetCurrentContainer(&parentType); container->Compact(); + // don't append the top level frameset to its parent, this was done in OpenFrameset + // XXX this is necessary because the parser is calling OpenContainer, CloseContainer + // on framesets. It should be calling OpenFrameset. + if (container == mFrameset) { + return CloseFrameset(aNode); + } if (nsnull != parent) { - PRBool allowReflow = parent == mBody; + PRBool allowReflow = parent == GetBodyOrFrameset(); #ifdef NS_DEBUG if (allowReflow) { SINK_TRACE(SINK_TRACE_REFLOW, @@ -821,7 +885,7 @@ HTMLContentSink::CloseContainer(const nsIParserNode& aNode) } #endif #if XXX - if (parent == mBody) { + if (parent == GetBodyOrFrameset()) { // We just closed a child of the body off. Trigger a // content-appended reflow if enough time has elapsed PRTime now = PR_Now(); @@ -976,9 +1040,14 @@ void HTMLContentSink::ReflowNewContent() nsIHTMLContent* HTMLContentSink::GetCurrentContainer(eHTMLTags* aType) { nsIHTMLContent* parent; - if (mStackPos <= 2) { // assume HTML and BODY are on the stack - parent = mBody; - *aType = eHTMLTag_body; + if (mStackPos <= 2) { // assume HTML and BODY/FRAMESET are on the stack + if (mBody) { + parent = mBody; + *aType = eHTMLTag_body; + } else { + parent = mFrameset; + *aType = eHTMLTag_frameset; + } } else { parent = mContainerStack[mStackPos - 1]; *aType = mNodeStack[mStackPos - 1]; @@ -1056,6 +1125,10 @@ NS_IMETHODIMP HTMLContentSink::AddLeaf(const nsIParserNode& aNode) FlushText(); rv = ProcessBRTag(&leaf, aNode); break; + case eHTMLTag_frame: + FlushText(); + rv = ProcessFrameTag(&leaf, aNode); + break; case eHTMLTag_hr: FlushText(); rv = ProcessHRTag(&leaf, aNode); @@ -1220,7 +1293,7 @@ HTMLContentSink::GetTableParent() } sp--; } - return mBody; + return GetBodyOrFrameset(); } nsresult @@ -1693,14 +1766,14 @@ nsresult HTMLContentSink::ProcessINPUTTag(nsIHTMLContent** aInstancePtrResult, else if (val.EqualsIgnoreCase("text")) { rv = NS_NewHTMLInputText(aInstancePtrResult, atom, mCurrentForm); } - else if (val.EqualsIgnoreCase("select1")) { // TEMP hack XXX - rv = NS_NewHTMLSelect(aInstancePtrResult, atom, mCurrentForm, 1); + else if (val.EqualsIgnoreCase("frameset1")) { // TEMP hack XXX + // rv = NS_NewHTMLFrameset(aInstancePtrResult, atom, mWebWidget, 1); } - else if (val.EqualsIgnoreCase("select2")) { // TEMP hack XXX - rv = NS_NewHTMLSelect(aInstancePtrResult, atom, mCurrentForm, 2); + else if (val.EqualsIgnoreCase("frameset2")) { // TEMP hack XXX + // rv = NS_NewHTMLFrameset(aInstancePtrResult, atom, mWebWidget, 2); } - else if (val.EqualsIgnoreCase("select3")) { // TEMP hack XXX - rv = NS_NewHTMLSelect(aInstancePtrResult, atom, mCurrentForm, 3); + else if (val.EqualsIgnoreCase("frameset3")) { // TEMP hack XXX + // rv = NS_NewHTMLFrameset(aInstancePtrResult, atom, mWebWidget, 3); } else { rv = NS_NewHTMLInputSubmit(aInstancePtrResult, atom, mCurrentForm); @@ -1721,6 +1794,18 @@ nsresult HTMLContentSink::ProcessINPUTTag(nsIHTMLContent** aInstancePtrResult, return rv; } +nsresult HTMLContentSink::ProcessFrameTag(nsIHTMLContent** aInstancePtrResult, + const nsIParserNode& aNode) +{ + nsAutoString tmp("FRAME"); + nsIAtom* atom = NS_NewAtom(tmp); + + nsresult rv = NS_NewHTMLFrame(aInstancePtrResult, atom, mWebShell); + + NS_RELEASE(atom); + return rv; +} + nsresult HTMLContentSink::ProcessTEXTAREATag(nsIHTMLContent** aInstancePtrResult, const nsIParserNode& aNode) @@ -1855,6 +1940,19 @@ HTMLContentSink::ProcessIFRAMETag(nsIHTMLContent** aInstancePtrResult, return rv; } +nsresult +HTMLContentSink::ProcessFRAMESETTag(nsIHTMLContent** aInstancePtrResult, + const nsIParserNode& aNode) +{ + nsAutoString tmp("FRAMESET"); + nsIAtom* atom = NS_NewAtom(tmp); + + nsresult rv = NS_NewHTMLIFrame(aInstancePtrResult, atom, mWebShell); + + NS_RELEASE(atom); + return rv; +} + nsresult HTMLContentSink::ProcessWBRTag(nsIHTMLContent** aInstancePtrResult, const nsIParserNode& aNode) { diff --git a/mozilla/layout/generic/nsPageFrame.cpp b/mozilla/layout/generic/nsPageFrame.cpp index 9f620e9c0c6..3c2a7814c83 100644 --- a/mozilla/layout/generic/nsPageFrame.cpp +++ b/mozilla/layout/generic/nsPageFrame.cpp @@ -41,7 +41,8 @@ void nsPageFrame::CreateFirstChild(nsIPresContext* aPresContext) if (nsnull != child) { nsIAtom* tag; tag = child->GetTag(); - if (nsHTMLAtoms::body == tag) { + // XXX added frameset check, is it necessary, what is a page frame anyway + if ((nsHTMLAtoms::body == tag) || (nsHTMLAtoms::frameset == tag)) { // Create a frame nsIContentDelegate* cd = child->GetDelegate(aPresContext); if (nsnull != cd) { diff --git a/mozilla/layout/html/base/src/nsPageFrame.cpp b/mozilla/layout/html/base/src/nsPageFrame.cpp index 9f620e9c0c6..3c2a7814c83 100644 --- a/mozilla/layout/html/base/src/nsPageFrame.cpp +++ b/mozilla/layout/html/base/src/nsPageFrame.cpp @@ -41,7 +41,8 @@ void nsPageFrame::CreateFirstChild(nsIPresContext* aPresContext) if (nsnull != child) { nsIAtom* tag; tag = child->GetTag(); - if (nsHTMLAtoms::body == tag) { + // XXX added frameset check, is it necessary, what is a page frame anyway + if ((nsHTMLAtoms::body == tag) || (nsHTMLAtoms::frameset == tag)) { // Create a frame nsIContentDelegate* cd = child->GetDelegate(aPresContext); if (nsnull != cd) { diff --git a/mozilla/layout/html/base/src/nsRootPart.cpp b/mozilla/layout/html/base/src/nsRootPart.cpp index dd1e3a86e63..fd744fe7d38 100644 --- a/mozilla/layout/html/base/src/nsRootPart.cpp +++ b/mozilla/layout/html/base/src/nsRootPart.cpp @@ -254,7 +254,7 @@ void RootContentFrame::CreateFirstChild(nsIPresContext* aPresContext) mLastContentOffset = mFirstContentOffset; } else { - // Create a frame for the body child + // Create a frame for the body/frameset child PRInt32 i, n; n = mContent->ChildCount(); for (i = 0; i < n; i++) { @@ -262,7 +262,7 @@ void RootContentFrame::CreateFirstChild(nsIPresContext* aPresContext) if (nsnull != child) { nsIAtom* tag; tag = child->GetTag(); - if (nsHTMLAtoms::body == tag) { + if ((nsHTMLAtoms::body == tag) || (nsHTMLAtoms::frameset == tag)) { // Create a frame nsIContentDelegate* cd = child->GetDelegate(aPresContext); if (nsnull != cd) { diff --git a/mozilla/layout/html/document/src/nsHTMLContentSink.cpp b/mozilla/layout/html/document/src/nsHTMLContentSink.cpp index 1df482f564c..b1d88192d3e 100644 --- a/mozilla/layout/html/document/src/nsHTMLContentSink.cpp +++ b/mozilla/layout/html/document/src/nsHTMLContentSink.cpp @@ -45,6 +45,10 @@ #include "nsIWebShell.h" extern nsresult NS_NewHTMLIFrame(nsIHTMLContent** aInstancePtrResult, nsIAtom* aTag, nsIWebShell* aWebShell); // XXX move +extern nsresult NS_NewHTMLFrame(nsIHTMLContent** aInstancePtrResult, + nsIAtom* aTag, nsIWebShell* aWebShell); // XXX move +extern nsresult NS_NewHTMLFrameset(nsIHTMLContent** aInstancePtrResult, + nsIAtom* aTag, nsIWebShell* aWebShell); // XXX move // XXX attribute values have entities in them - use the parsers expander! @@ -129,10 +133,10 @@ public: NS_IMETHOD CloseBody(const nsIParserNode& aNode); NS_IMETHOD OpenForm(const nsIParserNode& aNode); NS_IMETHOD CloseForm(const nsIParserNode& aNode); - NS_IMETHOD OpenMap(const nsIParserNode& aNode); - NS_IMETHOD CloseMap(const nsIParserNode& aNode); NS_IMETHOD OpenFrameset(const nsIParserNode& aNode); NS_IMETHOD CloseFrameset(const nsIParserNode& aNode); + NS_IMETHOD OpenMap(const nsIParserNode& aNode); + NS_IMETHOD CloseMap(const nsIParserNode& aNode); NS_IMETHOD OpenContainer(const nsIParserNode& aNode); NS_IMETHOD CloseContainer(const nsIParserNode& aNode); NS_IMETHOD AddLeaf(const nsIParserNode& aNode); @@ -157,6 +161,8 @@ protected: const nsIParserNode& aNode); nsresult ProcessEMBEDTag(nsIHTMLContent** aInstancePtrResult, const nsIParserNode& aNode); + nsresult ProcessFrameTag(nsIHTMLContent** aInstancePtrResult, + const nsIParserNode& aNode); nsresult ProcessHRTag(nsIHTMLContent** aInstancePtrResult, const nsIParserNode& aNode); nsresult ProcessINPUTTag(nsIHTMLContent** aInstancePtrResult, @@ -182,6 +188,8 @@ protected: nsresult ProcessIFRAMETag(nsIHTMLContent** aInstancePtrResult, const nsIParserNode& aNode); + nsresult ProcessFRAMESETTag(nsIHTMLContent** aInstancePtrResult, + const nsIParserNode& aNode); //---------------------------------------------------------------------- void FlushText(); @@ -205,6 +213,8 @@ protected: nsresult AddAttributes(const nsIParserNode& aNode, nsIHTMLContent* aInstancePtrResult); + nsIHTMLContent* GetBodyOrFrameset() { if (mBody) return mBody; else return mFrameset; } + nsresult LoadStyleSheet(nsIURL* aURL, nsIUnicharInputStream* aUIN); @@ -226,6 +236,7 @@ protected: nsIHTMLContent* mRoot; nsIHTMLContent* mBody; + nsIHTMLContent* mFrameset; nsIHTMLContent* mHead; PRTime mLastUpdateTime; @@ -233,6 +244,11 @@ protected: PRBool mLayoutStarted; PRInt32 mInMonolithicContainer; nsIWebShell* mWebShell; + + // XXX The parser needs to keep track of body tags and frameset tags + // and tell the content sink if they are to be ignored. For example, in nav4 + // ignores the frameset and + // ignores the body }; // Note: operator new zeros our memory @@ -252,6 +268,7 @@ HTMLContentSink::~HTMLContentSink() { NS_IF_RELEASE(mHead); NS_IF_RELEASE(mBody); + NS_IF_RELEASE(mFrameset); NS_IF_RELEASE(mRoot); NS_IF_RELEASE(mDocument); NS_IF_RELEASE(mDocumentURL); @@ -304,21 +321,6 @@ HTMLContentSink::Init(nsIDocument* aDoc, } mRoot->AppendChild(mHead, PR_FALSE); - // Make body container - NS_IF_RELEASE(mBody); - atom = NS_NewAtom("BODY"); - if (nsnull == atom) { - return NS_ERROR_OUT_OF_MEMORY; - } - rv = NS_NewBodyPart(&mBody, atom); - NS_RELEASE(atom); - if (NS_OK != rv) { - return rv; - } - - // Note: Can't do this here; see the comment in OpenBody - //XXX mRoot->AppendChild(mBody, PR_FALSE); - return rv; } @@ -348,8 +350,12 @@ HTMLContentSink::CloseHTML(const nsIParserNode& aNode) SINK_TRACE_NODE(SINK_TRACE_CALLS, "HTMLContentSink::CloseHTML", aNode); - NS_ASSERTION(mStackPos > 0, "bad bad"); - mNodeStack[--mStackPos] = eHTMLTag_unknown; + // XXX this is the way it used to be + //NS_ASSERTION(mStackPos > 0, "bad bad"); + //mNodeStack[--mStackPos] = eHTMLTag_unknown; + if (mStackPos > 0) { + mNodeStack[--mStackPos] = eHTMLTag_unknown; + } NS_IF_RELEASE(mCurrentForm); @@ -422,6 +428,19 @@ HTMLContentSink::OpenBody(const nsIParserNode& aNode) "HTMLContentSink::OpenBody", aNode); mNodeStack[mStackPos] = (eHTMLTags)aNode.GetNodeType(); + + // Make body container + NS_IF_RELEASE(mBody); + nsIAtom* atom = NS_NewAtom("BODY"); + if (nsnull == atom) { + return NS_ERROR_OUT_OF_MEMORY; + } + nsresult rv = NS_NewBodyPart(&mBody, atom); + NS_RELEASE(atom); + if (NS_OK != rv) { + return rv; + } + mContainerStack[mStackPos] = mBody; mStackPos++; @@ -558,6 +577,60 @@ HTMLContentSink::CloseForm(const nsIParserNode& aNode) return NS_OK; } +// XXX this is a copy of OpenBody, consolidate! +NS_IMETHODIMP +HTMLContentSink::OpenFrameset(const nsIParserNode& aNode) +{ + FlushText(); + + SINK_TRACE_NODE(SINK_TRACE_CALLS, + "HTMLContentSink::OpenFrameset", aNode); + + mNodeStack[mStackPos] = (eHTMLTags)aNode.GetNodeType(); + + // Make frameset container + NS_IF_RELEASE(mFrameset); + nsIAtom* atom = NS_NewAtom("FRAMESET"); + if (nsnull == atom) { + return NS_ERROR_OUT_OF_MEMORY; + } + nsresult rv = NS_NewHTMLFrameset(&mFrameset, atom, nsnull); + NS_RELEASE(atom); + if (NS_OK != rv) { + return rv; + } + + mContainerStack[mStackPos] = mFrameset; + mStackPos++; + + // Add attributes to the frameset content object + AddAttributes(aNode, mFrameset); + // XXX If the frameset already existed and has been reflowed somewhat + // then we need to trigger a style change + mRoot->AppendChild(mFrameset, PR_TRUE); + + return NS_OK; +} + +NS_IMETHODIMP +HTMLContentSink::CloseFrameset(const nsIParserNode& aNode) +{ + FlushText(); + + SINK_TRACE_NODE(SINK_TRACE_CALLS, + "HTMLContentSink::CloseFrameset", aNode); + + NS_ASSERTION(mStackPos > 0, "bad bad"); + mNodeStack[--mStackPos] = eHTMLTag_unknown; + + // Reflow any lingering content + if (!mLayoutStarted) { + StartLayout(); + } + + return NS_OK; +} + NS_IMETHODIMP HTMLContentSink::OpenMap(const nsIParserNode& aNode) { @@ -605,29 +678,6 @@ HTMLContentSink::CloseMap(const nsIParserNode& aNode) return NS_OK; } -NS_IMETHODIMP -HTMLContentSink::OpenFrameset(const nsIParserNode& aNode) -{ - FlushText(); - - SINK_TRACE_NODE(SINK_TRACE_CALLS, - "HTMLContentSink::OpenFrameset", aNode); - - mNodeStack[mStackPos++] = (eHTMLTags)aNode.GetNodeType(); - return NS_OK; -} - -NS_IMETHODIMP -HTMLContentSink::CloseFrameset(const nsIParserNode& aNode) -{ - FlushText(); - - SINK_TRACE_NODE(SINK_TRACE_CALLS, - "HTMLContentSink::CloseFrameset", aNode); - - mNodeStack[--mStackPos] = eHTMLTag_unknown; - return NS_OK; -} NS_IMETHODIMP HTMLContentSink::OpenContainer(const nsIParserNode& aNode) @@ -716,6 +766,14 @@ HTMLContentSink::OpenContainer(const nsIParserNode& aNode) rv = ProcessIFRAMETag(&container, aNode); break; + case eHTMLTag_frameset: + if (!mFrameset) { + rv = OpenFrameset(aNode); // top level frameset + } else { + rv = ProcessFRAMESETTag(&container, aNode); + } + break; + default: rv = NS_NewHTMLContainer(&container, atom); break; @@ -783,9 +841,15 @@ HTMLContentSink::CloseContainer(const nsIParserNode& aNode) eHTMLTags parentType; parent = GetCurrentContainer(&parentType); container->Compact(); + // don't append the top level frameset to its parent, this was done in OpenFrameset + // XXX this is necessary because the parser is calling OpenContainer, CloseContainer + // on framesets. It should be calling OpenFrameset. + if (container == mFrameset) { + return CloseFrameset(aNode); + } if (nsnull != parent) { - PRBool allowReflow = parent == mBody; + PRBool allowReflow = parent == GetBodyOrFrameset(); #ifdef NS_DEBUG if (allowReflow) { SINK_TRACE(SINK_TRACE_REFLOW, @@ -821,7 +885,7 @@ HTMLContentSink::CloseContainer(const nsIParserNode& aNode) } #endif #if XXX - if (parent == mBody) { + if (parent == GetBodyOrFrameset()) { // We just closed a child of the body off. Trigger a // content-appended reflow if enough time has elapsed PRTime now = PR_Now(); @@ -976,9 +1040,14 @@ void HTMLContentSink::ReflowNewContent() nsIHTMLContent* HTMLContentSink::GetCurrentContainer(eHTMLTags* aType) { nsIHTMLContent* parent; - if (mStackPos <= 2) { // assume HTML and BODY are on the stack - parent = mBody; - *aType = eHTMLTag_body; + if (mStackPos <= 2) { // assume HTML and BODY/FRAMESET are on the stack + if (mBody) { + parent = mBody; + *aType = eHTMLTag_body; + } else { + parent = mFrameset; + *aType = eHTMLTag_frameset; + } } else { parent = mContainerStack[mStackPos - 1]; *aType = mNodeStack[mStackPos - 1]; @@ -1056,6 +1125,10 @@ NS_IMETHODIMP HTMLContentSink::AddLeaf(const nsIParserNode& aNode) FlushText(); rv = ProcessBRTag(&leaf, aNode); break; + case eHTMLTag_frame: + FlushText(); + rv = ProcessFrameTag(&leaf, aNode); + break; case eHTMLTag_hr: FlushText(); rv = ProcessHRTag(&leaf, aNode); @@ -1220,7 +1293,7 @@ HTMLContentSink::GetTableParent() } sp--; } - return mBody; + return GetBodyOrFrameset(); } nsresult @@ -1693,14 +1766,14 @@ nsresult HTMLContentSink::ProcessINPUTTag(nsIHTMLContent** aInstancePtrResult, else if (val.EqualsIgnoreCase("text")) { rv = NS_NewHTMLInputText(aInstancePtrResult, atom, mCurrentForm); } - else if (val.EqualsIgnoreCase("select1")) { // TEMP hack XXX - rv = NS_NewHTMLSelect(aInstancePtrResult, atom, mCurrentForm, 1); + else if (val.EqualsIgnoreCase("frameset1")) { // TEMP hack XXX + // rv = NS_NewHTMLFrameset(aInstancePtrResult, atom, mWebWidget, 1); } - else if (val.EqualsIgnoreCase("select2")) { // TEMP hack XXX - rv = NS_NewHTMLSelect(aInstancePtrResult, atom, mCurrentForm, 2); + else if (val.EqualsIgnoreCase("frameset2")) { // TEMP hack XXX + // rv = NS_NewHTMLFrameset(aInstancePtrResult, atom, mWebWidget, 2); } - else if (val.EqualsIgnoreCase("select3")) { // TEMP hack XXX - rv = NS_NewHTMLSelect(aInstancePtrResult, atom, mCurrentForm, 3); + else if (val.EqualsIgnoreCase("frameset3")) { // TEMP hack XXX + // rv = NS_NewHTMLFrameset(aInstancePtrResult, atom, mWebWidget, 3); } else { rv = NS_NewHTMLInputSubmit(aInstancePtrResult, atom, mCurrentForm); @@ -1721,6 +1794,18 @@ nsresult HTMLContentSink::ProcessINPUTTag(nsIHTMLContent** aInstancePtrResult, return rv; } +nsresult HTMLContentSink::ProcessFrameTag(nsIHTMLContent** aInstancePtrResult, + const nsIParserNode& aNode) +{ + nsAutoString tmp("FRAME"); + nsIAtom* atom = NS_NewAtom(tmp); + + nsresult rv = NS_NewHTMLFrame(aInstancePtrResult, atom, mWebShell); + + NS_RELEASE(atom); + return rv; +} + nsresult HTMLContentSink::ProcessTEXTAREATag(nsIHTMLContent** aInstancePtrResult, const nsIParserNode& aNode) @@ -1855,6 +1940,19 @@ HTMLContentSink::ProcessIFRAMETag(nsIHTMLContent** aInstancePtrResult, return rv; } +nsresult +HTMLContentSink::ProcessFRAMESETTag(nsIHTMLContent** aInstancePtrResult, + const nsIParserNode& aNode) +{ + nsAutoString tmp("FRAMESET"); + nsIAtom* atom = NS_NewAtom(tmp); + + nsresult rv = NS_NewHTMLIFrame(aInstancePtrResult, atom, mWebShell); + + NS_RELEASE(atom); + return rv; +} + nsresult HTMLContentSink::ProcessWBRTag(nsIHTMLContent** aInstancePtrResult, const nsIParserNode& aNode) { diff --git a/mozilla/layout/html/document/src/nsHTMLFrameset.cpp b/mozilla/layout/html/document/src/nsHTMLFrameset.cpp index 111ed6611fa..43248156e38 100644 --- a/mozilla/layout/html/document/src/nsHTMLFrameset.cpp +++ b/mozilla/layout/html/document/src/nsHTMLFrameset.cpp @@ -38,7 +38,7 @@ #include "nsStyleCoord.h" #include "nsIStyleContext.h" #include "nsCSSLayout.h" - +#include "nsHTMLBase.h" #include "nsIDocumentLoader.h" class nsHTMLIFrame; static NS_DEFINE_IID(kIStreamObserverIID, NS_ISTREAMOBSERVER_IID); @@ -72,6 +72,15 @@ nsHTMLFramesetFrame::nsHTMLFramesetFrame(nsIContent* aContent, nsIFrame* aParent mColSizes = nsnull; } +nsHTMLFramesetFrame::~nsHTMLFramesetFrame() +{ + if (mRowSizes) delete [] mRowSizes; + if (mRowSpecs) delete [] mRowSpecs; + if (mColSizes) delete [] mColSizes; + if (mColSpecs) delete [] mColSpecs; + mRowSizes = mColSizes = nsnull; + mRowSpecs = mColSpecs = nsnull; +} /** * Translate the rows/cols specs into an array of integer sizes for @@ -263,24 +272,36 @@ nsHTMLFramesetFrame* nsHTMLFramesetFrame::GetFramesetParent(nsIFrame* aChild) return parent; } -void nsHTMLFramesetFrame::GetSizeOfChild(nsIFrame* aChild, - nsReflowMetrics& aDesiredSize) +void nsHTMLFramesetFrame::GetSizeOfChildAt(PRInt32 aIndexInParent, nsReflowMetrics& aSize, nsPoint& aCellIndex) { + PRInt32 row = aIndexInParent / mNumCols; + PRInt32 col = aIndexInParent - (row * mNumCols); // remainder from dividing index by mNumCols + if ((row < mNumRows) && (col < mNumCols)) { + aSize.width = mColSizes[col]; + aSize.height = mRowSizes[row]; + aCellIndex.x = col; + aCellIndex.y = row; + } else { + aSize.width = aSize.height = aCellIndex.x = aCellIndex.y = 0; + } +} + + +void nsHTMLFramesetFrame::GetSizeOfChild(nsIFrame* aChild, + nsReflowMetrics& aSize) +{ + // Reflow only creates children frames for and content. + // this assumption is used here int i = 0; for (nsIFrame* child = mFirstChild; child; child->GetNextSibling(child)) { if (aChild == child) { - PRInt32 row = i / mNumCols; - PRInt32 col = i - (row * mNumCols); // remainder from dividing i by mNumCols - if ((row < mNumRows) && (col < mNumCols)) { - aDesiredSize.width = mColSizes[col]; - aDesiredSize.height = mRowSizes[row]; - return; - } + nsPoint ignore; + GetSizeOfChildAt(i, aSize, ignore); } i++; } - aDesiredSize.width = 0; - aDesiredSize.height = 0; + aSize.width = 0; + aSize.height = 0; } @@ -293,7 +314,7 @@ nsHTMLFramesetFrame::Paint(nsIPresContext& aPresContext, return nsHTMLContainerFrame::Paint(aPresContext, aRenderingContext, aDirtyRect); } -void nsHTMLFramesetFrame::ParseRowCol(nsIAtom* aAttrType, PRInt32& aNumSpecs, nsFramesetSpec* aSpecs) +void nsHTMLFramesetFrame::ParseRowCol(nsIAtom* aAttrType, PRInt32& aNumSpecs, nsFramesetSpec** aSpecs) { nsHTMLValue value; nsAutoString rowsCols; @@ -303,16 +324,16 @@ void nsHTMLFramesetFrame::ParseRowCol(nsIAtom* aAttrType, PRInt32& aNumSpecs, ns value.GetStringValue(rowsCols); nsFramesetSpec* specs = new nsFramesetSpec[gMaxNumRowColSpecs]; aNumSpecs = ParseRowColSpec(rowsCols, gMaxNumRowColSpecs, specs); - aSpecs = new nsFramesetSpec[aNumSpecs]; + *aSpecs = new nsFramesetSpec[aNumSpecs]; for (int i = 0; i < aNumSpecs; i++) { - aSpecs[i] = specs[i]; + (*aSpecs)[i] = specs[i]; } delete [] specs; return; } } aNumSpecs = 1; - aSpecs = nsnull; + *aSpecs = nsnull; } /** @@ -390,9 +411,13 @@ nsHTMLFramesetFrame::Reflow(nsIPresContext& aPresContext, const nsReflowState& aReflowState, nsReflowStatus& aStatus) { - if (0 == mNumRows) { // row, col specs have not been parsed - ParseRowCol(nsHTMLAtoms::rows, mNumRows, mRowSpecs); - ParseRowCol(nsHTMLAtoms::cols, mNumCols, mColSpecs); + PRBool firstTime = (0 == mNumRows); + + if (firstTime) { // row, col specs have not been parsed + ParseRowCol(nsHTMLAtoms::rows, mNumRows, &mRowSpecs); + ParseRowCol(nsHTMLAtoms::cols, mNumCols, &mColSpecs); + mRowSizes = new nscoord[mNumRows]; + mColSizes = new nscoord[mNumCols]; } // XXX check to see if our size actually changes before recomputing @@ -407,7 +432,74 @@ nsHTMLFramesetFrame::Reflow(nsIPresContext& aPresContext, CalculateRowCol(&aPresContext, aReflowState.maxSize.height, mNumCols, mColSpecs, mColSizes); } - // XXX need to reflow the children, but only the first n children where n <= number of cells + + // create the children frames; skip those which aren't frameset or frame + mChildCount = 0; + if (firstTime) { + nsIFrame* lastFrame = nsnull; + nsHTMLFrameset* content = (nsHTMLFrameset*)mContent; + PRInt32 numChildren = content->ChildCount(); + for (int i = 0; i < numChildren; i++) { + nsHTMLTagContent* child = (nsHTMLTagContent*)(content->ChildAt(i)); + if (nsnull == child) { + continue; + } + nsIAtom* tag = child->GetTag(); + if ((nsHTMLAtoms::frameset == tag) || (nsHTMLAtoms::frame == tag)) { + nsIFrame* frame; + nsresult result = nsHTMLBase::CreateFrame(&aPresContext, this, child, nsnull, frame); + NS_RELEASE(child); + if (NS_OK != result) { + return result; + } + if (nsnull == lastFrame) { + mFirstChild = frame; + } else { + lastFrame->SetNextSibling(frame); + } + lastFrame = frame; + mChildCount++; + } + } + } + + // reflow the children + PRInt32 lastRow = 0; + PRInt32 i = 0; + nsPoint offset(0,0); + for (nsIFrame* child = mFirstChild; child; child->GetNextSibling(child)) { + nsReflowMetrics metrics(nsnull); + nsPoint cellIndex; + GetSizeOfChildAt(i, metrics, cellIndex); + + nsSize size(metrics.width, metrics.height); + nsReflowState childReflowState(child, aReflowState, size); + child->WillReflow(aPresContext); + nsReflowMetrics ignore(nsnull); + aStatus = ReflowChild(mFirstChild, &aPresContext, ignore, childReflowState); + NS_ASSERTION(NS_FRAME_IS_COMPLETE(aStatus), "bad status"); + + // Place and size the child + nsRect rect(offset.x, offset.y, metrics.width, metrics.height); + child->SetRect(rect); + child->DidReflow(aPresContext, NS_FRAME_REFLOW_FINISHED); + + if (lastRow != cellIndex.y) { // changed to next row + offset.x = 0; + offset.y += metrics.height; + } else { // in same row + offset.x += metrics.width; + } + lastRow = cellIndex.y; + i++; + } + + if (nsnull != aDesiredSize.maxElementSize) { + aDesiredSize.maxElementSize->width = aDesiredSize.width; + aDesiredSize.maxElementSize->height = aDesiredSize.height; + } + + aStatus = NS_FRAME_COMPLETE; return NS_OK; } diff --git a/mozilla/layout/html/document/src/nsHTMLFrameset.h b/mozilla/layout/html/document/src/nsHTMLFrameset.h index 3a1ee392141..f03972718a9 100644 --- a/mozilla/layout/html/document/src/nsHTMLFrameset.h +++ b/mozilla/layout/html/document/src/nsHTMLFrameset.h @@ -53,9 +53,13 @@ class nsHTMLFramesetFrame : public nsHTMLContainerFrame { public: nsHTMLFramesetFrame(nsIContent* aContent, nsIFrame* aParent); + virtual ~nsHTMLFramesetFrame(); + static PRInt32 gMaxNumRowColSpecs; - void GetSizeOfChild(nsIFrame* aChild, nsReflowMetrics& aDesiredSize); + void GetSizeOfChild(nsIFrame* aChild, nsReflowMetrics& aSize); + + void GetSizeOfChildAt(PRInt32 aIndexInParent, nsReflowMetrics& aSize, nsPoint& aCellIndex); static nsHTMLFramesetFrame* GetFramesetParent(nsIFrame* aChild); @@ -78,7 +82,7 @@ protected: virtual PRIntn GetSkipSides() const; - void ParseRowCol(nsIAtom* aAttrType, PRInt32& aNumSpecs, nsFramesetSpec* aSpecs); + void ParseRowCol(nsIAtom* aAttrType, PRInt32& aNumSpecs, nsFramesetSpec** aSpecs); PRInt32 ParseRowColSpec(nsString& aSpec, PRInt32 aMaxNumValues, nsFramesetSpec* aSpecs);