зеркало из https://github.com/mozilla/gecko-dev.git
Forms can now be container content.
This commit is contained in:
Родитель
3b4a77222c
Коммит
0ebbf485db
|
@ -123,7 +123,7 @@ public:
|
|||
|
||||
protected:
|
||||
nsFormControlList* mControls;
|
||||
nsGenericHTMLLeafElement mInner;
|
||||
nsGenericHTMLContainerElement mInner;
|
||||
};
|
||||
|
||||
// nsFormControlList
|
||||
|
|
|
@ -300,6 +300,8 @@ public:
|
|||
nsresult AddLeaf(const nsIParserNode& aNode);
|
||||
nsresult AddLeaf(nsIHTMLContent* aContent);
|
||||
nsresult AddComment(const nsIParserNode& aNode);
|
||||
nsresult DemoteContainer(const nsIParserNode& aNode,
|
||||
nsIHTMLContent*& aParent);
|
||||
nsresult End();
|
||||
|
||||
nsresult GrowStack();
|
||||
|
@ -308,6 +310,8 @@ public:
|
|||
nsresult FlushTags();
|
||||
|
||||
PRBool IsCurrentContainer(nsHTMLTag mType);
|
||||
PRBool IsAncestorContainer(nsHTMLTag mType);
|
||||
nsIHTMLContent* GetCurrentContainer();
|
||||
|
||||
void MaybeMarkSinkDirty();
|
||||
void MaybeMarkSinkClean();
|
||||
|
@ -933,6 +937,29 @@ SinkContext::IsCurrentContainer(nsHTMLTag aTag)
|
|||
}
|
||||
}
|
||||
|
||||
PRBool
|
||||
SinkContext::IsAncestorContainer(nsHTMLTag aTag)
|
||||
{
|
||||
PRInt32 stackPos = mStackPos-1;
|
||||
|
||||
while (stackPos >= 0) {
|
||||
if (aTag == mStack[stackPos].mType) {
|
||||
return PR_TRUE;
|
||||
}
|
||||
stackPos--;
|
||||
}
|
||||
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
nsIHTMLContent*
|
||||
SinkContext::GetCurrentContainer()
|
||||
{
|
||||
nsIHTMLContent* content = mStack[mStackPos-1].mContent;
|
||||
NS_ADDREF(content);
|
||||
return content;
|
||||
}
|
||||
|
||||
void
|
||||
SinkContext::MaybeMarkSinkDirty()
|
||||
{
|
||||
|
@ -1030,6 +1057,7 @@ SinkContext::OpenContainer(const nsIParserNode& aNode)
|
|||
nsresult
|
||||
SinkContext::CloseContainer(const nsIParserNode& aNode)
|
||||
{
|
||||
nsresult result = NS_OK;
|
||||
FlushText();
|
||||
|
||||
SINK_TRACE_NODE(SINK_TRACE_CALLS,
|
||||
|
@ -1044,7 +1072,7 @@ SinkContext::CloseContainer(const nsIParserNode& aNode)
|
|||
if (0 == (mStack[mStackPos].mFlags & APPENDED)) {
|
||||
NS_ASSERTION(mStackPos > 0, "container w/o parent");
|
||||
nsIHTMLContent* parent = mStack[mStackPos-1].mContent;
|
||||
parent->AppendChildTo(content, PR_FALSE);
|
||||
result = parent->AppendChildTo(content, PR_FALSE);
|
||||
}
|
||||
NS_IF_RELEASE(content);
|
||||
|
||||
|
@ -1053,6 +1081,19 @@ SinkContext::CloseContainer(const nsIParserNode& aNode)
|
|||
case eHTMLTag_table:
|
||||
mSink->mInMonolithicContainer--;
|
||||
break;
|
||||
case eHTMLTag_form:
|
||||
{
|
||||
nsHTMLTag parserNodeType = nsHTMLTag(aNode.GetNodeType());
|
||||
|
||||
// If there's a FORM on the stack, but this close tag doesn't
|
||||
// close the form, then close out the form *and* close out the
|
||||
// next container up. This is since the parser doesn't do fix up
|
||||
// of forms. When the end FORM tag comes through, we'll ignore
|
||||
// it.
|
||||
if (parserNodeType != nodeType) {
|
||||
result = CloseContainer(aNode);
|
||||
}
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -1067,7 +1108,94 @@ SinkContext::CloseContainer(const nsIParserNode& aNode)
|
|||
}
|
||||
#endif
|
||||
|
||||
return NS_OK;
|
||||
return result;
|
||||
}
|
||||
|
||||
static void
|
||||
SetDocumentInChildrenOf(nsIContent* aContent,
|
||||
nsIDocument* aDocument)
|
||||
{
|
||||
PRInt32 i, n;
|
||||
aContent->ChildCount(n);
|
||||
for (i = 0; i < n; i++) {
|
||||
nsIContent* child;
|
||||
aContent->ChildAt(i, child);
|
||||
if (nsnull != child) {
|
||||
child->SetDocument(aDocument, PR_TRUE);
|
||||
NS_RELEASE(child);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
nsresult
|
||||
SinkContext::DemoteContainer(const nsIParserNode& aNode,
|
||||
nsIHTMLContent*& aParent)
|
||||
{
|
||||
nsresult result = NS_OK;
|
||||
nsHTMLTag nodeType = nsHTMLTag(aNode.GetNodeType());
|
||||
|
||||
aParent = nsnull;
|
||||
// Search for the nearest container on the stack of the
|
||||
// specified type
|
||||
PRInt32 stackPos = mStackPos-1;
|
||||
while ((stackPos > 0) && (nodeType != mStack[stackPos].mType)) {
|
||||
stackPos--;
|
||||
}
|
||||
|
||||
// If we find such a container
|
||||
if (stackPos > 0) {
|
||||
nsIHTMLContent* container = mStack[stackPos].mContent;
|
||||
|
||||
// See if it has a parent on the stack. It should for all the
|
||||
// cases for which this is called, but put in a check anyway
|
||||
if (stackPos > 1) {
|
||||
nsIHTMLContent* parent = mStack[stackPos-1].mContent;
|
||||
|
||||
// If the demoted container hasn't yet been appended to its
|
||||
// parent, do so now.
|
||||
if (0 == (mStack[stackPos].mFlags & APPENDED)) {
|
||||
result = parent->AppendChildTo(container, PR_FALSE);
|
||||
}
|
||||
|
||||
if (NS_SUCCEEDED(result)) {
|
||||
// Move all of the demoted containers children to its parent
|
||||
PRInt32 i, count;
|
||||
container->ChildCount(count);
|
||||
|
||||
for (i = 0; i < count && NS_SUCCEEDED(result); i++) {
|
||||
nsIContent* child;
|
||||
|
||||
// Since we're removing as we go along, always get the
|
||||
// first child
|
||||
result = container->ChildAt(0, child);
|
||||
if (NS_SUCCEEDED(result)) {
|
||||
// Remove it from its old parent (the demoted container)
|
||||
result = container->RemoveChildAt(0, PR_FALSE);
|
||||
if (NS_SUCCEEDED(result)) {
|
||||
result = parent->AppendChildTo(child, PR_FALSE);
|
||||
SetDocumentInChildrenOf(child, mSink->mDocument);
|
||||
}
|
||||
NS_RELEASE(child);
|
||||
}
|
||||
}
|
||||
|
||||
// Remove the current element from the context stack,
|
||||
// since it's been demoted.
|
||||
while (stackPos < mStackPos-1) {
|
||||
mStack[stackPos].mType = mStack[stackPos+1].mType;
|
||||
mStack[stackPos].mContent = mStack[stackPos+1].mContent;
|
||||
mStack[stackPos].mFlags = mStack[stackPos+1].mFlags;
|
||||
stackPos++;
|
||||
}
|
||||
mStackPos--;
|
||||
}
|
||||
aParent = parent;
|
||||
NS_ADDREF(parent);
|
||||
}
|
||||
NS_RELEASE(container);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
nsresult
|
||||
|
@ -1820,33 +1948,59 @@ HTMLContentSink::CloseBody(const nsIParserNode& aNode)
|
|||
NS_IMETHODIMP
|
||||
HTMLContentSink::OpenForm(const nsIParserNode& aNode)
|
||||
{
|
||||
nsresult result = NS_OK;
|
||||
nsIHTMLContent* content = nsnull;
|
||||
|
||||
mCurrentContext->FlushText();
|
||||
|
||||
|
||||
SINK_TRACE_NODE(SINK_TRACE_CALLS,
|
||||
"HTMLContentSink::OpenForm", aNode);
|
||||
|
||||
// Close out previous form if it's there
|
||||
|
||||
// Close out previous form if it's there. If there is one
|
||||
// around, it's probably because the last one wasn't well-formed.
|
||||
NS_IF_RELEASE(mCurrentForm);
|
||||
|
||||
// set the current form
|
||||
nsAutoString tmp("form");
|
||||
nsIAtom* atom = NS_NewAtom(tmp);
|
||||
nsIHTMLContent* iContent = nsnull;
|
||||
nsresult rv = NS_NewHTMLFormElement(&iContent, atom);
|
||||
if ((NS_OK == rv) && iContent) {
|
||||
iContent->QueryInterface(kIDOMHTMLFormElementIID, (void**)&mCurrentForm);
|
||||
NS_RELEASE(iContent);
|
||||
|
||||
// Check if the parent is a table, tbody, thead, tfoot, tr, col or
|
||||
// colgroup. If so, this is just going to be a leaf element.
|
||||
// If so, we fix up by making the form leaf content.
|
||||
if (mCurrentContext->IsCurrentContainer(eHTMLTag_table) ||
|
||||
mCurrentContext->IsCurrentContainer(eHTMLTag_tbody) ||
|
||||
mCurrentContext->IsCurrentContainer(eHTMLTag_thead) ||
|
||||
mCurrentContext->IsCurrentContainer(eHTMLTag_tfoot) ||
|
||||
mCurrentContext->IsCurrentContainer(eHTMLTag_tr) ||
|
||||
mCurrentContext->IsCurrentContainer(eHTMLTag_col) ||
|
||||
mCurrentContext->IsCurrentContainer(eHTMLTag_colgroup)) {
|
||||
nsAutoString tmp("form");
|
||||
nsIAtom* atom = NS_NewAtom(tmp);
|
||||
result = NS_NewHTMLFormElement(&content, atom);
|
||||
if (NS_SUCCEEDED(result) && content) {
|
||||
content->QueryInterface(kIDOMHTMLFormElementIID, (void**)&mCurrentForm);
|
||||
NS_RELEASE(content);
|
||||
}
|
||||
NS_RELEASE(atom);
|
||||
|
||||
result = AddLeaf(aNode);
|
||||
}
|
||||
NS_RELEASE(atom);
|
||||
|
||||
AddLeaf(aNode);
|
||||
|
||||
else {
|
||||
// Otherwise the form can be a content parent.
|
||||
result = mCurrentContext->OpenContainer(aNode);
|
||||
if (NS_SUCCEEDED(result)) {
|
||||
|
||||
content = mCurrentContext->GetCurrentContainer();
|
||||
if (nsnull != content) {
|
||||
result = content->QueryInterface(kIDOMHTMLFormElementIID,
|
||||
(void**)&mCurrentForm);
|
||||
NS_RELEASE(content);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// add the form to the document
|
||||
if (mCurrentForm) {
|
||||
mHTMLDocument->AddForm(mCurrentForm);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// XXX MAYBE add code to place close form tag into the content model
|
||||
|
@ -1854,11 +2008,31 @@ HTMLContentSink::OpenForm(const nsIParserNode& aNode)
|
|||
NS_IMETHODIMP
|
||||
HTMLContentSink::CloseForm(const nsIParserNode& aNode)
|
||||
{
|
||||
nsresult result = NS_OK;
|
||||
|
||||
mCurrentContext->FlushText();
|
||||
SINK_TRACE_NODE(SINK_TRACE_CALLS,
|
||||
"HTMLContentSink::CloseForm", aNode);
|
||||
NS_IF_RELEASE(mCurrentForm);
|
||||
return NS_OK;
|
||||
|
||||
if (nsnull != mCurrentForm) {
|
||||
// Check if this is a well-formed form
|
||||
if (mCurrentContext->IsCurrentContainer(eHTMLTag_form)) {
|
||||
result = mCurrentContext->CloseContainer(aNode);
|
||||
}
|
||||
else if (mCurrentContext->IsAncestorContainer(eHTMLTag_form)) {
|
||||
nsIHTMLContent* parent;
|
||||
result = mCurrentContext->DemoteContainer(aNode, parent);
|
||||
if (NS_SUCCEEDED(result)) {
|
||||
if (parent == mBody) {
|
||||
NotifyBody();
|
||||
}
|
||||
NS_IF_RELEASE(parent);
|
||||
}
|
||||
}
|
||||
NS_RELEASE(mCurrentForm);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
|
|
@ -692,11 +692,6 @@ nsXMLContentSink::OpenContainer(const nsIParserNode& aNode)
|
|||
if (nsHTMLAtoms::script == tagAtom) {
|
||||
result = ProcessStartSCRIPTTag(aNode);
|
||||
}
|
||||
// XXX Treat the form elements as a leaf element (even if it is a
|
||||
// container). Need to do further processing with forms
|
||||
else if (nsHTMLAtoms::form == tagAtom) {
|
||||
pushContent = PR_FALSE;
|
||||
}
|
||||
NS_RELEASE(tagAtom);
|
||||
|
||||
nsIHTMLContent *htmlContent = nsnull;
|
||||
|
@ -778,10 +773,6 @@ nsXMLContentSink::CloseContainer(const nsIParserNode& aNode)
|
|||
if (nsHTMLAtoms::script == tagAtom) {
|
||||
result = ProcessEndSCRIPTTag(aNode);
|
||||
}
|
||||
// XXX Form content was never pushed on the stack
|
||||
else if (nsHTMLAtoms::form == tagAtom) {
|
||||
popContent = PR_FALSE;
|
||||
}
|
||||
NS_RELEASE(tagAtom);
|
||||
}
|
||||
|
||||
|
|
|
@ -2632,6 +2632,7 @@ nsCSSFrameConstructor::ConstructFrameByTag(nsIPresContext* aPresContext
|
|||
}
|
||||
else if (nsHTMLAtoms::form == aTag) {
|
||||
rv = NS_NewFormFrame(&newFrame);
|
||||
processChildren = PR_TRUE;
|
||||
}
|
||||
else if (nsHTMLAtoms::frameset == aTag) {
|
||||
rv = NS_NewHTMLFramesetFrame(&newFrame);
|
||||
|
|
|
@ -123,7 +123,7 @@ public:
|
|||
|
||||
protected:
|
||||
nsFormControlList* mControls;
|
||||
nsGenericHTMLLeafElement mInner;
|
||||
nsGenericHTMLContainerElement mInner;
|
||||
};
|
||||
|
||||
// nsFormControlList
|
||||
|
|
|
@ -300,6 +300,8 @@ public:
|
|||
nsresult AddLeaf(const nsIParserNode& aNode);
|
||||
nsresult AddLeaf(nsIHTMLContent* aContent);
|
||||
nsresult AddComment(const nsIParserNode& aNode);
|
||||
nsresult DemoteContainer(const nsIParserNode& aNode,
|
||||
nsIHTMLContent*& aParent);
|
||||
nsresult End();
|
||||
|
||||
nsresult GrowStack();
|
||||
|
@ -308,6 +310,8 @@ public:
|
|||
nsresult FlushTags();
|
||||
|
||||
PRBool IsCurrentContainer(nsHTMLTag mType);
|
||||
PRBool IsAncestorContainer(nsHTMLTag mType);
|
||||
nsIHTMLContent* GetCurrentContainer();
|
||||
|
||||
void MaybeMarkSinkDirty();
|
||||
void MaybeMarkSinkClean();
|
||||
|
@ -933,6 +937,29 @@ SinkContext::IsCurrentContainer(nsHTMLTag aTag)
|
|||
}
|
||||
}
|
||||
|
||||
PRBool
|
||||
SinkContext::IsAncestorContainer(nsHTMLTag aTag)
|
||||
{
|
||||
PRInt32 stackPos = mStackPos-1;
|
||||
|
||||
while (stackPos >= 0) {
|
||||
if (aTag == mStack[stackPos].mType) {
|
||||
return PR_TRUE;
|
||||
}
|
||||
stackPos--;
|
||||
}
|
||||
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
nsIHTMLContent*
|
||||
SinkContext::GetCurrentContainer()
|
||||
{
|
||||
nsIHTMLContent* content = mStack[mStackPos-1].mContent;
|
||||
NS_ADDREF(content);
|
||||
return content;
|
||||
}
|
||||
|
||||
void
|
||||
SinkContext::MaybeMarkSinkDirty()
|
||||
{
|
||||
|
@ -1030,6 +1057,7 @@ SinkContext::OpenContainer(const nsIParserNode& aNode)
|
|||
nsresult
|
||||
SinkContext::CloseContainer(const nsIParserNode& aNode)
|
||||
{
|
||||
nsresult result = NS_OK;
|
||||
FlushText();
|
||||
|
||||
SINK_TRACE_NODE(SINK_TRACE_CALLS,
|
||||
|
@ -1044,7 +1072,7 @@ SinkContext::CloseContainer(const nsIParserNode& aNode)
|
|||
if (0 == (mStack[mStackPos].mFlags & APPENDED)) {
|
||||
NS_ASSERTION(mStackPos > 0, "container w/o parent");
|
||||
nsIHTMLContent* parent = mStack[mStackPos-1].mContent;
|
||||
parent->AppendChildTo(content, PR_FALSE);
|
||||
result = parent->AppendChildTo(content, PR_FALSE);
|
||||
}
|
||||
NS_IF_RELEASE(content);
|
||||
|
||||
|
@ -1053,6 +1081,19 @@ SinkContext::CloseContainer(const nsIParserNode& aNode)
|
|||
case eHTMLTag_table:
|
||||
mSink->mInMonolithicContainer--;
|
||||
break;
|
||||
case eHTMLTag_form:
|
||||
{
|
||||
nsHTMLTag parserNodeType = nsHTMLTag(aNode.GetNodeType());
|
||||
|
||||
// If there's a FORM on the stack, but this close tag doesn't
|
||||
// close the form, then close out the form *and* close out the
|
||||
// next container up. This is since the parser doesn't do fix up
|
||||
// of forms. When the end FORM tag comes through, we'll ignore
|
||||
// it.
|
||||
if (parserNodeType != nodeType) {
|
||||
result = CloseContainer(aNode);
|
||||
}
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -1067,7 +1108,94 @@ SinkContext::CloseContainer(const nsIParserNode& aNode)
|
|||
}
|
||||
#endif
|
||||
|
||||
return NS_OK;
|
||||
return result;
|
||||
}
|
||||
|
||||
static void
|
||||
SetDocumentInChildrenOf(nsIContent* aContent,
|
||||
nsIDocument* aDocument)
|
||||
{
|
||||
PRInt32 i, n;
|
||||
aContent->ChildCount(n);
|
||||
for (i = 0; i < n; i++) {
|
||||
nsIContent* child;
|
||||
aContent->ChildAt(i, child);
|
||||
if (nsnull != child) {
|
||||
child->SetDocument(aDocument, PR_TRUE);
|
||||
NS_RELEASE(child);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
nsresult
|
||||
SinkContext::DemoteContainer(const nsIParserNode& aNode,
|
||||
nsIHTMLContent*& aParent)
|
||||
{
|
||||
nsresult result = NS_OK;
|
||||
nsHTMLTag nodeType = nsHTMLTag(aNode.GetNodeType());
|
||||
|
||||
aParent = nsnull;
|
||||
// Search for the nearest container on the stack of the
|
||||
// specified type
|
||||
PRInt32 stackPos = mStackPos-1;
|
||||
while ((stackPos > 0) && (nodeType != mStack[stackPos].mType)) {
|
||||
stackPos--;
|
||||
}
|
||||
|
||||
// If we find such a container
|
||||
if (stackPos > 0) {
|
||||
nsIHTMLContent* container = mStack[stackPos].mContent;
|
||||
|
||||
// See if it has a parent on the stack. It should for all the
|
||||
// cases for which this is called, but put in a check anyway
|
||||
if (stackPos > 1) {
|
||||
nsIHTMLContent* parent = mStack[stackPos-1].mContent;
|
||||
|
||||
// If the demoted container hasn't yet been appended to its
|
||||
// parent, do so now.
|
||||
if (0 == (mStack[stackPos].mFlags & APPENDED)) {
|
||||
result = parent->AppendChildTo(container, PR_FALSE);
|
||||
}
|
||||
|
||||
if (NS_SUCCEEDED(result)) {
|
||||
// Move all of the demoted containers children to its parent
|
||||
PRInt32 i, count;
|
||||
container->ChildCount(count);
|
||||
|
||||
for (i = 0; i < count && NS_SUCCEEDED(result); i++) {
|
||||
nsIContent* child;
|
||||
|
||||
// Since we're removing as we go along, always get the
|
||||
// first child
|
||||
result = container->ChildAt(0, child);
|
||||
if (NS_SUCCEEDED(result)) {
|
||||
// Remove it from its old parent (the demoted container)
|
||||
result = container->RemoveChildAt(0, PR_FALSE);
|
||||
if (NS_SUCCEEDED(result)) {
|
||||
result = parent->AppendChildTo(child, PR_FALSE);
|
||||
SetDocumentInChildrenOf(child, mSink->mDocument);
|
||||
}
|
||||
NS_RELEASE(child);
|
||||
}
|
||||
}
|
||||
|
||||
// Remove the current element from the context stack,
|
||||
// since it's been demoted.
|
||||
while (stackPos < mStackPos-1) {
|
||||
mStack[stackPos].mType = mStack[stackPos+1].mType;
|
||||
mStack[stackPos].mContent = mStack[stackPos+1].mContent;
|
||||
mStack[stackPos].mFlags = mStack[stackPos+1].mFlags;
|
||||
stackPos++;
|
||||
}
|
||||
mStackPos--;
|
||||
}
|
||||
aParent = parent;
|
||||
NS_ADDREF(parent);
|
||||
}
|
||||
NS_RELEASE(container);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
nsresult
|
||||
|
@ -1820,33 +1948,59 @@ HTMLContentSink::CloseBody(const nsIParserNode& aNode)
|
|||
NS_IMETHODIMP
|
||||
HTMLContentSink::OpenForm(const nsIParserNode& aNode)
|
||||
{
|
||||
nsresult result = NS_OK;
|
||||
nsIHTMLContent* content = nsnull;
|
||||
|
||||
mCurrentContext->FlushText();
|
||||
|
||||
|
||||
SINK_TRACE_NODE(SINK_TRACE_CALLS,
|
||||
"HTMLContentSink::OpenForm", aNode);
|
||||
|
||||
// Close out previous form if it's there
|
||||
|
||||
// Close out previous form if it's there. If there is one
|
||||
// around, it's probably because the last one wasn't well-formed.
|
||||
NS_IF_RELEASE(mCurrentForm);
|
||||
|
||||
// set the current form
|
||||
nsAutoString tmp("form");
|
||||
nsIAtom* atom = NS_NewAtom(tmp);
|
||||
nsIHTMLContent* iContent = nsnull;
|
||||
nsresult rv = NS_NewHTMLFormElement(&iContent, atom);
|
||||
if ((NS_OK == rv) && iContent) {
|
||||
iContent->QueryInterface(kIDOMHTMLFormElementIID, (void**)&mCurrentForm);
|
||||
NS_RELEASE(iContent);
|
||||
|
||||
// Check if the parent is a table, tbody, thead, tfoot, tr, col or
|
||||
// colgroup. If so, this is just going to be a leaf element.
|
||||
// If so, we fix up by making the form leaf content.
|
||||
if (mCurrentContext->IsCurrentContainer(eHTMLTag_table) ||
|
||||
mCurrentContext->IsCurrentContainer(eHTMLTag_tbody) ||
|
||||
mCurrentContext->IsCurrentContainer(eHTMLTag_thead) ||
|
||||
mCurrentContext->IsCurrentContainer(eHTMLTag_tfoot) ||
|
||||
mCurrentContext->IsCurrentContainer(eHTMLTag_tr) ||
|
||||
mCurrentContext->IsCurrentContainer(eHTMLTag_col) ||
|
||||
mCurrentContext->IsCurrentContainer(eHTMLTag_colgroup)) {
|
||||
nsAutoString tmp("form");
|
||||
nsIAtom* atom = NS_NewAtom(tmp);
|
||||
result = NS_NewHTMLFormElement(&content, atom);
|
||||
if (NS_SUCCEEDED(result) && content) {
|
||||
content->QueryInterface(kIDOMHTMLFormElementIID, (void**)&mCurrentForm);
|
||||
NS_RELEASE(content);
|
||||
}
|
||||
NS_RELEASE(atom);
|
||||
|
||||
result = AddLeaf(aNode);
|
||||
}
|
||||
NS_RELEASE(atom);
|
||||
|
||||
AddLeaf(aNode);
|
||||
|
||||
else {
|
||||
// Otherwise the form can be a content parent.
|
||||
result = mCurrentContext->OpenContainer(aNode);
|
||||
if (NS_SUCCEEDED(result)) {
|
||||
|
||||
content = mCurrentContext->GetCurrentContainer();
|
||||
if (nsnull != content) {
|
||||
result = content->QueryInterface(kIDOMHTMLFormElementIID,
|
||||
(void**)&mCurrentForm);
|
||||
NS_RELEASE(content);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// add the form to the document
|
||||
if (mCurrentForm) {
|
||||
mHTMLDocument->AddForm(mCurrentForm);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// XXX MAYBE add code to place close form tag into the content model
|
||||
|
@ -1854,11 +2008,31 @@ HTMLContentSink::OpenForm(const nsIParserNode& aNode)
|
|||
NS_IMETHODIMP
|
||||
HTMLContentSink::CloseForm(const nsIParserNode& aNode)
|
||||
{
|
||||
nsresult result = NS_OK;
|
||||
|
||||
mCurrentContext->FlushText();
|
||||
SINK_TRACE_NODE(SINK_TRACE_CALLS,
|
||||
"HTMLContentSink::CloseForm", aNode);
|
||||
NS_IF_RELEASE(mCurrentForm);
|
||||
return NS_OK;
|
||||
|
||||
if (nsnull != mCurrentForm) {
|
||||
// Check if this is a well-formed form
|
||||
if (mCurrentContext->IsCurrentContainer(eHTMLTag_form)) {
|
||||
result = mCurrentContext->CloseContainer(aNode);
|
||||
}
|
||||
else if (mCurrentContext->IsAncestorContainer(eHTMLTag_form)) {
|
||||
nsIHTMLContent* parent;
|
||||
result = mCurrentContext->DemoteContainer(aNode, parent);
|
||||
if (NS_SUCCEEDED(result)) {
|
||||
if (parent == mBody) {
|
||||
NotifyBody();
|
||||
}
|
||||
NS_IF_RELEASE(parent);
|
||||
}
|
||||
}
|
||||
NS_RELEASE(mCurrentForm);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
|
|
@ -418,6 +418,7 @@ iframe {
|
|||
}
|
||||
form {
|
||||
display: block;
|
||||
margin: 1em 0;
|
||||
}
|
||||
input {
|
||||
vertical-align: bottom;
|
||||
|
|
|
@ -38,7 +38,6 @@
|
|||
#include "nsIPresShell.h"
|
||||
#include "nsIPresContext.h"
|
||||
#include "nsIStyleContext.h"
|
||||
#include "nsLeafFrame.h"
|
||||
#include "nsCSSRendering.h"
|
||||
#include "nsHTMLIIDs.h"
|
||||
#include "nsDebug.h"
|
||||
|
@ -61,7 +60,6 @@ static NS_DEFINE_CID(kIOServiceCID, NS_IOSERVICE_CID);
|
|||
#include "nsDocument.h"
|
||||
#include "nsIDOMHTMLFormElement.h"
|
||||
#include "nsIDOMNSHTMLFormElement.h"
|
||||
#include "nsLeafFrame.h"
|
||||
#include "nsHTMLParts.h"
|
||||
#include "nsIReflowCommand.h"
|
||||
|
||||
|
@ -144,7 +142,7 @@ nsFormFrame::QueryInterface(REFNSIID aIID, void** aInstancePtr)
|
|||
*aInstancePtr = (void*)(nsIFormManager*)this;
|
||||
return NS_OK;
|
||||
}
|
||||
return nsLeafFrame::QueryInterface(aIID, aInstancePtr);
|
||||
return nsBlockFrame::QueryInterface(aIID, aInstancePtr);
|
||||
}
|
||||
|
||||
nsrefcnt nsFormFrame::AddRef(void)
|
||||
|
@ -160,7 +158,7 @@ nsrefcnt nsFormFrame::Release(void)
|
|||
}
|
||||
|
||||
nsFormFrame::nsFormFrame()
|
||||
: nsLeafFrame()
|
||||
: nsBlockFrame()
|
||||
{
|
||||
mTextSubmitter = nsnull;
|
||||
}
|
||||
|
@ -183,21 +181,6 @@ nsFormFrame::CanSubmit(nsFormControlFrame& aFrame)
|
|||
return PR_FALSE;
|
||||
}
|
||||
|
||||
void
|
||||
nsFormFrame::GetDesiredSize(nsIPresContext* aPresContext,
|
||||
const nsHTMLReflowState& aReflowState,
|
||||
nsHTMLReflowMetrics& aDesiredSize)
|
||||
{
|
||||
aDesiredSize.width = 0;
|
||||
aDesiredSize.height = 0;
|
||||
aDesiredSize.ascent = 0;
|
||||
aDesiredSize.descent = 0;
|
||||
if (aDesiredSize.maxElementSize) {
|
||||
aDesiredSize.maxElementSize->width = 0;
|
||||
aDesiredSize.maxElementSize->height = 0;
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsFormFrame::GetAction(nsString* aAction)
|
||||
{
|
||||
|
@ -282,17 +265,6 @@ nsFormFrame::GetEnctype(PRInt32* aEnctype)
|
|||
return result;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsFormFrame::Reflow(nsIPresContext& aPresContext,
|
||||
nsHTMLReflowMetrics& aDesiredSize,
|
||||
const nsHTMLReflowState& aReflowState,
|
||||
nsReflowStatus& aStatus)
|
||||
{
|
||||
GetDesiredSize(&aPresContext, aReflowState, aDesiredSize);
|
||||
aStatus = NS_FRAME_COMPLETE;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsFormFrame::OnReset()
|
||||
{
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
#define nsFormFrame_h___
|
||||
|
||||
#include "nsIFormManager.h"
|
||||
#include "nsLeafFrame.h"
|
||||
#include "nsBlockFrame.h"
|
||||
#include "nsVoidArray.h"
|
||||
|
||||
class nsString;
|
||||
|
@ -36,16 +36,11 @@ class nsIPresContext;
|
|||
class nsFormFrame;
|
||||
class nsIUnicodeEncoder;
|
||||
|
||||
class nsFormFrame : public nsLeafFrame,
|
||||
class nsFormFrame : public nsBlockFrame,
|
||||
public nsIFormManager
|
||||
{
|
||||
public:
|
||||
nsFormFrame();
|
||||
|
||||
NS_IMETHOD Reflow(nsIPresContext& aPresContext,
|
||||
nsHTMLReflowMetrics& aDesiredSize,
|
||||
const nsHTMLReflowState& aReflowState,
|
||||
nsReflowStatus& aStatus);
|
||||
virtual ~nsFormFrame();
|
||||
|
||||
NS_IMETHOD QueryInterface(REFNSIID aIID, void** aInstancePtr);
|
||||
|
@ -82,9 +77,6 @@ public:
|
|||
protected:
|
||||
NS_IMETHOD_(nsrefcnt) AddRef(void);
|
||||
NS_IMETHOD_(nsrefcnt) Release(void);
|
||||
virtual void GetDesiredSize(nsIPresContext* aPresContext,
|
||||
const nsHTMLReflowState& aReflowState,
|
||||
nsHTMLReflowMetrics& aDesiredSize);
|
||||
void RemoveRadioGroups();
|
||||
void ProcessAsURLEncoded(PRBool aIsPost, nsString& aData, nsIFormControlFrame* aFrame);
|
||||
void ProcessAsMultipart(nsString& aData, nsIFormControlFrame* aFrame);
|
||||
|
|
|
@ -2632,6 +2632,7 @@ nsCSSFrameConstructor::ConstructFrameByTag(nsIPresContext* aPresContext
|
|||
}
|
||||
else if (nsHTMLAtoms::form == aTag) {
|
||||
rv = NS_NewFormFrame(&newFrame);
|
||||
processChildren = PR_TRUE;
|
||||
}
|
||||
else if (nsHTMLAtoms::frameset == aTag) {
|
||||
rv = NS_NewHTMLFramesetFrame(&newFrame);
|
||||
|
|
|
@ -418,6 +418,7 @@ iframe {
|
|||
}
|
||||
form {
|
||||
display: block;
|
||||
margin: 1em 0;
|
||||
}
|
||||
input {
|
||||
vertical-align: bottom;
|
||||
|
|
|
@ -692,11 +692,6 @@ nsXMLContentSink::OpenContainer(const nsIParserNode& aNode)
|
|||
if (nsHTMLAtoms::script == tagAtom) {
|
||||
result = ProcessStartSCRIPTTag(aNode);
|
||||
}
|
||||
// XXX Treat the form elements as a leaf element (even if it is a
|
||||
// container). Need to do further processing with forms
|
||||
else if (nsHTMLAtoms::form == tagAtom) {
|
||||
pushContent = PR_FALSE;
|
||||
}
|
||||
NS_RELEASE(tagAtom);
|
||||
|
||||
nsIHTMLContent *htmlContent = nsnull;
|
||||
|
@ -778,10 +773,6 @@ nsXMLContentSink::CloseContainer(const nsIParserNode& aNode)
|
|||
if (nsHTMLAtoms::script == tagAtom) {
|
||||
result = ProcessEndSCRIPTTag(aNode);
|
||||
}
|
||||
// XXX Form content was never pushed on the stack
|
||||
else if (nsHTMLAtoms::form == tagAtom) {
|
||||
popContent = PR_FALSE;
|
||||
}
|
||||
NS_RELEASE(tagAtom);
|
||||
}
|
||||
|
||||
|
|
|
@ -659,37 +659,25 @@ XULContentSinkImpl::CloseContainer(const nsIParserNode& aNode)
|
|||
FlushText();
|
||||
}
|
||||
|
||||
// XXX The following code is a hack to make forms work in XUL. Forms aren't
|
||||
// really pushed and popped like other elements.
|
||||
nsAutoString tag;
|
||||
PRInt32 nameSpaceID;
|
||||
SplitQualifiedName(aNode.GetText(), nameSpaceID, tag);
|
||||
PRBool popContent = PR_TRUE;
|
||||
if (nameSpaceID == kNameSpaceID_HTML) {
|
||||
if (tag.Equals("form"))
|
||||
popContent = PR_FALSE;
|
||||
}
|
||||
|
||||
if (popContent) {
|
||||
nsIRDFResource* resource;
|
||||
nsIRDFResource* resource;
|
||||
|
||||
if (NS_FAILED(PopResourceAndState(resource, mState))) {
|
||||
if (NS_FAILED(PopResourceAndState(resource, mState))) {
|
||||
#ifdef PR_LOGGING
|
||||
if (PR_LOG_TEST(gLog, PR_LOG_ALWAYS)) {
|
||||
char* tagStr = aNode.GetText().ToNewCString();
|
||||
PR_LOG(gLog, PR_LOG_ALWAYS,
|
||||
("xul: extra close tag '</%s>' at line %d\n",
|
||||
tagStr, aNode.GetSourceLineNumber()));
|
||||
delete[] tagStr;
|
||||
}
|
||||
#endif
|
||||
// Failure to return NS_OK causes stuff to freak out. See Bug 4433.
|
||||
return NS_OK;
|
||||
if (PR_LOG_TEST(gLog, PR_LOG_ALWAYS)) {
|
||||
char* tagStr = aNode.GetText().ToNewCString();
|
||||
PR_LOG(gLog, PR_LOG_ALWAYS,
|
||||
("xul: extra close tag '</%s>' at line %d\n",
|
||||
tagStr, aNode.GetSourceLineNumber()));
|
||||
delete[] tagStr;
|
||||
}
|
||||
|
||||
NS_IF_RELEASE(resource);
|
||||
#endif
|
||||
// Failure to return NS_OK causes stuff to freak out. See Bug 4433.
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IF_RELEASE(resource);
|
||||
|
||||
PRInt32 nestLevel = mContextStack->Count();
|
||||
if (nestLevel == 0) {
|
||||
mState = eXULContentSinkState_InEpilog;
|
||||
|
@ -1439,21 +1427,10 @@ XULContentSinkImpl::OpenTag(const nsIParserNode& aNode)
|
|||
SplitQualifiedName(aNode.GetText(), nameSpaceID, tag);
|
||||
|
||||
// HTML tags must be lowercase
|
||||
PRBool pushContent = PR_TRUE;
|
||||
if (nameSpaceID == kNameSpaceID_HTML) {
|
||||
if (tag.Equals("script")) {
|
||||
return OpenScript(aNode);
|
||||
}
|
||||
else if (tag.Equals("form")) {
|
||||
// XXX Forms (for whatever reason) are treated differently. Their
|
||||
// children are treated as if they were children of the form's
|
||||
// parent node, and the form itself is added in as a sibling.
|
||||
// This makes no sense to me, but it is what the other two
|
||||
// content sinks are doing, so I'm blindly following it.
|
||||
// I would like to know if this is a hack or if this really is
|
||||
// the right thing to do. - Dave
|
||||
pushContent = PR_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
// Figure out the URI of this object, and create an RDF node for it.
|
||||
|
@ -1565,9 +1542,7 @@ XULContentSinkImpl::OpenTag(const nsIParserNode& aNode)
|
|||
|
||||
// Push the element onto the context stack, so that child
|
||||
// containers will hook up to us as their parent.
|
||||
// (XXX The push content hack is for HTML form content. See above.)
|
||||
if (pushContent)
|
||||
PushResourceAndState(rdfResource, mState);
|
||||
PushResourceAndState(rdfResource, mState);
|
||||
mState = eXULContentSinkState_InDocumentElement;
|
||||
return NS_OK;
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче