diff --git a/mozilla/content/base/src/nsCommentNode.cpp b/mozilla/content/base/src/nsCommentNode.cpp index a5f2ebf3ea0..087e665ccc2 100644 --- a/mozilla/content/base/src/nsCommentNode.cpp +++ b/mozilla/content/base/src/nsCommentNode.cpp @@ -32,11 +32,13 @@ static NS_DEFINE_IID(kIDOMCommentIID, NS_IDOMCOMMENT_IID); static NS_DEFINE_IID(kIEnumeratorIID, NS_IENUMERATOR_IID); +static NS_DEFINE_IID(kITextContentIID, NS_ITEXT_CONTENT_IID); class nsCommentNode : public nsIDOMComment, public nsIScriptObjectOwner, public nsIDOMEventReceiver, - public nsIContent + public nsIContent, + public nsITextContent { public: nsCommentNode(); @@ -159,6 +161,18 @@ public: return mInner.GetRangeList(aResult); } + NS_IMETHOD GetText(const nsTextFragment*& aFragmentsResult, + PRInt32& aNumFragmentsResult) + { return mInner.GetText(aFragmentsResult, aNumFragmentsResult); } + NS_IMETHOD SetText(const PRUnichar* aBuffer, + PRInt32 aLength, + PRBool aNotify); + NS_IMETHOD SetText(const char* aBuffer, + PRInt32 aLength, + PRBool aNotify); + NS_IMETHOD IsOnlyWhitespace(PRBool* aResult) + { return mInner.IsOnlyWhitespace(aResult); } + protected: nsGenericDOMDataNode mInner; }; @@ -202,6 +216,12 @@ nsCommentNode::QueryInterface(REFNSIID aIID, void** aInstancePtr) NS_ADDREF_THIS(); return NS_OK; } + if (aIID.Equals(kITextContentIID)) { + nsITextContent* tmp = this; + *aInstancePtr = (void*) tmp; + NS_ADDREF_THIS(); + return NS_OK; + } return NS_NOINTERFACE; } @@ -230,20 +250,30 @@ nsCommentNode::GetNodeType(PRUint16* aNodeType) NS_IMETHODIMP nsCommentNode::CloneNode(PRBool aDeep, nsIDOMNode** aReturn) { + nsresult result = NS_OK; nsCommentNode* it = new nsCommentNode(); if (nsnull == it) { return NS_ERROR_OUT_OF_MEMORY; } - nsAutoString data; - nsresult result = GetData(data); + // XXX Increment the ref count before calling any + // methods. If they do a QI and then a Release() + // the instance will be deleted. + result = it->QueryInterface(kIDOMNodeIID, (void**) aReturn); if (NS_FAILED(result)) { return result; } + nsAutoString data; + result = GetData(data); + if (NS_FAILED(result)) { + NS_RELEASE(*aReturn); + return result; + } result = it->SetData(data); if (NS_FAILED(result)) { + NS_RELEASE(*aReturn); return result; } - return it->QueryInterface(kIDOMNodeIID, (void**) aReturn); + return result; } NS_IMETHODIMP @@ -254,13 +284,13 @@ nsCommentNode::List(FILE* out, PRInt32 aIndent) const PRInt32 indx; for (indx = aIndent; --indx >= 0; ) fputs(" ", out); - fprintf(out, "Comment refcount=%d<", mRefCnt); + fprintf(out, "Comment refcount=%d\n", out); return NS_OK; } @@ -385,3 +415,65 @@ nsCommentNode::FinishConvertToXIF(nsXIFConverter& aConverter) const } #endif +// This would ideally be done by the parser, but for the sake +// of "genericity" it's being done in the comment content code +static void +StripCommentDelimiters(nsString& aCommentString) +{ + PRInt32 offset; + static char* kCommentStart = ""; + static char* kCommentAlternateEnd = "--!>"; + static char kMinus = '-'; + static char kExclamation = '!'; + + offset = aCommentString.Find(kCommentStart); + offset += strlen(kCommentStart); + if (-1 != offset) { + // Take up to 2 '-' characters + if (kMinus == aCommentString.CharAt(offset)) { + offset++; + if (kMinus == aCommentString.CharAt(offset)) { + offset++; + } + } + aCommentString.Cut(0, offset); + } + + offset = aCommentString.RFind(kCommentEnd); + if (-1 != offset) { + // Take up to 1 more '-' + if (kMinus == aCommentString.CharAt(offset-1)) { + offset--; + } + aCommentString.Cut(offset, aCommentString.Length()-offset); + } + else { + offset = aCommentString.RFind(kCommentAlternateEnd); + if (-1 != offset) { + aCommentString.Cut(offset, aCommentString.Length()-offset); + } + } +} + +NS_IMETHODIMP +nsCommentNode::SetText(const PRUnichar* aBuffer, + PRInt32 aLength, + PRBool aNotify) +{ + nsAutoString str(aBuffer); + + StripCommentDelimiters(str); + return mInner.SetText(str.GetUnicode(), str.Length(), aNotify); +} + +NS_IMETHODIMP +nsCommentNode::SetText(const char* aBuffer, + PRInt32 aLength, + PRBool aNotify) +{ + nsAutoString str(aBuffer); + + StripCommentDelimiters(str); + return mInner.SetText(str.GetUnicode(), str.Length(), aNotify); +} diff --git a/mozilla/content/base/src/nsGenericDOMDataNode.cpp b/mozilla/content/base/src/nsGenericDOMDataNode.cpp index 5c303c5d605..91a2fb61c4b 100644 --- a/mozilla/content/base/src/nsGenericDOMDataNode.cpp +++ b/mozilla/content/base/src/nsGenericDOMDataNode.cpp @@ -51,6 +51,7 @@ static NS_DEFINE_IID(kIEnumeratorIID, NS_IENUMERATOR_IID); static NS_DEFINE_IID(kIDOMDocumentIID, NS_IDOMDOCUMENT_IID); static NS_DEFINE_IID(kIDOMTextIID, NS_IDOMTEXT_IID); static NS_DEFINE_IID(kITextContentIID, NS_ITEXT_CONTENT_IID); +static NS_DEFINE_IID(kIDOMNodeListIID, NS_IDOMNODELIST_IID); //---------------------------------------------------------------------- @@ -184,6 +185,20 @@ nsGenericDOMDataNode::GetNextSibling(nsIDOMNode** aNextSibling) return result; } +nsresult +nsGenericDOMDataNode::GetChildNodes(nsIDOMNodeList** aChildNodes) +{ + // XXX Since we believe this won't be done very often, we won't + // burn another slot in the data node and just create a new + // (empty) childNodes list every time we're asked. + nsChildContentList* list = new nsChildContentList(nsnull); + if (nsnull == list) { + return NS_ERROR_OUT_OF_MEMORY; + } + + return list->QueryInterface(kIDOMNodeListIID, (void**)aChildNodes); +} + nsresult nsGenericDOMDataNode::GetOwnerDocument(nsIDOMDocument** aOwnerDocument) { @@ -238,13 +253,20 @@ nsGenericDOMDataNode::SetData(const nsString& aData) // text replacement we should just collapse all the ranges. if (mRangeList) nsRange::TextOwnerChanged(mContent, 0, mText.GetLength(), 0); - mText = aData; - - // Notify the document that the text changed - if (nsnull != mDocument) { - mDocument->ContentChanged(mContent, nsnull); + nsresult result; + nsCOMPtr textContent = do_QueryInterface(mContent, &result); + + // If possible, let the container content object have a go at it. + if (NS_SUCCEEDED(result)) { + result = textContent->SetText(aData.GetUnicode(), + aData.Length(), + PR_TRUE); } - return NS_OK; + else { + result = SetText(aData.GetUnicode(), aData.Length(), PR_TRUE); + } + + return result; } nsresult @@ -308,6 +330,8 @@ nsresult nsGenericDOMDataNode::ReplaceData(PRUint32 aOffset, PRUint32 aCount, const nsString& aData) { + nsresult result = NS_OK; + // sanitize arguments PRUint32 textLength = mText.GetLength(); if (aOffset > textLength) { @@ -343,15 +367,18 @@ nsGenericDOMDataNode::ReplaceData(PRUint32 aOffset, PRUint32 aCount, } // Switch to new buffer - mText.SetTo(to, newLength); + nsCOMPtr textContent = do_QueryInterface(mContent, &result); + + // If possible, let the container content object have a go at it. + if (NS_SUCCEEDED(result)) { + result = textContent->SetText(to, newLength, PR_TRUE); + } + else { + result = SetText(to, newLength, PR_TRUE); + } delete [] to; - // Notify the document that the text changed - if (nsnull != mDocument) { - mDocument->ContentChanged(mContent, nsnull); - } - - return NS_OK; + return result; } //---------------------------------------------------------------------- diff --git a/mozilla/content/base/src/nsGenericDOMDataNode.h b/mozilla/content/base/src/nsGenericDOMDataNode.h index 34a8bbdd6b3..18ed5ed8590 100644 --- a/mozilla/content/base/src/nsGenericDOMDataNode.h +++ b/mozilla/content/base/src/nsGenericDOMDataNode.h @@ -62,10 +62,7 @@ struct nsGenericDOMDataNode { } nsresult GetPreviousSibling(nsIDOMNode** aPreviousSibling); nsresult GetNextSibling(nsIDOMNode** aNextSibling); - nsresult GetChildNodes(nsIDOMNodeList** aChildNodes) { - *aChildNodes = nsnull; - return NS_OK; - } + nsresult GetChildNodes(nsIDOMNodeList** aChildNodes); nsresult HasChildNodes(PRBool* aHasChildNodes) { *aHasChildNodes = PR_FALSE; return NS_OK; diff --git a/mozilla/content/base/src/nsTextNode.cpp b/mozilla/content/base/src/nsTextNode.cpp index f6428cdedeb..1ef328462bb 100644 --- a/mozilla/content/base/src/nsTextNode.cpp +++ b/mozilla/content/base/src/nsTextNode.cpp @@ -142,21 +142,31 @@ nsTextNode::GetNodeType(PRUint16* aNodeType) NS_IMETHODIMP nsTextNode::CloneNode(PRBool aDeep, nsIDOMNode** aReturn) { + nsresult result = NS_OK; nsTextNode* it; NS_NEWXPCOM(it, nsTextNode); if (nsnull == it) { return NS_ERROR_OUT_OF_MEMORY; } - nsAutoString data; - nsresult result = GetData(data); + // XXX Increment the ref count before calling any + // methods. If they do a QI and then a Release() + // the instance will be deleted. + result = it->QueryInterface(kIDOMNodeIID, (void**) aReturn); if (NS_FAILED(result)) { return result; } + nsAutoString data; + result = GetData(data); + if (NS_FAILED(result)) { + NS_RELEASE(*aReturn); + return result; + } result = it->SetData(data); if (NS_FAILED(result)) { + NS_RELEASE(*aReturn); return result; } - return it->QueryInterface(kIDOMNodeIID, (void**) aReturn); + return result; } NS_IMETHODIMP diff --git a/mozilla/content/xml/content/src/nsXMLCDATASection.cpp b/mozilla/content/xml/content/src/nsXMLCDATASection.cpp index c785a57c17b..21a1aad8da4 100644 --- a/mozilla/content/xml/content/src/nsXMLCDATASection.cpp +++ b/mozilla/content/xml/content/src/nsXMLCDATASection.cpp @@ -148,21 +148,31 @@ nsXMLCDATASection::GetNodeType(PRUint16* aNodeType) NS_IMETHODIMP nsXMLCDATASection::CloneNode(PRBool aDeep, nsIDOMNode** aReturn) { + nsresult result = NS_OK; nsXMLCDATASection* it; NS_NEWXPCOM(it, nsXMLCDATASection); if (nsnull == it) { return NS_ERROR_OUT_OF_MEMORY; } - nsAutoString data; - nsresult result = GetData(data); + // XXX Increment the ref count before calling any + // methods. If they do a QI and then a Release() + // the instance will be deleted. + result = it->QueryInterface(kIDOMNodeIID, (void**) aReturn); if (NS_FAILED(result)) { return result; } + nsAutoString data; + result = GetData(data); + if (NS_FAILED(result)) { + NS_RELEASE(*aReturn); + return result; + } result = it->SetData(data); if (NS_FAILED(result)) { + NS_RELEASE(*aReturn); return result; } - return it->QueryInterface(kIDOMNodeIID, (void**) aReturn); + return result; } NS_IMETHODIMP diff --git a/mozilla/layout/base/src/nsCommentNode.cpp b/mozilla/layout/base/src/nsCommentNode.cpp index a5f2ebf3ea0..087e665ccc2 100644 --- a/mozilla/layout/base/src/nsCommentNode.cpp +++ b/mozilla/layout/base/src/nsCommentNode.cpp @@ -32,11 +32,13 @@ static NS_DEFINE_IID(kIDOMCommentIID, NS_IDOMCOMMENT_IID); static NS_DEFINE_IID(kIEnumeratorIID, NS_IENUMERATOR_IID); +static NS_DEFINE_IID(kITextContentIID, NS_ITEXT_CONTENT_IID); class nsCommentNode : public nsIDOMComment, public nsIScriptObjectOwner, public nsIDOMEventReceiver, - public nsIContent + public nsIContent, + public nsITextContent { public: nsCommentNode(); @@ -159,6 +161,18 @@ public: return mInner.GetRangeList(aResult); } + NS_IMETHOD GetText(const nsTextFragment*& aFragmentsResult, + PRInt32& aNumFragmentsResult) + { return mInner.GetText(aFragmentsResult, aNumFragmentsResult); } + NS_IMETHOD SetText(const PRUnichar* aBuffer, + PRInt32 aLength, + PRBool aNotify); + NS_IMETHOD SetText(const char* aBuffer, + PRInt32 aLength, + PRBool aNotify); + NS_IMETHOD IsOnlyWhitespace(PRBool* aResult) + { return mInner.IsOnlyWhitespace(aResult); } + protected: nsGenericDOMDataNode mInner; }; @@ -202,6 +216,12 @@ nsCommentNode::QueryInterface(REFNSIID aIID, void** aInstancePtr) NS_ADDREF_THIS(); return NS_OK; } + if (aIID.Equals(kITextContentIID)) { + nsITextContent* tmp = this; + *aInstancePtr = (void*) tmp; + NS_ADDREF_THIS(); + return NS_OK; + } return NS_NOINTERFACE; } @@ -230,20 +250,30 @@ nsCommentNode::GetNodeType(PRUint16* aNodeType) NS_IMETHODIMP nsCommentNode::CloneNode(PRBool aDeep, nsIDOMNode** aReturn) { + nsresult result = NS_OK; nsCommentNode* it = new nsCommentNode(); if (nsnull == it) { return NS_ERROR_OUT_OF_MEMORY; } - nsAutoString data; - nsresult result = GetData(data); + // XXX Increment the ref count before calling any + // methods. If they do a QI and then a Release() + // the instance will be deleted. + result = it->QueryInterface(kIDOMNodeIID, (void**) aReturn); if (NS_FAILED(result)) { return result; } + nsAutoString data; + result = GetData(data); + if (NS_FAILED(result)) { + NS_RELEASE(*aReturn); + return result; + } result = it->SetData(data); if (NS_FAILED(result)) { + NS_RELEASE(*aReturn); return result; } - return it->QueryInterface(kIDOMNodeIID, (void**) aReturn); + return result; } NS_IMETHODIMP @@ -254,13 +284,13 @@ nsCommentNode::List(FILE* out, PRInt32 aIndent) const PRInt32 indx; for (indx = aIndent; --indx >= 0; ) fputs(" ", out); - fprintf(out, "Comment refcount=%d<", mRefCnt); + fprintf(out, "Comment refcount=%d\n", out); return NS_OK; } @@ -385,3 +415,65 @@ nsCommentNode::FinishConvertToXIF(nsXIFConverter& aConverter) const } #endif +// This would ideally be done by the parser, but for the sake +// of "genericity" it's being done in the comment content code +static void +StripCommentDelimiters(nsString& aCommentString) +{ + PRInt32 offset; + static char* kCommentStart = ""; + static char* kCommentAlternateEnd = "--!>"; + static char kMinus = '-'; + static char kExclamation = '!'; + + offset = aCommentString.Find(kCommentStart); + offset += strlen(kCommentStart); + if (-1 != offset) { + // Take up to 2 '-' characters + if (kMinus == aCommentString.CharAt(offset)) { + offset++; + if (kMinus == aCommentString.CharAt(offset)) { + offset++; + } + } + aCommentString.Cut(0, offset); + } + + offset = aCommentString.RFind(kCommentEnd); + if (-1 != offset) { + // Take up to 1 more '-' + if (kMinus == aCommentString.CharAt(offset-1)) { + offset--; + } + aCommentString.Cut(offset, aCommentString.Length()-offset); + } + else { + offset = aCommentString.RFind(kCommentAlternateEnd); + if (-1 != offset) { + aCommentString.Cut(offset, aCommentString.Length()-offset); + } + } +} + +NS_IMETHODIMP +nsCommentNode::SetText(const PRUnichar* aBuffer, + PRInt32 aLength, + PRBool aNotify) +{ + nsAutoString str(aBuffer); + + StripCommentDelimiters(str); + return mInner.SetText(str.GetUnicode(), str.Length(), aNotify); +} + +NS_IMETHODIMP +nsCommentNode::SetText(const char* aBuffer, + PRInt32 aLength, + PRBool aNotify) +{ + nsAutoString str(aBuffer); + + StripCommentDelimiters(str); + return mInner.SetText(str.GetUnicode(), str.Length(), aNotify); +} diff --git a/mozilla/layout/base/src/nsGenericDOMDataNode.cpp b/mozilla/layout/base/src/nsGenericDOMDataNode.cpp index 5c303c5d605..91a2fb61c4b 100644 --- a/mozilla/layout/base/src/nsGenericDOMDataNode.cpp +++ b/mozilla/layout/base/src/nsGenericDOMDataNode.cpp @@ -51,6 +51,7 @@ static NS_DEFINE_IID(kIEnumeratorIID, NS_IENUMERATOR_IID); static NS_DEFINE_IID(kIDOMDocumentIID, NS_IDOMDOCUMENT_IID); static NS_DEFINE_IID(kIDOMTextIID, NS_IDOMTEXT_IID); static NS_DEFINE_IID(kITextContentIID, NS_ITEXT_CONTENT_IID); +static NS_DEFINE_IID(kIDOMNodeListIID, NS_IDOMNODELIST_IID); //---------------------------------------------------------------------- @@ -184,6 +185,20 @@ nsGenericDOMDataNode::GetNextSibling(nsIDOMNode** aNextSibling) return result; } +nsresult +nsGenericDOMDataNode::GetChildNodes(nsIDOMNodeList** aChildNodes) +{ + // XXX Since we believe this won't be done very often, we won't + // burn another slot in the data node and just create a new + // (empty) childNodes list every time we're asked. + nsChildContentList* list = new nsChildContentList(nsnull); + if (nsnull == list) { + return NS_ERROR_OUT_OF_MEMORY; + } + + return list->QueryInterface(kIDOMNodeListIID, (void**)aChildNodes); +} + nsresult nsGenericDOMDataNode::GetOwnerDocument(nsIDOMDocument** aOwnerDocument) { @@ -238,13 +253,20 @@ nsGenericDOMDataNode::SetData(const nsString& aData) // text replacement we should just collapse all the ranges. if (mRangeList) nsRange::TextOwnerChanged(mContent, 0, mText.GetLength(), 0); - mText = aData; - - // Notify the document that the text changed - if (nsnull != mDocument) { - mDocument->ContentChanged(mContent, nsnull); + nsresult result; + nsCOMPtr textContent = do_QueryInterface(mContent, &result); + + // If possible, let the container content object have a go at it. + if (NS_SUCCEEDED(result)) { + result = textContent->SetText(aData.GetUnicode(), + aData.Length(), + PR_TRUE); } - return NS_OK; + else { + result = SetText(aData.GetUnicode(), aData.Length(), PR_TRUE); + } + + return result; } nsresult @@ -308,6 +330,8 @@ nsresult nsGenericDOMDataNode::ReplaceData(PRUint32 aOffset, PRUint32 aCount, const nsString& aData) { + nsresult result = NS_OK; + // sanitize arguments PRUint32 textLength = mText.GetLength(); if (aOffset > textLength) { @@ -343,15 +367,18 @@ nsGenericDOMDataNode::ReplaceData(PRUint32 aOffset, PRUint32 aCount, } // Switch to new buffer - mText.SetTo(to, newLength); + nsCOMPtr textContent = do_QueryInterface(mContent, &result); + + // If possible, let the container content object have a go at it. + if (NS_SUCCEEDED(result)) { + result = textContent->SetText(to, newLength, PR_TRUE); + } + else { + result = SetText(to, newLength, PR_TRUE); + } delete [] to; - // Notify the document that the text changed - if (nsnull != mDocument) { - mDocument->ContentChanged(mContent, nsnull); - } - - return NS_OK; + return result; } //---------------------------------------------------------------------- diff --git a/mozilla/layout/base/src/nsGenericDOMDataNode.h b/mozilla/layout/base/src/nsGenericDOMDataNode.h index 34a8bbdd6b3..18ed5ed8590 100644 --- a/mozilla/layout/base/src/nsGenericDOMDataNode.h +++ b/mozilla/layout/base/src/nsGenericDOMDataNode.h @@ -62,10 +62,7 @@ struct nsGenericDOMDataNode { } nsresult GetPreviousSibling(nsIDOMNode** aPreviousSibling); nsresult GetNextSibling(nsIDOMNode** aNextSibling); - nsresult GetChildNodes(nsIDOMNodeList** aChildNodes) { - *aChildNodes = nsnull; - return NS_OK; - } + nsresult GetChildNodes(nsIDOMNodeList** aChildNodes); nsresult HasChildNodes(PRBool* aHasChildNodes) { *aHasChildNodes = PR_FALSE; return NS_OK; diff --git a/mozilla/layout/base/src/nsTextNode.cpp b/mozilla/layout/base/src/nsTextNode.cpp index f6428cdedeb..1ef328462bb 100644 --- a/mozilla/layout/base/src/nsTextNode.cpp +++ b/mozilla/layout/base/src/nsTextNode.cpp @@ -142,21 +142,31 @@ nsTextNode::GetNodeType(PRUint16* aNodeType) NS_IMETHODIMP nsTextNode::CloneNode(PRBool aDeep, nsIDOMNode** aReturn) { + nsresult result = NS_OK; nsTextNode* it; NS_NEWXPCOM(it, nsTextNode); if (nsnull == it) { return NS_ERROR_OUT_OF_MEMORY; } - nsAutoString data; - nsresult result = GetData(data); + // XXX Increment the ref count before calling any + // methods. If they do a QI and then a Release() + // the instance will be deleted. + result = it->QueryInterface(kIDOMNodeIID, (void**) aReturn); if (NS_FAILED(result)) { return result; } + nsAutoString data; + result = GetData(data); + if (NS_FAILED(result)) { + NS_RELEASE(*aReturn); + return result; + } result = it->SetData(data); if (NS_FAILED(result)) { + NS_RELEASE(*aReturn); return result; } - return it->QueryInterface(kIDOMNodeIID, (void**) aReturn); + return result; } NS_IMETHODIMP diff --git a/mozilla/layout/xml/content/src/nsXMLCDATASection.cpp b/mozilla/layout/xml/content/src/nsXMLCDATASection.cpp index c785a57c17b..21a1aad8da4 100644 --- a/mozilla/layout/xml/content/src/nsXMLCDATASection.cpp +++ b/mozilla/layout/xml/content/src/nsXMLCDATASection.cpp @@ -148,21 +148,31 @@ nsXMLCDATASection::GetNodeType(PRUint16* aNodeType) NS_IMETHODIMP nsXMLCDATASection::CloneNode(PRBool aDeep, nsIDOMNode** aReturn) { + nsresult result = NS_OK; nsXMLCDATASection* it; NS_NEWXPCOM(it, nsXMLCDATASection); if (nsnull == it) { return NS_ERROR_OUT_OF_MEMORY; } - nsAutoString data; - nsresult result = GetData(data); + // XXX Increment the ref count before calling any + // methods. If they do a QI and then a Release() + // the instance will be deleted. + result = it->QueryInterface(kIDOMNodeIID, (void**) aReturn); if (NS_FAILED(result)) { return result; } + nsAutoString data; + result = GetData(data); + if (NS_FAILED(result)) { + NS_RELEASE(*aReturn); + return result; + } result = it->SetData(data); if (NS_FAILED(result)) { + NS_RELEASE(*aReturn); return result; } - return it->QueryInterface(kIDOMNodeIID, (void**) aReturn); + return result; } NS_IMETHODIMP