From 3bc59122848659c6cca96bc6092f8f6219a4a51c Mon Sep 17 00:00:00 2001 From: "buster%netscape.com" Date: Thu, 19 Aug 1999 13:30:48 +0000 Subject: [PATCH] Fixed a ton of errors where we were not handling error results correctly. Added some comments of the form "// XXX: ERROR_HANDLING " wherever I saw a potential error but wasn't 100% sure of the intention of the code. Fixed a few bugs along the way. --- editor/base/ChangeAttributeTxn.cpp | 33 +- editor/base/CreateElementTxn.cpp | 181 +- editor/base/DeleteElementTxn.cpp | 11 +- editor/base/DeleteRangeTxn.cpp | 183 +- editor/base/DeleteTextTxn.cpp | 54 +- editor/base/InsertElementTxn.cpp | 26 +- editor/base/InsertTextTxn.cpp | 31 +- editor/base/JoinElementTxn.cpp | 96 +- editor/base/SplitElementTxn.cpp | 67 +- editor/base/nsEditor.cpp | 40 +- editor/base/nsEditor.h | 2 +- editor/base/nsEditorEventListeners.cpp | 401 ++- editor/base/nsHTMLEditor.cpp | 2947 +++++++++-------- editor/base/nsHTMLEditor.h | 18 +- editor/base/nsTextEditRules.cpp | 420 ++- editor/base/nsTextEditor.cpp | 1362 ++++---- editor/libeditor/base/ChangeAttributeTxn.cpp | 33 +- editor/libeditor/base/CreateElementTxn.cpp | 181 +- editor/libeditor/base/DeleteElementTxn.cpp | 11 +- editor/libeditor/base/DeleteRangeTxn.cpp | 183 +- editor/libeditor/base/DeleteTextTxn.cpp | 54 +- editor/libeditor/base/InsertElementTxn.cpp | 26 +- editor/libeditor/base/InsertTextTxn.cpp | 31 +- editor/libeditor/base/JoinElementTxn.cpp | 96 +- editor/libeditor/base/SplitElementTxn.cpp | 67 +- editor/libeditor/base/nsEditor.cpp | 40 +- editor/libeditor/base/nsEditor.h | 2 +- editor/libeditor/html/nsHTMLEditor.cpp | 2947 +++++++++-------- editor/libeditor/html/nsHTMLEditor.h | 18 +- .../libeditor/text/nsEditorEventListeners.cpp | 401 ++- editor/libeditor/text/nsTextEditRules.cpp | 420 ++- 31 files changed, 5610 insertions(+), 4772 deletions(-) diff --git a/editor/base/ChangeAttributeTxn.cpp b/editor/base/ChangeAttributeTxn.cpp index 54773f5fe693..ee7b5dd0ff94 100644 --- a/editor/base/ChangeAttributeTxn.cpp +++ b/editor/base/ChangeAttributeTxn.cpp @@ -35,23 +35,24 @@ NS_IMETHODIMP ChangeAttributeTxn::Init(nsIEditor *aEditor, const nsString& aValue, PRBool aRemoveAttribute) { - if (nsnull!=aEditor && nsnull!=aElement) - { - mEditor = aEditor; - mElement = do_QueryInterface(aElement); - mAttribute = aAttribute; - mValue = aValue; - mRemoveAttribute = aRemoveAttribute; - mAttributeWasSet=PR_FALSE; - mUndoValue=""; - return NS_OK; - } - else - return NS_ERROR_NULL_POINTER; + NS_ASSERTION(aEditor && aElement, "bad arg"); + if (!aEditor || !aElement) { return NS_ERROR_NULL_POINTER; } + + mEditor = aEditor; + mElement = do_QueryInterface(aElement); + mAttribute = aAttribute; + mValue = aValue; + mRemoveAttribute = aRemoveAttribute; + mAttributeWasSet=PR_FALSE; + mUndoValue=""; + return NS_OK; } NS_IMETHODIMP ChangeAttributeTxn::Do(void) { + NS_ASSERTION(mEditor && mElement, "bad state"); + if (!mEditor || !mElement) { return NS_ERROR_NOT_INITIALIZED; } + // need to get the current value of the attribute and save it, and set mAttributeWasSet nsresult result = mEditor->GetAttributeValue(mElement, mAttribute, mUndoValue, mAttributeWasSet); // XXX: hack until attribute-was-set code is implemented @@ -70,6 +71,9 @@ NS_IMETHODIMP ChangeAttributeTxn::Do(void) NS_IMETHODIMP ChangeAttributeTxn::Undo(void) { + NS_ASSERTION(mEditor && mElement, "bad state"); + if (!mEditor || !mElement) { return NS_ERROR_NOT_INITIALIZED; } + nsresult result=NS_OK; if (PR_TRUE==mAttributeWasSet) result = mElement->SetAttribute(mAttribute, mUndoValue); @@ -81,6 +85,9 @@ NS_IMETHODIMP ChangeAttributeTxn::Undo(void) NS_IMETHODIMP ChangeAttributeTxn::Redo(void) { + NS_ASSERTION(mEditor && mElement, "bad state"); + if (!mEditor || !mElement) { return NS_ERROR_NOT_INITIALIZED; } + nsresult result; if (PR_FALSE==mRemoveAttribute) diff --git a/editor/base/CreateElementTxn.cpp b/editor/base/CreateElementTxn.cpp index 930a59ec7599..d86043e4d284 100644 --- a/editor/base/CreateElementTxn.cpp +++ b/editor/base/CreateElementTxn.cpp @@ -41,24 +41,21 @@ NS_IMETHODIMP CreateElementTxn::Init(nsIEditor *aEditor, PRUint32 aOffsetInParent) { NS_ASSERTION(aEditor&&aParent, "null args"); - if (aEditor && aParent) - { - mEditor = aEditor; - mTag = aTag; - mParent = do_QueryInterface(aParent); - mOffsetInParent = aOffsetInParent; + if (!aEditor || !aParent) { return NS_ERROR_NULL_POINTER; } + + mEditor = aEditor; + mTag = aTag; + mParent = do_QueryInterface(aParent); + mOffsetInParent = aOffsetInParent; #ifdef NS_DEBUG - { - nsCOMPtr testChildNodes; - nsresult testResult = mParent->GetChildNodes(getter_AddRefs(testChildNodes)); - NS_ASSERTION(testChildNodes, "bad parent type, can't have children."); - NS_ASSERTION(NS_SUCCEEDED(testResult), "bad result."); - } -#endif - return NS_OK; + { + nsCOMPtr testChildNodes; + nsresult testResult = mParent->GetChildNodes(getter_AddRefs(testChildNodes)); + NS_ASSERTION(testChildNodes, "bad parent type, can't have children."); + NS_ASSERTION(NS_SUCCEEDED(testResult), "bad result."); } - else - return NS_ERROR_NULL_POINTER; +#endif + return NS_OK; } @@ -70,69 +67,69 @@ NS_IMETHODIMP CreateElementTxn::Do(void) { if (gNoisy) { printf("Do Create Element parent = %p, offset = %d\n", mParent.get(), mOffsetInParent); } - NS_ASSERTION(mEditor, "bad state -- null editor"); - nsresult result = NS_ERROR_NULL_POINTER; - if (mEditor) + NS_ASSERTION(mEditor && mParent, "bad state"); + if (!mEditor || !mParent) return NS_ERROR_NOT_INITIALIZED; + nsresult result; + // create a new node + nsCOMPtrdoc; + result = mEditor->GetDocument(getter_AddRefs(doc)); + if (NS_FAILED(result)) return result; + if (!doc) return NS_ERROR_NULL_POINTER; + + if (nsEditor::GetTextNodeTag() == mTag) { - // create a new node - nsCOMPtrdoc; - result = mEditor->GetDocument(getter_AddRefs(doc)); - if ((NS_SUCCEEDED(result)) && (doc)) + const nsString stringData; + nsCOMPtrnewTextNode; + result = doc->CreateTextNode(stringData, getter_AddRefs(newTextNode)); + if (NS_FAILED(result)) return result; + if (!newTextNode) return NS_ERROR_NULL_POINTER; + mNewNode = do_QueryInterface(newTextNode); + } + else + { + nsCOMPtrnewElement; + result = doc->CreateElement(mTag, getter_AddRefs(newElement)); + if (NS_FAILED(result)) return result; + if (!newElement) return NS_ERROR_NULL_POINTER; + mNewNode = do_QueryInterface(newElement); + } + NS_ASSERTION(((NS_SUCCEEDED(result)) && (mNewNode)), "could not create element."); + if (!mNewNode) return NS_ERROR_NULL_POINTER; + + if (gNoisy) { printf(" newNode = %p\n", mNewNode.get()); } + // insert the new node + nsCOMPtr resultNode; + if (CreateElementTxn::eAppend==(PRInt32)mOffsetInParent) + { + result = mParent->AppendChild(mNewNode, getter_AddRefs(resultNode)); + } + else + { + nsCOMPtr childNodes; + result = mParent->GetChildNodes(getter_AddRefs(childNodes)); + if ((NS_SUCCEEDED(result)) && (childNodes)) { - if (nsEditor::GetTextNodeTag() == mTag) + PRUint32 count; + childNodes->GetLength(&count); + if (mOffsetInParent>count) + mOffsetInParent = count; + result = childNodes->Item(mOffsetInParent, getter_AddRefs(mRefNode)); + if (NS_SUCCEEDED(result)) // note, it's ok for mRefNode to be null. that means append { - const nsString stringData; - nsCOMPtrnewTextNode; - result = doc->CreateTextNode(stringData, getter_AddRefs(newTextNode)); - if (NS_SUCCEEDED(result) && newTextNode) { - mNewNode = do_QueryInterface(newTextNode); - } - } - else - { - nsCOMPtrnewElement; - result = doc->CreateElement(mTag, getter_AddRefs(newElement)); - if (NS_SUCCEEDED(result) && newElement) { - mNewNode = do_QueryInterface(newElement); - } - } - NS_ASSERTION(((NS_SUCCEEDED(result)) && (mNewNode)), "could not create element."); - if ((NS_SUCCEEDED(result)) && (mNewNode)) - { - if (gNoisy) { printf(" newNode = %p\n", mNewNode.get()); } - // insert the new node - nsCOMPtr resultNode; - if (CreateElementTxn::eAppend==(PRInt32)mOffsetInParent) + result = mParent->InsertBefore(mNewNode, mRefNode, getter_AddRefs(resultNode)); + if (NS_SUCCEEDED(result)) { - result = mParent->AppendChild(mNewNode, getter_AddRefs(resultNode)); - } - else - { - nsCOMPtr childNodes; - result = mParent->GetChildNodes(getter_AddRefs(childNodes)); - if ((NS_SUCCEEDED(result)) && (childNodes)) - { - PRUint32 count; - childNodes->GetLength(&count); - if (mOffsetInParent>count) - mOffsetInParent = count; - result = childNodes->Item(mOffsetInParent, getter_AddRefs(mRefNode)); - if (NS_SUCCEEDED(result)) // note, it's ok for mRefNode to be null. that means append - { - result = mParent->InsertBefore(mNewNode, mRefNode, getter_AddRefs(resultNode)); - if (NS_SUCCEEDED(result)) - { - nsCOMPtr selection; - nsresult selectionResult = mEditor->GetSelection(getter_AddRefs(selection)); - if (NS_SUCCEEDED(selectionResult) && selection) { - PRInt32 offset=0; - nsEditor::GetChildOffset(mNewNode, mParent, offset); - selectionResult = selection->Collapse(mParent, offset+1); - NS_ASSERTION((NS_SUCCEEDED(selectionResult)), "selection could not be collapsed after insert."); - } - } - } - } + nsCOMPtr selection; + result = mEditor->GetSelection(getter_AddRefs(selection)); + if (NS_FAILED(result)) return result; + if (!selection) return NS_ERROR_NULL_POINTER; + + PRInt32 offset=0; + result = nsEditor::GetChildOffset(mNewNode, mParent, offset); + if (NS_FAILED(result)) return result; + + result = selection->Collapse(mParent, offset+1); + NS_ASSERTION((NS_SUCCEEDED(result)), "selection could not be collapsed after insert."); } } } @@ -144,20 +141,24 @@ NS_IMETHODIMP CreateElementTxn::Undo(void) { if (gNoisy) { printf("Undo Create Element, mParent = %p, node = %p\n", mParent.get(), mNewNode.get()); } + NS_ASSERTION(mEditor && mParent, "bad state"); + if (!mEditor || !mParent) return NS_ERROR_NOT_INITIALIZED; + nsCOMPtr resultNode; nsresult result = mParent->RemoveChild(mNewNode, getter_AddRefs(resultNode)); if (NS_SUCCEEDED(result)) { nsCOMPtr selection; - nsresult selectionResult = mEditor->GetSelection(getter_AddRefs(selection)); - if (NS_SUCCEEDED(selectionResult) && selection) { - PRInt32 offset=0; - if (mRefNode) { - nsEditor::GetChildOffset(mRefNode, mParent, offset); - } - selectionResult = selection->Collapse(mParent, offset); - NS_ASSERTION((NS_SUCCEEDED(selectionResult)), "selection could not be collapsed after undo of insert."); + result = mEditor->GetSelection(getter_AddRefs(selection)); + if (NS_FAILED(result)) return result; + if (!selection) return NS_ERROR_NULL_POINTER; + + PRInt32 offset=0; + if (mRefNode) { + nsEditor::GetChildOffset(mRefNode, mParent, offset); } + result = selection->Collapse(mParent, offset); + NS_ASSERTION((NS_SUCCEEDED(result)), "selection could not be collapsed after undo of insert."); } return result; } @@ -165,6 +166,8 @@ NS_IMETHODIMP CreateElementTxn::Undo(void) NS_IMETHODIMP CreateElementTxn::Redo(void) { if (gNoisy) { printf("Redo Create Element\n"); } + NS_ASSERTION(mEditor && mParent, "bad state"); + if (!mEditor || !mParent) return NS_ERROR_NOT_INITIALIZED; // first, reset mNewNode so it has no attributes or content nsCOMPtrnodeAsText; @@ -182,12 +185,12 @@ NS_IMETHODIMP CreateElementTxn::Redo(void) { nsCOMPtr selection; result = mEditor->GetSelection(getter_AddRefs(selection)); - if (NS_SUCCEEDED(result) && selection) { - PRInt32 offset=0; - nsEditor::GetChildOffset(mNewNode, mParent, offset); - nsresult selectionResult = selection->Collapse(mParent, offset); - NS_ASSERTION((NS_SUCCEEDED(selectionResult)), "selection could not be collapsed after undo of insert."); - } + if (NS_FAILED(result)) return result; + if (!selection) return NS_ERROR_NULL_POINTER; + PRInt32 offset=0; + nsEditor::GetChildOffset(mNewNode, mParent, offset); + result = selection->Collapse(mParent, offset); + NS_ASSERTION((NS_SUCCEEDED(result)), "selection could not be collapsed after undo of insert."); } return result; } diff --git a/editor/base/DeleteElementTxn.cpp b/editor/base/DeleteElementTxn.cpp index 771c0f26849a..bfe55418fb85 100644 --- a/editor/base/DeleteElementTxn.cpp +++ b/editor/base/DeleteElementTxn.cpp @@ -51,16 +51,11 @@ DeleteElementTxn::~DeleteElementTxn() NS_IMETHODIMP DeleteElementTxn::Do(void) { if (gNoisy) { printf("%p Do Delete Element element = %p\n", this, mElement.get()); } - if (!mElement) - return NS_ERROR_NULL_POINTER; + if (!mElement) return NS_ERROR_NOT_INITIALIZED; nsresult result = mElement->GetParentNode(getter_AddRefs(mParent)); - if (NS_FAILED(result)) { - return result; - } - if (!mParent) { - return NS_OK; // this is a no-op, there's no parent to delete mElement from - } + if (NS_FAILED(result)) { return result; } + if (!mParent) { return NS_OK; } // this is a no-op, there's no parent to delete mElement from #ifdef NS_DEBUG // begin debug output diff --git a/editor/base/DeleteRangeTxn.cpp b/editor/base/DeleteRangeTxn.cpp index 816264ab4ea6..8cc9dbf21d45 100644 --- a/editor/base/DeleteRangeTxn.cpp +++ b/editor/base/DeleteRangeTxn.cpp @@ -46,21 +46,22 @@ DeleteRangeTxn::DeleteRangeTxn() NS_IMETHODIMP DeleteRangeTxn::Init(nsIEditor *aEditor, nsIDOMRange *aRange) { - if (aEditor && aRange) - { - mEditor = aEditor; - mRange = do_QueryInterface(aRange); - - nsresult result = aRange->GetStartParent(getter_AddRefs(mStartParent)); - NS_ASSERTION((NS_SUCCEEDED(result)), "GetStartParent failed."); - result = aRange->GetEndParent(getter_AddRefs(mEndParent)); - NS_ASSERTION((NS_SUCCEEDED(result)), "GetEndParent failed."); - result = aRange->GetStartOffset(&mStartOffset); - NS_ASSERTION((NS_SUCCEEDED(result)), "GetStartOffset failed."); - result = aRange->GetEndOffset(&mEndOffset); - NS_ASSERTION((NS_SUCCEEDED(result)), "GetEndOffset failed."); - result = aRange->GetCommonParent(getter_AddRefs(mCommonParent)); - NS_ASSERTION((NS_SUCCEEDED(result)), "GetCommonParent failed."); + NS_ASSERTION(aEditor && aRange, "bad state"); + if (!aEditor || !aRange) { return NS_ERROR_NOT_INITIALIZED; } + + mEditor = aEditor; + mRange = do_QueryInterface(aRange); + + nsresult result = aRange->GetStartParent(getter_AddRefs(mStartParent)); + NS_ASSERTION((NS_SUCCEEDED(result)), "GetStartParent failed."); + result = aRange->GetEndParent(getter_AddRefs(mEndParent)); + NS_ASSERTION((NS_SUCCEEDED(result)), "GetEndParent failed."); + result = aRange->GetStartOffset(&mStartOffset); + NS_ASSERTION((NS_SUCCEEDED(result)), "GetStartOffset failed."); + result = aRange->GetEndOffset(&mEndOffset); + NS_ASSERTION((NS_SUCCEEDED(result)), "GetEndOffset failed."); + result = aRange->GetCommonParent(getter_AddRefs(mCommonParent)); + NS_ASSERTION((NS_SUCCEEDED(result)), "GetCommonParent failed."); #ifdef NS_DEBUG { @@ -96,10 +97,8 @@ NS_IMETHODIMP DeleteRangeTxn::Init(nsIEditor *aEditor, nsIDOMRange *aRange) } } #endif - return result; - } - else - return NS_ERROR_NULL_POINTER; + return result; + } DeleteRangeTxn::~DeleteRangeTxn() @@ -109,11 +108,10 @@ DeleteRangeTxn::~DeleteRangeTxn() NS_IMETHODIMP DeleteRangeTxn::Do(void) { if (gNoisy) { printf("Do Delete Range\n"); } - if (!mStartParent || !mEndParent || !mCommonParent) - return NS_ERROR_NULL_POINTER; + if (!mStartParent || !mEndParent || !mCommonParent || !mEditor) + return NS_ERROR_NOT_INITIALIZED; nsresult result; - // build the child transactions if (mStartParent==mEndParent) @@ -145,9 +143,9 @@ NS_IMETHODIMP DeleteRangeTxn::Do(void) // set the resulting selection nsCOMPtr selection; result = mEditor->GetSelection(getter_AddRefs(selection)); - if (NS_SUCCEEDED(result)) { - result = selection->Collapse(mStartParent, mStartOffset); - } + if (NS_FAILED(result)) return result; + if (!selection) return NS_ERROR_NULL_POINTER; + result = selection->Collapse(mStartParent, mStartOffset); } return result; @@ -156,19 +154,21 @@ NS_IMETHODIMP DeleteRangeTxn::Do(void) NS_IMETHODIMP DeleteRangeTxn::Undo(void) { if (gNoisy) { printf("Undo Delete Range\n"); } - if (!mStartParent || !mEndParent || !mCommonParent) - return NS_ERROR_NULL_POINTER; + if (!mStartParent || !mEndParent || !mCommonParent || !mEditor) + return NS_ERROR_NOT_INITIALIZED; nsresult result = EditAggregateTxn::Undo(); - if (NS_SUCCEEDED(result)) { + if (NS_SUCCEEDED(result)) + { // set the resulting selection nsCOMPtr selection; result = mEditor->GetSelection(getter_AddRefs(selection)); - if (NS_SUCCEEDED(result)) { - selection->Collapse(mStartParent, mStartOffset); - selection->Extend(mEndParent, mEndOffset); - } + if (NS_FAILED(result)) return result; + if (!selection) return NS_ERROR_NULL_POINTER; + result = selection->Collapse(mStartParent, mStartOffset); + if (NS_FAILED(result)) return result; + result = selection->Extend(mEndParent, mEndOffset); } return result; @@ -177,8 +177,8 @@ NS_IMETHODIMP DeleteRangeTxn::Undo(void) NS_IMETHODIMP DeleteRangeTxn::Redo(void) { if (gNoisy) { printf("Redo Delete Range\n"); } - if (!mStartParent || !mEndParent || !mCommonParent) - return NS_ERROR_NULL_POINTER; + if (!mStartParent || !mEndParent || !mCommonParent || !mEditor) + return NS_ERROR_NOT_INITIALIZED; nsresult result = EditAggregateTxn::Redo(); @@ -186,9 +186,9 @@ NS_IMETHODIMP DeleteRangeTxn::Redo(void) // set the resulting selection nsCOMPtr selection; result = mEditor->GetSelection(getter_AddRefs(selection)); - if (NS_SUCCEEDED(result)) { - result = selection->Collapse(mStartParent, mStartOffset); - } + if (NS_FAILED(result)) return result; + if (!selection) return NS_ERROR_NULL_POINTER; + result = selection->Collapse(mStartParent, mStartOffset); } return result; @@ -224,9 +224,10 @@ NS_IMETHODIMP DeleteRangeTxn::GetRedoString(nsString *aString) return NS_OK; } -NS_IMETHODIMP DeleteRangeTxn::CreateTxnsToDeleteBetween(nsIDOMNode *aStartParent, - PRUint32 aStartOffset, - PRUint32 aEndOffset) +NS_IMETHODIMP +DeleteRangeTxn::CreateTxnsToDeleteBetween(nsIDOMNode *aStartParent, + PRUint32 aStartOffset, + PRUint32 aEndOffset) { nsresult result; // see what kind of node we have @@ -236,44 +237,42 @@ NS_IMETHODIMP DeleteRangeTxn::CreateTxnsToDeleteBetween(nsIDOMNode *aStartParent { // if the node is a text node, then delete text content DeleteTextTxn *txn; result = TransactionFactory::GetNewTransaction(DeleteTextTxn::GetCID(), (EditTxn **)&txn); - if (nsnull!=txn) - { - PRInt32 numToDel; - if (aStartOffset==aEndOffset) - numToDel = 1; - else - numToDel = aEndOffset-aStartOffset; - txn->Init(mEditor, textNode, aStartOffset, numToDel); - AppendChild(txn); - } + if (NS_FAILED(result)) return result; + if (!txn) return NS_ERROR_NULL_POINTER; + + PRInt32 numToDel; + if (aStartOffset==aEndOffset) + numToDel = 1; + else + numToDel = aEndOffset-aStartOffset; + txn->Init(mEditor, textNode, aStartOffset, numToDel); + AppendChild(txn); } else { PRUint32 childCount; nsCOMPtr children; result = aStartParent->GetChildNodes(getter_AddRefs(children)); - if ((NS_SUCCEEDED(result)) && children) + if (NS_FAILED(result)) return result; + if (!children) return NS_ERROR_NULL_POINTER; + + children->GetLength(&childCount); + NS_ASSERTION(aEndOffset<=childCount, "bad aEndOffset"); + PRUint32 i; + for (i=aStartOffset; iGetLength(&childCount); - NS_ASSERTION(aEndOffset<=childCount, "bad aEndOffset"); - PRUint32 i; - for (i=aStartOffset; i child; - result = children->Item(i, getter_AddRefs(child)); - if ((NS_SUCCEEDED(result)) && child) - { - DeleteElementTxn *txn; - result = TransactionFactory::GetNewTransaction(DeleteElementTxn::GetCID(), (EditTxn **)&txn); - if (nsnull!=txn) - { - txn->Init(child); - AppendChild(txn); - } - else - return NS_ERROR_NULL_POINTER; - } - } + nsCOMPtr child; + result = children->Item(i, getter_AddRefs(child)); + if (NS_FAILED(result)) return result; + if (!child) return NS_ERROR_NULL_POINTER; + + DeleteElementTxn *txn; + result = TransactionFactory::GetNewTransaction(DeleteElementTxn::GetCID(), (EditTxn **)&txn); + if (NS_FAILED(result)) return result; + if (!txn) return NS_ERROR_NULL_POINTER; + + txn->Init(child); + AppendChild(txn); } } return result; @@ -306,13 +305,11 @@ NS_IMETHODIMP DeleteRangeTxn::CreateTxnsToDeleteContent(nsIDOMNode *aParent, { DeleteTextTxn *txn; result = TransactionFactory::GetNewTransaction(DeleteTextTxn::GetCID(), (EditTxn **)&txn); - if (nsnull!=txn) - { - txn->Init(mEditor, textNode, start, numToDelete); - AppendChild(txn); - } - else - return NS_ERROR_NULL_POINTER; + if (NS_FAILED(result)) return result; + if (!txn) return NS_ERROR_NULL_POINTER; + + txn->Init(mEditor, textNode, start, numToDelete); + AppendChild(txn); } } @@ -332,11 +329,11 @@ NS_IMETHODIMP DeleteRangeTxn::CreateTxnsToDeleteNodesBetween() nsnull, nsIContentIterator::GetIID(), getter_AddRefs(iter)); - if (!NS_SUCCEEDED(result)) - return result; + if (NS_FAILED(result)) return result; + if (!iter) return NS_ERROR_NULL_POINTER; + result = iter->Init(mRange); - if (!NS_SUCCEEDED(result)) - return result; + if (NS_FAILED(result)) return result; while (NS_COMFALSE == iter->IsDone()) { @@ -344,18 +341,16 @@ NS_IMETHODIMP DeleteRangeTxn::CreateTxnsToDeleteNodesBetween() nsCOMPtr content; result = iter->CurrentNode(getter_AddRefs(content)); node = do_QueryInterface(content); - if ((NS_SUCCEEDED(result)) && node) - { - DeleteElementTxn *txn; - result = TransactionFactory::GetNewTransaction(DeleteElementTxn::GetCID(), (EditTxn **)&txn); - if (nsnull!=txn) - { - txn->Init(node); - AppendChild(txn); - } - else - return NS_ERROR_NULL_POINTER; - } + if (NS_FAILED(result)) return result; + if (!node) return NS_ERROR_NULL_POINTER; + + DeleteElementTxn *txn; + result = TransactionFactory::GetNewTransaction(DeleteElementTxn::GetCID(), (EditTxn **)&txn); + if (NS_FAILED(result)) return result; + if (!txn) return NS_ERROR_NULL_POINTER; + + txn->Init(node); + AppendChild(txn); iter->Next(); } return result; diff --git a/editor/base/DeleteTextTxn.cpp b/editor/base/DeleteTextTxn.cpp index cf7139391813..811242077bfc 100644 --- a/editor/base/DeleteTextTxn.cpp +++ b/editor/base/DeleteTextTxn.cpp @@ -41,6 +41,8 @@ NS_IMETHODIMP DeleteTextTxn::Init(nsIEditor *aEditor, PRUint32 aNumCharsToDelete) { NS_ASSERTION(aEditor&&aElement, "bad arg"); + if (!aEditor || !aElement) { return NS_ERROR_NULL_POINTER; } + mEditor = aEditor; mElement = do_QueryInterface(aElement); mOffset = aOffset; @@ -57,22 +59,20 @@ NS_IMETHODIMP DeleteTextTxn::Init(nsIEditor *aEditor, NS_IMETHODIMP DeleteTextTxn::Do(void) { if (gNoisy) { printf("Do Delete Text\n"); } - nsresult result = NS_ERROR_NULL_POINTER; - if (mEditor && mElement) + NS_ASSERTION(mEditor && mElement, "bad state"); + if (!mEditor || !mElement) { return NS_ERROR_NOT_INITIALIZED; } + // get the text that we're about to delete + nsresult result = mElement->SubstringData(mOffset, mNumCharsToDelete, mDeletedText); + NS_ASSERTION(NS_SUCCEEDED(result), "could not get text to delete."); + result = mElement->DeleteData(mOffset, mNumCharsToDelete); + if (NS_SUCCEEDED(result)) { - // get the text that we're about to delete - result = mElement->SubstringData(mOffset, mNumCharsToDelete, mDeletedText); - NS_ASSERTION(NS_SUCCEEDED(result), "could not get text to delete."); - result = mElement->DeleteData(mOffset, mNumCharsToDelete); - if (NS_SUCCEEDED(result)) - { - nsCOMPtr selection; - nsresult selectionResult = mEditor->GetSelection(getter_AddRefs(selection)); - if (NS_SUCCEEDED(selectionResult) && selection) { - selectionResult = selection->Collapse(mElement, mOffset); - NS_ASSERTION((NS_SUCCEEDED(selectionResult)), "selection could not be collapsed after undo of insert."); - } - } + nsCOMPtr selection; + result = mEditor->GetSelection(getter_AddRefs(selection)); + if (NS_FAILED(result)) return result; + if (!selection) return NS_ERROR_NULL_POINTER; + result = selection->Collapse(mElement, mOffset); + NS_ASSERTION((NS_SUCCEEDED(result)), "selection could not be collapsed after undo of insert."); } return result; } @@ -82,19 +82,19 @@ NS_IMETHODIMP DeleteTextTxn::Do(void) NS_IMETHODIMP DeleteTextTxn::Undo(void) { if (gNoisy) { printf("Undo Delete Text\n"); } - nsresult result = NS_ERROR_NULL_POINTER; - if (mEditor && mElement) + NS_ASSERTION(mEditor && mElement, "bad state"); + if (!mEditor || !mElement) { return NS_ERROR_NOT_INITIALIZED; } + + nsresult result; + result = mElement->InsertData(mOffset, mDeletedText); + if (NS_SUCCEEDED(result)) { - result = mElement->InsertData(mOffset, mDeletedText); - if (NS_SUCCEEDED(result)) - { - nsCOMPtr selection; - nsresult selectionResult = mEditor->GetSelection(getter_AddRefs(selection)); - if (NS_SUCCEEDED(selectionResult) && selection) { - selectionResult = selection->Collapse(mElement, mOffset); - NS_ASSERTION((NS_SUCCEEDED(selectionResult)), "selection could not be collapsed after undo of insert."); - } - } + nsCOMPtr selection; + nsresult selectionResult = mEditor->GetSelection(getter_AddRefs(selection)); + if (NS_FAILED(result)) return result; + if (!selection) return NS_ERROR_NULL_POINTER; + result = selection->Collapse(mElement, mOffset); + NS_ASSERTION((NS_SUCCEEDED(result)), "selection could not be collapsed after undo of insert."); } return result; } diff --git a/editor/base/InsertElementTxn.cpp b/editor/base/InsertElementTxn.cpp index 213d298a2962..d107dfc95b22 100644 --- a/editor/base/InsertElementTxn.cpp +++ b/editor/base/InsertElementTxn.cpp @@ -64,8 +64,7 @@ NS_IMETHODIMP InsertElementTxn::Do(void) printf("%p Do Insert Element of %p into parent %p at offset %d\n", this, nodeAsContent.get(), parentAsContent.get(), mOffset); } - if (!mNode || !mParent) - return NS_ERROR_NULL_POINTER; + if (!mNode || !mParent) return NS_ERROR_NOT_INITIALIZED; nsresult result; nsCOMPtrrefNode; @@ -92,16 +91,16 @@ NS_IMETHODIMP InsertElementTxn::Do(void) nsCOMPtr resultNode; result = mParent->InsertBefore(mNode, refNode, getter_AddRefs(resultNode)); - if (NS_SUCCEEDED(result) && resultNode) - { - nsCOMPtr selection; - result = mEditor->GetSelection(getter_AddRefs(selection)); - if ((NS_SUCCEEDED(result)) && selection) - { // place the selection just after the inserted element - selection->Collapse(mParent, mOffset+1); - //selection->Extend(mParent, mOffset+1); - } - } + if (NS_FAILED(result)) return result; + if (!resultNode) return NS_ERROR_NULL_POINTER; + + nsCOMPtr selection; + result = mEditor->GetSelection(getter_AddRefs(selection)); + if (NS_FAILED(result)) return result; + if (!selection) return NS_ERROR_NULL_POINTER; + // place the selection just after the inserted element + selection->Collapse(mParent, mOffset+1); + //selection->Extend(mParent, mOffset+1); return result; } @@ -109,8 +108,7 @@ NS_IMETHODIMP InsertElementTxn::Undo(void) { if (gNoisy) { printf("%p Undo Insert Element of %p into parent %p at offset %d\n", this, mNode.get(), mParent.get(), mOffset); } - if (!mNode || !mParent) - return NS_ERROR_NULL_POINTER; + if (!mNode || !mParent) return NS_ERROR_NOT_INITIALIZED; nsCOMPtr resultNode; nsresult result = mParent->RemoveChild(mNode, getter_AddRefs(resultNode)); diff --git a/editor/base/InsertTextTxn.cpp b/editor/base/InsertTextTxn.cpp index 9f7a45912472..5f3a9442a314 100644 --- a/editor/base/InsertTextTxn.cpp +++ b/editor/base/InsertTextTxn.cpp @@ -62,6 +62,9 @@ NS_IMETHODIMP InsertTextTxn::Init(nsIDOMCharacterData *aElement, printf("\n"); #endif + NS_ASSERTION(aElement&&aPresShell, "bad args"); + if (!aElement || !aPresShell) return NS_ERROR_NULL_POINTER; + mElement = do_QueryInterface(aElement); mOffset = aOffset; mStringToInsert = aStringToInsert; @@ -72,16 +75,19 @@ NS_IMETHODIMP InsertTextTxn::Init(nsIDOMCharacterData *aElement, NS_IMETHODIMP InsertTextTxn::Do(void) { if (gNoisy) { printf("Do Insert Text element = %p\n", mElement.get()); } + NS_ASSERTION(mElement && mPresShell, "bad state"); + if (!mElement || !mPresShell) { return NS_ERROR_NOT_INITIALIZED; } + // advance caret: This requires the presentation shell to get the selection. nsCOMPtr selection; nsresult result = mPresShell->GetSelection(SELECTION_NORMAL, getter_AddRefs(selection)); - NS_ASSERTION(selection,"Could not get selection in InsertTextTxn::Do\n"); - if (NS_SUCCEEDED(result) && selection) { - result = mElement->InsertData(mOffset, mStringToInsert); - if (NS_SUCCEEDED(result)) { - result = selection->Collapse(mElement, mOffset+mStringToInsert.Length()); - NS_ASSERTION((NS_SUCCEEDED(result)), "selection could not be collapsed after insert."); - } + if (NS_FAILED(result)) return result; + if (!selection) return NS_ERROR_NULL_POINTER; + result = mElement->InsertData(mOffset, mStringToInsert); + if (NS_SUCCEEDED(result)) + { + result = selection->Collapse(mElement, mOffset+mStringToInsert.Length()); + NS_ASSERTION((NS_SUCCEEDED(result)), "selection could not be collapsed after insert."); } return result; } @@ -89,6 +95,9 @@ NS_IMETHODIMP InsertTextTxn::Do(void) NS_IMETHODIMP InsertTextTxn::Undo(void) { if (gNoisy) { printf("Undo Insert Text element = %p\n", mElement.get()); } + NS_ASSERTION(mElement && mPresShell, "bad state"); + if (!mElement || !mPresShell) { return NS_ERROR_NOT_INITIALIZED; } + nsresult result; PRUint32 length = mStringToInsert.Length(); result = mElement->DeleteData(mOffset, length); @@ -96,10 +105,10 @@ NS_IMETHODIMP InsertTextTxn::Undo(void) { // set the selection to the insertion point where the string was removed nsCOMPtr selection; result = mPresShell->GetSelection(SELECTION_NORMAL, getter_AddRefs(selection)); - if (NS_SUCCEEDED(result) && selection) { - result = selection->Collapse(mElement, mOffset); - NS_ASSERTION((NS_SUCCEEDED(result)), "selection could not be collapsed after undo of insert."); - } + if (NS_FAILED(result)) return result; + if (!selection) return NS_ERROR_NULL_POINTER; + result = selection->Collapse(mElement, mOffset); + NS_ASSERTION((NS_SUCCEEDED(result)), "selection could not be collapsed after undo of insert."); } return result; } diff --git a/editor/base/JoinElementTxn.cpp b/editor/base/JoinElementTxn.cpp index c6d3902fbda3..62869cfa5b41 100644 --- a/editor/base/JoinElementTxn.cpp +++ b/editor/base/JoinElementTxn.cpp @@ -37,6 +37,8 @@ NS_IMETHODIMP JoinElementTxn::Init(nsIEditor *aEditor, nsIDOMNode *aLeftNode, nsIDOMNode *aRightNode) { + NS_PRECONDITION((aEditor && aLeftNode && aRightNode), "null arg"); + if (!aEditor || !aLeftNode || !aRightNode) { return NS_ERROR_NULL_POINTER; } mEditor = aEditor; mLeftNode = do_QueryInterface(aLeftNode); mRightNode = do_QueryInterface(aRightNode); @@ -52,54 +54,54 @@ JoinElementTxn::~JoinElementTxn() NS_IMETHODIMP JoinElementTxn::Do(void) { if (gNoisy) { printf("%p Do Join of %p and %p\n", this, mLeftNode.get(), mRightNode.get()); } - nsresult result; + NS_PRECONDITION((mEditor && mLeftNode && mRightNode), "null arg"); + if (!mEditor || !mLeftNode || !mRightNode) { return NS_ERROR_NOT_INITIALIZED; } - if ((mLeftNode) && (mRightNode)) - { // get the parent node - nsCOMPtrleftParent; - result = mLeftNode->GetParentNode(getter_AddRefs(leftParent)); - if ((NS_SUCCEEDED(result)) && (leftParent)) - { // verify that mLeftNode and mRightNode have the same parent - nsCOMPtrrightParent; - result = mRightNode->GetParentNode(getter_AddRefs(rightParent)); - if ((NS_SUCCEEDED(result)) && (rightParent)) - { - if (leftParent==rightParent) - { - mParent= do_QueryInterface(leftParent); // set this instance mParent. - // Other methods will see a non-null mParent and know all is well - nsCOMPtr childNodes; - result = mLeftNode->GetChildNodes(getter_AddRefs(childNodes)); - if ((NS_SUCCEEDED(result)) && (childNodes)) { - childNodes->GetLength(&mOffset); - } - else - { - nsCOMPtr leftNodeAsText; - leftNodeAsText = do_QueryInterface(mLeftNode); - if (leftNodeAsText) { - leftNodeAsText->GetLength(&mOffset); - } - } - result = nsEditor::JoinNodesImpl(mRightNode, mLeftNode, mParent, PR_FALSE); - if (NS_SUCCEEDED(result)) - { - if (gNoisy) { printf(" left node = %p removed\n", mLeftNode.get()); } - nsCOMPtrselection; - mEditor->GetSelection(getter_AddRefs(selection)); - if (selection) - { - selection->Collapse(mRightNode, mOffset); - } - } - } - else - { - NS_ASSERTION(PR_FALSE, "2 nodes do not have same parent"); - return NS_ERROR_INVALID_ARG; - } + // get the parent node + nsCOMPtrleftParent; + nsresult result = mLeftNode->GetParentNode(getter_AddRefs(leftParent)); + if (NS_FAILED(result)) return result; + if (!leftParent) return NS_ERROR_NULL_POINTER; + + // verify that mLeftNode and mRightNode have the same parent + nsCOMPtrrightParent; + result = mRightNode->GetParentNode(getter_AddRefs(rightParent)); + if (NS_FAILED(result)) return result; + if (!rightParent) return NS_ERROR_NULL_POINTER; + + if (leftParent==rightParent) + { + mParent= do_QueryInterface(leftParent); // set this instance mParent. + // Other methods will see a non-null mParent and know all is well + nsCOMPtr childNodes; + result = mLeftNode->GetChildNodes(getter_AddRefs(childNodes)); + if (NS_FAILED(result)) return result; + if (childNodes) { + childNodes->GetLength(&mOffset); + } + else + { + nsCOMPtr leftNodeAsText; + leftNodeAsText = do_QueryInterface(mLeftNode); + if (leftNodeAsText) { + leftNodeAsText->GetLength(&mOffset); } } + result = nsEditor::JoinNodesImpl(mRightNode, mLeftNode, mParent, PR_FALSE); + if (NS_SUCCEEDED(result)) + { + if (gNoisy) { printf(" left node = %p removed\n", mLeftNode.get()); } + nsCOMPtrselection; + result = mEditor->GetSelection(getter_AddRefs(selection)); + if (NS_FAILED(result)) return result; + if (!selection) return NS_ERROR_NULL_POINTER; + selection->Collapse(mRightNode, mOffset); + } + } + else + { + NS_ASSERTION(PR_FALSE, "2 nodes do not have same parent"); + return NS_ERROR_INVALID_ARG; } return result; } @@ -110,9 +112,7 @@ NS_IMETHODIMP JoinElementTxn::Undo(void) { if (gNoisy) { printf("%p Undo Join, right node = %p\n", this, mRightNode.get()); } NS_ASSERTION(mRightNode && mLeftNode && mParent, "bad state"); - if (!mRightNode || !mLeftNode || !mParent) { - return NS_ERROR_NOT_INITIALIZED; - } + if (!mRightNode || !mLeftNode || !mParent) { return NS_ERROR_NOT_INITIALIZED; } nsresult result; nsCOMPtrresultNode; // first, massage the existing node so it is in its post-split state diff --git a/editor/base/SplitElementTxn.cpp b/editor/base/SplitElementTxn.cpp index 179c1231f233..8ee8bec46284 100644 --- a/editor/base/SplitElementTxn.cpp +++ b/editor/base/SplitElementTxn.cpp @@ -39,6 +39,9 @@ NS_IMETHODIMP SplitElementTxn::Init(nsIEditor *aEditor, nsIDOMNode *aNode, PRInt32 aOffset) { + NS_ASSERTION(aEditor && aNode, "bad args"); + if (!aEditor || !aNode) { return NS_ERROR_NOT_INITIALIZED; } + mEditor = aEditor; mExistingRightNode = do_QueryInterface(aNode); mOffset = aOffset; @@ -52,36 +55,33 @@ SplitElementTxn::~SplitElementTxn() NS_IMETHODIMP SplitElementTxn::Do(void) { if (gNoisy) { printf("%p Do Split of node %p offset %d\n", this, mExistingRightNode.get(), mOffset); } - NS_ASSERTION(mExistingRightNode, "bad state"); - if (!mExistingRightNode) { - return NS_ERROR_NOT_INITIALIZED; - } + NS_ASSERTION(mExistingRightNode && mEditor, "bad state"); + if (!mExistingRightNode || !mEditor) { return NS_ERROR_NOT_INITIALIZED; } + // create a new node nsresult result = mExistingRightNode->CloneNode(PR_FALSE, getter_AddRefs(mNewLeftNode)); NS_ASSERTION(((NS_SUCCEEDED(result)) && (mNewLeftNode)), "could not create element."); + if (NS_FAILED(result)) return result; + if (!mNewLeftNode) return NS_ERROR_NULL_POINTER; - if ((NS_SUCCEEDED(result)) && (mNewLeftNode)) + if (gNoisy) { printf(" created left node = %p\n", mNewLeftNode.get()); } + // get the parent node + result = mExistingRightNode->GetParentNode(getter_AddRefs(mParent)); + if (NS_FAILED(result)) return result; + if (!mParent) return NS_ERROR_NULL_POINTER; + + // insert the new node + result = nsEditor::SplitNodeImpl(mExistingRightNode, mOffset, mNewLeftNode, mParent); + if (NS_SUCCEEDED(result) && mNewLeftNode) { - if (gNoisy) { printf(" created left node = %p\n", mNewLeftNode.get()); } - // get the parent node - result = mExistingRightNode->GetParentNode(getter_AddRefs(mParent)); - // insert the new node - if ((NS_SUCCEEDED(result)) && (mParent)) - { - result = nsEditor::SplitNodeImpl(mExistingRightNode, mOffset, mNewLeftNode, mParent); - if (NS_SUCCEEDED(result) && mNewLeftNode) - { - nsCOMPtrselection; - mEditor->GetSelection(getter_AddRefs(selection)); - if (selection) - { - selection->Collapse(mNewLeftNode, mOffset); - } - } - else { - result = NS_ERROR_NOT_IMPLEMENTED; - } - } + nsCOMPtrselection; + mEditor->GetSelection(getter_AddRefs(selection)); + if (NS_FAILED(result)) return result; + if (!selection) return NS_ERROR_NULL_POINTER; + result = selection->Collapse(mNewLeftNode, mOffset); + } + else { + result = NS_ERROR_NOT_IMPLEMENTED; } return result; } @@ -92,8 +92,8 @@ NS_IMETHODIMP SplitElementTxn::Undo(void) printf("%p Undo Split of existing node %p and new node %p offset %d\n", this, mExistingRightNode.get(), mNewLeftNode.get(), mOffset); } - NS_ASSERTION(mExistingRightNode && mNewLeftNode && mParent, "bad state"); - if (!mExistingRightNode || !mNewLeftNode || !mParent) { + NS_ASSERTION(mEditor && mExistingRightNode && mNewLeftNode && mParent, "bad state"); + if (!mEditor || !mExistingRightNode || !mNewLeftNode || !mParent) { return NS_ERROR_NOT_INITIALIZED; } @@ -110,10 +110,9 @@ NS_IMETHODIMP SplitElementTxn::Undo(void) if (gNoisy) { printf(" left node = %p removed\n", mNewLeftNode.get()); } nsCOMPtrselection; mEditor->GetSelection(getter_AddRefs(selection)); - if (selection) - { - selection->Collapse(mExistingRightNode, mOffset); - } + if (NS_FAILED(result)) return result; + if (!selection) return NS_ERROR_NULL_POINTER; + result = selection->Collapse(mExistingRightNode, mOffset); } else { result = NS_ERROR_NOT_IMPLEMENTED; @@ -126,8 +125,8 @@ NS_IMETHODIMP SplitElementTxn::Undo(void) */ NS_IMETHODIMP SplitElementTxn::Redo(void) { - NS_ASSERTION(mExistingRightNode && mNewLeftNode && mParent, "bad state"); - if (!mExistingRightNode || !mNewLeftNode || !mParent) { + NS_ASSERTION(mEditor && mExistingRightNode && mNewLeftNode && mParent, "bad state"); + if (!mEditor || !mExistingRightNode || !mNewLeftNode || !mParent) { return NS_ERROR_NOT_INITIALIZED; } if (gNoisy) { @@ -146,7 +145,7 @@ NS_IMETHODIMP SplitElementTxn::Redo(void) if (gNoisy) { printf("** after delete of text in right text node %p offset %d\n", rightNodeAsText.get(), mOffset); - if (gNoisy) {mEditor->DebugDumpContent(); } // DEBUG + mEditor->DebugDumpContent(); // DEBUG } } else diff --git a/editor/base/nsEditor.cpp b/editor/base/nsEditor.cpp index 01adf94ad49d..e69eca6ff05b 100644 --- a/editor/base/nsEditor.cpp +++ b/editor/base/nsEditor.cpp @@ -239,6 +239,7 @@ nsEditor::Init(nsIDOMDocument *aDoc, nsIPresShell* aPresShell, PRUint32 aFlags) // disable links nsCOMPtr context; mPresShell->GetPresContext(getter_AddRefs(context)); + if (!context) return NS_ERROR_NULL_POINTER; context->SetLinkHandler(0); // Set up the DTD @@ -252,9 +253,9 @@ nsEditor::Init(nsIDOMDocument *aDoc, nsIPresShell* aPresShell, PRUint32 aFlags) if (!mEditProperty) {return NS_ERROR_NULL_POINTER;} mPresShell->GetViewManager(&mViewManager); - if (mViewManager){ - mViewManager->Release(); //we want a weak link - } + if (!mViewManager) {return NS_ERROR_NULL_POINTER;} + mViewManager->Release(); //we want a weak link + mPresShell->SetDisplayNonTextSelection(PR_TRUE);//we want to see all the selection reflected to user mUpdateCount=0; InsertTextTxn::ClassInit(); @@ -267,22 +268,25 @@ nsEditor::Init(nsIDOMDocument *aDoc, nsIPresShell* aPresShell, PRUint32 aFlags) mIMEBufferLength = 0; /* Show the caret */ + // XXX: I suppose it's legal to fail to get a caret, so don't propogate the + // result of GetCaret nsCOMPtr caret; if (NS_SUCCEEDED(mPresShell->GetCaret(getter_AddRefs(caret))) && caret) { caret->SetCaretVisible(PR_TRUE); caret->SetCaretReadOnly(PR_FALSE); } + // NOTE: We don't fail if we can't get prefs or string bundles // since we could still be used as the text edit widget without prefs // Get the prefs service (Note: can't use nsCOMPtr for service pointers) - result = nsServiceManager::GetService(kPrefCID, - nsIPref::GetIID(), - (nsISupports**)&mPrefs); - if (NS_FAILED(result) || !mPrefs) + nsresult ignoredResult = nsServiceManager::GetService(kPrefCID, + nsIPref::GetIID(), + (nsISupports**)&mPrefs); + if (NS_FAILED(ignoredResult) || !mPrefs) { - printf("ERROR: Failed to get Prefs Service instance.\n"); + if (gNoisy) { printf("ERROR: Failed to get Prefs Service instance.\n");} } // TODO: Cache basic preferences? @@ -290,20 +294,21 @@ nsEditor::Init(nsIDOMDocument *aDoc, nsIPresShell* aPresShell, PRUint32 aFlags) // respond to while running nsIStringBundleService* service; - result = nsServiceManager::GetService(kStringBundleServiceCID, - nsIStringBundleService::GetIID(), - (nsISupports**)&service); + ignoredResult = nsServiceManager::GetService(kStringBundleServiceCID, + nsIStringBundleService::GetIID(), + (nsISupports**)&service); - if (NS_SUCCEEDED(result) && service) + if (NS_SUCCEEDED(ignoredResult) && service) { nsILocale* locale = nsnull; - result = service->CreateBundle(EDITOR_BUNDLE_URL, locale, - getter_AddRefs(mStringBundle)); + ignoredResult = service->CreateBundle(EDITOR_BUNDLE_URL, locale, + getter_AddRefs(mStringBundle)); // We don't need to keep service around once we created the bundle nsServiceManager::ReleaseService(kStringBundleServiceCID, service); } else { - printf("ERROR: Failed to get StringBundle Service instance.\n"); + if (gNoisy) printf("ERROR: Failed to get StringBundle Service instance.\n"); } + /* Example of getting a string: nsString value; @@ -374,8 +379,8 @@ NS_IMETHODIMP nsEditor::SaveDocument(PRBool saveAs, PRBool saveCopy) // get the document nsCOMPtr doc; rv = GetDocument(getter_AddRefs(doc)); - if (NS_FAILED(rv) || !doc) - return rv; + if (NS_FAILED(rv)) return rv; + if (!doc) return NS_ERROR_NULL_POINTER; nsCOMPtr diskDoc = do_QueryInterface(doc); if (!diskDoc) @@ -1238,7 +1243,6 @@ nsEditor::SetCompositionString(const nsString& aCompositionString, nsIPrivateTex return result; } - #ifdef XP_MAC #pragma mark - #pragma mark --- public nsEditor methods --- diff --git a/editor/base/nsEditor.h b/editor/base/nsEditor.h index 82420966c538..03e2b2b92b2b 100644 --- a/editor/base/nsEditor.h +++ b/editor/base/nsEditor.h @@ -387,7 +387,7 @@ public: * @param aNodeToKeep The node that will remain after the join. * @param aNodeToJoin The node that will be joined with aNodeToKeep. * There is no requirement that the two nodes be of the same type. - * @param aParent The parent of aExistingRightNode + * @param aParent The parent of aNodeToKeep * @param aNodeToKeepIsFirst if PR_TRUE, the contents|children of aNodeToKeep come before the * contents|children of aNodeToJoin, otherwise their positions are switched. */ diff --git a/editor/base/nsEditorEventListeners.cpp b/editor/base/nsEditorEventListeners.cpp index 7ac517663e53..72a44858842d 100644 --- a/editor/base/nsEditorEventListeners.cpp +++ b/editor/base/nsEditorEventListeners.cpp @@ -47,12 +47,18 @@ #include "nsIDragSession.h" #include "nsITransferable.h" #include "nsIFormatConverter.h" +#include "nsIContentIterator.h" +#include "nsIContent.h" +#include "nsLayoutCID.h" // Drag & Drop, Clipboard Support static NS_DEFINE_CID(kCDragServiceCID, NS_DRAGSERVICE_CID); static NS_DEFINE_CID(kCTransferableCID, NS_TRANSFERABLE_CID); static NS_DEFINE_IID(kCDataFlavorCID, NS_DATAFLAVOR_CID); -static NS_DEFINE_IID(kCXIFFormatConverterCID, NS_XIFFORMATCONVERTER_CID); +static NS_DEFINE_IID(kContentIteratorCID, NS_CONTENTITERATOR_CID); +static NS_DEFINE_CID(kCClipboardCID, NS_CLIPBOARD_CID); +static NS_DEFINE_IID(kCXIFConverterCID, NS_XIFFORMATCONVERTER_CID); + /* @@ -116,8 +122,7 @@ nsresult nsTextEditorKeyListener::KeyDown(nsIDOMEvent* aKeyEvent) { PRUint32 keyCode; - PRBool isShift; - PRBool ctrlKey; + PRBool isShift, ctrlKey, altKey, metaKey; nsCOMPtruiEvent; uiEvent = do_QueryInterface(aKeyEvent); @@ -126,87 +131,87 @@ nsTextEditorKeyListener::KeyDown(nsIDOMEvent* aKeyEvent) return NS_OK; } - if (NS_SUCCEEDED(uiEvent->GetKeyCode(&keyCode)) && - NS_SUCCEEDED(uiEvent->GetShiftKey(&isShift)) && - NS_SUCCEEDED(uiEvent->GetCtrlKey(&ctrlKey)) - ) { - PRBool keyProcessed; - ProcessShortCutKeys(aKeyEvent, keyProcessed); - if (PR_FALSE==keyProcessed) - { - switch(keyCode) { -// case nsIDOMUIEvent::VK_BACK: -// mEditor->DeleteSelection(nsIEditor::eDeleteLeft); -// break; + PRBool keyProcessed; + ProcessShortCutKeys(aKeyEvent, keyProcessed); + if (PR_FALSE==keyProcessed) + { + if (NS_SUCCEEDED(uiEvent->GetKeyCode(&keyCode)) && + NS_SUCCEEDED(uiEvent->GetShiftKey(&isShift)) && + NS_SUCCEEDED(uiEvent->GetCtrlKey(&ctrlKey)) && + NS_SUCCEEDED(uiEvent->GetAltKey(&altKey)) && + NS_SUCCEEDED(uiEvent->GetMetaKey(&metaKey))) + { + { + switch(keyCode) { + // case nsIDOMUIEvent::VK_BACK: + // mEditor->DeleteSelection(nsIEditor::eDeleteLeft); + // break; - case nsIDOMUIEvent::VK_DELETE: - mEditor->DeleteSelection(nsIEditor::eDeleteNext); - break; + case nsIDOMUIEvent::VK_DELETE: + mEditor->DeleteSelection(nsIEditor::eDeleteNext); + break; -// case nsIDOMUIEvent::VK_RETURN: - //case nsIDOMUIEvent::VK_ENTER: // why does this not exist? - // Need to implement creation of either

or
nodes. -// mEditor->InsertBreak(); -// break; + // case nsIDOMUIEvent::VK_RETURN: + //case nsIDOMUIEvent::VK_ENTER: // why does this not exist? + // Need to implement creation of either

or
nodes. + // mEditor->InsertBreak(); + // break; - case nsIDOMUIEvent::VK_LEFT: - case nsIDOMUIEvent::VK_RIGHT: - case nsIDOMUIEvent::VK_UP: - case nsIDOMUIEvent::VK_DOWN: - // these have already been handled in nsRangeList. Why are we getting them - // again here (Mac)? In switch to avoid putting in bogus chars. + case nsIDOMUIEvent::VK_LEFT: + case nsIDOMUIEvent::VK_RIGHT: + case nsIDOMUIEvent::VK_UP: + case nsIDOMUIEvent::VK_DOWN: + // these have already been handled in nsRangeList. Why are we getting them + // again here (Mac)? In switch to avoid putting in bogus chars. - //return NS_OK to allow page scrolling. - return NS_OK; - break; + //return NS_OK to allow page scrolling. + return NS_OK; + break; - case nsIDOMUIEvent::VK_HOME: - case nsIDOMUIEvent::VK_END: - // who handles these? -#if DEBUG - printf("Key not handled\n"); -#endif - return NS_OK; - break; + case nsIDOMUIEvent::VK_HOME: + case nsIDOMUIEvent::VK_END: + // who handles these? + #if DEBUG + printf("Key not handled\n"); + #endif + return NS_OK; + break; - case nsIDOMUIEvent::VK_PAGE_UP: - case nsIDOMUIEvent::VK_PAGE_DOWN: - //return NS_OK to allow page scrolling. - return NS_OK; - break; + case nsIDOMUIEvent::VK_PAGE_UP: + case nsIDOMUIEvent::VK_PAGE_DOWN: + //return NS_OK to allow page scrolling. + return NS_OK; + break; - case nsIDOMUIEvent::VK_TAB: - { - PRUint32 flags=0; - mEditor->GetFlags(&flags); - if (! (flags & nsIHTMLEditor::eEditorSingleLineMask)) - { - PRBool ctrlKey, altKey, metaKey; - uiEvent->GetCtrlKey(&ctrlKey); - uiEvent->GetAltKey(&altKey); - uiEvent->GetMetaKey(&metaKey); - if (metaKey || altKey) - return NS_OK; // don't consume - // else we insert the tab straight through - nsAutoString key; - key += keyCode; + case nsIDOMUIEvent::VK_TAB: + { + PRUint32 flags=0; + mEditor->GetFlags(&flags); + if (! (flags & nsIHTMLEditor::eEditorSingleLineMask)) + { + if (metaKey || altKey) + return NS_OK; // don't consume + // else we insert the tab straight through + nsAutoString key; + key += keyCode; - nsCOMPtr htmlEditor = do_QueryInterface(mEditor); - if (htmlEditor) - htmlEditor->InsertText(key); - return NS_ERROR_BASE; // this means "I handled the event, don't do default processing" - } - else { - return NS_OK; - } - break; - } + nsCOMPtr htmlEditor = do_QueryInterface(mEditor); + if (htmlEditor) + htmlEditor->InsertText(key); + return NS_ERROR_BASE; // this means "I handled the event, don't do default processing" + } + else { + return NS_OK; + } + break; + } - default: - return NS_OK; // this indicates that we have not handled the keyDown event in any way. - } - } - } + default: + return NS_OK; // this indicates that we have not handled the keyDown event in any way. + } + } + } + } return NS_ERROR_BASE; } @@ -238,19 +243,20 @@ nsTextEditorKeyListener::KeyPress(nsIDOMEvent* aKeyEvent) // eaiser // - PRBool ctrlKey, altKey, metaKey; - uiEvent->GetCtrlKey(&ctrlKey); - uiEvent->GetAltKey(&altKey); - uiEvent->GetMetaKey(&metaKey); - if (metaKey) - return NS_OK; // don't consume - - nsCOMPtr htmlEditor = do_QueryInterface(mEditor); - if (!htmlEditor) return NS_ERROR_NO_INTERFACE; - + PRBool ctrlKey, altKey, metaKey; + uiEvent->GetCtrlKey(&ctrlKey); + uiEvent->GetAltKey(&altKey); + uiEvent->GetMetaKey(&metaKey); + + if (metaKey) + return NS_OK; // don't consume + + nsCOMPtr htmlEditor = do_QueryInterface(mEditor); + if (!htmlEditor) return NS_ERROR_NO_INTERFACE; + if (NS_SUCCEEDED(uiEvent->GetKeyCode(&keyCode))) { - if (nsIDOMUIEvent::VK_BACK==keyCode) { + if (nsIDOMUIEvent::VK_BACK==keyCode) { mEditor->DeleteSelection(nsIEditor::eDeletePrevious); return NS_ERROR_BASE; // consumed } @@ -261,14 +267,14 @@ nsTextEditorKeyListener::KeyPress(nsIDOMEvent* aKeyEvent) } if ((PR_FALSE==altKey) && (PR_FALSE==ctrlKey) && - (NS_SUCCEEDED(uiEvent->GetCharCode(&character)))) + (NS_SUCCEEDED(uiEvent->GetCharCode(&character)))) { - if (nsIDOMUIEvent::VK_TAB==character) { - return NS_OK; // ignore tabs here, they're handled in keyDown if at all - } + if (nsIDOMUIEvent::VK_TAB==character) { + return NS_OK; // ignore tabs here, they're handled in keyDown if at all + } key += character; htmlEditor->InsertText(key); - } + } return NS_ERROR_BASE; // consumed @@ -843,6 +849,62 @@ nsTextEditorMouseListener::HandleEvent(nsIDOMEvent* aEvent) +// XXX: evil global functions, move them to proper support module + +nsresult +IsNodeInSelection(nsIDOMNode *aInNode, nsIDOMSelection *aInSelection, PRBool &aOutIsInSel) +{ + aOutIsInSel = PR_FALSE; // init out-param + if (!aInNode || !aInSelection) { return NS_ERROR_NULL_POINTER; } + + nsCOMPtriter; + nsresult result = nsComponentManager::CreateInstance(kContentIteratorCID, nsnull, + nsIContentIterator::GetIID(), + getter_AddRefs(iter)); + if (NS_FAILED(result)) { return result; } + if (!iter) { return NS_ERROR_OUT_OF_MEMORY; } + + nsCOMPtr enumerator; + result = aInSelection->GetEnumerator(getter_AddRefs(enumerator)); + if (NS_FAILED(result)) { return result; } + if (!enumerator) { return NS_ERROR_OUT_OF_MEMORY; } + + for (enumerator->First(); NS_OK!=enumerator->IsDone(); enumerator->Next()) + { + nsCOMPtr currentItem; + result = enumerator->CurrentItem(getter_AddRefs(currentItem)); + if ((NS_SUCCEEDED(result)) && (currentItem)) + { + nsCOMPtr range( do_QueryInterface(currentItem) ); + + iter->Init(range); + nsCOMPtr currentContent; + iter->CurrentNode(getter_AddRefs(currentContent)); + while (NS_COMFALSE == iter->IsDone()) + { + nsCOMPtrcurrentNode = do_QueryInterface(currentContent); + if (currentNode.get()==aInNode) + { + // if it's a start or end node, need to test whether the (x,y) + // of the event falls within the selection + + // talk to Mike + + aOutIsInSel = PR_TRUE; + return NS_OK; + } + /* do not check result here, and especially do not return the result code. + * we rely on iter->IsDone to tell us when the iteration is complete + */ + iter->Next(); + iter->CurrentNode(getter_AddRefs(currentContent)); + } + } + } + return NS_OK; +} + + nsresult nsTextEditorMouseListener::MouseDown(nsIDOMEvent* aMouseEvent) { @@ -856,49 +918,141 @@ nsTextEditorMouseListener::MouseDown(nsIDOMEvent* aMouseEvent) return NS_OK; } - // We only do anything special for middle-mouse click (paste); - // ignore all other events. + nsCOMPtr editor (do_QueryInterface(mEditor)); + if (!editor) { return NS_OK; } + + + // get the document + nsCOMPtrdomDoc; + editor->GetDocument(getter_AddRefs(domDoc)); + if (!domDoc) { return NS_OK; } + nsCOMPtrdoc = do_QueryInterface(domDoc); + if (!doc) { return NS_OK; } + PRUint16 button = 0; uiEvent->GetButton(&button); - if (button != 2) - return NS_OK; + // left button click might be a drag-start + if (1==button) + { +#ifndef EXPERIMENTAL_DRAG_CODE + return NS_OK; +#else + nsString XIFBuffer; + // get the DOM select here + nsCOMPtr sel; + editor->GetSelection(getter_AddRefs(sel)); + + // convert the DOMselection to XIF + if (sel) + { + // if we are within the selection, start the drag - nsCOMPtr editor (do_QueryInterface(mEditor)); - if (!editor) - return NS_ERROR_FAILURE; + nsCOMPtr target; + nsresult rv = aMouseEvent->GetTarget(getter_AddRefs(target)); + if (NS_FAILED(rv) || !target) { return NS_OK; } + PRBool isInSel; + rv = IsNodeInSelection(target, sel, isInSel); + if (NS_FAILED(rv) || PR_FALSE==isInSel) { return NS_OK; } + doc->CreateXIF(XIFBuffer, sel); - // Set the selection to the point under the mouse cursor: - nsCOMPtr mouseEvent (do_QueryInterface(aMouseEvent)); + // Get the Clipboard + nsIClipboard* clipboard; + rv = nsServiceManager::GetService(kCClipboardCID, + nsIClipboard::GetIID(), + (nsISupports **)&clipboard); + if (NS_OK == rv) + { + // Create a data flavor to tell the transferable + // that it is about to receive XIF + nsAutoString flavor(kXIFMime); - if (!mouseEvent) - return NS_ERROR_BASE; // NS_ERROR_BASE means "We did process the event". - nsCOMPtr parent; - if (!NS_SUCCEEDED(mouseEvent->GetRangeParent(getter_AddRefs(parent)))) - return NS_ERROR_BASE; // NS_ERROR_BASE means "We did process the event". - PRInt32 offset = 0; - if (!NS_SUCCEEDED(mouseEvent->GetRangeOffset(&offset))) - return NS_ERROR_BASE; // NS_ERROR_BASE means "We did process the event". + // Create a transferable for putting data on the Clipboard + nsCOMPtr trans; + rv = nsComponentManager::CreateInstance(kCTransferableCID, nsnull, + nsITransferable::GetIID(), + (void**) getter_AddRefs(trans)); + if (NS_OK == rv) { + // The data on the clipboard will be in "XIF" format + // so give the clipboard transferable a "XIFConverter" for + // converting from XIF to other formats + nsCOMPtr xifConverter; + rv = nsComponentManager::CreateInstance(kCXIFConverterCID, nsnull, + nsIFormatConverter::GetIID(), (void**) getter_AddRefs(xifConverter)); + if (NS_OK == rv) { + // Add the XIF DataFlavor to the transferable + // this tells the transferable that it can handle receiving the XIF format + trans->AddDataFlavor(&flavor); - nsCOMPtr selection; - if (NS_SUCCEEDED(editor->GetSelection(getter_AddRefs(selection)))) - (void)selection->Collapse(parent, offset); + // Add the converter for going from XIF to other formats + trans->SetConverter(xifConverter); - // If the ctrl key is pressed, we'll do paste as quotation. - // Would've used the alt key, but the kde wmgr treats alt-middle specially. - PRBool ctrlKey = PR_FALSE; - uiEvent->GetCtrlKey(&ctrlKey); + // Now add the XIF data to the transferable + // the transferable wants the number bytes for the data and since it is double byte + // we multiply by 2 + trans->SetTransferData(&flavor, XIFBuffer.ToNewUnicode(), XIFBuffer.Length()*2); - if (ctrlKey) - { - nsCOMPtr mailEditor = do_QueryInterface(mEditor); - if (mailEditor) - mailEditor->PasteAsQuotation(); + // Now invoke the drag session + nsIDragService* dragService; + nsresult rv = nsServiceManager::GetService(kCDragServiceCID, + nsIDragService::GetIID(), + (nsISupports **)&dragService); + if (NS_OK == rv) { + nsCOMPtr items; + NS_NewISupportsArray(getter_AddRefs(items)); + if ( items ) { + items->AppendElement(trans); + dragService->InvokeDragSession(items, nsnull, nsIDragService::DRAGDROP_ACTION_COPY | nsIDragService::DRAGDROP_ACTION_MOVE); + } + nsServiceManager::ReleaseService(kCDragServiceCID, dragService); + } + } + } + nsServiceManager::ReleaseService(kCClipboardCID, clipboard); + } + return NS_ERROR_BASE; // return that we've handled the event + } +#endif } - return editor->Paste(); + // middle-mouse click (paste); + else if (button == 2) + { + + // Set the selection to the point under the mouse cursor: + nsCOMPtr mouseEvent (do_QueryInterface(aMouseEvent)); + + if (!mouseEvent) + return NS_ERROR_BASE; // NS_ERROR_BASE means "We did process the event". + nsCOMPtr parent; + if (!NS_SUCCEEDED(mouseEvent->GetRangeParent(getter_AddRefs(parent)))) + return NS_ERROR_BASE; // NS_ERROR_BASE means "We did process the event". + PRInt32 offset = 0; + if (!NS_SUCCEEDED(mouseEvent->GetRangeOffset(&offset))) + return NS_ERROR_BASE; // NS_ERROR_BASE means "We did process the event". + + nsCOMPtr selection; + if (NS_SUCCEEDED(editor->GetSelection(getter_AddRefs(selection)))) + (void)selection->Collapse(parent, offset); + + // If the ctrl key is pressed, we'll do paste as quotation. + // Would've used the alt key, but the kde wmgr treats alt-middle specially. + PRBool ctrlKey = PR_FALSE; + uiEvent->GetCtrlKey(&ctrlKey); + + if (ctrlKey) + { + nsCOMPtr mailEditor = do_QueryInterface(mEditor); + if (mailEditor) + mailEditor->PasteAsQuotation(); + } + editor->Paste(); + return NS_ERROR_BASE; // NS_ERROR_BASE means "We did process the event". + } + return NS_OK; // did not process the event } + nsresult nsTextEditorMouseListener::MouseUp(nsIDOMEvent* aMouseEvent) { @@ -1425,9 +1579,6 @@ nsTextEditorFocusListener::HandleEvent(nsIDOMEvent* aEvent) nsresult nsTextEditorFocusListener::Focus(nsIDOMEvent* aEvent) { - // turn on selection and caret - if (mEditor) - { // turn on selection and caret if (mEditor) { @@ -1474,8 +1625,6 @@ nsTextEditorFocusListener::Focus(nsIDOMEvent* aEvent) } return NS_OK; } - return NS_OK; -} nsresult nsTextEditorFocusListener::Blur(nsIDOMEvent* aEvent) diff --git a/editor/base/nsHTMLEditor.cpp b/editor/base/nsHTMLEditor.cpp index a1ca754660f1..c003726c549e 100644 --- a/editor/base/nsHTMLEditor.cpp +++ b/editor/base/nsHTMLEditor.cpp @@ -102,7 +102,7 @@ static NS_DEFINE_CID(kCClipboardCID, NS_CLIPBOARD_CID); static NS_DEFINE_CID(kCTransferableCID, NS_TRANSFERABLE_CID); #ifdef NS_DEBUG -static PRBool gNoisy = PR_FALSE; +static PRBool gNoisy = PR_TRUE; #else static const PRBool gNoisy = PR_FALSE; #endif @@ -164,7 +164,8 @@ nsHTMLEditor::~nsHTMLEditor() //the autopointers will clear themselves up. //but we need to also remove the listeners or we have a leak nsCOMPtrselection; - nsresult result = nsEditor::GetSelection(getter_AddRefs(selection)); + nsresult result = GetSelection(getter_AddRefs(selection)); + // if we don't get the selection, just skip this if (NS_SUCCEEDED(result) && selection) { nsCOMPtrlistener; @@ -255,7 +256,7 @@ NS_IMETHODIMP nsHTMLEditor::Init(nsIDOMDocument *aDoc, nsresult result = NS_ERROR_NULL_POINTER; // Init the base editor result = nsEditor::Init(aDoc, aPresShell, aFlags); - if (NS_OK != result) { return result; } + if (NS_FAILED(result)) { return result; } // init the type-in state mTypeInState = new TypeInState(); @@ -263,8 +264,8 @@ NS_IMETHODIMP nsHTMLEditor::Init(nsIDOMDocument *aDoc, NS_ADDREF(mTypeInState); nsCOMPtrselection; - result = nsEditor::GetSelection(getter_AddRefs(selection)); - if (NS_OK != result) { return result; } + result = GetSelection(getter_AddRefs(selection)); + if (NS_FAILED(result)) { return result; } if (selection) { nsCOMPtrlistener; @@ -279,22 +280,21 @@ NS_IMETHODIMP nsHTMLEditor::Init(nsIDOMDocument *aDoc, // get a key listener result = NS_NewEditorKeyListener(getter_AddRefs(mKeyListenerP), this); - if (NS_OK != result) { + if (NS_FAILED(result)) { HandleEventListenerError(); return result; } // get a mouse listener result = NS_NewEditorMouseListener(getter_AddRefs(mMouseListenerP), this); - if (NS_OK != result) { + if (NS_FAILED(result)) { HandleEventListenerError(); return result; } // get a text listener result = NS_NewEditorTextListener(getter_AddRefs(mTextListenerP),this); - if (NS_OK !=result) - { + if (NS_FAILED(result)) { #ifdef DEBUG_TAGUE printf("nsTextEditor.cpp: failed to get TextEvent Listener\n"); #endif @@ -304,8 +304,7 @@ printf("nsTextEditor.cpp: failed to get TextEvent Listener\n"); // get a composition listener result = NS_NewEditorCompositionListener(getter_AddRefs(mCompositionListenerP),this); - if (NS_OK!=result) - { + if (NS_FAILED(result)) { #ifdef DEBUG_TAGUE printf("nsTextEditor.cpp: failed to get TextEvent Listener\n"); #endif @@ -315,16 +314,14 @@ printf("nsTextEditor.cpp: failed to get TextEvent Listener\n"); // get a drag listener result = NS_NewEditorDragListener(getter_AddRefs(mDragListenerP), this); - if (NS_OK != result) - { + if (NS_FAILED(result)) { HandleEventListenerError(); - //return result; // XXX: why is this return commented out? + return result; } // get a focus listener result = NS_NewEditorFocusListener(getter_AddRefs(mFocusListenerP), this); - if (NS_OK != result) - { + if (NS_FAILED(result)) { HandleEventListenerError(); return result; } @@ -332,8 +329,7 @@ printf("nsTextEditor.cpp: failed to get TextEvent Listener\n"); // get the DOM event receiver nsCOMPtr erP; result = aDoc->QueryInterface(nsIDOMEventReceiver::GetIID(), getter_AddRefs(erP)); - if (!NS_SUCCEEDED(result)) - { + if (NS_FAILED(result)) { HandleEventListenerError(); return result; } @@ -341,16 +337,35 @@ printf("nsTextEditor.cpp: failed to get TextEvent Listener\n"); // register the event listeners with the DOM event reveiver result = erP->AddEventListenerByIID(mKeyListenerP, nsIDOMKeyListener::GetIID()); NS_ASSERTION(NS_SUCCEEDED(result), "failed to register key listener"); - result = erP->AddEventListenerByIID(mMouseListenerP, nsIDOMMouseListener::GetIID()); - NS_ASSERTION(NS_SUCCEEDED(result), "failed to register mouse listener"); - result = erP->AddEventListenerByIID(mFocusListenerP, nsIDOMFocusListener::GetIID()); - NS_ASSERTION(NS_SUCCEEDED(result), "failed to register focus listener"); - result = erP->AddEventListenerByIID(mTextListenerP, nsIDOMTextListener::GetIID()); - NS_ASSERTION(NS_SUCCEEDED(result), "failed to register text listener"); - result = erP->AddEventListenerByIID(mCompositionListenerP, nsIDOMCompositionListener::GetIID()); - NS_ASSERTION(NS_SUCCEEDED(result), "failed to register composition listener"); - result = erP->AddEventListenerByIID(mDragListenerP, nsIDOMDragListener::GetIID()); - NS_ASSERTION(NS_SUCCEEDED(result), "failed to register drag listener"); + if (NS_SUCCEEDED(result)) + { + result = erP->AddEventListenerByIID(mMouseListenerP, nsIDOMMouseListener::GetIID()); + NS_ASSERTION(NS_SUCCEEDED(result), "failed to register mouse listener"); + if (NS_SUCCEEDED(result)) + { + result = erP->AddEventListenerByIID(mFocusListenerP, nsIDOMFocusListener::GetIID()); + NS_ASSERTION(NS_SUCCEEDED(result), "failed to register focus listener"); + if (NS_SUCCEEDED(result)) + { + result = erP->AddEventListenerByIID(mTextListenerP, nsIDOMTextListener::GetIID()); + NS_ASSERTION(NS_SUCCEEDED(result), "failed to register text listener"); + if (NS_SUCCEEDED(result)) + { + result = erP->AddEventListenerByIID(mCompositionListenerP, nsIDOMCompositionListener::GetIID()); + NS_ASSERTION(NS_SUCCEEDED(result), "failed to register composition listener"); + if (NS_SUCCEEDED(result)) + { + result = erP->AddEventListenerByIID(mDragListenerP, nsIDOMDragListener::GetIID()); + NS_ASSERTION(NS_SUCCEEDED(result), "failed to register drag listener"); + } + } + } + } + } + if (NS_FAILED(result)) { + HandleEventListenerError(); + return result; + } result = NS_OK; EnableUndo(PR_TRUE); @@ -418,109 +433,110 @@ NS_IMETHODIMP nsHTMLEditor::SetInlineProperty(nsIAtom *aProperty, nsresult result=NS_ERROR_NOT_INITIALIZED; nsCOMPtrselection; - result = nsEditor::GetSelection(getter_AddRefs(selection)); - if ((NS_SUCCEEDED(result)) && selection) + result = GetSelection(getter_AddRefs(selection)); + if (NS_FAILED(result)) return result; + if (!selection) return NS_ERROR_NULL_POINTER; + PRBool cancel; + nsTextRulesInfo ruleInfo(nsTextEditRules::kSetTextProperty); + result = mRules->WillDoAction(selection, &ruleInfo, &cancel); + if ((PR_FALSE==cancel) && (NS_SUCCEEDED(result))) { - PRBool cancel; - nsTextRulesInfo ruleInfo(nsTextEditRules::kSetTextProperty); - result = mRules->WillDoAction(selection, &ruleInfo, &cancel); - if ((PR_FALSE==cancel) && (NS_SUCCEEDED(result))) + PRBool isCollapsed; + selection->GetIsCollapsed(&isCollapsed); + if (PR_TRUE==isCollapsed) { - PRBool isCollapsed; - selection->GetIsCollapsed(&isCollapsed); - if (PR_TRUE==isCollapsed) - { - // manipulating text attributes on a collapsed selection only sets state for the next text insertion - SetTypeInStateForProperty(*mTypeInState, aProperty, aAttribute, aValue); + // manipulating text attributes on a collapsed selection only sets state for the next text insertion + SetTypeInStateForProperty(*mTypeInState, aProperty, aAttribute, aValue); + } + else + { + // set the text property for all selected ranges + nsEditor::BeginTransaction(); + nsCOMPtr enumerator; + result = selection->GetEnumerator(getter_AddRefs(enumerator)); + if (NS_FAILED(result)) return result; + if (!enumerator) return NS_ERROR_NULL_POINTER; + + enumerator->First(); + nsCOMPtr currentItem; + result = enumerator->CurrentItem(getter_AddRefs(currentItem)); + if (NS_FAILED(result)) return result; + if (!currentItem) return NS_ERROR_NULL_POINTER; + + nsCOMPtr range( do_QueryInterface(currentItem) ); + nsCOMPtrcommonParent; + result = range->GetCommonParent(getter_AddRefs(commonParent)); + if (NS_FAILED(result)) return result; + if (!commonParent) return NS_ERROR_NULL_POINTER; + + PRInt32 startOffset, endOffset; + range->GetStartOffset(&startOffset); + range->GetEndOffset(&endOffset); + nsCOMPtr startParent; nsCOMPtr endParent; + range->GetStartParent(getter_AddRefs(startParent)); + range->GetEndParent(getter_AddRefs(endParent)); + PRBool startIsText = IsTextNode(startParent); + PRBool endIsText = IsTextNode(endParent); + if ((PR_TRUE==startIsText) && (PR_TRUE==endIsText) && + (startParent.get()==endParent.get())) + { // the range is entirely contained within a single text node + // commonParent==aStartParent, so get the "real" parent of the selection + startParent->GetParentNode(getter_AddRefs(commonParent)); + result = SetTextPropertiesForNode(startParent, commonParent, + startOffset, endOffset, + aProperty, aAttribute, aValue); } else { - // set the text property for all selected ranges - nsEditor::BeginTransaction(); - nsCOMPtr enumerator; - result = selection->GetEnumerator(getter_AddRefs(enumerator)); - if (NS_SUCCEEDED(result) && enumerator) + nsCOMPtr startGrandParent; + result = startParent->GetParentNode(getter_AddRefs(startGrandParent)); + if (NS_FAILED(result)) return result; + if (!startGrandParent) return NS_ERROR_NULL_POINTER; + nsCOMPtr endGrandParent; + result = endParent->GetParentNode(getter_AddRefs(endGrandParent)); + if (NS_FAILED(result)) return result; + if (!endGrandParent) return NS_ERROR_NULL_POINTER; + + PRBool canCollapseStyleNode = PR_FALSE; + if ((PR_TRUE==startIsText) && (PR_TRUE==endIsText) && + endGrandParent.get()==startGrandParent.get()) { - enumerator->First(); - nsCOMPtr currentItem; - result = enumerator->CurrentItem(getter_AddRefs(currentItem)); - if ((NS_SUCCEEDED(result)) && (currentItem)) - { - nsCOMPtr range( do_QueryInterface(currentItem) ); - nsCOMPtrcommonParent; - result = range->GetCommonParent(getter_AddRefs(commonParent)); - if ((NS_SUCCEEDED(result)) && commonParent) - { - PRInt32 startOffset, endOffset; - range->GetStartOffset(&startOffset); - range->GetEndOffset(&endOffset); - nsCOMPtr startParent; nsCOMPtr endParent; - range->GetStartParent(getter_AddRefs(startParent)); - range->GetEndParent(getter_AddRefs(endParent)); - PRBool startIsText = IsTextNode(startParent); - PRBool endIsText = IsTextNode(endParent); - if ((PR_TRUE==startIsText) && (PR_TRUE==endIsText) && - (startParent.get()==endParent.get())) - { // the range is entirely contained within a single text node - // commonParent==aStartParent, so get the "real" parent of the selection - startParent->GetParentNode(getter_AddRefs(commonParent)); - result = SetTextPropertiesForNode(startParent, commonParent, - startOffset, endOffset, - aProperty, aAttribute, aValue); - } - else - { - nsCOMPtr startGrandParent; - startParent->GetParentNode(getter_AddRefs(startGrandParent)); - nsCOMPtr endGrandParent; - endParent->GetParentNode(getter_AddRefs(endGrandParent)); - if (NS_SUCCEEDED(result)) - { - PRBool canCollapseStyleNode = PR_FALSE; - if ((PR_TRUE==startIsText) && (PR_TRUE==endIsText) && - endGrandParent.get()==startGrandParent.get()) - { - result = IntermediateNodesAreInline(range, startParent, startOffset, - endParent, endOffset, - canCollapseStyleNode); - } - if (NS_SUCCEEDED(result)) - { - if (PR_TRUE==canCollapseStyleNode) - { // the range is between 2 nodes that have a common (immediate) grandparent, - // and any intermediate nodes are just inline style nodes - result = SetTextPropertiesForNodesWithSameParent(startParent,startOffset, - endParent, endOffset, - commonParent, - aProperty, aAttribute, aValue); - } - else - { // the range is between 2 nodes that have no simple relationship - result = SetTextPropertiesForNodeWithDifferentParents(range, - startParent,startOffset, - endParent, endOffset, - commonParent, - aProperty, aAttribute, aValue); - } - } - } - } - if (NS_SUCCEEDED(result)) - { // compute a range for the selection - // don't want to actually do anything with selection, because - // we are still iterating through it. Just want to create and remember - // an nsIDOMRange, and later add the range to the selection after clearing it. - // XXX: I'm blocked here because nsIDOMSelection doesn't provide a mechanism - // for setting a compound selection yet. - } - } + result = IntermediateNodesAreInline(range, startParent, startOffset, + endParent, endOffset, + canCollapseStyleNode); + } + if (NS_SUCCEEDED(result)) + { + if (PR_TRUE==canCollapseStyleNode) + { // the range is between 2 nodes that have a common (immediate) grandparent, + // and any intermediate nodes are just inline style nodes + result = SetTextPropertiesForNodesWithSameParent(startParent,startOffset, + endParent, endOffset, + commonParent, + aProperty, aAttribute, aValue); + } + else + { // the range is between 2 nodes that have no simple relationship + result = SetTextPropertiesForNodeWithDifferentParents(range, + startParent,startOffset, + endParent, endOffset, + commonParent, + aProperty, aAttribute, aValue); } } - nsEditor::EndTransaction(); } - // post-process - result = mRules->DidDoAction(selection, &ruleInfo, result); + if (NS_SUCCEEDED(result)) + { // compute a range for the selection + // don't want to actually do anything with selection, because + // we are still iterating through it. Just want to create and remember + // an nsIDOMRange, and later add the range to the selection after clearing it. + // XXX: I'm blocked here because nsIDOMSelection doesn't provide a mechanism + // for setting a compound selection yet. + } + nsEditor::EndTransaction(); } + // post-process + result = mRules->DidDoAction(selection, &ruleInfo, result); } if (gNoisy) {DebugDumpContent(); } // DEBUG if (gNoisy) @@ -535,9 +551,9 @@ NS_IMETHODIMP nsHTMLEditor::SetInlineProperty(nsIAtom *aProperty, } NS_IMETHODIMP nsHTMLEditor::GetInlineProperty(nsIAtom *aProperty, - const nsString *aAttribute, - const nsString *aValue, - PRBool &aFirst, PRBool &aAny, PRBool &aAll) + const nsString *aAttribute, + const nsString *aValue, + PRBool &aFirst, PRBool &aAny, PRBool &aAll) { if (!aProperty) return NS_ERROR_NULL_POINTER; @@ -551,100 +567,101 @@ NS_IMETHODIMP nsHTMLEditor::GetInlineProperty(nsIAtom *aProperty, delete [] propCString; } */ - nsresult result=NS_ERROR_NOT_INITIALIZED; + nsresult result; aAny=PR_FALSE; aAll=PR_TRUE; aFirst=PR_FALSE; PRBool first=PR_TRUE; nsCOMPtrselection; - result = nsEditor::GetSelection(getter_AddRefs(selection)); - if ((NS_SUCCEEDED(result)) && selection) + result = GetSelection(getter_AddRefs(selection)); + if (NS_FAILED(result)) return result; + if (!selection) return NS_ERROR_NULL_POINTER; + + PRBool isCollapsed; + selection->GetIsCollapsed(&isCollapsed); + nsCOMPtr enumerator; + result = selection->GetEnumerator(getter_AddRefs(enumerator)); + if (NS_FAILED(result)) return result; + if (!enumerator) return NS_ERROR_NULL_POINTER; + + enumerator->First(); + nsCOMPtr currentItem; + result = enumerator->CurrentItem(getter_AddRefs(currentItem)); + // XXX: should be a while loop, to get each separate range + // XXX: ERROR_HANDLING can currentItem be null? + if ((NS_SUCCEEDED(result)) && currentItem) { - PRBool isCollapsed; - selection->GetIsCollapsed(&isCollapsed); - nsCOMPtr enumerator; - result = selection->GetEnumerator(getter_AddRefs(enumerator)); - if (NS_SUCCEEDED(result) && enumerator) + PRBool firstNodeInRange = PR_TRUE; // for each range, set a flag + nsCOMPtr range( do_QueryInterface(currentItem) ); + nsCOMPtr iter; + result = nsComponentManager::CreateInstance(kCContentIteratorCID, nsnull, + nsIContentIterator::GetIID(), + getter_AddRefs(iter)); + if (NS_FAILED(result)) return result; + if (!iter) return NS_ERROR_NULL_POINTER; + + iter->Init(range); + nsCOMPtr content; + result = iter->CurrentNode(getter_AddRefs(content)); + while (NS_COMFALSE == iter->IsDone()) { - enumerator->First(); - nsCOMPtr currentItem; - result = enumerator->CurrentItem(getter_AddRefs(currentItem)); - // XXX: should be a while loop, to get each separate range - if ((NS_SUCCEEDED(result)) && currentItem) + //if (gNoisy) { printf(" checking node %p\n", content.get()); } + nsCOMPtrtext; + text = do_QueryInterface(content); + PRBool skipNode = PR_FALSE; + if (text) { - PRBool firstNodeInRange = PR_TRUE; // for each range, set a flag - nsCOMPtr range( do_QueryInterface(currentItem) ); - nsCOMPtr iter; - result = nsComponentManager::CreateInstance(kCContentIteratorCID, nsnull, - nsIContentIterator::GetIID(), - getter_AddRefs(iter)); - if ((NS_SUCCEEDED(result)) && iter) + if (PR_FALSE==isCollapsed && PR_TRUE==first && PR_TRUE==firstNodeInRange) { - iter->Init(range); - nsCOMPtr content; - result = iter->CurrentNode(getter_AddRefs(content)); - while (NS_COMFALSE == iter->IsDone()) + firstNodeInRange = PR_FALSE; + PRInt32 startOffset; + range->GetStartOffset(&startOffset); + PRUint32 count; + text->GetLength(&count); + if (startOffset==(PRInt32)count) { - //if (gNoisy) { printf(" checking node %p\n", content.get()); } - nsCOMPtrtext; - text = do_QueryInterface(content); - PRBool skipNode = PR_FALSE; - if (text) - { - if (PR_FALSE==isCollapsed && PR_TRUE==first && PR_TRUE==firstNodeInRange) - { - firstNodeInRange = PR_FALSE; - PRInt32 startOffset; - range->GetStartOffset(&startOffset); - PRUint32 count; - text->GetLength(&count); - if (startOffset==(PRInt32)count) - { - //if (gNoisy) { printf(" skipping node %p\n", content.get()); } - skipNode = PR_TRUE; - } - } - } - else - { // handle non-text leaf nodes here - PRBool canContainChildren; - content->CanContainChildren(canContainChildren); - if (PR_TRUE==canContainChildren) - { - //if (gNoisy) { printf(" skipping non-leaf node %p\n", content.get()); } - skipNode = PR_TRUE; - } - else { - //if (gNoisy) { printf(" testing non-text leaf node %p\n", content.get()); } - } - } - if (PR_FALSE==skipNode) - { - nsCOMPtrnode; - node = do_QueryInterface(content); - if (node) - { - PRBool isSet; - nsCOMPtrresultNode; - IsTextPropertySetByContent(node, aProperty, aAttribute, aValue, isSet, getter_AddRefs(resultNode)); - if (PR_TRUE==first) - { - aFirst = isSet; - first = PR_FALSE; - } - if (PR_TRUE==isSet) { - aAny = PR_TRUE; - } - else { - aAll = PR_FALSE; - } - } - } - iter->Next(); - iter->CurrentNode(getter_AddRefs(content)); + //if (gNoisy) { printf(" skipping node %p\n", content.get()); } + skipNode = PR_TRUE; } } } + else + { // handle non-text leaf nodes here + PRBool canContainChildren; + content->CanContainChildren(canContainChildren); + if (PR_TRUE==canContainChildren) + { + //if (gNoisy) { printf(" skipping non-leaf node %p\n", content.get()); } + skipNode = PR_TRUE; + } + else { + //if (gNoisy) { printf(" testing non-text leaf node %p\n", content.get()); } + } + } + if (PR_FALSE==skipNode) + { + nsCOMPtrnode; + node = do_QueryInterface(content); + if (node) + { + PRBool isSet; + nsCOMPtrresultNode; + IsTextPropertySetByContent(node, aProperty, aAttribute, aValue, isSet, getter_AddRefs(resultNode)); + if (PR_TRUE==first) + { + aFirst = isSet; + first = PR_FALSE; + } + if (PR_TRUE==isSet) { + aAny = PR_TRUE; + } + else { + aAll = PR_FALSE; + } + } + } + iter->Next(); + iter->CurrentNode(getter_AddRefs(content)); } } if (PR_FALSE==aAny) { // make sure that if none of the selection is set, we don't report all is set @@ -664,99 +681,113 @@ NS_IMETHODIMP nsHTMLEditor::RemoveInlineProperty(nsIAtom *aProperty, const nsStr nsAutoString propString; aProperty->ToString(propString); char *propCString = propString.ToNewCString(); - if (gNoisy) { printf("---------- start nsTextEditor::RemoveTextProperty %s ----------\n", propCString); } + if (gNoisy) { printf("---------- start nsTextEditor::RemoveInlineProperty %s ----------\n", propCString); } delete [] propCString; } - nsresult result=NS_ERROR_NOT_INITIALIZED; + nsresult result; nsCOMPtrselection; - result = nsEditor::GetSelection(getter_AddRefs(selection)); - if ((NS_SUCCEEDED(result)) && selection) + result = GetSelection(getter_AddRefs(selection)); + if (NS_FAILED(result)) return result; + if (!selection) return NS_ERROR_NULL_POINTER; + + PRBool cancel; + nsTextRulesInfo ruleInfo(nsTextEditRules::kRemoveTextProperty); + result = mRules->WillDoAction(selection, &ruleInfo, &cancel); + if (NS_FAILED(result)) return result; + if (PR_FALSE==cancel) { - PRBool cancel; - nsTextRulesInfo ruleInfo(nsTextEditRules::kRemoveTextProperty); - result = mRules->WillDoAction(selection, &ruleInfo, &cancel); - if ((PR_FALSE==cancel) && (NS_SUCCEEDED(result))) + PRBool isCollapsed; + selection->GetIsCollapsed(&isCollapsed); + if (PR_TRUE==isCollapsed) { - PRBool isCollapsed; - selection->GetIsCollapsed(&isCollapsed); - if (PR_TRUE==isCollapsed) - { - // manipulating text attributes on a collapsed selection only sets state for the next text insertion - SetTypeInStateForProperty(*mTypeInState, aProperty, aAttribute, nsnull); - } - else - { - // removing text properties can really shuffle text nodes around - // so we need to keep some extra state to restore a reasonable selection - // after we're done - nsCOMPtr parentForSelection; // selection's block parent - PRInt32 rangeStartOffset, rangeEndOffset; - GetTextSelectionOffsetsForRange(selection, getter_AddRefs(parentForSelection), - rangeStartOffset, rangeEndOffset); - nsEditor::BeginTransaction(); - nsCOMPtr startParent, endParent; - PRInt32 startOffset, endOffset; - nsCOMPtr enumerator; - result = selection->GetEnumerator(getter_AddRefs(enumerator)); - if (NS_SUCCEEDED(result) && enumerator) - { - enumerator->First(); - nsCOMPtrcurrentItem; - result = enumerator->CurrentItem(getter_AddRefs(currentItem)); - if ((NS_SUCCEEDED(result)) && (currentItem)) - { - nsCOMPtr range( do_QueryInterface(currentItem) ); - nsCOMPtrcommonParent; - result = range->GetCommonParent(getter_AddRefs(commonParent)); - if ((NS_SUCCEEDED(result)) && commonParent) - { - range->GetStartOffset(&startOffset); - range->GetEndOffset(&endOffset); - range->GetStartParent(getter_AddRefs(startParent)); - range->GetEndParent(getter_AddRefs(endParent)); - if (startParent.get()==endParent.get()) - { // the range is entirely contained within a single text node - // commonParent==aStartParent, so get the "real" parent of the selection - startParent->GetParentNode(getter_AddRefs(commonParent)); - result = RemoveTextPropertiesForNode(startParent, commonParent, - startOffset, endOffset, - aProperty, nsnull); - } - else - { - result = RemoveTextPropertiesForNodeWithDifferentParents(startParent,startOffset, - endParent, endOffset, - commonParent, - aProperty, nsnull); - } - if (NS_SUCCEEDED(result)) - { // compute a range for the selection - // don't want to actually do anything with selection, because - // we are still iterating through it. Just want to create and remember - // an nsIDOMRange, and later add the range to the selection after clearing it. - // XXX: I'm blocked here because nsIDOMSelection doesn't provide a mechanism - // for setting a compound selection yet. - } - } - } - } - nsEditor::EndTransaction(); - if (NS_SUCCEEDED(result)) - { - ResetTextSelectionForRange(parentForSelection, rangeStartOffset, rangeEndOffset, selection); - } - } - // post-process - result = mRules->DidDoAction(selection, &ruleInfo, result); + // manipulating text attributes on a collapsed selection only sets state for the next text insertion + SetTypeInStateForProperty(*mTypeInState, aProperty, aAttribute, nsnull); } + else + { + // removing text properties can really shuffle text nodes around + // so we need to keep some extra state to restore a reasonable selection + // after we're done + nsCOMPtr parentForSelection; // selection's block parent + PRInt32 rangeStartOffset, rangeEndOffset; + GetTextSelectionOffsetsForRange(selection, getter_AddRefs(parentForSelection), + rangeStartOffset, rangeEndOffset); + nsEditor::BeginTransaction(); + nsCOMPtr startParent, endParent; + PRInt32 startOffset, endOffset; + nsCOMPtr enumerator; + result = selection->GetEnumerator(getter_AddRefs(enumerator)); + if (NS_FAILED(result)) return result; + if (!enumerator) return NS_ERROR_NULL_POINTER; + + enumerator->First(); + nsCOMPtrcurrentItem; + result = enumerator->CurrentItem(getter_AddRefs(currentItem)); + if (NS_FAILED(result)) return result; + //XXX: should be a while loop to get all ranged in selection + if (currentItem) + { + nsCOMPtr range( do_QueryInterface(currentItem) ); + nsCOMPtrcommonParent; + result = range->GetCommonParent(getter_AddRefs(commonParent)); + if (NS_FAILED(result)) return result; + if (!commonParent) return NS_ERROR_NULL_POINTER; + + range->GetStartOffset(&startOffset); + range->GetEndOffset(&endOffset); + result = range->GetStartParent(getter_AddRefs(startParent)); + if (NS_FAILED(result)) return result; + if (!startParent) return NS_ERROR_NULL_POINTER; + result = range->GetEndParent(getter_AddRefs(endParent)); + if (NS_FAILED(result)) return result; + if (!endParent) return NS_ERROR_NULL_POINTER; + + if (startParent.get()==endParent.get()) + { // the range is entirely contained within a single text node + // commonParent==aStartParent, so get the "real" parent of the selection + startParent->GetParentNode(getter_AddRefs(commonParent)); + result = RemoveTextPropertiesForNode(startParent, commonParent, + startOffset, endOffset, + aProperty, nsnull); + } + else + { + result = RemoveTextPropertiesForNodeWithDifferentParents(startParent,startOffset, + endParent, endOffset, + commonParent, + aProperty, nsnull); + } + if (NS_FAILED(result)) return result; + + { // compute a range for the selection + // don't want to actually do anything with selection, because + // we are still iterating through it. Just want to create and remember + // an nsIDOMRange, and later add the range to the selection after clearing it. + // XXX: I'm blocked here because nsIDOMSelection doesn't provide a mechanism + // for setting a compound selection yet. + } + } + if (NS_SUCCEEDED(result)) + { + result = CollapseAdjacentTextNodes(selection); // we may have created wasteful consecutive text nodes. collapse them. + } + nsEditor::EndTransaction(); + if (NS_SUCCEEDED(result)) + { + // XXX: ERROR_HANDLING should get a result and validate it + ResetTextSelectionForRange(parentForSelection, rangeStartOffset, rangeEndOffset, selection); + } + } + // post-process + result = mRules->DidDoAction(selection, &ruleInfo, result); } if (gNoisy) { nsAutoString propString; aProperty->ToString(propString); char *propCString = propString.ToNewCString(); - if (gNoisy) { printf("---------- end nsTextEditor::RemoveTextProperty %s ----------\n", propCString); } + if (gNoisy) { printf("---------- end nsTextEditor::RemoveInlineProperty %s ----------\n", propCString); } delete [] propCString; } return result; @@ -773,7 +804,10 @@ NS_IMETHODIMP nsHTMLEditor::DeleteSelection(nsIEditor::ESelectionCollapseDirecti if (NS_FAILED(result)) { return result; } // pre-process - nsEditor::GetSelection(getter_AddRefs(selection)); + result = GetSelection(getter_AddRefs(selection)); + if (NS_FAILED(result)) return result; + if (!selection) return NS_ERROR_NULL_POINTER; + nsTextRulesInfo ruleInfo(nsTextEditRules::kDeleteSelection); ruleInfo.collapsedAction = aAction; result = mRules->WillDoAction(selection, &ruleInfo, &cancel); @@ -784,6 +818,7 @@ NS_IMETHODIMP nsHTMLEditor::DeleteSelection(nsIEditor::ESelectionCollapseDirecti result = mRules->DidDoAction(selection, &ruleInfo, result); } + // XXX: ERROR_HANDLING is there any reason to not consider this a serious error? nsresult endTxnResult = nsEditor::EndTransaction(); // don't return this result! NS_ASSERTION ((NS_SUCCEEDED(endTxnResult)), "bad end transaction result"); @@ -798,7 +833,9 @@ NS_IMETHODIMP nsHTMLEditor::InsertText(const nsString& aStringToInsert) PRBool cancel= PR_FALSE; // pre-process - nsEditor::GetSelection(getter_AddRefs(selection)); + nsresult result = GetSelection(getter_AddRefs(selection)); + if (NS_FAILED(result)) return result; + if (!selection) return NS_ERROR_NULL_POINTER; nsString resultString; PlaceholderTxn *placeholderTxn=nsnull; nsTextRulesInfo ruleInfo(nsTextEditRules::kInsertText); @@ -808,7 +845,7 @@ NS_IMETHODIMP nsHTMLEditor::InsertText(const nsString& aStringToInsert) ruleInfo.typeInState = *mTypeInState; ruleInfo.maxLength = mMaxTextLength; - nsresult result = mRules->WillDoAction(selection, &ruleInfo, &cancel); + result = mRules->WillDoAction(selection, &ruleInfo, &cancel); if ((PR_FALSE==cancel) && (NS_SUCCEEDED(result))) { result = InsertTextImpl(resultString); @@ -833,8 +870,8 @@ NS_IMETHODIMP nsHTMLEditor::InsertHTML(const nsString& aInputString) nsCOMPtrselection; res = GetSelection(getter_AddRefs(selection)); - if (NS_FAILED(res)) - return res; + if (NS_FAILED(res)) return res; + if (!selection) return NS_ERROR_NULL_POINTER; // Get the first range in the selection, for context: nsCOMPtr range; @@ -887,6 +924,7 @@ NS_IMETHODIMP nsHTMLEditor::InsertHTML(const nsString& aInputString) { nsCOMPtr parent; PRInt32 offset; + // XXX: ERROR_HANDLING error return codes are lost if (NS_SUCCEEDED(saverange->GetEndParent(getter_AddRefs(parent)))) if (NS_SUCCEEDED(saverange->GetEndOffset(&offset))) selection->Collapse(parent, offset); @@ -933,7 +971,10 @@ NS_IMETHODIMP nsHTMLEditor::InsertBreak() nsAutoEditBatch beginBatching(this); // pre-process - nsEditor::GetSelection(getter_AddRefs(selection)); + res = GetSelection(getter_AddRefs(selection)); + if (NS_FAILED(res)) return res; + if (!selection) return NS_ERROR_NULL_POINTER; + nsTextRulesInfo ruleInfo(nsHTMLEditRules::kInsertBreak); res = mRules->WillDoAction(selection, &ruleInfo, &cancel); if ((PR_FALSE==cancel) && (NS_SUCCEEDED(res))) @@ -942,12 +983,14 @@ NS_IMETHODIMP nsHTMLEditor::InsertBreak() nsCOMPtr newNode; nsAutoString tag("BR"); res = DeleteSelectionAndCreateNode(tag, getter_AddRefs(newNode)); - if (NS_SUCCEEDED(res) && newNode) + if (!newNode) res = NS_ERROR_NULL_POINTER; // don't return here, so DidDoAction is called + if (NS_SUCCEEDED(res)) { // set the selection to the new node nsCOMPtrparent; res = newNode->GetParentNode(getter_AddRefs(parent)); - if (NS_SUCCEEDED(res) && parent) + if (!parent) res = NS_ERROR_NULL_POINTER; // don't return here, so DidDoAction is called + if (NS_SUCCEEDED(res)) { PRInt32 offsetInParent=-1; // we use the -1 as a marker to see if we need to compute this or not nsCOMPtrnextNode; @@ -966,7 +1009,8 @@ NS_IMETHODIMP nsHTMLEditor::InsertBreak() else { nextNode = do_QueryInterface(newNode); } - res = nsEditor::GetSelection(getter_AddRefs(selection)); + res = GetSelection(getter_AddRefs(selection)); + if (!selection) res = NS_ERROR_NULL_POINTER; // don't return here, so DidDoAction is called if (NS_SUCCEEDED(res)) { if (-1==offsetInParent) @@ -974,12 +1018,12 @@ NS_IMETHODIMP nsHTMLEditor::InsertBreak() nextNode->GetParentNode(getter_AddRefs(parent)); res = GetChildOffset(nextNode, parent, offsetInParent); if (NS_SUCCEEDED(res)) { - selection->Collapse(parent, offsetInParent+1); // +1 to insert just after the break + res = selection->Collapse(parent, offsetInParent+1); // +1 to insert just after the break } } else { - selection->Collapse(nextNode, offsetInParent); + res = selection->Collapse(nextNode, offsetInParent); } } } @@ -1005,7 +1049,7 @@ nsHTMLEditor::InsertElement(nsIDOMElement* aElement, PRBool aDeleteSelection) //PRBool setCaretAfterElement = PR_TRUE; nsCOMPtrselection; - res = nsEditor::GetSelection(getter_AddRefs(selection)); + res = GetSelection(getter_AddRefs(selection)); if (!NS_SUCCEEDED(res) || !selection) return NS_ERROR_FAILURE; @@ -1039,9 +1083,11 @@ nsHTMLEditor::InsertElement(nsIDOMElement* aElement, PRBool aDeleteSelection) // TODO: Move this logic to a new method nsIDOMSelection::CollapseToStart()??? nsCOMPtr firstRange; res = selection->GetRangeAt(0, getter_AddRefs(firstRange)); + // XXX: ERROR_HANDLING can firstRange legally be null? if (NS_SUCCEEDED(res) && firstRange) { nsCOMPtr parent; + // XXX: ERROR_HANDLING bad XPCOM usage, should check for null parent separately res = firstRange->GetCommonParent(getter_AddRefs(parent)); if (NS_SUCCEEDED(res) && parent) { @@ -1059,6 +1105,7 @@ nsHTMLEditor::InsertElement(nsIDOMElement* aElement, PRBool aDeleteSelection) nsCOMPtr parentSelectedNode; PRInt32 offsetForInsert; res = selection->GetAnchorNode(getter_AddRefs(parentSelectedNode)); + // XXX: ERROR_HANDLING bad XPCOM usage if (NS_SUCCEEDED(res) && NS_SUCCEEDED(selection->GetAnchorOffset(&offsetForInsert)) && parentSelectedNode) { #ifdef DEBUG_cmanske @@ -1127,10 +1174,10 @@ nsHTMLEditor::InsertElement(nsIDOMElement* aElement, PRBool aDeleteSelection) return res; } - +// XXX: error handling in this routine needs to be cleaned up! NS_IMETHODIMP nsHTMLEditor::DeleteSelectionAndCreateNode(const nsString& aTag, - nsIDOMNode ** aNewNode) + nsIDOMNode ** aNewNode) { nsCOMPtr parentSelectedNode; PRInt32 offsetOfNewNode; @@ -1142,14 +1189,15 @@ nsHTMLEditor::DeleteSelectionAndCreateNode(const nsString& aTag, nsCOMPtr newNode; result = CreateNode(aTag, parentSelectedNode, offsetOfNewNode, getter_AddRefs(newNode)); - + // XXX: ERROR_HANDLING check result, and make sure aNewNode is set correctly in success/failure cases *aNewNode = newNode; // we want the selection to be just after the new node nsCOMPtr selection; result = GetSelection(getter_AddRefs(selection)); - if ((NS_SUCCEEDED(result)) && selection) - selection->Collapse(parentSelectedNode, offsetOfNewNode+1); + if (NS_FAILED(result)) return result; + if (!selection) return NS_ERROR_NULL_POINTER; + result = selection->Collapse(parentSelectedNode, offsetOfNewNode+1); return result; } @@ -1163,23 +1211,24 @@ nsHTMLEditor::SelectElement(nsIDOMElement* aElement) if (IsElementInBody(aElement)) { nsCOMPtr selection; - res = nsEditor::GetSelection(getter_AddRefs(selection)); - if (NS_SUCCEEDED(res) && selection) + res = GetSelection(getter_AddRefs(selection)); + if (NS_FAILED(res)) return res; + if (!selection) return NS_ERROR_NULL_POINTER; + nsCOMPtrparent; + res = aElement->GetParentNode(getter_AddRefs(parent)); + if (NS_SUCCEEDED(res) && parent) { - nsCOMPtrparent; - res = aElement->GetParentNode(getter_AddRefs(parent)); - if (NS_SUCCEEDED(res) && parent) - { - PRInt32 offsetInParent; - res = GetChildOffset(aElement, parent, offsetInParent); + PRInt32 offsetInParent; + res = GetChildOffset(aElement, parent, offsetInParent); - if (NS_SUCCEEDED(res)) - { - // Collapse selection to just before desired element, - selection->Collapse(parent, offsetInParent); - // then extend it to just after - selection->Extend(parent, offsetInParent+1); - } + if (NS_SUCCEEDED(res)) + { + // Collapse selection to just before desired element, + res = selection->Collapse(parent, offsetInParent); + if (NS_SUCCEEDED(res)) { + // then extend it to just after + res = selection->Extend(parent, offsetInParent+1); + } } } } @@ -1195,34 +1244,32 @@ nsHTMLEditor::SetCaretAfterElement(nsIDOMElement* aElement) if (aElement && IsElementInBody(aElement)) { nsCOMPtr selection; - res = nsEditor::GetSelection(getter_AddRefs(selection)); - if (NS_SUCCEEDED(res) && selection) + res = GetSelection(getter_AddRefs(selection)); + if (NS_FAILED(res)) return res; + if (!selection) return NS_ERROR_NULL_POINTER; + nsCOMPtrparent; + res = aElement->GetParentNode(getter_AddRefs(parent)); + if (NS_FAILED(res)) return res; + if (!parent) return NS_ERROR_NULL_POINTER; + PRInt32 offsetInParent; + res = GetChildOffset(aElement, parent, offsetInParent); + if (NS_SUCCEEDED(res)) { - nsCOMPtrparent; - res = aElement->GetParentNode(getter_AddRefs(parent)); - if (NS_SUCCEEDED(res) && parent) - { - PRInt32 offsetInParent; - res = GetChildOffset(aElement, parent, offsetInParent); - if (NS_SUCCEEDED(res)) - { - // Collapse selection to just after desired element, - selection->Collapse(parent, offsetInParent+1); + // Collapse selection to just after desired element, + res = selection->Collapse(parent, offsetInParent+1); #ifdef DEBUG_cmanske - { - nsAutoString name; - parent->GetNodeName(name); - printf("SetCaretAfterElement: Parent node: "); - wprintf(name.GetUnicode()); - printf(" Offset: %d\n\nHTML:\n", offsetInParent+1); - nsString Format("text/html"); - nsString ContentsAs; - OutputToString(ContentsAs, Format, 2); - wprintf(ContentsAs.GetUnicode()); - } -#endif - } + { + nsAutoString name; + parent->GetNodeName(name); + printf("SetCaretAfterElement: Parent node: "); + wprintf(name.GetUnicode()); + printf(" Offset: %d\n\nHTML:\n", offsetInParent+1); + nsString Format("text/html"); + nsString ContentsAs; + OutputToString(ContentsAs, Format, 2); + wprintf(ContentsAs.GetUnicode()); } +#endif } } return res; @@ -1259,6 +1306,8 @@ NS_IMETHODIMP nsHTMLEditor::SetParagraphFormat(const nsString& aParagraphFormat) // get the paragraph style(s) for the selection +// XXX: ERROR_HANDLING -- this method needs a little work to ensure all error codes are +// checked properly, all null pointers are checked, and no memory leaks occur NS_IMETHODIMP nsHTMLEditor::GetParagraphStyle(nsStringArray *aTagList) { @@ -1267,58 +1316,61 @@ nsHTMLEditor::GetParagraphStyle(nsStringArray *aTagList) nsresult res; nsCOMPtrselection; - res = nsEditor::GetSelection(getter_AddRefs(selection)); - if ((NS_SUCCEEDED(res)) && selection) + res = GetSelection(getter_AddRefs(selection)); + if (NS_FAILED(res)) return res; + if (!selection) return NS_ERROR_NULL_POINTER; + + nsCOMPtr enumerator; + res = selection->GetEnumerator(getter_AddRefs(enumerator)); + if (NS_FAILED(res)) return res; + if (!enumerator) return NS_ERROR_NULL_POINTER; + + enumerator->First(); + nsCOMPtr currentItem; + res = enumerator->CurrentItem(getter_AddRefs(currentItem)); + if (NS_FAILED(res)) return res; + //XXX: should be while loop? + if (currentItem) { - nsCOMPtr enumerator; - res = selection->GetEnumerator(getter_AddRefs(enumerator)); - if (NS_SUCCEEDED(res) && enumerator) + nsCOMPtr range( do_QueryInterface(currentItem) ); + // scan the range for all the independent block content blockSections + // and get the block parent of each + nsISupportsArray *blockSections; + res = NS_NewISupportsArray(&blockSections); + if (NS_FAILED(res)) return res; + if (!blockSections) return NS_ERROR_NULL_POINTER; + res = GetBlockSectionsForRange(range, blockSections); + if (NS_SUCCEEDED(res)) { - enumerator->First(); - nsCOMPtr currentItem; - res = enumerator->CurrentItem(getter_AddRefs(currentItem)); - if ((NS_SUCCEEDED(res)) && (currentItem)) + nsIDOMRange *subRange; + subRange = (nsIDOMRange *)(blockSections->ElementAt(0)); + while (subRange) { - nsCOMPtr range( do_QueryInterface(currentItem) ); - // scan the range for all the independent block content blockSections - // and get the block parent of each - nsISupportsArray *blockSections; - res = NS_NewISupportsArray(&blockSections); - if ((NS_SUCCEEDED(res)) && blockSections) + nsCOMPtrstartParent; + res = subRange->GetStartParent(getter_AddRefs(startParent)); + if (NS_SUCCEEDED(res) && startParent) { - res = GetBlockSectionsForRange(range, blockSections); - if (NS_SUCCEEDED(res)) + nsCOMPtr blockParent; + res = GetBlockParent(startParent, getter_AddRefs(blockParent)); + if (NS_SUCCEEDED(res) && blockParent) { - nsIDOMRange *subRange; - subRange = (nsIDOMRange *)(blockSections->ElementAt(0)); - while (subRange && (NS_SUCCEEDED(res))) - { - nsCOMPtrstartParent; - res = subRange->GetStartParent(getter_AddRefs(startParent)); - if (NS_SUCCEEDED(res) && startParent) - { - nsCOMPtr blockParent; - res = GetBlockParent(startParent, getter_AddRefs(blockParent)); - if (NS_SUCCEEDED(res) && blockParent) - { - nsAutoString blockParentTag; - blockParent->GetTagName(blockParentTag); - PRBool isRoot; - IsRootTag(blockParentTag, isRoot); - if ((PR_FALSE==isRoot) && (-1==aTagList->IndexOf(blockParentTag))) { - aTagList->AppendString(blockParentTag); - } - } - } - NS_RELEASE(subRange); - blockSections->RemoveElementAt(0); - subRange = (nsIDOMRange *)(blockSections->ElementAt(0)); + nsAutoString blockParentTag; + blockParent->GetTagName(blockParentTag); + PRBool isRoot; + IsRootTag(blockParentTag, isRoot); + if ((PR_FALSE==isRoot) && (-1==aTagList->IndexOf(blockParentTag))) { + aTagList->AppendString(blockParentTag); } } - NS_RELEASE(blockSections); } + NS_RELEASE(subRange); + if (NS_FAILED(res)) + break; // don't return here, need to release blockSections + blockSections->RemoveElementAt(0); + subRange = (nsIDOMRange *)(blockSections->ElementAt(0)); } } + NS_RELEASE(blockSections); } return res; @@ -1337,32 +1389,33 @@ nsHTMLEditor::AddBlockParent(nsString& aParentTag) nsresult res=NS_ERROR_NOT_INITIALIZED; nsCOMPtrselection; - res = nsEditor::GetSelection(getter_AddRefs(selection)); - if ((NS_SUCCEEDED(res)) && selection) + res = GetSelection(getter_AddRefs(selection)); + if (NS_FAILED(res)) return res; + if (!selection) return NS_ERROR_NULL_POINTER; + + // set the block parent for all selected ranges + nsAutoSelectionReset selectionResetter(selection); + nsAutoEditBatch beginBatching(this); + nsCOMPtr enumerator; + enumerator = do_QueryInterface(selection); + if (enumerator) { - // set the block parent for all selected ranges - nsAutoSelectionReset selectionResetter(selection); - nsAutoEditBatch beginBatching(this); - nsCOMPtr enumerator; - enumerator = do_QueryInterface(selection); - if (enumerator) + enumerator->First(); + nsCOMPtr currentItem; + res = enumerator->CurrentItem(getter_AddRefs(currentItem)); + // XXX: ERROR_HANDLING can currentItem be null? + if ((NS_SUCCEEDED(res)) && (currentItem)) { - enumerator->First(); - nsCOMPtr currentItem; - res = enumerator->CurrentItem(getter_AddRefs(currentItem)); - if ((NS_SUCCEEDED(res)) && (currentItem)) - { - nsCOMPtr range( do_QueryInterface(currentItem) ); - // scan the range for all the independent block content blockSections - // and apply the transformation to them - res = ReParentContentOfRange(range, aParentTag, eInsertParent); - } - } - if (NS_SUCCEEDED(res)) - { // set the selection - // XXX: can't do anything until I can create ranges + nsCOMPtr range( do_QueryInterface(currentItem) ); + // scan the range for all the independent block content blockSections + // and apply the transformation to them + res = ReParentContentOfRange(range, aParentTag, eInsertParent); } } + if (NS_SUCCEEDED(res)) + { // set the selection + // XXX: can't do anything until I can create ranges + } if (gNoisy) {printf("Finished nsHTMLEditor::AddBlockParent with this content:\n"); DebugDumpContent(); } // DEBUG return res; @@ -1381,27 +1434,28 @@ nsHTMLEditor::ReplaceBlockParent(nsString& aParentTag) nsresult res=NS_ERROR_NOT_INITIALIZED; nsCOMPtrselection; - res = nsEditor::GetSelection(getter_AddRefs(selection)); - if ((NS_SUCCEEDED(res)) && selection) + res = GetSelection(getter_AddRefs(selection)); + if (NS_FAILED(res)) return res; + if (!selection) return NS_ERROR_NULL_POINTER; + + nsAutoSelectionReset selectionResetter(selection); + // set the block parent for all selected ranges + nsAutoEditBatch beginBatching(this); + nsCOMPtr enumerator; + res = selection->GetEnumerator(getter_AddRefs(enumerator)); + if (NS_FAILED(res)) return res; + if (!enumerator) return NS_ERROR_NULL_POINTER; + + enumerator->First(); + nsCOMPtr currentItem; + res = enumerator->CurrentItem(getter_AddRefs(currentItem)); + // XXX: ERROR_HANDLING can currentItem be null? + if ((NS_SUCCEEDED(res)) && (currentItem)) { - nsAutoSelectionReset selectionResetter(selection); - // set the block parent for all selected ranges - nsAutoEditBatch beginBatching(this); - nsCOMPtr enumerator; - res = selection->GetEnumerator(getter_AddRefs(enumerator)); - if (NS_SUCCEEDED(res) && enumerator) - { - enumerator->First(); - nsCOMPtr currentItem; - res = enumerator->CurrentItem(getter_AddRefs(currentItem)); - if ((NS_SUCCEEDED(res)) && (currentItem)) - { - nsCOMPtr range( do_QueryInterface(currentItem) ); - // scan the range for all the independent block content blockSections - // and apply the transformation to them - res = ReParentContentOfRange(range, aParentTag, eReplaceParent); - } - } + nsCOMPtr range( do_QueryInterface(currentItem) ); + // scan the range for all the independent block content blockSections + // and apply the transformation to them + res = ReParentContentOfRange(range, aParentTag, eReplaceParent); } if (gNoisy) {printf("Finished nsHTMLEditor::AddBlockParent with this content:\n"); DebugDumpContent(); } // DEBUG @@ -1418,24 +1472,25 @@ nsHTMLEditor::RemoveParagraphStyle() nsresult res=NS_ERROR_NOT_INITIALIZED; nsCOMPtrselection; - res = nsEditor::GetSelection(getter_AddRefs(selection)); - if ((NS_SUCCEEDED(res)) && selection) + res = GetSelection(getter_AddRefs(selection)); + if (NS_FAILED(res)) return res; + if (!selection) return NS_ERROR_NULL_POINTER; + + nsAutoSelectionReset selectionResetter(selection); + nsAutoEditBatch beginBatching(this); + nsCOMPtr enumerator; + res = selection->GetEnumerator(getter_AddRefs(enumerator)); + if (NS_FAILED(res)) return res; + if (!enumerator) return NS_ERROR_NULL_POINTER; + + enumerator->First(); + nsCOMPtr currentItem; + res = enumerator->CurrentItem(getter_AddRefs(currentItem)); + // XXX: ERROR_HANDLING can currentItem be null? + if ((NS_SUCCEEDED(res)) && (currentItem)) { - nsAutoSelectionReset selectionResetter(selection); - nsAutoEditBatch beginBatching(this); - nsCOMPtr enumerator; - res = selection->GetEnumerator(getter_AddRefs(enumerator)); - if (NS_SUCCEEDED(res) && enumerator) - { - enumerator->First(); - nsCOMPtr currentItem; - res = enumerator->CurrentItem(getter_AddRefs(currentItem)); - if ((NS_SUCCEEDED(res)) && (currentItem)) - { - nsCOMPtr range( do_QueryInterface(currentItem) ); - res = RemoveParagraphStyleFromRange(range); - } - } + nsCOMPtr range( do_QueryInterface(currentItem) ); + res = RemoveParagraphStyleFromRange(range); } return res; } @@ -1447,26 +1502,27 @@ nsHTMLEditor::RemoveParent(const nsString &aParentTag) printf("---------- nsHTMLEditor::RemoveParent ----------\n"); } - nsresult res=NS_ERROR_NOT_INITIALIZED; + nsresult res; nsCOMPtrselection; - res = nsEditor::GetSelection(getter_AddRefs(selection)); - if ((NS_SUCCEEDED(res)) && selection) + res = GetSelection(getter_AddRefs(selection)); + if (NS_FAILED(res)) return res; + if (!selection) return NS_ERROR_NULL_POINTER; + + nsAutoSelectionReset selectionResetter(selection); + nsAutoEditBatch beginBatching(this); + nsCOMPtr enumerator; + res = selection->GetEnumerator(getter_AddRefs(enumerator)); + if (NS_FAILED(res)) return res; + if (!enumerator) return NS_ERROR_NULL_POINTER; + + enumerator->First(); + nsCOMPtr currentItem; + res = enumerator->CurrentItem(getter_AddRefs(currentItem)); + // XXX: ERROR_HANDLING can currentItem be null? + if ((NS_SUCCEEDED(res)) && (currentItem)) { - nsAutoSelectionReset selectionResetter(selection); - nsAutoEditBatch beginBatching(this); - nsCOMPtr enumerator; - res = selection->GetEnumerator(getter_AddRefs(enumerator)); - if (NS_SUCCEEDED(res) && enumerator) - { - enumerator->First(); - nsCOMPtr currentItem; - res = enumerator->CurrentItem(getter_AddRefs(currentItem)); - if ((NS_SUCCEEDED(res)) && (currentItem)) - { - nsCOMPtr range( do_QueryInterface(currentItem) ); - res = RemoveParentFromRange(aParentTag, range); - } - } + nsCOMPtr range( do_QueryInterface(currentItem) ); + res = RemoveParentFromRange(aParentTag, range); } return res; } @@ -1483,7 +1539,10 @@ nsHTMLEditor::InsertList(const nsString& aListType) nsAutoEditBatch beginBatching(this); // pre-process - nsEditor::GetSelection(getter_AddRefs(selection)); + res = GetSelection(getter_AddRefs(selection)); + if (NS_FAILED(res)) return res; + if (!selection) return NS_ERROR_NULL_POINTER; + nsTextRulesInfo ruleInfo(nsHTMLEditRules::kMakeList); if (aListType == "ol") ruleInfo.bOrdered = PR_TRUE; else ruleInfo.bOrdered = PR_FALSE; @@ -1491,8 +1550,6 @@ nsHTMLEditor::InsertList(const nsString& aListType) if (cancel || (NS_FAILED(res))) return res; // Find out if the selection is collapsed: - if (NS_FAILED(res) || !selection) return res; - PRBool isCollapsed; res = selection->GetIsCollapsed(&isCollapsed); if (NS_FAILED(res)) return res; @@ -1567,15 +1624,15 @@ nsHTMLEditor::InsertBasicBlock(const nsString& aBlockType) nsAutoEditBatch beginBatching(this); // pre-process - nsEditor::GetSelection(getter_AddRefs(selection)); + res = GetSelection(getter_AddRefs(selection)); + if (NS_FAILED(res)) return res; + if (!selection) return NS_ERROR_NULL_POINTER; nsTextRulesInfo ruleInfo(nsHTMLEditRules::kMakeBasicBlock); ruleInfo.blockType = &aBlockType; res = mRules->WillDoAction(selection, &ruleInfo, &cancel); if (cancel || (NS_FAILED(res))) return res; // Find out if the selection is collapsed: - if (NS_FAILED(res) || !selection) return res; - PRBool isCollapsed; res = selection->GetIsCollapsed(&isCollapsed); if (NS_FAILED(res)) return res; @@ -1645,7 +1702,10 @@ nsHTMLEditor::Indent(const nsString& aIndent) // pre-process nsCOMPtr selection; - nsEditor::GetSelection(getter_AddRefs(selection)); + res = GetSelection(getter_AddRefs(selection)); + if (NS_FAILED(res)) return res; + if (!selection) return NS_ERROR_NULL_POINTER; + nsTextRulesInfo ruleInfo(nsHTMLEditRules::kIndent); if (aIndent == "outdent") ruleInfo.action = nsHTMLEditRules::kOutdent; @@ -1666,7 +1726,6 @@ nsHTMLEditor::Indent(const nsString& aIndent) nsAutoString inward("indent"); if (aIndent == inward) { - if (isCollapsed) { // have to find a place to put the blockquote @@ -1722,7 +1781,8 @@ nsHTMLEditor::Align(const nsString& aAlignType) // Find out if the selection is collapsed: nsCOMPtr selection; nsresult res = GetSelection(getter_AddRefs(selection)); - if (NS_FAILED(res) || !selection) return res; + if (NS_FAILED(res)) return res; + if (!selection) return NS_ERROR_NULL_POINTER; nsTextRulesInfo ruleInfo(nsHTMLEditRules::kAlign); ruleInfo.alignType = &aAlignType; res = mRules->WillDoAction(selection, &ruleInfo, &cancel); @@ -1742,9 +1802,9 @@ nsHTMLEditor::GetElementOrParentByTagName(const nsString &aTagName, nsIDOMNode * if (!aNode) { nsCOMPtrselection; - res = nsEditor::GetSelection(getter_AddRefs(selection)); - if (NS_FAILED(res) || !selection) - return res; + res = GetSelection(getter_AddRefs(selection)); + if (NS_FAILED(res)) return res; + if (!selection) return NS_ERROR_NULL_POINTER; //TODO: Do I need to release the node? if(NS_FAILED(selection->GetAnchorNode(&aNode))) @@ -1790,6 +1850,7 @@ nsHTMLEditor::GetElementOrParentByTagName(const nsString &aTagName, nsIDOMNode * } // Search up the parent chain // We should never fail because of root test below, but lets be safe + // XXX: ERROR_HANDLING error return code lost if (!NS_SUCCEEDED(currentNode->GetParentNode(getter_AddRefs(parent))) || !parent) break; @@ -1837,10 +1898,10 @@ nsHTMLEditor::GetSelectedElement(const nsString& aTagName, nsIDOMElement** aRetu nsresult res=NS_ERROR_NOT_INITIALIZED; //PRBool first=PR_TRUE; nsCOMPtrselection; - res = nsEditor::GetSelection(getter_AddRefs(selection)); - if (NS_FAILED(res) || !selection) - return res; - + res = GetSelection(getter_AddRefs(selection)); + if (NS_FAILED(res)) return res; + if (!selection) return NS_ERROR_NULL_POINTER; + PRBool isCollapsed; selection->GetIsCollapsed(&isCollapsed); nsCOMPtr selectedElement; @@ -1853,12 +1914,14 @@ nsHTMLEditor::GetSelectedElement(const nsString& aTagName, nsIDOMElement** aRetu // included a collapsed selection (just a caret in a link) nsCOMPtr anchorNode; res = selection->GetAnchorNode(getter_AddRefs(anchorNode)); + if (NS_FAILED(res)) return res; PRInt32 anchorOffset = -1; if (anchorNode) selection->GetAnchorOffset(&anchorOffset); nsCOMPtr focusNode; - selection->GetFocusNode(getter_AddRefs(focusNode)); + res = selection->GetFocusNode(getter_AddRefs(focusNode)); + if (NS_FAILED(res)) return res; PRInt32 focusOffset = -1; if (focusNode) selection->GetFocusOffset(&focusOffset); @@ -1881,6 +1944,7 @@ nsHTMLEditor::GetSelectedElement(const nsString& aTagName, nsIDOMElement** aRetu #endif nsCOMPtr parentLinkOfAnchor; res = GetElementOrParentByTagName("href", anchorNode, getter_AddRefs(parentLinkOfAnchor)); + // XXX: ERROR_HANDLING can parentLinkOfAnchor be null? if (NS_SUCCEEDED(res) && parentLinkOfAnchor) { if (isCollapsed) @@ -1920,6 +1984,7 @@ nsHTMLEditor::GetSelectedElement(const nsString& aTagName, nsIDOMElement** aRetu { nsCOMPtr enumerator; res = selection->GetEnumerator(getter_AddRefs(enumerator)); + // XXX: ERROR_HANDLING unclear what to do here, should an error just be returned if enumerator is null or res failed? if (NS_SUCCEEDED(res) && enumerator) { enumerator->First(); @@ -1932,6 +1997,7 @@ nsHTMLEditor::GetSelectedElement(const nsString& aTagName, nsIDOMElement** aRetu res = nsComponentManager::CreateInstance(kCContentIteratorCID, nsnull, nsIContentIterator::GetIID(), getter_AddRefs(iter)); + // XXX: ERROR_HANDLING XPCOM usage if ((NS_SUCCEEDED(res)) && iter) { iter->Init(range); @@ -2050,6 +2116,7 @@ nsHTMLEditor::CreateElementWithDefaults(const nsString& aTagName, nsIDOMElement* char buf[16]; PRInt32 iAlign; // Currently using 0=left, 1=center, and 2=right + // XXX: ERROR_HANDLING if these results are intentionally thrown away, it should be documented here if( NS_SUCCEEDED(mPrefs->GetIntPref("editor.hrule.align", &iAlign))) { switch (iAlign) { @@ -2121,11 +2188,11 @@ nsHTMLEditor::CreateElementWithDefaults(const nsString& aTagName, nsIDOMElement* space += nbsp; // If we fail here, we return NS_OK anyway, since we have an OK cell node nsresult result = mDoc->CreateTextNode(space, getter_AddRefs(newTextNode)); - if (NS_SUCCEEDED(result) && newTextNode) - { - nsCOMPtrresultNode; - result = newCellNode->AppendChild(newTextNode, getter_AddRefs(resultNode)); - } + if (NS_FAILED(result)) return result; + if (!newTextNode) return NS_ERROR_NULL_POINTER; + + nsCOMPtrresultNode; + result = newCellNode->AppendChild(newTextNode, getter_AddRefs(resultNode)); } } // ADD OTHER DEFAULT ATTRIBUTES HERE @@ -2147,6 +2214,9 @@ nsHTMLEditor::SaveHLineSettings(nsIDOMElement* aElement) nsAutoString align, width, height, noshade; res = NS_ERROR_UNEXPECTED; + // XXX: ERROR_HANDLING if return codes are intentionally thrown away, it should be documented here + // it looks like if any GetAttribute call failes, an error is returned + // is that the desired behavior? if (NS_SUCCEEDED(aElement->GetAttribute("align", align)) && NS_SUCCEEDED(aElement->GetAttribute("height", height)) && NS_SUCCEEDED(aElement->GetAttribute("width", width)) && @@ -2190,6 +2260,10 @@ nsHTMLEditor::InsertLinkAroundSelection(nsIDOMElement* aAnchorElement) // We must have a real selection res = GetSelection(getter_AddRefs(selection)); + if (!selection) + { + res = NS_ERROR_NULL_POINTER; + } if (NS_FAILED(res) || !selection) goto DELETE_ANCHOR; @@ -2208,6 +2282,7 @@ nsHTMLEditor::InsertLinkAroundSelection(nsIDOMElement* aAnchorElement) if (anchor) { nsAutoString href; + // XXX: ERROR_HANDLING return code lost if (NS_SUCCEEDED(anchor->GetHref(href)) && href.GetUnicode() && href.Length() > 0) { nsAutoEditBatch beginBatching(this); @@ -2228,7 +2303,8 @@ DELETE_ANCHOR: return res; } - +// XXX: this method sets the attribute on the body element directly, +// and is not undoable. It should go through the transaction system! NS_IMETHODIMP nsHTMLEditor::SetBackgroundColor(const nsString& aColor) { // nsresult result; @@ -2243,9 +2319,11 @@ NS_IMETHODIMP nsHTMLEditor::SetBackgroundColor(const nsString& aColor) // Set the background color attribute on the body tag nsCOMPtr bodyElement; nsresult res = nsEditor::GetBodyElement(getter_AddRefs(bodyElement)); - if (NS_SUCCEEDED(res) && bodyElement) + if (!bodyElement) res = NS_ERROR_NULL_POINTER; + if (NS_SUCCEEDED(res)) { nsAutoEditBatch beginBatching(this); + // XXX: ERROR_HANDLING should this be "res = SetAttribute..." bodyElement->SetAttribute("bgcolor", aColor); } @@ -2263,9 +2341,11 @@ NS_IMETHODIMP nsHTMLEditor::SetBodyAttribute(const nsString& aAttribute, const n nsCOMPtr bodyElement; res = nsEditor::GetBodyElement(getter_AddRefs(bodyElement)); - if (NS_SUCCEEDED(res) && bodyElement) + if (!bodyElement) res = NS_ERROR_NULL_POINTER; + if (NS_SUCCEEDED(res)) { // Use the editor's method which goes through the transaction system + // XXX: ERROR_HANDLING should this be "res = SetAttribute..." SetAttribute(bodyElement, aAttribute, aValue); } return res; @@ -2330,21 +2410,21 @@ nsHTMLEditor::GetDocumentLength(PRInt32 *aCount) nsCOMPtr sel; result = GetSelection(getter_AddRefs(sel)); - if ((NS_SUCCEEDED(result)) && sel) + if (NS_FAILED(result)) return result; + if (!sel) return NS_ERROR_NULL_POINTER; + + nsAutoSelectionReset selectionResetter(sel); + result = SelectAll(); + if (NS_SUCCEEDED(result)) { - nsAutoSelectionReset selectionResetter(sel); - result = SelectAll(); + PRInt32 start, end; + result = GetTextSelectionOffsets(sel, start, end); if (NS_SUCCEEDED(result)) { - PRInt32 start, end; - result = GetTextSelectionOffsets(sel, start, end); - if (NS_SUCCEEDED(result)) - { - NS_ASSERTION(0==start, "GetTextSelectionOffsets failed to set start correctly."); - NS_ASSERTION(0<=end, "GetTextSelectionOffsets failed to set end correctly."); - if (0<=end) { - *aCount = end; - } + NS_ASSERTION(0==start, "GetTextSelectionOffsets failed to set start correctly."); + NS_ASSERTION(0<=end, "GetTextSelectionOffsets failed to set end correctly."); + if (0<=end) { + *aCount = end; } } } @@ -2374,11 +2454,12 @@ NS_IMETHODIMP nsHTMLEditor::GetMaxTextLength(PRInt32& aMaxTextLength) NS_IMETHODIMP nsHTMLEditor::AddStyleSheet(nsICSSStyleSheet* aSheet) { - AddStyleSheetTxn* aTxn; - nsresult rv = CreateTxnForAddStyleSheet(aSheet, &aTxn); - if (NS_SUCCEEDED(rv) && aTxn) + AddStyleSheetTxn* txn; + nsresult rv = CreateTxnForAddStyleSheet(aSheet, &txn); + if (!txn) rv = NS_ERROR_NULL_POINTER; + if (NS_SUCCEEDED(rv)) { - rv = Do(aTxn); + rv = Do(txn); if (NS_SUCCEEDED(rv)) { mLastStyleSheet = do_QueryInterface(aSheet); // save it so we can remove before applying the next one @@ -2392,11 +2473,12 @@ nsHTMLEditor::AddStyleSheet(nsICSSStyleSheet* aSheet) NS_IMETHODIMP nsHTMLEditor::RemoveStyleSheet(nsICSSStyleSheet* aSheet) { - RemoveStyleSheetTxn* aTxn; - nsresult rv = CreateTxnForRemoveStyleSheet(aSheet, &aTxn); - if (NS_SUCCEEDED(rv) && aTxn) + RemoveStyleSheetTxn* txn; + nsresult rv = CreateTxnForRemoveStyleSheet(aSheet, &txn); + if (!txn) rv = NS_ERROR_NULL_POINTER; + if (NS_SUCCEEDED(rv)) { - rv = Do(aTxn); + rv = Do(txn); if (NS_SUCCEEDED(rv)) { mLastStyleSheet = nsnull; // forget it @@ -2588,8 +2670,8 @@ NS_IMETHODIMP nsHTMLEditor::PasteAsCitedQuotation(const nsString& aCitation) nsCOMPtr newNode; nsAutoString tag("blockquote"); nsresult res = DeleteSelectionAndCreateNode(tag, getter_AddRefs(newNode)); - if (NS_FAILED(res) || !newNode) - return res; + if (NS_FAILED(res)) return res; + if (!newNode) return NS_ERROR_NULL_POINTER; // Try to set type=cite. Ignore it if this fails. nsCOMPtr newElement (do_QueryInterface(newNode)); @@ -2609,6 +2691,8 @@ NS_IMETHODIMP nsHTMLEditor::PasteAsCitedQuotation(const nsString& aCitation) printf("Can't get selection!"); #endif } + if (NS_FAILED(res)) return res; + if (!selection) return NS_ERROR_NULL_POINTER; res = selection->Collapse(newNode, 0); if (NS_FAILED(res)) @@ -2616,6 +2700,7 @@ NS_IMETHODIMP nsHTMLEditor::PasteAsCitedQuotation(const nsString& aCitation) #ifdef DEBUG_akkana printf("Couldn't collapse"); #endif + // XXX: error result: should res be returned here? } res = Paste(); @@ -2715,8 +2800,8 @@ NS_IMETHODIMP nsHTMLEditor::InsertAsCitedQuotation(const nsString& aQuotedText, nsCOMPtr newNode; nsAutoString tag("blockquote"); nsresult res = DeleteSelectionAndCreateNode(tag, getter_AddRefs(newNode)); - if (NS_FAILED(res) || !newNode) - return res; + if (NS_FAILED(res)) return res; + if (!newNode) return NS_ERROR_NULL_POINTER; // Try to set type=cite. Ignore it if this fails. nsCOMPtr newElement (do_QueryInterface(newNode)); @@ -2744,15 +2829,15 @@ nsHTMLEditor::GetEmbeddedObjects(nsISupportsArray** aNodeList) nsresult res; res = NS_NewISupportsArray(aNodeList); - if (NS_FAILED(res) || !*aNodeList) - return res; - //NS_ADDREF(*aNodeList); + if (NS_FAILED(res)) return res; + if (!*aNodeList) return NS_ERROR_NULL_POINTER; nsCOMPtr iter; res = nsComponentManager::CreateInstance(kCContentIteratorCID, nsnull, nsIContentIterator::GetIID(), getter_AddRefs(iter)); - if ((NS_SUCCEEDED(res)) && iter) + if (!iter) return NS_ERROR_NULL_POINTER; + if ((NS_SUCCEEDED(res))) { // get the root content nsCOMPtr rootContent; @@ -3114,6 +3199,7 @@ nsHTMLEditor::ReplaceStyleSheet(nsICSSStyleSheet *aNewSheet) if (mLastStyleSheet) { rv = RemoveStyleSheet(mLastStyleSheet); + //XXX: rv is ignored here, why? } rv = AddStyleSheet(aNewSheet); @@ -3136,7 +3222,7 @@ void nsHTMLEditor::ApplyStyleSheetToPresShellDocument(nsICSSStyleSheet* aSheet, rv = editor->ReplaceStyleSheet(aSheet); } - // we lose the return value here. Set a flag in the editor? + // XXX: we lose the return value here. Set a flag in the editor? } @@ -3248,7 +3334,8 @@ void nsHTMLEditor::IsTextPropertySetByContent(nsIDOMNode *aNode, aProperty->ToString(propName); nsCOMPtrparent; result = aNode->GetParentNode(getter_AddRefs(parent)); - while (NS_SUCCEEDED(result) && parent) + if (NS_FAILED(result)) return; + while (parent) { nsCOMPtrelement; element = do_QueryInterface(parent); @@ -3324,6 +3411,7 @@ nsresult nsHTMLEditor::GetTextSelectionOffsets(nsIDOMSelection *aSelection, PRInt32 &aStartOffset, PRInt32 &aEndOffset) { + if(!aSelection) { return NS_ERROR_NULL_POINTER; } nsresult result; // initialize out params aStartOffset = 0; // default to first char in selection @@ -3338,115 +3426,46 @@ nsresult nsHTMLEditor::GetTextSelectionOffsets(nsIDOMSelection *aSelection, nsCOMPtr enumerator; result = aSelection->GetEnumerator(getter_AddRefs(enumerator)); - if (NS_SUCCEEDED(result) && enumerator) + if (NS_FAILED(result)) return result; + if (!enumerator) return NS_ERROR_NULL_POINTER; + + // don't use "result" in this block + enumerator->First(); + nsCOMPtr currentItem; + nsresult findParentResult = enumerator->CurrentItem(getter_AddRefs(currentItem)); + if ((NS_SUCCEEDED(findParentResult)) && (currentItem)) { - // don't use "result" in this block - enumerator->First(); - nsCOMPtr currentItem; - nsresult findParentResult = enumerator->CurrentItem(getter_AddRefs(currentItem)); - if ((NS_SUCCEEDED(findParentResult)) && (currentItem)) - { - nsCOMPtr range( do_QueryInterface(currentItem) ); - range->GetCommonParent(getter_AddRefs(parentNode)); - } - else parentNode = do_QueryInterface(startNode); + nsCOMPtr range( do_QueryInterface(currentItem) ); + range->GetCommonParent(getter_AddRefs(parentNode)); } + else { + parentNode = do_QueryInterface(startNode); + } + nsCOMPtr iter; result = nsComponentManager::CreateInstance(kCContentIteratorCID, nsnull, nsIContentIterator::GetIID(), getter_AddRefs(iter)); - if ((NS_SUCCEEDED(result)) && iter) + if (NS_FAILED(result)) return result; + if (!iter) return NS_ERROR_NULL_POINTER; + + PRUint32 totalLength=0; + nsCOMPtrtextNode; + nsCOMPtrblockParentContent = do_QueryInterface(parentNode); + iter->Init(blockParentContent); + // loop through the content iterator for each content node + nsCOMPtr content; + result = iter->CurrentNode(getter_AddRefs(content)); + while (NS_COMFALSE == iter->IsDone()) { - PRUint32 totalLength=0; - nsCOMPtrtextNode; - nsCOMPtrblockParentContent = do_QueryInterface(parentNode); - iter->Init(blockParentContent); - // loop through the content iterator for each content node - nsCOMPtr content; - result = iter->CurrentNode(getter_AddRefs(content)); - while (NS_COMFALSE == iter->IsDone()) + textNode = do_QueryInterface(content); + if (textNode) { - textNode = do_QueryInterface(content); - if (textNode) + nsCOMPtrcurrentNode = do_QueryInterface(textNode); + if (!currentNode) {return NS_ERROR_NO_INTERFACE;} + if (PR_TRUE==IsEditable(currentNode)) { - nsCOMPtrcurrentNode = do_QueryInterface(textNode); - if (!currentNode) {return NS_ERROR_NO_INTERFACE;} - if (PR_TRUE==IsEditable(currentNode)) - { - if (currentNode.get() == startNode.get()) - { - aStartOffset = totalLength + startOffset; - } - if (currentNode.get() == endNode.get()) - { - aEndOffset = totalLength + endOffset; - break; - } - PRUint32 length; - textNode->GetLength(&length); - totalLength += length; - } - } - iter->Next(); - iter->CurrentNode(getter_AddRefs(content)); - } - if (-1==aEndOffset) { - aEndOffset = totalLength; - } - } - return result; -} - - - -void nsHTMLEditor::GetTextSelectionOffsetsForRange(nsIDOMSelection *aSelection, - nsIDOMNode **aParent, - PRInt32 &aStartOffset, - PRInt32 &aEndOffset) -{ - nsresult result; - - nsCOMPtr startNode, endNode; - PRInt32 startOffset, endOffset; - aSelection->GetAnchorNode(getter_AddRefs(startNode)); - aSelection->GetAnchorOffset(&startOffset); - aSelection->GetFocusNode(getter_AddRefs(endNode)); - aSelection->GetFocusOffset(&endOffset); - - nsCOMPtr enumerator; - result = aSelection->GetEnumerator(getter_AddRefs(enumerator)); - if (NS_SUCCEEDED(result) && enumerator) - { - enumerator->First(); - nsCOMPtr currentItem; - result = enumerator->CurrentItem(getter_AddRefs(currentItem)); - if ((NS_SUCCEEDED(result)) && currentItem) - { - nsCOMPtr range( do_QueryInterface(currentItem) ); - range->GetCommonParent(aParent); - } - } - - nsCOMPtr iter; - result = nsComponentManager::CreateInstance(kCContentIteratorCID, nsnull, - nsIContentIterator::GetIID(), - getter_AddRefs(iter)); - if ((NS_SUCCEEDED(result)) && iter) - { - PRUint32 totalLength=0; - nsCOMPtrtextNode; - nsCOMPtrblockParentContent = do_QueryInterface(*aParent); - iter->Init(blockParentContent); - // loop through the content iterator for each content node - nsCOMPtr content; - result = iter->CurrentNode(getter_AddRefs(content)); - while (NS_COMFALSE == iter->IsDone()) - { - textNode = do_QueryInterface(content); - if (textNode) - { - nsCOMPtrcurrentNode = do_QueryInterface(textNode); if (currentNode.get() == startNode.get()) { aStartOffset = totalLength + startOffset; @@ -3460,10 +3479,84 @@ void nsHTMLEditor::GetTextSelectionOffsetsForRange(nsIDOMSelection *aSelection, textNode->GetLength(&length); totalLength += length; } - iter->Next(); - iter->CurrentNode(getter_AddRefs(content)); } + iter->Next(); + iter->CurrentNode(getter_AddRefs(content)); } + if (-1==aEndOffset) { + aEndOffset = totalLength; + } + return result; +} + + +NS_IMETHODIMP +nsHTMLEditor::GetTextSelectionOffsetsForRange(nsIDOMSelection *aSelection, + nsIDOMNode **aParent, + PRInt32 &aStartOffset, + PRInt32 &aEndOffset) +{ + if (!aSelection) { return NS_ERROR_NULL_POINTER; } + aStartOffset = aEndOffset = 0; + nsresult result; + + nsCOMPtr startNode, endNode; + PRInt32 startOffset, endOffset; + aSelection->GetAnchorNode(getter_AddRefs(startNode)); + aSelection->GetAnchorOffset(&startOffset); + aSelection->GetFocusNode(getter_AddRefs(endNode)); + aSelection->GetFocusOffset(&endOffset); + + nsCOMPtr enumerator; + result = aSelection->GetEnumerator(getter_AddRefs(enumerator)); + if (NS_FAILED(result)) return result; + if (!enumerator) return NS_ERROR_NULL_POINTER; + enumerator->First(); + nsCOMPtr currentItem; + result = enumerator->CurrentItem(getter_AddRefs(currentItem)); + if ((NS_SUCCEEDED(result)) && currentItem) + { + nsCOMPtr range( do_QueryInterface(currentItem) ); + range->GetCommonParent(aParent); + } + + nsCOMPtr iter; + result = nsComponentManager::CreateInstance(kCContentIteratorCID, nsnull, + nsIContentIterator::GetIID(), + getter_AddRefs(iter)); + if (NS_FAILED(result)) return result; + if (!iter) return NS_ERROR_NULL_POINTER; + + PRUint32 totalLength=0; + nsCOMPtrtextNode; + nsCOMPtrblockParentContent = do_QueryInterface(*aParent); + iter->Init(blockParentContent); + // loop through the content iterator for each content node + nsCOMPtr content; + result = iter->CurrentNode(getter_AddRefs(content)); + while (NS_COMFALSE == iter->IsDone()) + { + textNode = do_QueryInterface(content); + if (textNode) + { + nsCOMPtrcurrentNode = do_QueryInterface(textNode); + if (currentNode.get() == startNode.get()) + { + aStartOffset = totalLength + startOffset; + } + if (currentNode.get() == endNode.get()) + { + aEndOffset = totalLength + endOffset; + break; + } + PRUint32 length; + textNode->GetLength(&length); + totalLength += length; + } + iter->Next(); + iter->CurrentNode(getter_AddRefs(content)); + } + return result; } void nsHTMLEditor::ResetTextSelectionForRange(nsIDOMNode *aParent, @@ -3471,6 +3564,7 @@ void nsHTMLEditor::ResetTextSelectionForRange(nsIDOMNode *aParent, PRInt32 aEndOffset, nsIDOMSelection *aSelection) { + if (!aParent || !aSelection) { return; } // XXX: should return an error nsCOMPtr startNode, endNode; PRInt32 startOffset, endOffset; @@ -3479,43 +3573,42 @@ void nsHTMLEditor::ResetTextSelectionForRange(nsIDOMNode *aParent, result = nsComponentManager::CreateInstance(kCContentIteratorCID, nsnull, nsIContentIterator::GetIID(), getter_AddRefs(iter)); - if ((NS_SUCCEEDED(result)) && iter) + if (NS_FAILED(result)) return; + if (!iter) return; + PRBool setStart = PR_FALSE; + PRUint32 totalLength=0; + nsCOMPtrtextNode; + nsCOMPtrblockParentContent = do_QueryInterface(aParent); + iter->Init(blockParentContent); + // loop through the content iterator for each content node + nsCOMPtr content; + result = iter->CurrentNode(getter_AddRefs(content)); + while (NS_COMFALSE == iter->IsDone()) { - PRBool setStart = PR_FALSE; - PRUint32 totalLength=0; - nsCOMPtrtextNode; - nsCOMPtrblockParentContent = do_QueryInterface(aParent); - iter->Init(blockParentContent); - // loop through the content iterator for each content node - nsCOMPtr content; - result = iter->CurrentNode(getter_AddRefs(content)); - while (NS_COMFALSE == iter->IsDone()) + textNode = do_QueryInterface(content); + if (textNode) { - textNode = do_QueryInterface(content); - if (textNode) + PRUint32 length; + textNode->GetLength(&length); + if ((PR_FALSE==setStart) && aStartOffset<=(PRInt32)(totalLength+length)) { - PRUint32 length; - textNode->GetLength(&length); - if ((PR_FALSE==setStart) && aStartOffset<=(PRInt32)(totalLength+length)) - { - setStart = PR_TRUE; - startNode = do_QueryInterface(textNode); - startOffset = aStartOffset-totalLength; - } - if (aEndOffset<=(PRInt32)(totalLength+length)) - { - endNode = do_QueryInterface(textNode); - endOffset = aEndOffset-totalLength; - break; - } - totalLength += length; + setStart = PR_TRUE; + startNode = do_QueryInterface(textNode); + startOffset = aStartOffset-totalLength; } - iter->Next(); - iter->CurrentNode(getter_AddRefs(content)); + if (aEndOffset<=(PRInt32)(totalLength+length)) + { + endNode = do_QueryInterface(textNode); + endOffset = aEndOffset-totalLength; + break; + } + totalLength += length; } - aSelection->Collapse(startNode, startOffset); - aSelection->Extend(endNode, endOffset); - } + iter->Next(); + iter->CurrentNode(getter_AddRefs(content)); + } + aSelection->Collapse(startNode, startOffset); + aSelection->Extend(endNode, endOffset); } #pragma mark - @@ -3651,8 +3744,9 @@ nsHTMLEditor::ReParentBlockContent(nsIDOMNode *aNode, PRBool removeBreakAfter = PR_FALSE; nsCOMPtrancestor; nsresult res = aNode->GetParentNode(getter_AddRefs(ancestor)); + if (NS_FAILED(res)) return res; nsCOMPtrpreviousAncestor = do_QueryInterface(aNode); - while (NS_SUCCEEDED(res) && ancestor) + while (ancestor) { nsCOMPtrancestorElement = do_QueryInterface(ancestor); nsAutoString ancestorTag; @@ -3663,118 +3757,136 @@ nsHTMLEditor::ReParentBlockContent(nsIDOMNode *aNode, } previousAncestor = do_QueryInterface(ancestor); res = ancestorElement->GetParentNode(getter_AddRefs(ancestor)); + if (NS_FAILED(res)) return res; } // now, previousAncestor is the node we are operating on nsCOMPtrleftNode, rightNode; res = GetBlockSection(previousAncestor, - getter_AddRefs(leftNode), - getter_AddRefs(rightNode)); - if ((NS_SUCCEEDED(res)) && leftNode && rightNode) + getter_AddRefs(leftNode), + getter_AddRefs(rightNode)); + if (NS_FAILED(res)) return res; + if (!leftNode || !rightNode) return NS_ERROR_NULL_POINTER; + + // determine some state for managing
s around the new block + PRBool isSubordinateBlock = PR_FALSE; // if true, the content is already in a subordinate block + PRBool isRootBlock = PR_FALSE; // if true, the content is in a root block + nsCOMPtrblockParentElement = do_QueryInterface(blockParentNode); + if (blockParentElement) { - // determine some state for managing
s around the new block - PRBool isSubordinateBlock = PR_FALSE; // if true, the content is already in a subordinate block - PRBool isRootBlock = PR_FALSE; // if true, the content is in a root block - nsCOMPtrblockParentElement = do_QueryInterface(blockParentNode); - if (blockParentElement) - { - nsAutoString blockParentTag; - blockParentElement->GetTagName(blockParentTag); - IsSubordinateBlock(blockParentTag, isSubordinateBlock); - IsRootTag(blockParentTag, isRootBlock); - } + nsAutoString blockParentTag; + blockParentElement->GetTagName(blockParentTag); + IsSubordinateBlock(blockParentTag, isSubordinateBlock); + IsRootTag(blockParentTag, isRootBlock); + } - if (PR_TRUE==isRootBlock) - { // we're creating a block element where a block element did not previously exist - removeBreakBefore = PR_TRUE; - removeBreakAfter = PR_TRUE; - } + if (PR_TRUE==isRootBlock) + { // we're creating a block element where a block element did not previously exist + removeBreakBefore = PR_TRUE; + removeBreakAfter = PR_TRUE; + } - // apply the transformation - PRInt32 offsetInParent=0; - if (eInsertParent==aTransformation || PR_TRUE==isRootBlock) + // apply the transformation + PRInt32 offsetInParent=0; + if (eInsertParent==aTransformation || PR_TRUE==isRootBlock) + { + res = GetChildOffset(leftNode, blockParentNode, offsetInParent); + NS_ASSERTION((NS_SUCCEEDED(res)), "bad res from GetChildOffset"); + res = CreateNode(aParentTag, blockParentNode, offsetInParent, aNewParentNode); + if (gNoisy) { printf("created a node in blockParentNode at offset %d\n", offsetInParent); } + } + else + { + nsCOMPtr grandParent; + res = blockParentNode->GetParentNode(getter_AddRefs(grandParent)); + if (NS_FAILED(res)) return res; + if (!grandParent) return NS_ERROR_NULL_POINTER; + nsCOMPtrfirstChildNode, lastChildNode; + blockParentNode->GetFirstChild(getter_AddRefs(firstChildNode)); + blockParentNode->GetLastChild(getter_AddRefs(lastChildNode)); + if (firstChildNode==leftNode && lastChildNode==rightNode) { + res = GetChildOffset(blockParentNode, grandParent, offsetInParent); + NS_ASSERTION((NS_SUCCEEDED(res)), "bad res from GetChildOffset"); + res = CreateNode(aParentTag, grandParent, offsetInParent, aNewParentNode); + if (gNoisy) { printf("created a node in grandParent at offset %d\n", offsetInParent); } + } + else + { + // We're in the case where the content of blockParentNode is separated by
's, + // creating multiple block content ranges. + // Split blockParentNode around the blockContent + if (gNoisy) { printf("splitting a node because of
s\n"); } + nsCOMPtr newLeftNode; + if (firstChildNode!=leftNode) + { + res = GetChildOffset(leftNode, blockParentNode, offsetInParent); + if (gNoisy) { printf("splitting left at %d\n", offsetInParent); } + res = SplitNode(blockParentNode, offsetInParent, getter_AddRefs(newLeftNode)); + // after this split, blockParentNode still contains leftNode and rightNode + } + if (lastChildNode!=rightNode) + { + res = GetChildOffset(rightNode, blockParentNode, offsetInParent); + offsetInParent++; + if (gNoisy) { printf("splitting right at %d\n", offsetInParent); } + res = SplitNode(blockParentNode, offsetInParent, getter_AddRefs(newLeftNode)); + blockParentNode = do_QueryInterface(newLeftNode); + } res = GetChildOffset(leftNode, blockParentNode, offsetInParent); NS_ASSERTION((NS_SUCCEEDED(res)), "bad res from GetChildOffset"); res = CreateNode(aParentTag, blockParentNode, offsetInParent, aNewParentNode); if (gNoisy) { printf("created a node in blockParentNode at offset %d\n", offsetInParent); } + // what we need to do here is remove the existing block parent when we're all done. + removeBlockParent = PR_TRUE; } - else + } + if ((NS_SUCCEEDED(res)) && *aNewParentNode) + { // move all the children/contents of blockParentNode to aNewParentNode + nsCOMPtrchildNode = do_QueryInterface(rightNode); + nsCOMPtrpreviousSiblingNode; + while (NS_SUCCEEDED(res) && childNode) { - nsCOMPtr grandParent; - res = blockParentNode->GetParentNode(getter_AddRefs(grandParent)); - if ((NS_SUCCEEDED(res)) && grandParent) + childNode->GetPreviousSibling(getter_AddRefs(previousSiblingNode)); + // explicitly delete of childNode from it's current parent + // can't just rely on DOM semantics of InsertNode doing the delete implicitly, doesn't undo! + res = nsEditor::DeleteNode(childNode); + if (NS_SUCCEEDED(res)) { - nsCOMPtrfirstChildNode, lastChildNode; - blockParentNode->GetFirstChild(getter_AddRefs(firstChildNode)); - blockParentNode->GetLastChild(getter_AddRefs(lastChildNode)); - if (firstChildNode==leftNode && lastChildNode==rightNode) + res = nsEditor::InsertNode(childNode, *aNewParentNode, 0); + if (gNoisy) { - res = GetChildOffset(blockParentNode, grandParent, offsetInParent); - NS_ASSERTION((NS_SUCCEEDED(res)), "bad res from GetChildOffset"); - res = CreateNode(aParentTag, grandParent, offsetInParent, aNewParentNode); - if (gNoisy) { printf("created a node in grandParent at offset %d\n", offsetInParent); } + printf("re-parented sibling node %p\n", childNode.get()); } - else - { - // We're in the case where the content of blockParentNode is separated by
's, - // creating multiple block content ranges. - // Split blockParentNode around the blockContent - if (gNoisy) { printf("splitting a node because of
s\n"); } - nsCOMPtr newLeftNode; - if (firstChildNode!=leftNode) - { - res = GetChildOffset(leftNode, blockParentNode, offsetInParent); - if (gNoisy) { printf("splitting left at %d\n", offsetInParent); } - res = SplitNode(blockParentNode, offsetInParent, getter_AddRefs(newLeftNode)); - // after this split, blockParentNode still contains leftNode and rightNode - } - if (lastChildNode!=rightNode) - { - res = GetChildOffset(rightNode, blockParentNode, offsetInParent); - offsetInParent++; - if (gNoisy) { printf("splitting right at %d\n", offsetInParent); } - res = SplitNode(blockParentNode, offsetInParent, getter_AddRefs(newLeftNode)); - blockParentNode = do_QueryInterface(newLeftNode); - } - res = GetChildOffset(leftNode, blockParentNode, offsetInParent); - NS_ASSERTION((NS_SUCCEEDED(res)), "bad res from GetChildOffset"); - res = CreateNode(aParentTag, blockParentNode, offsetInParent, aNewParentNode); - if (gNoisy) { printf("created a node in blockParentNode at offset %d\n", offsetInParent); } - // what we need to do here is remove the existing block parent when we're all done. - removeBlockParent = PR_TRUE; + } + if (childNode==leftNode || rightNode==leftNode) { + break; + } + childNode = do_QueryInterface(previousSiblingNode); + } // end while loop + } + // clean up the surrounding content to maintain vertical whitespace + if (NS_SUCCEEDED(res)) + { + // if the prior node is a
and we did something to change vertical whitespacing, delete the
+ nsCOMPtr brNode; + res = GetPriorNode(leftNode, PR_TRUE, getter_AddRefs(brNode)); + if (NS_SUCCEEDED(res) && brNode) + { + nsCOMPtr brContent = do_QueryInterface(brNode); + if (brContent) + { + nsCOMPtr brContentTag; + brContent->GetTag(*getter_AddRefs(brContentTag)); + if (nsIEditProperty::br==brContentTag.get()) { + res = DeleteNode(brNode); } } } - if ((NS_SUCCEEDED(res)) && *aNewParentNode) - { // move all the children/contents of blockParentNode to aNewParentNode - nsCOMPtrchildNode = do_QueryInterface(rightNode); - nsCOMPtrpreviousSiblingNode; - while (NS_SUCCEEDED(res) && childNode) - { - childNode->GetPreviousSibling(getter_AddRefs(previousSiblingNode)); - // explicitly delete of childNode from it's current parent - // can't just rely on DOM semantics of InsertNode doing the delete implicitly, doesn't undo! - res = nsEditor::DeleteNode(childNode); - if (NS_SUCCEEDED(res)) - { - res = nsEditor::InsertNode(childNode, *aNewParentNode, 0); - if (gNoisy) - { - printf("re-parented sibling node %p\n", childNode.get()); - } - } - if (childNode==leftNode || rightNode==leftNode) { - break; - } - childNode = do_QueryInterface(previousSiblingNode); - } // end while loop - } - // clean up the surrounding content to maintain vertical whitespace + + // if the next node is a
and we did something to change vertical whitespacing, delete the
if (NS_SUCCEEDED(res)) { - // if the prior node is a
and we did something to change vertical whitespacing, delete the
- nsCOMPtr brNode; - res = GetPriorNode(leftNode, PR_TRUE, getter_AddRefs(brNode)); + res = GetNextNode(rightNode, PR_TRUE, getter_AddRefs(brNode)); if (NS_SUCCEEDED(res) && brNode) { nsCOMPtr brContent = do_QueryInterface(brNode); @@ -3787,54 +3899,36 @@ nsHTMLEditor::ReParentBlockContent(nsIDOMNode *aNode, } } } - - // if the next node is a
and we did something to change vertical whitespacing, delete the
- if (NS_SUCCEEDED(res)) - { - res = GetNextNode(rightNode, PR_TRUE, getter_AddRefs(brNode)); - if (NS_SUCCEEDED(res) && brNode) - { - nsCOMPtr brContent = do_QueryInterface(brNode); - if (brContent) - { - nsCOMPtr brContentTag; - brContent->GetTag(*getter_AddRefs(brContentTag)); - if (nsIEditProperty::br==brContentTag.get()) { - res = DeleteNode(brNode); - } - } - } - } } - if ((NS_SUCCEEDED(res)) && (PR_TRUE==removeBlockParent)) - { // we determined we need to remove the previous block parent. Do it! - // go through list backwards so deletes don't interfere with the iteration - nsCOMPtr childNodes; - res = blockParentNode->GetChildNodes(getter_AddRefs(childNodes)); - if ((NS_SUCCEEDED(res)) && (childNodes)) + } + if ((NS_SUCCEEDED(res)) && (PR_TRUE==removeBlockParent)) + { // we determined we need to remove the previous block parent. Do it! + // go through list backwards so deletes don't interfere with the iteration + nsCOMPtr childNodes; + res = blockParentNode->GetChildNodes(getter_AddRefs(childNodes)); + if ((NS_SUCCEEDED(res)) && (childNodes)) + { + nsCOMPtrgrandParent; + blockParentNode->GetParentNode(getter_AddRefs(grandParent)); + //PRInt32 offsetInParent; + res = GetChildOffset(blockParentNode, grandParent, offsetInParent); + PRUint32 childCount; + childNodes->GetLength(&childCount); + PRInt32 i=childCount-1; + for ( ; ((NS_SUCCEEDED(res)) && (0<=i)); i--) { - nsCOMPtrgrandParent; - blockParentNode->GetParentNode(getter_AddRefs(grandParent)); - //PRInt32 offsetInParent; - res = GetChildOffset(blockParentNode, grandParent, offsetInParent); - PRUint32 childCount; - childNodes->GetLength(&childCount); - PRInt32 i=childCount-1; - for ( ; ((NS_SUCCEEDED(res)) && (0<=i)); i--) + nsCOMPtr childNode; + res = childNodes->Item(i, getter_AddRefs(childNode)); + if ((NS_SUCCEEDED(res)) && (childNode)) { - nsCOMPtr childNode; - res = childNodes->Item(i, getter_AddRefs(childNode)); - if ((NS_SUCCEEDED(res)) && (childNode)) - { - res = DeleteNode(childNode); - if (NS_SUCCEEDED(res)) { - res = InsertNode(childNode, grandParent, offsetInParent); - } + res = DeleteNode(childNode); + if (NS_SUCCEEDED(res)) { + res = InsertNode(childNode, grandParent, offsetInParent); } } - if (gNoisy) { printf("removing the old block parent %p\n", blockParentNode.get()); } - res = DeleteNode(blockParentNode); } + if (gNoisy) { printf("removing the old block parent %p\n", blockParentNode.get()); } + res = DeleteNode(blockParentNode); } } return res; @@ -3849,29 +3943,34 @@ nsHTMLEditor::ReParentContentOfRange(nsIDOMRange *aRange, nsresult res; nsISupportsArray *blockSections; res = NS_NewISupportsArray(&blockSections); - if ((NS_SUCCEEDED(res)) && blockSections) + if (NS_FAILED(res)) return res; + if (!blockSections) return NS_ERROR_NULL_POINTER; + + res = GetBlockSectionsForRange(aRange, blockSections); + if (NS_FAILED(res)) return res; + + // no embedded returns allowed below here in this method, or you'll get a space leak + nsIDOMRange *subRange; + subRange = (nsIDOMRange *)(blockSections->ElementAt(0)); + while (subRange) { - res = GetBlockSectionsForRange(aRange, blockSections); - if (NS_SUCCEEDED(res)) + nsCOMPtrstartParent; + res = subRange->GetStartParent(getter_AddRefs(startParent)); + if (NS_SUCCEEDED(res) && startParent) { - nsIDOMRange *subRange; - subRange = (nsIDOMRange *)(blockSections->ElementAt(0)); - while (subRange && (NS_SUCCEEDED(res))) - { - nsCOMPtrstartParent; - res = subRange->GetStartParent(getter_AddRefs(startParent)); - if (NS_SUCCEEDED(res) && startParent) - { - if (gNoisy) { printf("ReParentContentOfRange calling ReParentContentOfNode\n"); } - res = ReParentContentOfNode(startParent, aParentTag, aTranformation); - } - NS_RELEASE(subRange); - blockSections->RemoveElementAt(0); - subRange = (nsIDOMRange *)(blockSections->ElementAt(0)); - } + if (gNoisy) { printf("ReParentContentOfRange calling ReParentContentOfNode\n"); } + res = ReParentContentOfNode(startParent, aParentTag, aTranformation); } - NS_RELEASE(blockSections); + NS_RELEASE(subRange); + if (NS_FAILED(res)) + { // be sure to break after free of subRange + break; + } + blockSections->RemoveElementAt(0); + subRange = (nsIDOMRange *)(blockSections->ElementAt(0)); } + NS_RELEASE(blockSections); + return res; } @@ -3883,23 +3982,27 @@ nsHTMLEditor::RemoveParagraphStyleFromRange(nsIDOMRange *aRange) nsresult res; nsISupportsArray *blockSections; res = NS_NewISupportsArray(&blockSections); - if ((NS_SUCCEEDED(res)) && blockSections) + if (NS_FAILED(res)) return res; + if (!blockSections) return NS_ERROR_NULL_POINTER; + + res = GetBlockSectionsForRange(aRange, blockSections); + if (NS_FAILED(res)) return res; + + nsIDOMRange *subRange; + subRange = (nsIDOMRange *)(blockSections->ElementAt(0)); + while (subRange) { - res = GetBlockSectionsForRange(aRange, blockSections); - if (NS_SUCCEEDED(res)) - { - nsIDOMRange *subRange; - subRange = (nsIDOMRange *)(blockSections->ElementAt(0)); - while (subRange && (NS_SUCCEEDED(res))) - { - res = RemoveParagraphStyleFromBlockContent(subRange); - NS_RELEASE(subRange); - blockSections->RemoveElementAt(0); - subRange = (nsIDOMRange *)(blockSections->ElementAt(0)); - } - } - NS_RELEASE(blockSections); + res = RemoveParagraphStyleFromBlockContent(subRange); + NS_RELEASE(subRange); + if (NS_FAILED(res)) + { // be sure to break after subrange is released + break; + } + blockSections->RemoveElementAt(0); + subRange = (nsIDOMRange *)(blockSections->ElementAt(0)); } + NS_RELEASE(blockSections); + return res; } @@ -3912,7 +4015,9 @@ nsHTMLEditor::RemoveParagraphStyleFromBlockContent(nsIDOMRange *aRange) aRange->GetStartParent(getter_AddRefs(startParent)); nsCOMPtrblockParentElement; res = GetBlockParent(startParent, getter_AddRefs(blockParentElement)); - while ((NS_SUCCEEDED(res)) && blockParentElement) + if (NS_FAILED(res)) return res; + + while (blockParentElement) { nsAutoString blockParentTag; blockParentElement->GetTagName(blockParentTag); @@ -3930,6 +4035,9 @@ nsHTMLEditor::RemoveParagraphStyleFromBlockContent(nsIDOMRange *aRange) { nsCOMPtrgrandParent; blockParentElement->GetParentNode(getter_AddRefs(grandParent)); + if (NS_FAILED(res)) return res; + if (!grandParent) return NS_ERROR_NULL_POINTER; + PRInt32 offsetInParent; res = GetChildOffset(blockParentElement, grandParent, offsetInParent); PRUint32 childCount; @@ -3942,17 +4050,22 @@ nsHTMLEditor::RemoveParagraphStyleFromBlockContent(nsIDOMRange *aRange) if ((NS_SUCCEEDED(res)) && (childNode)) { res = DeleteNode(childNode); - if (NS_SUCCEEDED(res)) { + if (NS_SUCCEEDED(res)) + { res = InsertNode(childNode, grandParent, offsetInParent); - } + if (NS_FAILED(res)) return res; + } } } - if (NS_SUCCEEDED(res)) { + if (NS_SUCCEEDED(res)) + { res = DeleteNode(blockParentElement); + if (NS_FAILED(res)) return res; } } } res = GetBlockParent(startParent, getter_AddRefs(blockParentElement)); + if (NS_FAILED(res)) return res; } return res; } @@ -3965,23 +4078,27 @@ nsHTMLEditor::RemoveParentFromRange(const nsString &aParentTag, nsIDOMRange *aRa nsresult res; nsISupportsArray *blockSections; res = NS_NewISupportsArray(&blockSections); - if ((NS_SUCCEEDED(res)) && blockSections) + if (NS_FAILED(res)) return res; + if (!blockSections) return NS_ERROR_NULL_POINTER; + res = GetBlockSectionsForRange(aRange, blockSections); + if (NS_SUCCEEDED(res)) { - res = GetBlockSectionsForRange(aRange, blockSections); - if (NS_SUCCEEDED(res)) + nsIDOMRange *subRange; + subRange = (nsIDOMRange *)(blockSections->ElementAt(0)); + while (subRange && (NS_SUCCEEDED(res))) { - nsIDOMRange *subRange; + res = RemoveParentFromBlockContent(aParentTag, subRange); + NS_RELEASE(subRange); + if (NS_FAILED(res)) + { + break; + } + blockSections->RemoveElementAt(0); subRange = (nsIDOMRange *)(blockSections->ElementAt(0)); - while (subRange && (NS_SUCCEEDED(res))) - { - res = RemoveParentFromBlockContent(aParentTag, subRange); - NS_RELEASE(subRange); - blockSections->RemoveElementAt(0); - subRange = (nsIDOMRange *)(blockSections->ElementAt(0)); - } } - NS_RELEASE(blockSections); } + NS_RELEASE(blockSections); + return res; } @@ -3992,55 +4109,59 @@ nsHTMLEditor::RemoveParentFromBlockContent(const nsString &aParentTag, nsIDOMRan nsresult res; nsCOMPtrstartParent; res = aRange->GetStartParent(getter_AddRefs(startParent)); - if ((NS_SUCCEEDED(res)) && startParent) - { - nsCOMPtrparentNode; - nsCOMPtrparentElement; - res = startParent->GetParentNode(getter_AddRefs(parentNode)); - while ((NS_SUCCEEDED(res)) && parentNode) + if (NS_FAILED(res)) return res; + if (!startParent) return NS_ERROR_NULL_POINTER; + + nsCOMPtrparentNode; + nsCOMPtrparentElement; + res = startParent->GetParentNode(getter_AddRefs(parentNode)); + if (NS_FAILED(res)) return res; + + while (parentNode) + { + parentElement = do_QueryInterface(parentNode); + nsAutoString parentTag; + parentElement->GetTagName(parentTag); + PRBool isRoot; + IsRootTag(parentTag, isRoot); + if (aParentTag.EqualsIgnoreCase(parentTag)) { - parentElement = do_QueryInterface(parentNode); - nsAutoString parentTag; - parentElement->GetTagName(parentTag); - PRBool isRoot; - IsRootTag(parentTag, isRoot); - if (aParentTag.EqualsIgnoreCase(parentTag)) + // go through list backwards so deletes don't interfere with the iteration + nsCOMPtr childNodes; + res = parentElement->GetChildNodes(getter_AddRefs(childNodes)); + if (NS_FAILED(res)) return res; + if (!childNodes) return NS_ERROR_NULL_POINTER; + + nsCOMPtrgrandParent; + parentElement->GetParentNode(getter_AddRefs(grandParent)); + PRInt32 offsetInParent; + res = GetChildOffset(parentElement, grandParent, offsetInParent); + if (NS_FAILED(res)) return res; + + PRUint32 childCount; + childNodes->GetLength(&childCount); + PRInt32 i=childCount-1; + for ( ; ((NS_SUCCEEDED(res)) && (0<=i)); i--) { - // go through list backwards so deletes don't interfere with the iteration - nsCOMPtr childNodes; - res = parentElement->GetChildNodes(getter_AddRefs(childNodes)); - if ((NS_SUCCEEDED(res)) && (childNodes)) - { - nsCOMPtrgrandParent; - parentElement->GetParentNode(getter_AddRefs(grandParent)); - PRInt32 offsetInParent; - res = GetChildOffset(parentElement, grandParent, offsetInParent); - PRUint32 childCount; - childNodes->GetLength(&childCount); - PRInt32 i=childCount-1; - for ( ; ((NS_SUCCEEDED(res)) && (0<=i)); i--) - { - nsCOMPtr childNode; - res = childNodes->Item(i, getter_AddRefs(childNode)); - if ((NS_SUCCEEDED(res)) && (childNode)) - { - res = DeleteNode(childNode); - if (NS_SUCCEEDED(res)) { - res = InsertNode(childNode, grandParent, offsetInParent); - } - } - } - if (NS_SUCCEEDED(res)) { - res = DeleteNode(parentElement); - } - } - break; + nsCOMPtr childNode; + res = childNodes->Item(i, getter_AddRefs(childNode)); + if (NS_FAILED(res)) return res; + if (!childNode) return NS_ERROR_NULL_POINTER; + res = DeleteNode(childNode); + if (NS_FAILED(res)) return res; + res = InsertNode(childNode, grandParent, offsetInParent); + if (NS_FAILED(res)) return res; } - else if (PR_TRUE==isRoot) { // hit a local root node, terminate loop - break; - } - res = parentElement->GetParentNode(getter_AddRefs(parentNode)); + res = DeleteNode(parentElement); + if (NS_FAILED(res)) { return res; } + + break; } + else if (PR_TRUE==isRoot) { // hit a local root node, terminate loop + break; + } + res = parentElement->GetParentNode(getter_AddRefs(parentNode)); + if (NS_FAILED(res)) return res; } return res; } @@ -4053,23 +4174,22 @@ PRBool nsHTMLEditor::IsElementInBody(nsIDOMElement* aElement) { nsIDOMElement* bodyElement = nsnull; nsresult res = nsEditor::GetBodyElement(&bodyElement); - if (NS_SUCCEEDED(res) && bodyElement) + if (NS_FAILED(res)) return res; + if (!bodyElement) return NS_ERROR_NULL_POINTER; + nsCOMPtr parent; + nsCOMPtr currentElement = do_QueryInterface(aElement); + if (currentElement) { - nsCOMPtr parent; - nsCOMPtr currentElement = do_QueryInterface(aElement); - if (currentElement) - { - do { - currentElement->GetParentNode(getter_AddRefs(parent)); - if (parent) - { - if (parent == bodyElement) - return PR_TRUE; + do { + currentElement->GetParentNode(getter_AddRefs(parent)); + if (parent) + { + if (parent == bodyElement) + return PR_TRUE; - currentElement = parent; - } - } while(parent); - } + currentElement = parent; + } + } while(parent); } } return PR_FALSE; @@ -4134,7 +4254,7 @@ nsHTMLEditor::SetCaretInTableCell(nsIDOMElement* aElement) // Set selection at beginning of deepest node // Should we set nsCOMPtr selection; - res = nsEditor::GetSelection(getter_AddRefs(selection)); + res = GetSelection(getter_AddRefs(selection)); if (NS_SUCCEEDED(res) && selection) { res = selection->Collapse(parent, offset); @@ -4211,141 +4331,141 @@ nsHTMLEditor::DeleteSelectionAndPrepareToCreateNode(nsCOMPtr &parent nsresult result=NS_ERROR_NOT_INITIALIZED; nsCOMPtr selection; result = GetSelection(getter_AddRefs(selection)); - if ((NS_SUCCEEDED(result)) && selection) + if (NS_FAILED(result)) return result; + if (!selection) return NS_ERROR_NULL_POINTER; + + PRBool collapsed; + result = selection->GetIsCollapsed(&collapsed); + if (NS_SUCCEEDED(result) && !collapsed) { - PRBool collapsed; - result = selection->GetIsCollapsed(&collapsed); - if (NS_SUCCEEDED(result) && !collapsed) - { - result = DeleteSelection(nsIEditor::eDoNothing); - if (NS_FAILED(result)) { - return result; - } - // get the new selection - result = GetSelection(getter_AddRefs(selection)); - if (NS_FAILED(result)) { - return result; - } + result = DeleteSelection(nsIEditor::eDoNothing); + if (NS_FAILED(result)) { + return result; + } + // get the new selection + result = GetSelection(getter_AddRefs(selection)); + if (NS_FAILED(result)) { + return result; + } #ifdef NS_DEBUG - nsCOMPtrtestSelectedNode; - nsresult debugResult = selection->GetAnchorNode(getter_AddRefs(testSelectedNode)); - // no selection is ok. - // if there is a selection, it must be collapsed - if (testSelectedNode) - { - PRBool testCollapsed; - debugResult = selection->GetIsCollapsed(&testCollapsed); - NS_ASSERTION((NS_SUCCEEDED(result)), "couldn't get a selection after deletion"); - NS_ASSERTION(PR_TRUE==testCollapsed, "selection not reset after deletion"); - } -#endif - } - // split the selected node - PRInt32 offsetOfSelectedNode; - result = selection->GetAnchorNode(getter_AddRefs(parentSelectedNode)); - if (NS_SUCCEEDED(result) && NS_SUCCEEDED(selection->GetAnchorOffset(&offsetOfSelectedNode)) && parentSelectedNode) + nsCOMPtrtestSelectedNode; + nsresult debugResult = selection->GetAnchorNode(getter_AddRefs(testSelectedNode)); + // no selection is ok. + // if there is a selection, it must be collapsed + if (testSelectedNode) { - nsCOMPtr selectedNode; - PRUint32 selectedNodeContentCount=0; - nsCOMPtrselectedParentNodeAsText; - selectedParentNodeAsText = do_QueryInterface(parentSelectedNode); + PRBool testCollapsed; + debugResult = selection->GetIsCollapsed(&testCollapsed); + NS_ASSERTION((NS_SUCCEEDED(result)), "couldn't get a selection after deletion"); + NS_ASSERTION(PR_TRUE==testCollapsed, "selection not reset after deletion"); + } +#endif + } + // split the selected node + PRInt32 offsetOfSelectedNode; + result = selection->GetAnchorNode(getter_AddRefs(parentSelectedNode)); + if (NS_SUCCEEDED(result) && NS_SUCCEEDED(selection->GetAnchorOffset(&offsetOfSelectedNode)) && parentSelectedNode) + { + nsCOMPtr selectedNode; + PRUint32 selectedNodeContentCount=0; + nsCOMPtrselectedParentNodeAsText; + selectedParentNodeAsText = do_QueryInterface(parentSelectedNode); - /* if the selection is a text node, split the text node if necesary - and compute where to put the new node - */ - if (selectedParentNodeAsText) - { - PRInt32 indexOfTextNodeInParent; - selectedNode = do_QueryInterface(parentSelectedNode); - selectedNode->GetParentNode(getter_AddRefs(parentSelectedNode)); - selectedParentNodeAsText->GetLength(&selectedNodeContentCount); - GetChildOffset(selectedNode, parentSelectedNode, indexOfTextNodeInParent); + /* if the selection is a text node, split the text node if necesary + and compute where to put the new node + */ + if (selectedParentNodeAsText) + { + PRInt32 indexOfTextNodeInParent; + selectedNode = do_QueryInterface(parentSelectedNode); + selectedNode->GetParentNode(getter_AddRefs(parentSelectedNode)); + selectedParentNodeAsText->GetLength(&selectedNodeContentCount); + GetChildOffset(selectedNode, parentSelectedNode, indexOfTextNodeInParent); - if ((offsetOfSelectedNode!=0) && (((PRUint32)offsetOfSelectedNode)!=selectedNodeContentCount)) - { - nsCOMPtr newSiblingNode; - result = SplitNode(selectedNode, offsetOfSelectedNode, getter_AddRefs(newSiblingNode)); - // now get the node's offset in it's parent, and insert the new tag there - if (NS_SUCCEEDED(result)) { - result = GetChildOffset(selectedNode, parentSelectedNode, offsetOfNewNode); - } - } - else - { // determine where to insert the new node - if (0==offsetOfSelectedNode) { - offsetOfNewNode = indexOfTextNodeInParent; // insert new node as previous sibling to selection parent - } - else { // insert new node as last child - GetChildOffset(selectedNode, parentSelectedNode, offsetOfNewNode); - offsetOfNewNode++; // offsets are 0-based, and we need the index of the new node - } + if ((offsetOfSelectedNode!=0) && (((PRUint32)offsetOfSelectedNode)!=selectedNodeContentCount)) + { + nsCOMPtr newSiblingNode; + result = SplitNode(selectedNode, offsetOfSelectedNode, getter_AddRefs(newSiblingNode)); + // now get the node's offset in it's parent, and insert the new tag there + if (NS_SUCCEEDED(result)) { + result = GetChildOffset(selectedNode, parentSelectedNode, offsetOfNewNode); } } - /* if the selection is not a text node, split the parent node if necesary - and compute where to put the new node - */ - else - { // it's an interior node - nsCOMPtrparentChildList; - parentSelectedNode->GetChildNodes(getter_AddRefs(parentChildList)); - if ((NS_SUCCEEDED(result)) && parentChildList) + else + { // determine where to insert the new node + if (0==offsetOfSelectedNode) { + offsetOfNewNode = indexOfTextNodeInParent; // insert new node as previous sibling to selection parent + } + else { // insert new node as last child + GetChildOffset(selectedNode, parentSelectedNode, offsetOfNewNode); + offsetOfNewNode++; // offsets are 0-based, and we need the index of the new node + } + } + } + /* if the selection is not a text node, split the parent node if necesary + and compute where to put the new node + */ + else + { // it's an interior node + nsCOMPtrparentChildList; + parentSelectedNode->GetChildNodes(getter_AddRefs(parentChildList)); + if ((NS_SUCCEEDED(result)) && parentChildList) + { + result = parentChildList->Item(offsetOfSelectedNode, getter_AddRefs(selectedNode)); + if ((NS_SUCCEEDED(result)) && selectedNode) { - result = parentChildList->Item(offsetOfSelectedNode, getter_AddRefs(selectedNode)); - if ((NS_SUCCEEDED(result)) && selectedNode) + nsCOMPtrselectedNodeAsText; + selectedNodeAsText = do_QueryInterface(selectedNode); + nsCOMPtrchildList; + //CM: I added "result =" + result = selectedNode->GetChildNodes(getter_AddRefs(childList)); + if (NS_SUCCEEDED(result)) { - nsCOMPtrselectedNodeAsText; - selectedNodeAsText = do_QueryInterface(selectedNode); - nsCOMPtrchildList; - //CM: I added "result =" - result = selectedNode->GetChildNodes(getter_AddRefs(childList)); - if (NS_SUCCEEDED(result)) + if (childList) { - if (childList) - { - childList->GetLength(&selectedNodeContentCount); - } - else - { - // This is the case where the collapsed selection offset - // points to an inline node with no children - // This must also be where the new node should be inserted - // and there is no splitting necessary - offsetOfNewNode = offsetOfSelectedNode; - return NS_OK; - } - } + childList->GetLength(&selectedNodeContentCount); + } else { - return NS_ERROR_FAILURE; + // This is the case where the collapsed selection offset + // points to an inline node with no children + // This must also be where the new node should be inserted + // and there is no splitting necessary + offsetOfNewNode = offsetOfSelectedNode; + return NS_OK; } - if ((offsetOfSelectedNode!=0) && (((PRUint32)offsetOfSelectedNode)!=selectedNodeContentCount)) - { - nsCOMPtr newSiblingNode; - result = SplitNode(selectedNode, offsetOfSelectedNode, getter_AddRefs(newSiblingNode)); - // now get the node's offset in it's parent, and insert the new tag there - if (NS_SUCCEEDED(result)) { - result = GetChildOffset(selectedNode, parentSelectedNode, offsetOfNewNode); - } + } + else + { + return NS_ERROR_FAILURE; + } + if ((offsetOfSelectedNode!=0) && (((PRUint32)offsetOfSelectedNode)!=selectedNodeContentCount)) + { + nsCOMPtr newSiblingNode; + result = SplitNode(selectedNode, offsetOfSelectedNode, getter_AddRefs(newSiblingNode)); + // now get the node's offset in it's parent, and insert the new tag there + if (NS_SUCCEEDED(result)) { + result = GetChildOffset(selectedNode, parentSelectedNode, offsetOfNewNode); } - else - { // determine where to insert the new node - if (0==offsetOfSelectedNode) { - offsetOfNewNode = 0; // insert new node as first child - } - else { // insert new node as last child - GetChildOffset(selectedNode, parentSelectedNode, offsetOfNewNode); - offsetOfNewNode++; // offsets are 0-based, and we need the index of the new node - } + } + else + { // determine where to insert the new node + if (0==offsetOfSelectedNode) { + offsetOfNewNode = 0; // insert new node as first child + } + else { // insert new node as last child + GetChildOffset(selectedNode, parentSelectedNode, offsetOfNewNode); + offsetOfNewNode++; // offsets are 0-based, and we need the index of the new node } } } } + } - // Here's where the new node was inserted - } - else { - printf("InsertBreak into an empty document is not yet supported\n"); - } + // Here's where the new node was inserted + } + else { + printf("InsertBreak into an empty document is not yet supported\n"); } return result; } @@ -4384,7 +4504,7 @@ nsCOMPtr nsHTMLEditor::FindPreElement() void nsHTMLEditor::HandleEventListenerError() { - printf("failed to add event listener\n"); + if (gNoisy) { printf("failed to add event listener\n"); } // null out the nsCOMPtrs mKeyListenerP = nsnull; mMouseListenerP = nsnull; @@ -4430,48 +4550,48 @@ nsHTMLEditor::SetTextPropertiesForNode(nsIDOMNode *aNode, { nsCOMPtrnewStyleNode; result = nsEditor::CreateNode(tag, aParent, 0, getter_AddRefs(newStyleNode)); - if (NS_SUCCEEDED(result) && newStyleNode) + if (NS_FAILED(result)) return result; + if (!newStyleNode) return NS_ERROR_NULL_POINTER; + + nsCOMPtrnodeAsChar; + nodeAsChar = do_QueryInterface(aNode); + if (nodeAsChar) { - nsCOMPtrnodeAsChar; - nodeAsChar = do_QueryInterface(aNode); - if (nodeAsChar) - { - result = MoveContentOfNodeIntoNewParent(aNode, newStyleNode, aStartOffset, aEndOffset); - } - else - { // handle non-text selection - nsCOMPtr parent; // used just to make the code easier to understand - nsCOMPtr child; - parent = do_QueryInterface(aNode); - child = GetChildAt(parent, aStartOffset); - // XXX: need to loop for aStartOffset!=aEndOffset-1? - PRInt32 offsetInParent = aStartOffset; // remember where aNode was in aParent - if (NS_SUCCEEDED(result)) - { // remove child from parent - result = nsEditor::DeleteNode(child); + result = MoveContentOfNodeIntoNewParent(aNode, newStyleNode, aStartOffset, aEndOffset); + } + else + { // handle non-text selection + nsCOMPtr parent; // used just to make the code easier to understand + nsCOMPtr child; + parent = do_QueryInterface(aNode); + child = GetChildAt(parent, aStartOffset); + // XXX: need to loop for aStartOffset!=aEndOffset-1? + PRInt32 offsetInParent = aStartOffset; // remember where aNode was in aParent + if (NS_SUCCEEDED(result)) + { // remove child from parent + result = nsEditor::DeleteNode(child); + if (NS_SUCCEEDED(result)) + { // put child into the newStyleNode + result = nsEditor::InsertNode(child, newStyleNode, 0); if (NS_SUCCEEDED(result)) - { // put child into the newStyleNode - result = nsEditor::InsertNode(child, newStyleNode, 0); - if (NS_SUCCEEDED(result)) - { // put newStyleNode in parent where child was - result = nsEditor::InsertNode(newStyleNode, parent, offsetInParent); - } + { // put newStyleNode in parent where child was + result = nsEditor::InsertNode(newStyleNode, parent, offsetInParent); } } } - if (NS_SUCCEEDED(result)) + } + if (NS_SUCCEEDED(result)) + { + if (aAttribute && 0!=aAttribute->Length()) { - if (aAttribute && 0!=aAttribute->Length()) - { - nsCOMPtr newStyleElement; - newStyleElement = do_QueryInterface(newStyleNode); - nsAutoString value; - if (aValue) { - value = *aValue; - } - // XXX should be a call to editor to change attribute! - result = newStyleElement->SetAttribute(*aAttribute, value); + nsCOMPtr newStyleElement; + newStyleElement = do_QueryInterface(newStyleNode); + nsAutoString value; + if (aValue) { + value = *aValue; } + // XXX should be a call to editor to change attribute! + result = newStyleElement->SetAttribute(*aAttribute, value); } } } @@ -4571,13 +4691,12 @@ NS_IMETHODIMP nsHTMLEditor::MoveContentOfNodeIntoNewParent(nsIDOMNode *aNode, if (NS_SUCCEEDED(result)) { // set the selection nsCOMPtrselection; - result = nsEditor::GetSelection(getter_AddRefs(selection)); - if (NS_SUCCEEDED(result)) - { - selection->Collapse(newChildNode, 0); - PRInt32 endOffset = aEndOffset-aStartOffset; - selection->Extend(newChildNode, endOffset); - } + result = GetSelection(getter_AddRefs(selection)); + if (NS_FAILED(result)) return result; + if (!selection) return NS_ERROR_NULL_POINTER; + selection->Collapse(newChildNode, 0); + PRInt32 endOffset = aEndOffset-aStartOffset; + selection->Extend(newChildNode, endOffset); } } } @@ -4603,54 +4722,50 @@ nsHTMLEditor::SetTextPropertiesForNodesWithSameParent(nsIDOMNode *aStartNode, const nsString *aAttribute, const nsString *aValue) { - if (gNoisy) { printf("nsTextEditor::SetTextPropertiesForNodesWithSameParent\n"); } + if (gNoisy) { printf("---------- start nsTextEditor::SetTextPropertiesForNodesWithSameParent ----------\n"); } nsresult result=NS_OK; PRBool textPropertySet; nsCOMPtrresultNode; IsTextPropertySetByContent(aStartNode, aPropName, aAttribute, aValue, textPropertySet, getter_AddRefs(resultNode)); if (PR_FALSE==textPropertySet) { - if (aValue && 0!=aValue->Length()) - { - result = RemoveTextPropertiesForNodesWithSameParent(aStartNode, aStartOffset, - aEndNode, aEndOffset, - aParent, aPropName, aAttribute); - } + result = RemoveTextPropertiesForNodeWithDifferentParents(aStartNode, aStartOffset, + aEndNode, aEndOffset, + aParent, aPropName, aAttribute); + if (NS_FAILED(result)) return result; + nsAutoString tag; aPropName->ToString(tag); // create the new style node, which will be the new parent for the selected nodes nsCOMPtrnewStyleNode; nsCOMPtrdoc; result = GetDocument(getter_AddRefs(doc)); - if (NS_SUCCEEDED(result) && doc) + if (NS_FAILED(result)) return result; + if (!doc) return NS_ERROR_NULL_POINTER; + + nsCOMPtrnewElement; + result = doc->CreateElement(tag, getter_AddRefs(newElement)); + if (NS_FAILED(result)) return result; + if (!newElement) return NS_ERROR_NULL_POINTER; + + newStyleNode = do_QueryInterface(newElement); + if (!newStyleNode) return NS_ERROR_NULL_POINTER; + result = MoveContiguousContentIntoNewParent(aStartNode, aStartOffset, aEndNode, aEndOffset, aParent, newStyleNode); + if (NS_SUCCEEDED(result) && aAttribute && 0!=aAttribute->Length()) { - nsCOMPtrnewElement; - result = doc->CreateElement(tag, getter_AddRefs(newElement)); - if (NS_SUCCEEDED(result) && newElement) - { - newStyleNode = do_QueryInterface(newElement); - } - } - if (NS_SUCCEEDED(result) && newStyleNode) - { - result = MoveContiguousContentIntoNewParent(aStartNode, aStartOffset, aEndNode, aEndOffset, aParent, newStyleNode); - if (NS_SUCCEEDED(result) && aAttribute && 0!=aAttribute->Length()) - { - nsCOMPtr newStyleElement; - newStyleElement = do_QueryInterface(newStyleNode); - nsAutoString value; - if (aValue) { - value = *aValue; - } - result = newStyleElement->SetAttribute(*aAttribute, value); + nsCOMPtr newStyleElement; + newStyleElement = do_QueryInterface(newStyleNode); + nsAutoString value; + if (aValue) { + value = *aValue; } + result = newStyleElement->SetAttribute(*aAttribute, value); } } + if (gNoisy) { printf("---------- end nsTextEditor::SetTextPropertiesForNodesWithSameParent ----------\n"); } return result; } -//XXX won't work for selections that are not leaf nodes! -// should fix up the end points to make sure they are leaf nodes NS_IMETHODIMP nsHTMLEditor::MoveContiguousContentIntoNewParent(nsIDOMNode *aStartNode, PRInt32 aStartOffset, @@ -4660,7 +4775,8 @@ nsHTMLEditor::MoveContiguousContentIntoNewParent(nsIDOMNode *aStartNode, nsIDOMNode *aNewParentNode) { if (!aStartNode || !aEndNode || !aNewParentNode) { return NS_ERROR_NULL_POINTER; } - if (gNoisy) { printf("nsTextEditor::MoveContiguousContentIntoNewParent\n"); } + if (gNoisy) { printf("--- start nsTextEditor::MoveContiguousContentIntoNewParent ---\n"); } + if (gNoisy) {DebugDumpContent(); } // DEBUG nsresult result = NS_OK; nsCOMPtrstartNode, endNode; @@ -4676,6 +4792,7 @@ nsHTMLEditor::MoveContiguousContentIntoNewParent(nsIDOMNode *aStartNode, { result = nsEditor::SplitNode(aStartNode, aStartOffset, getter_AddRefs(newLeftNode)); if (gNoisy) { printf("split aStartNode, newLeftNode = %p\n", newLeftNode.get()); } + if (gNoisy) {DebugDumpContent(); } // DEBUG } else { if (gNoisy) { printf("did not split aStartNode\n"); } @@ -4698,6 +4815,7 @@ nsHTMLEditor::MoveContiguousContentIntoNewParent(nsIDOMNode *aStartNode, { result = nsEditor::SplitNode(aEndNode, aEndOffset, getter_AddRefs(newRightNode)); if (gNoisy) { printf("split aEndNode, newRightNode = %p\n", newRightNode.get()); } + if (gNoisy) {DebugDumpContent(); } // DEBUG } else { newRightNode = do_QueryInterface(aEndNode); @@ -4726,6 +4844,8 @@ nsHTMLEditor::MoveContiguousContentIntoNewParent(nsIDOMNode *aStartNode, { // insert aNewParentNode into aGrandParentNode result = nsEditor::InsertNode(aNewParentNode, aGrandParentNode, offsetInParent); + if (gNoisy) printf("just after InsertNode 1\n"); + if (gNoisy) {DebugDumpContent(); } // DEBUG if (NS_SUCCEEDED(result)) { // move the right half of the start node into the new parent node nsCOMPtrintermediateNode; @@ -4733,10 +4853,14 @@ nsHTMLEditor::MoveContiguousContentIntoNewParent(nsIDOMNode *aStartNode, if (NS_SUCCEEDED(result)) { result = nsEditor::DeleteNode(startNode); + if (gNoisy) printf("just after DeleteNode 1\n"); + if (gNoisy) {DebugDumpContent(); } // DEBUG if (NS_SUCCEEDED(result)) { PRInt32 childIndex=0; result = nsEditor::InsertNode(startNode, aNewParentNode, childIndex); + if (gNoisy) printf("just after InsertNode 2\n"); + if (gNoisy) {DebugDumpContent(); } // DEBUG childIndex++; if (NS_SUCCEEDED(result)) { // move all the intermediate nodes into the new parent node @@ -4751,8 +4875,13 @@ nsHTMLEditor::MoveContiguousContentIntoNewParent(nsIDOMNode *aStartNode, // get the next sibling before moving the current child!!! intermediateNode->GetNextSibling(getter_AddRefs(nextSibling)); result = nsEditor::DeleteNode(intermediateNode); - if (NS_SUCCEEDED(result)) { + if (gNoisy) printf("just after DeleteNode 3\n"); + if (gNoisy) {DebugDumpContent(); } // DEBUG + if (NS_SUCCEEDED(result)) + { result = nsEditor::InsertNode(intermediateNode, aNewParentNode, childIndex); + if (gNoisy) printf("just after InsertNode 4\n"); + if (gNoisy) {DebugDumpContent(); } // DEBUG childIndex++; } intermediateNode = do_QueryInterface(nextSibling); @@ -4760,19 +4889,22 @@ nsHTMLEditor::MoveContiguousContentIntoNewParent(nsIDOMNode *aStartNode, if (NS_SUCCEEDED(result)) { // move the left half of the end node into the new parent node result = nsEditor::DeleteNode(newRightNode); + if (gNoisy) printf("just after DeleteNode 5\n"); + if (gNoisy) {DebugDumpContent(); } // DEBUG if (NS_SUCCEEDED(result)) { result = nsEditor::InsertNode(newRightNode, aNewParentNode, childIndex); + if (gNoisy) printf("just after InsertNode 5\n"); + if (gNoisy) {DebugDumpContent(); } // DEBUG // now set the selection if (NS_SUCCEEDED(result)) { nsCOMPtrselection; - result = nsEditor::GetSelection(getter_AddRefs(selection)); - if (NS_SUCCEEDED(result)) - { - selection->Collapse(startNode, startOffset); - selection->Extend(newRightNode, endOffset); - } + result = GetSelection(getter_AddRefs(selection)); + if (NS_FAILED(result)) return result; + if (!selection) return NS_ERROR_NULL_POINTER; + selection->Collapse(startNode, startOffset); + selection->Extend(newRightNode, endOffset); } } } @@ -4783,6 +4915,8 @@ nsHTMLEditor::MoveContiguousContentIntoNewParent(nsIDOMNode *aStartNode, } } } + if (gNoisy) { printf("--- end nsTextEditor::MoveContiguousContentIntoNewParent ---\n"); } + if (gNoisy) {DebugDumpContent(); } // DEBUG return result; } @@ -4822,7 +4956,7 @@ nsHTMLEditor::SetTextPropertiesForNodeWithDifferentParents(nsIDOMRange *aRange, // RemoveTextProperties... might have changed selection endpoints, get new ones nsCOMPtrselection; - result = nsEditor::GetSelection(getter_AddRefs(selection)); + result = GetSelection(getter_AddRefs(selection)); if (NS_FAILED(result)) { return result; } if (!selection) { return NS_ERROR_NULL_POINTER; } selection->GetAnchorOffset(&aStartOffset); @@ -4832,164 +4966,174 @@ nsHTMLEditor::SetTextPropertiesForNodeWithDifferentParents(nsIDOMRange *aRange, nsCOMPtriter; result = nsComponentManager::CreateInstance(kCContentIteratorCID, nsnull, nsIContentIterator::GetIID(), getter_AddRefs(iter)); - if ((NS_SUCCEEDED(result)) && iter) + if (NS_FAILED(result)) return result; + if (!iter) return NS_ERROR_NULL_POINTER; + + // find our starting point + PRBool startIsText = IsTextNode(aStartNode); + nsCOMPtrstartContent; + if (PR_TRUE==startIsText) { + startContent = do_QueryInterface(aStartNode); + } + else { + nsCOMPtrnode = GetChildAt(aStartNode, aStartOffset); + startContent = do_QueryInterface(node); + } + + // find our ending point + PRBool endIsText = IsTextNode(aEndNode); + nsCOMPtrendContent; + if (PR_TRUE==endIsText) { + endContent = do_QueryInterface(aEndNode); + } + else { - // find our starting point - PRBool startIsText = IsTextNode(aStartNode); - nsCOMPtrstartContent; - if (PR_TRUE==startIsText) { - startContent = do_QueryInterface(aStartNode); + nsCOMPtrtheEndNode; + if (aEndOffset>0) + { + theEndNode = GetChildAt(aEndNode, aEndOffset-1); } else { - nsCOMPtrnode = GetChildAt(aStartNode, aStartOffset); - startContent = do_QueryInterface(node); + // XXX: we need to find the previous node and set the selection correctly + NS_ASSERTION(0, "unexpected selection"); + return NS_ERROR_NOT_IMPLEMENTED; } + endContent = do_QueryInterface(theEndNode); + } - // find our ending point - PRBool endIsText = IsTextNode(aEndNode); - nsCOMPtrendContent; - if (PR_TRUE==endIsText) { - endContent = do_QueryInterface(aEndNode); - } - else + if (!startContent || !endContent) { return NS_ERROR_NULL_POINTER; } + // iterate over the nodes between the starting and ending points + iter->Init(aRange); + nsCOMPtr content; + iter->CurrentNode(getter_AddRefs(content)); + nsAutoString tag; + aPropName->ToString(tag); + while (NS_COMFALSE == iter->IsDone()) + { + if ((content.get() != startContent.get()) && + (content.get() != endContent.get())) { - nsCOMPtrtheEndNode; - if (aEndOffset>0) + nsCOMPtrnode; + node = do_QueryInterface(content); + if (IsEditable(node)) { - theEndNode = GetChildAt(aEndNode, aEndOffset-1); - } - else { - // XXX: we need to find the previous node and set the selection correctly - NS_ASSERTION(0, "unexpected selection"); - return NS_ERROR_NOT_IMPLEMENTED; - } - endContent = do_QueryInterface(theEndNode); - } - - if (!startContent || !endContent) { return NS_ERROR_NULL_POINTER; } - // iterate over the nodes between the starting and ending points - iter->Init(aRange); - nsCOMPtr content; - iter->CurrentNode(getter_AddRefs(content)); - nsAutoString tag; - aPropName->ToString(tag); - while (NS_COMFALSE == iter->IsDone()) - { - if ((content.get() != startContent.get()) && - (content.get() != endContent.get())) - { - nsCOMPtrnode; - node = do_QueryInterface(content); - if (IsEditable(node)) - { - PRBool canContainChildren; - content->CanContainChildren(canContainChildren); - if (PR_FALSE==canContainChildren) - { - nsEditor::GetTagString(node,tag); - if (tag != "br") // skip
, even though it's a leaf - { // only want to wrap the text node in a new style node if it doesn't already have that style - if (gNoisy) { printf("node %p is an editable leaf.\n", node.get()); } - PRBool textPropertySet; - nsCOMPtrresultNode; - IsTextPropertySetByContent(node, aPropName, aAttribute, aValue, textPropertySet, getter_AddRefs(resultNode)); - if (PR_FALSE==textPropertySet) + PRBool canContainChildren; + content->CanContainChildren(canContainChildren); + if (PR_FALSE==canContainChildren) + { + nsEditor::GetTagString(node,tag); + if (tag != "br") // skip
, even though it's a leaf + { // only want to wrap the text node in a new style node if it doesn't already have that style + if (gNoisy) { printf("node %p is an editable leaf.\n", node.get()); } + PRBool textPropertySet; + nsCOMPtrresultNode; + IsTextPropertySetByContent(node, aPropName, aAttribute, aValue, textPropertySet, getter_AddRefs(resultNode)); + if (PR_FALSE==textPropertySet) + { + if (gNoisy) { printf("property not set\n"); } + node->GetParentNode(getter_AddRefs(parent)); + if (!parent) { return NS_ERROR_NULL_POINTER; } + nsCOMPtrparentContent; + parentContent = do_QueryInterface(parent); + nsCOMPtrparentNode = do_QueryInterface(parent); + if (PR_TRUE==IsTextNode(node)) { - if (gNoisy) { printf("property not set\n"); } - node->GetParentNode(getter_AddRefs(parent)); - if (!parent) { return NS_ERROR_NULL_POINTER; } - nsCOMPtrparentContent; - parentContent = do_QueryInterface(parent); - nsCOMPtrparentNode = do_QueryInterface(parent); - if (PR_TRUE==IsTextNode(node)) - { - startOffset = 0; - result = GetLengthOfDOMNode(node, (PRUint32&)endOffset); - } - else - { - parentContent->IndexOf(content, startOffset); - endOffset = startOffset+1; - } - if (gNoisy) { printf("start/end = %d %d\n", startOffset, endOffset); } - if (NS_SUCCEEDED(result)) { - result = SetTextPropertiesForNode(node, parentNode, startOffset, endOffset, aPropName, aAttribute, aValue); - } + startOffset = 0; + result = GetLengthOfDOMNode(node, (PRUint32&)endOffset); + } + else + { + parentContent->IndexOf(content, startOffset); + endOffset = startOffset+1; + } + if (gNoisy) { printf("start/end = %d %d\n", startOffset, endOffset); } + if (NS_SUCCEEDED(result)) { + result = SetTextPropertiesForNode(node, parentNode, startOffset, endOffset, aPropName, aAttribute, aValue); } } } } - // XXX: shouldn't there be an else here for non-text leaf nodes? } - // note we don't check the result, we just rely on iter->IsDone - iter->Next(); - iter->CurrentNode(getter_AddRefs(content)); + // XXX: shouldn't there be an else here for non-text leaf nodes? } - // handle endpoints + // note we don't check the result, we just rely on iter->IsDone + iter->Next(); + iter->CurrentNode(getter_AddRefs(content)); + } + // handle endpoints + if (NS_SUCCEEDED(result)) + { + // create a style node for the text in the start parent + nsCOMPtrstartNode = do_QueryInterface(startContent); + result = startNode->GetParentNode(getter_AddRefs(parent)); + if (NS_FAILED(result)) return result; + if (!parent) return NS_ERROR_NULL_POINTER; + + nsCOMPtrnodeAsChar; + nodeAsChar = do_QueryInterface(startNode); + if (nodeAsChar) + { + nodeAsChar->GetLength(&count); + if (gNoisy) { printf("processing start node %p.\n", nodeAsChar.get()); } + if (aStartOffset!=(PRInt32)count) + { + result = SetTextPropertiesForNode(startNode, parent, aStartOffset, count, aPropName, aAttribute, aValue); + startOffset = 0; + } + } + else + { + nsCOMPtrgrandParent; + result = parent->GetParentNode(getter_AddRefs(grandParent)); + if (NS_FAILED(result)) return result; + if (!grandParent) return NS_ERROR_NULL_POINTER; + if (gNoisy) { printf("processing start node %p.\n", parent.get()); } + result = SetTextPropertiesForNode(parent, grandParent, aStartOffset, aStartOffset+1, aPropName, aAttribute, aValue); + startNode = do_QueryInterface(parent); + startOffset = aStartOffset; + } + + if (NS_SUCCEEDED(result)) { - // create a style node for the text in the start parent - nsCOMPtrstartNode = do_QueryInterface(startContent); - result = startNode->GetParentNode(getter_AddRefs(parent)); + // create a style node for the text in the end parent + nsCOMPtrendNode = do_QueryInterface(endContent); + result = endNode->GetParentNode(getter_AddRefs(parent)); if (NS_FAILED(result)) { return result; } - nsCOMPtrnodeAsChar; - nodeAsChar = do_QueryInterface(startNode); + nodeAsChar = do_QueryInterface(endNode); if (nodeAsChar) - { + { nodeAsChar->GetLength(&count); - if (gNoisy) { printf("processing start node %p.\n", nodeAsChar.get()); } - result = SetTextPropertiesForNode(startNode, parent, aStartOffset, count, aPropName, aAttribute, aValue); - startOffset = 0; + if (gNoisy) { printf("processing end node %p.\n", nodeAsChar.get()); } + if (0!=aEndOffset) + { + result = SetTextPropertiesForNode(endNode, parent, 0, aEndOffset, aPropName, aAttribute, aValue); + // SetTextPropertiesForNode kindly computed the proper selection focus node and offset for us, + // remember them here + selection->GetFocusOffset(&endOffset); + selection->GetFocusNode(getter_AddRefs(endNode)); + } } else { + NS_ASSERTION(0!=aEndOffset, "unexpected selection end offset"); + if (0==aEndOffset) { return NS_ERROR_NOT_IMPLEMENTED; } nsCOMPtrgrandParent; result = parent->GetParentNode(getter_AddRefs(grandParent)); - if (gNoisy) { printf("processing start node %p.\n", parent.get()); } - result = SetTextPropertiesForNode(parent, grandParent, aStartOffset, aStartOffset+1, aPropName, aAttribute, aValue); - startNode = do_QueryInterface(parent); - startOffset = aStartOffset; + if (NS_FAILED(result)) return result; + if (!grandParent) return NS_ERROR_NULL_POINTER; + if (gNoisy) { printf("processing end node %p.\n", parent.get()); } + result = SetTextPropertiesForNode(parent, grandParent, aEndOffset-1, aEndOffset, aPropName, aAttribute, aValue); + endNode = do_QueryInterface(parent); + endOffset = 0; } - - if (NS_SUCCEEDED(result)) { - // create a style node for the text in the end parent - nsCOMPtrendNode = do_QueryInterface(endContent); - result = endNode->GetParentNode(getter_AddRefs(parent)); - if (NS_FAILED(result)) { - return result; - } - nodeAsChar = do_QueryInterface(endNode); - if (nodeAsChar) - { - nodeAsChar->GetLength(&count); - if (gNoisy) { printf("processing end node %p.\n", nodeAsChar.get()); } - result = SetTextPropertiesForNode(endNode, parent, 0, aEndOffset, aPropName, aAttribute, aValue); - // SetTextPropertiesForNode kindly computed the proper selection focus node and offset for us, - // remember them here - selection->GetFocusOffset(&endOffset); - selection->GetFocusNode(getter_AddRefs(endNode)); - } - else - { - NS_ASSERTION(0!=aEndOffset, "unexpected selection end offset"); - if (0==aEndOffset) { return NS_ERROR_NOT_IMPLEMENTED; } - nsCOMPtrgrandParent; - result = parent->GetParentNode(getter_AddRefs(grandParent)); - if (gNoisy) { printf("processing end node %p.\n", parent.get()); } - result = SetTextPropertiesForNode(parent, grandParent, aEndOffset-1, aEndOffset, aPropName, aAttribute, aValue); - endNode = do_QueryInterface(parent); - endOffset = 0; - } - if (NS_SUCCEEDED(result)) - { - selection->Collapse(startNode, startOffset); - selection->Extend(endNode, aEndOffset); - } + selection->Collapse(startNode, startOffset); + selection->Extend(endNode, aEndOffset); } } } @@ -5222,79 +5366,8 @@ nsHTMLEditor::RemoveTextPropertiesForNodesWithSameParent(nsIDOMNode *aStartNode, nsIAtom *aPropName, const nsString *aAttribute) { - if (gNoisy) { printf("nsTextEditor::RemoveTextPropertiesForNodesWithSameParent\n"); } - nsresult result=NS_OK; - PRInt32 startOffset = aStartOffset; - PRInt32 endOffset; - nsCOMPtrnodeAsChar; - nsCOMPtrparentNode = do_QueryInterface(aParent); - - // remove aPropName from all intermediate nodes - nsCOMPtrsiblingNode; - nsCOMPtrnextSiblingNode; // temp to hold the next node in the list - result = aStartNode->GetNextSibling(getter_AddRefs(siblingNode)); - while (siblingNode && NS_SUCCEEDED(result)) - { - // get next sibling right away, before we move siblingNode! - siblingNode->GetNextSibling(getter_AddRefs(nextSiblingNode)); - if (aEndNode==siblingNode.get()) { // found the end node, handle that below - break; - } - else - { // found a sibling node between aStartNode and aEndNode, remove the style node - PRUint32 childCount=0; - nodeAsChar = do_QueryInterface(siblingNode); - if (nodeAsChar) { - nodeAsChar->GetLength(&childCount); - } - else - { - nsCOMPtrgrandChildNodes; - result = siblingNode->GetChildNodes(getter_AddRefs(grandChildNodes)); - if (NS_SUCCEEDED(result) && grandChildNodes) { - grandChildNodes->GetLength(&childCount); - } - if (0==childCount) - { // node has no children - // XXX: for now, I think that's ok. just pass in 0 - } - } - if (NS_SUCCEEDED(result)) { - siblingNode->GetParentNode(getter_AddRefs(parentNode)); - result = RemoveTextPropertiesForNode(siblingNode, parentNode, 0, childCount, aPropName, aAttribute); - } - } - siblingNode = do_QueryInterface(nextSiblingNode); - } - if (NS_SUCCEEDED(result)) - { - // remove aPropName from aStartNode - //nsCOMPtrnodeAsChar; - nodeAsChar = do_QueryInterface(aStartNode); - if (nodeAsChar) { - nodeAsChar->GetLength((PRUint32 *)&endOffset); - } - else - { - if (gNoisy) { printf("not yet supported\n");} - return NS_ERROR_NOT_IMPLEMENTED; - } - result = aStartNode->GetParentNode(getter_AddRefs(parentNode)); - if (NS_SUCCEEDED(result)) { - result = RemoveTextPropertiesForNode(aStartNode, parentNode, startOffset, endOffset, aPropName, aAttribute); - } - } - if (NS_SUCCEEDED(result)) - { - // remove aPropName from the end node - startOffset = 0; - endOffset = aEndOffset; - result = aEndNode->GetParentNode(getter_AddRefs(parentNode)); - if (NS_SUCCEEDED(result)) { - result = RemoveTextPropertiesForNode(aEndNode, parentNode, startOffset, endOffset, aPropName, aAttribute); - } - } - return result; + NS_ASSERTION(0, "obsolete"); + return NS_ERROR_NOT_IMPLEMENTED; } NS_IMETHODIMP @@ -5306,7 +5379,7 @@ nsHTMLEditor::RemoveTextPropertiesForNodeWithDifferentParents(nsIDOMNode *aStar nsIAtom *aPropName, const nsString *aAttribute) { - if (gNoisy) { printf("start nsTextEditor::RemoveTextPropertiesForNodeWithDifferentParents\n"); } + if (gNoisy) { printf("----- start nsTextEditor::RemoveTextPropertiesForNodeWithDifferentParents-----\n"); } nsresult result=NS_OK; if (!aStartNode || !aEndNode || !aParent || !aPropName) return NS_ERROR_NULL_POINTER; @@ -5323,6 +5396,7 @@ nsHTMLEditor::RemoveTextPropertiesForNodeWithDifferentParents(nsIDOMNode *aStar nsCOMPtrendNode = do_QueryInterface(aEndNode); // use computed endpoint based on end points passed in nsCOMPtrparent; // the parent of the node we're operating on PRBool skippedStartNode = PR_FALSE; // we skip the start node if aProp is not set on it + PRBool skippedEndNode = PR_FALSE; // we skip the end node if aProp is not set on it PRUint32 count; nsCOMPtrnodeAsChar; nodeAsChar = do_QueryInterface(startNode); @@ -5377,7 +5451,8 @@ nsHTMLEditor::RemoveTextPropertiesForNodeWithDifferentParents(nsIDOMNode *aStar if (nodeAsChar) { result = endNode->GetParentNode(getter_AddRefs(parent)); - if (NS_FAILED(result)) { return result; } + if (NS_FAILED(result)) return result; + if (!parent) return NS_ERROR_NULL_POINTER; nodeAsChar->GetLength(&count); if (aEndOffset!=0) { // only do this if at least one child is selected @@ -5385,20 +5460,37 @@ nsHTMLEditor::RemoveTextPropertiesForNodeWithDifferentParents(nsIDOMNode *aStar if (PR_TRUE==textPropertySet) { result = RemoveTextPropertiesForNode(endNode, parent, 0, aEndOffset, aPropName, aAttribute); - if (0!=aEndOffset) { + if (0!=aEndOffset && (((PRInt32)count)!=aEndOffset)) { rangeEndOffset = 0; // we split endNode at aEndOffset and it is the right node now } } - else { if (gNoisy) { printf("skipping end node because aProperty not set.\n"); } } + else + { + skippedEndNode = PR_TRUE; + if (gNoisy) { printf("skipping end node because aProperty not set.\n"); } + } } - else { if (gNoisy) { printf("skipping end node because aEndOffset==0\n"); } } + else + { + skippedEndNode = PR_TRUE; + if (gNoisy) { printf("skipping end node because aEndOffset==0\n"); } + } } else { endNode = GetChildAt(aEndNode, aEndOffset); parent = do_QueryInterface(aEndNode); if (!endNode || !parent) {return NS_ERROR_NULL_POINTER;} - result = RemoveTextPropertiesForNode(endNode, parent, aEndOffset, aEndOffset+1, aPropName, aAttribute); + IsTextPropertySetByContent(endNode, aPropName, aAttribute, nsnull, textPropertySet, getter_AddRefs(resultNode)); + if (PR_TRUE==textPropertySet) + { + result = RemoveTextPropertiesForNode(endNode, parent, aEndOffset, aEndOffset+1, aPropName, aAttribute); + } + else + { + skippedEndNode = PR_TRUE; + if (gNoisy) { printf("skipping end node because property not set\n"); } + } } } @@ -5433,42 +5525,42 @@ nsHTMLEditor::RemoveTextPropertiesForNodeWithDifferentParents(nsIDOMNode *aStar nsCOMPtriter; result = nsComponentManager::CreateInstance(kCContentIteratorCID, nsnull, nsIContentIterator::GetIID(), getter_AddRefs(iter)); - if ((NS_SUCCEEDED(result)) && iter) + if (NS_FAILED(result)) return result; + if (!iter) return NS_ERROR_NULL_POINTER; + + nsCOMPtrstartContent; + startContent = do_QueryInterface(startNode); + nsCOMPtrendContent; + endContent = do_QueryInterface(endNode); + if (startContent && endContent) { - nsCOMPtrstartContent; - startContent = do_QueryInterface(startNode); - nsCOMPtrendContent; - endContent = do_QueryInterface(endNode); - if (startContent && endContent) + iter->Init(range); + nsCOMPtr content; + iter->CurrentNode(getter_AddRefs(content)); + nsAutoString propName; // the property we are removing + aPropName->ToString(propName); + while (NS_COMFALSE == iter->IsDone()) { - iter->Init(range); - nsCOMPtr content; - iter->CurrentNode(getter_AddRefs(content)); - nsAutoString propName; // the property we are removing - aPropName->ToString(propName); - while (NS_COMFALSE == iter->IsDone()) + if ((content.get() != startContent.get()) && + (content.get() != endContent.get())) { - if ((content.get() != startContent.get()) && - (content.get() != endContent.get())) + nsCOMPtrelement; + element = do_QueryInterface(content); + if (element) { - nsCOMPtrelement; - element = do_QueryInterface(content); - if (element) + nsString tag; + element->GetTagName(tag); + if (propName.EqualsIgnoreCase(tag)) { - nsString tag; - element->GetTagName(tag); - if (propName.EqualsIgnoreCase(tag)) - { - if (-1==nodeList.IndexOf(content.get())) { - nodeList.AppendElement((void *)(content.get())); - } + if (-1==nodeList.IndexOf(content.get())) { + nodeList.AppendElement((void *)(content.get())); } } } - // note we don't check the result, we just rely on iter->IsDone - iter->Next(); - iter->CurrentNode(getter_AddRefs(content)); } + // note we don't check the result, we just rely on iter->IsDone + iter->Next(); + iter->CurrentNode(getter_AddRefs(content)); } } @@ -5505,7 +5597,6 @@ nsHTMLEditor::RemoveTextPropertiesForNodeWithDifferentParents(nsIDOMNode *aStar if (gNoisy) { printf("deleted next sibling node %p\n", childNode.get()); - DebugDumpContent(); // DEBUG } } childNode = do_QueryInterface(previousSiblingNode); @@ -5515,7 +5606,6 @@ nsHTMLEditor::RemoveTextPropertiesForNodeWithDifferentParents(nsIDOMNode *aStar if (gNoisy) { printf("deleted style node %p\n", styleNode.get()); - DebugDumpContent(); // DEBUG } } } @@ -5526,20 +5616,209 @@ nsHTMLEditor::RemoveTextPropertiesForNodeWithDifferentParents(nsIDOMNode *aStar } } nsCOMPtrselection; - result = nsEditor::GetSelection(getter_AddRefs(selection)); - if (NS_SUCCEEDED(result)) - { - selection->Collapse(startNode, rangeStartOffset); - selection->Extend(endNode, rangeEndOffset); - if (gNoisy) { printf("RTPFNWDP set selection.\n"); } - } + result = GetSelection(getter_AddRefs(selection)); + if (NS_FAILED(result)) return result; + if (!selection) return NS_ERROR_NULL_POINTER; + + // set the sel. start point. if we skipped the start node, just use it + if (PR_TRUE==skippedStartNode) + startNode = do_QueryInterface(aStartNode); + result = selection->Collapse(startNode, rangeStartOffset); + if (NS_FAILED(result)) return result; + + // set the sel. end point. if we skipped the end node, just use it + if (PR_TRUE==skippedEndNode) + endNode = do_QueryInterface(aEndNode); + result = selection->Extend(endNode, rangeEndOffset); + if (NS_FAILED(result)) return result; + if (gNoisy) { printf("RTPFNWDP set selection.\n"); } } if (gNoisy) { - printf("end nsTextEditor::RemoveTextPropertiesForNodeWithDifferentParents, dumping content...\n"); + printf("----- end nsTextEditor::RemoveTextPropertiesForNodeWithDifferentParents, dumping content...-----\n"); DebugDumpContent(); } return result; } +/* this method scans the selection for adjacent text nodes and collapses them into a single text node + * "adjacent" means literally adjacent siblings of the same parent + * In all cases, the content of the right text node is moved into + * the left node, and the right node is deleted. + * Uses nsEditor::JoinNodes so action is undoable. Should be called within the context of a batch transaction + */ + /* + XXX: TODO: use a helper function of next/prev sibling that only deals with editable content + */ +NS_IMETHODIMP +nsHTMLEditor::CollapseAdjacentTextNodes(nsIDOMSelection *aInSelection) +{ + if (gNoisy) + { + printf("---------- start nsTextEditor::CollapseAdjacentTextNodes ----------\n"); + DebugDumpContent(); + } + if (!aInSelection) return NS_ERROR_NULL_POINTER; + + nsVoidArray textNodes; // we can't actually do anything during iteration, so store the text nodes in an array + // don't bother ref counting them because we know we can hold them for the + // lifetime of this method + + PRBool isCollapsed; + aInSelection->GetIsCollapsed(&isCollapsed); + if (PR_TRUE==isCollapsed) { return NS_OK; } // no need to scan collapsed selection + + // store info about selection endpoints so we can re-establish selection after collapsing text nodes + // XXX: won't work for multiple selections (this will create a single selection from anchor to focus) + nsCOMPtr parentForSelection; // selection's block parent + PRInt32 rangeStartOffset, rangeEndOffset; // selection offsets + nsresult result = GetTextSelectionOffsetsForRange(aInSelection, getter_AddRefs(parentForSelection), + rangeStartOffset, rangeEndOffset); + if (NS_FAILED(result)) return result; + if (!parentForSelection) return NS_ERROR_NULL_POINTER; + + // first, do the endpoints of the selection, so we don't rely on the iteration to include them + nsCOMPtranchor, focus; + nsCOMPtranchorText, focusText; + aInSelection->GetAnchorNode(getter_AddRefs(anchor)); + anchorText = do_QueryInterface(anchor); + if (anchorText) + { + textNodes.AppendElement((void*)(anchorText.get())); + } + aInSelection->GetFocusNode(getter_AddRefs(focus)); + focusText = do_QueryInterface(focus); + + // for all the ranges in the selection, build a list of text nodes + nsCOMPtr enumerator; + result = aInSelection->GetEnumerator(getter_AddRefs(enumerator)); + if (NS_FAILED(result)) return result; + if (!enumerator) return NS_ERROR_NULL_POINTER; + + enumerator->First(); + nsCOMPtr currentItem; + result = enumerator->CurrentItem(getter_AddRefs(currentItem)); + if (NS_FAILED(result)) return result; + if (!currentItem) return NS_OK; // there are no ranges in the selection, so nothing to do + + while ((NS_COMFALSE == enumerator->IsDone())) + { + nsCOMPtr range( do_QueryInterface(currentItem) ); + nsCOMPtr iter; + result = nsComponentManager::CreateInstance(kCContentIteratorCID, nsnull, + nsIContentIterator::GetIID(), + getter_AddRefs(iter)); + if (NS_FAILED(result)) return result; + if (!iter) return NS_ERROR_NULL_POINTER; + + iter->Init(range); + nsCOMPtr content; + result = iter->CurrentNode(getter_AddRefs(content)); + while (NS_COMFALSE == iter->IsDone()) + { + nsCOMPtr text = do_QueryInterface(content); + if (text && anchorText.get() != text.get() && focusText.get() != text.get()) + { + textNodes.AppendElement((void*)(text.get())); + } + iter->Next(); + iter->CurrentNode(getter_AddRefs(content)); + } + enumerator->Next(); + enumerator->CurrentItem(getter_AddRefs(currentItem)); + } + // now add the focus to the list, if it's a text node + if (focusText) + { + textNodes.AppendElement((void*)(focusText.get())); + } + + + // now that I have a list of text nodes, collapse adjacent text nodes + PRInt32 count = textNodes.Count(); + const PRInt32 initialCount = count; + while (1 prevSiblingOfLeftTextNode; + result = leftTextNode->GetPreviousSibling(getter_AddRefs(prevSiblingOfLeftTextNode)); + if (NS_FAILED(result)) return result; + if (prevSiblingOfLeftTextNode) + { + nsCOMPtrprevSiblingAsText = do_QueryInterface(prevSiblingOfLeftTextNode); + if (prevSiblingAsText) + { + nsCOMPtr parent; + result = leftTextNode->GetParentNode(getter_AddRefs(parent)); + if (NS_FAILED(result)) return result; + if (!parent) return NS_ERROR_NULL_POINTER; + result = JoinNodes(prevSiblingOfLeftTextNode, leftTextNode, parent); + if (NS_FAILED(result)) return result; + } + } + } + + // get the prev sibling of the right node, and see if it's leftTextNode + nsCOMPtr prevSiblingOfRightTextNode; + result = rightTextNode->GetPreviousSibling(getter_AddRefs(prevSiblingOfRightTextNode)); + if (NS_FAILED(result)) return result; + if (prevSiblingOfRightTextNode) + { + nsCOMPtrprevSiblingAsText = do_QueryInterface(prevSiblingOfRightTextNode); + if (prevSiblingAsText) + { + if (prevSiblingAsText.get()==leftTextNode) + { + nsCOMPtr parent; + result = rightTextNode->GetParentNode(getter_AddRefs(parent)); + if (NS_FAILED(result)) return result; + if (!parent) return NS_ERROR_NULL_POINTER; + result = JoinNodes(leftTextNode, rightTextNode, parent); + if (NS_FAILED(result)) return result; + } + } + } + + // special case: check next sibling of the rightmost text node + if (2==count) + { + nsCOMPtr nextSiblingOfRightTextNode; + result = rightTextNode->GetNextSibling(getter_AddRefs(nextSiblingOfRightTextNode)); + if (NS_FAILED(result)) return result; + if (nextSiblingOfRightTextNode) + { + nsCOMPtrnextSiblingAsText = do_QueryInterface(nextSiblingOfRightTextNode); + if (nextSiblingAsText) + { + nsCOMPtr parent; + result = rightTextNode->GetParentNode(getter_AddRefs(parent)); + if (NS_FAILED(result)) return result; + if (!parent) return NS_ERROR_NULL_POINTER; + result = JoinNodes(rightTextNode, nextSiblingOfRightTextNode, parent); + if (NS_FAILED(result)) return result; + } + } + } + + // remove the rightmost remaining text node from the array and work our way towards the beginning + textNodes.RemoveElementAt(0); // remove the leftmost text node from the list + count --; + } + + ResetTextSelectionForRange(parentForSelection, rangeStartOffset, rangeEndOffset, aInSelection); + + if (gNoisy) + { + printf("---------- end nsTextEditor::CollapseAdjacentTextNodes ----------\n"); + DebugDumpContent(); + } + + return result; +} diff --git a/editor/base/nsHTMLEditor.h b/editor/base/nsHTMLEditor.h index 90f448548c38..debfd5ecb8e9 100644 --- a/editor/base/nsHTMLEditor.h +++ b/editor/base/nsHTMLEditor.h @@ -192,7 +192,15 @@ protected: virtual void InitRules(); - NS_IMETHOD GetLayoutObject(nsIDOMNode *aNode, nsISupports **aLayoutObject); + /** returns the layout object (nsIFrame in the real world) for aNode + * @param aNode the content to get a frame for + * @param aLayoutObject the "primary frame" for aNode, if one exists. May be null + * @return NS_OK whether a frame is found or not + * an error if some serious error occurs + */ + NS_IMETHOD GetLayoutObject(nsIDOMNode *aInNode, nsISupports **aOutLayoutObject); + + NS_IMETHOD CollapseAdjacentTextNodes(nsIDOMSelection *aInSelection); NS_IMETHOD DeleteSelectionAndPrepareToCreateNode(nsCOMPtr &parentSelectedNode, PRInt32& offsetOfNewNode); @@ -382,10 +390,10 @@ protected: const nsString *aAttribute, const nsString *aValue); - void GetTextSelectionOffsetsForRange(nsIDOMSelection *aSelection, - nsIDOMNode **aParent, - PRInt32 &aStartOffset, - PRInt32 &aEndOffset); + NS_IMETHOD GetTextSelectionOffsetsForRange(nsIDOMSelection *aSelection, + nsIDOMNode **aParent, + PRInt32 &aStartOffset, + PRInt32 &aEndOffset); void ResetTextSelectionForRange(nsIDOMNode *aParent, PRInt32 aStartOffset, diff --git a/editor/base/nsTextEditRules.cpp b/editor/base/nsTextEditRules.cpp index f8044504665f..65b8f0be0c04 100644 --- a/editor/base/nsTextEditRules.cpp +++ b/editor/base/nsTextEditRules.cpp @@ -104,11 +104,10 @@ nsTextEditRules::SetFlags(PRUint32 aFlags) // put a "white-space: pre" style on the body nsCOMPtr bodyElement; nsresult res = mEditor->GetBodyElement(getter_AddRefs(bodyElement)); - if (NS_SUCCEEDED(res) && bodyElement) - { - // not going through the editor to do this. - bodyElement->SetAttribute("style", "white-space: pre"); - } + if (NS_FAILED(res)) return res; + if (!bodyElement) return NS_ERROR_NULL_POINTER; + // not going through the editor to do this. + bodyElement->SetAttribute("style", "white-space: pre"); } } mFlags = aFlags; @@ -394,7 +393,9 @@ nsTextEditRules::CreateStyleForInsertText(nsIDOMSelection *aSelection, TypeInSta // splitting anchor twice sets newTextNode as an empty text node between // two halves of the original text node result = mEditor->SplitNode(anchorAsText, offset, getter_AddRefs(newTextNode)); - result = mEditor->SplitNode(anchorAsText, 0, getter_AddRefs(newTextNode)); + if (NS_SUCCEEDED(result)) { + result = mEditor->SplitNode(anchorAsText, 0, getter_AddRefs(newTextNode)); + } } } // now we have the new text node we are going to insert into. @@ -464,37 +465,30 @@ nsTextEditRules::CreateStyleForInsertText(nsIDOMSelection *aSelection, TypeInSta } else // we have no selection, so insert a style tag in the body { - nsCOMPtrdoc; - mEditor->GetDocument(getter_AddRefs(doc)); - nsCOMPtrnodeList; - nsAutoString bodyTag = "body"; - result = doc->GetElementsByTagName(bodyTag, getter_AddRefs(nodeList)); - if ((NS_SUCCEEDED(result)) && nodeList) - { - PRUint32 count; - nodeList->GetLength(&count); - NS_ASSERTION(1==count, "there is not exactly 1 body in the document!"); - nsCOMPtrbodyNode; - result = nodeList->Item(0, getter_AddRefs(bodyNode)); - if ((NS_SUCCEEDED(result)) && bodyNode) - { // now we've got the body tag. insert the style tag - if (aTypeInState.IsSet(NS_TYPEINSTATE_BOLD)) - { - if (PR_TRUE==aTypeInState.GetBold()) { - InsertStyleAndNewTextNode(bodyNode, nsIEditProperty::b, aSelection); - } + nsCOMPtr bodyElement; + nsresult res = mEditor->GetBodyElement(getter_AddRefs(bodyElement)); + if (NS_FAILED(res)) return res; + if (!bodyElement) return NS_ERROR_NULL_POINTER; + + nsCOMPtrbodyNode = do_QueryInterface(bodyElement); + if (bodyNode) + { // now we've got the body tag. insert the style tag + if (aTypeInState.IsSet(NS_TYPEINSTATE_BOLD)) + { + if (PR_TRUE==aTypeInState.GetBold()) { + InsertStyleAndNewTextNode(bodyNode, nsIEditProperty::b, aSelection); } - if (aTypeInState.IsSet(NS_TYPEINSTATE_ITALIC)) - { - if (PR_TRUE==aTypeInState.GetItalic()) { - InsertStyleAndNewTextNode(bodyNode, nsIEditProperty::i, aSelection); - } + } + if (aTypeInState.IsSet(NS_TYPEINSTATE_ITALIC)) + { + if (PR_TRUE==aTypeInState.GetItalic()) { + InsertStyleAndNewTextNode(bodyNode, nsIEditProperty::i, aSelection); } - if (aTypeInState.IsSet(NS_TYPEINSTATE_UNDERLINE)) - { - if (PR_TRUE==aTypeInState.GetUnderline()) { - InsertStyleAndNewTextNode(bodyNode, nsIEditProperty::u, aSelection); - } + } + if (aTypeInState.IsSet(NS_TYPEINSTATE_UNDERLINE)) + { + if (PR_TRUE==aTypeInState.GetUnderline()) { + InsertStyleAndNewTextNode(bodyNode, nsIEditProperty::u, aSelection); } } } @@ -513,12 +507,11 @@ nsTextEditRules::CreateFontStyleForInsertText(nsIDOMNode *aNewTextNode, if (0!=aValue.Length()) { result = InsertStyleNode(aNewTextNode, nsIEditProperty::font, aSelection, getter_AddRefs(newStyleNode)); - if (NS_SUCCEEDED(result) && newStyleNode) - { - nsCOMPtrelement = do_QueryInterface(newStyleNode); - if (element) { - result = mEditor->SetAttribute(element, aAttr, aValue); - } + if (NS_FAILED(result)) return result; + if (!newStyleNode) return NS_ERROR_NULL_POINTER; + nsCOMPtrelement = do_QueryInterface(newStyleNode); + if (element) { + result = mEditor->SetAttribute(element, aAttr, aValue); } } else @@ -540,21 +533,26 @@ nsTextEditRules::InsertStyleNode(nsIDOMNode *aNode, nsresult result; nsCOMPtrparent; aNode->GetParentNode(getter_AddRefs(parent)); + if (NS_FAILED(result)) return result; + if (!parent) return NS_ERROR_NULL_POINTER; + PRInt32 offsetInParent; - nsEditor::GetChildOffset(aNode, parent, offsetInParent); + result = nsEditor::GetChildOffset(aNode, parent, offsetInParent); + if (NS_FAILED(result)) return result; + nsAutoString tag; aTag->ToString(tag); result = mEditor->CreateNode(tag, parent, offsetInParent, aNewNode); - if ((NS_SUCCEEDED(result)) && *aNewNode) + if (NS_FAILED(result)) return result; + if (!aNewNode) return NS_ERROR_NULL_POINTER; + + result = mEditor->DeleteNode(aNode); + if (NS_SUCCEEDED(result)) { - result = mEditor->DeleteNode(aNode); - if (NS_SUCCEEDED(result)) - { - result = mEditor->InsertNode(aNode, *aNewNode, 0); - if (NS_SUCCEEDED(result)) { - if (aSelection) { - aSelection->Collapse(aNode, 0); - } + result = mEditor->InsertNode(aNode, *aNewNode, 0); + if (NS_SUCCEEDED(result)) { + if (aSelection) { + result = aSelection->Collapse(aNode, 0); } } } @@ -575,16 +573,17 @@ nsTextEditRules::InsertStyleAndNewTextNode(nsIDOMNode *aParentNode, nsIAtom *aTa nsCOMPtranchor; PRInt32 offset; result = aSelection->GetAnchorNode(getter_AddRefs(anchor)); - if (NS_SUCCEEDED(result) && NS_SUCCEEDED(aSelection->GetAnchorOffset(&offset)) && anchor) + if (NS_FAILED(result)) return result; + if (!anchor) return NS_ERROR_NULL_POINTER; + result = aSelection->GetAnchorOffset(&offset); + if (NS_FAILED(result)) return result; + nsCOMPtranchorAsText; + anchorAsText = do_QueryInterface(anchor); + if (anchorAsText) { - nsCOMPtranchorAsText; - anchorAsText = do_QueryInterface(anchor); - if (anchorAsText) - { - nsCOMPtr newStyleNode; - result = InsertStyleNode(anchor, aTag, aSelection, getter_AddRefs(newStyleNode)); - return result; - } + nsCOMPtr newStyleNode; + result = InsertStyleNode(anchor, aTag, aSelection, getter_AddRefs(newStyleNode)); + return result; } } // if we get here, there is no selected text node so we create one. @@ -593,15 +592,15 @@ nsTextEditRules::InsertStyleAndNewTextNode(nsIDOMNode *aParentNode, nsIAtom *aTa nsCOMPtrnewStyleNode; nsCOMPtrnewTextNode; result = mEditor->CreateNode(tag, aParentNode, 0, getter_AddRefs(newStyleNode)); - if (NS_SUCCEEDED(result)) - { - result = mEditor->CreateNode(nsEditor::GetTextNodeTag(), newStyleNode, 0, getter_AddRefs(newTextNode)); - if (NS_SUCCEEDED(result)) - { - if (aSelection) { - aSelection->Collapse(newTextNode, 0); - } - } + if (NS_FAILED(result)) return result; + if (!newStyleNode) return NS_ERROR_NULL_POINTER; + + result = mEditor->CreateNode(nsEditor::GetTextNodeTag(), newStyleNode, 0, getter_AddRefs(newTextNode)); + if (NS_FAILED(result)) return result; + if (!newTextNode) return NS_ERROR_NULL_POINTER; + + if (aSelection) { + result = aSelection->Collapse(newTextNode, 0); } return result; } @@ -707,55 +706,63 @@ nsTextEditRules::DidDeleteSelection(nsIDOMSelection *aSelection, nsCOMPtranchor; PRInt32 offset; result = aSelection->GetAnchorNode(getter_AddRefs(anchor)); - if (NS_SUCCEEDED(result) && NS_SUCCEEDED(aSelection->GetAnchorOffset(&offset)) && anchor) + if (NS_FAILED(result)) return result; + if (!anchor) return NS_ERROR_NULL_POINTER; + result = aSelection->GetAnchorOffset(&offset); + if (NS_FAILED(result)) return result; + + nsCOMPtr anchorChildren; + result = anchor->GetChildNodes(getter_AddRefs(anchorChildren)); + nsCOMPtr selectedNode; + if ((NS_SUCCEEDED(result)) && anchorChildren) { + result = anchorChildren->Item(offset, getter_AddRefs(selectedNode)); + } + else { + selectedNode = do_QueryInterface(anchor); + } + if ((NS_SUCCEEDED(result)) && selectedNode) { - nsCOMPtr anchorChildren; - result = anchor->GetChildNodes(getter_AddRefs(anchorChildren)); - nsCOMPtr selectedNode; - if ((NS_SUCCEEDED(result)) && anchorChildren) { - result = anchorChildren->Item(offset, getter_AddRefs(selectedNode)); - } - else { - selectedNode = do_QueryInterface(anchor); - } - if ((NS_SUCCEEDED(result)) && selectedNode) + nsCOMPtrselectedNodeAsText; + selectedNodeAsText = do_QueryInterface(selectedNode); + if (selectedNodeAsText) { - nsCOMPtrselectedNodeAsText; - selectedNodeAsText = do_QueryInterface(selectedNode); - if (selectedNodeAsText) + nsCOMPtr siblingNode; + selectedNode->GetPreviousSibling(getter_AddRefs(siblingNode)); + if (siblingNode) { - nsCOMPtr siblingNode; - selectedNode->GetPreviousSibling(getter_AddRefs(siblingNode)); - if (siblingNode) + nsCOMPtrsiblingNodeAsText; + siblingNodeAsText = do_QueryInterface(siblingNode); + if (siblingNodeAsText) { - nsCOMPtrsiblingNodeAsText; - siblingNodeAsText = do_QueryInterface(siblingNode); - if (siblingNodeAsText) - { - PRUint32 siblingLength; // the length of siblingNode before the join - siblingNodeAsText->GetLength(&siblingLength); - nsCOMPtr parentNode; - selectedNode->GetParentNode(getter_AddRefs(parentNode)); - result = mEditor->JoinNodes(siblingNode, selectedNode, parentNode); - // selectedNode will remain after the join, siblingNode is removed - } + PRUint32 siblingLength; // the length of siblingNode before the join + siblingNodeAsText->GetLength(&siblingLength); + nsCOMPtr parentNode; + result = selectedNode->GetParentNode(getter_AddRefs(parentNode)); + if (NS_FAILED(result)) return result; + if (!parentNode) return NS_ERROR_NULL_POINTER; + result = mEditor->JoinNodes(siblingNode, selectedNode, parentNode); + // selectedNode will remain after the join, siblingNode is removed } - selectedNode->GetNextSibling(getter_AddRefs(siblingNode)); - if (siblingNode) + } + selectedNode->GetNextSibling(getter_AddRefs(siblingNode)); + if (siblingNode) + { + nsCOMPtrsiblingNodeAsText; + siblingNodeAsText = do_QueryInterface(siblingNode); + if (siblingNodeAsText) { - nsCOMPtrsiblingNodeAsText; - siblingNodeAsText = do_QueryInterface(siblingNode); - if (siblingNodeAsText) - { - PRUint32 selectedNodeLength; // the length of siblingNode before the join - selectedNodeAsText->GetLength(&selectedNodeLength); - nsCOMPtr parentNode; - selectedNode->GetParentNode(getter_AddRefs(parentNode)); - result = mEditor->JoinNodes(selectedNode, siblingNode, parentNode); - // selectedNode will remain after the join, siblingNode is removed - // set selection - aSelection->Collapse(siblingNode, selectedNodeLength); - } + PRUint32 selectedNodeLength; // the length of siblingNode before the join + selectedNodeAsText->GetLength(&selectedNodeLength); + nsCOMPtr parentNode; + result = selectedNode->GetParentNode(getter_AddRefs(parentNode)); + if (NS_FAILED(result)) return result; + if (!parentNode) return NS_ERROR_NULL_POINTER; + + result = mEditor->JoinNodes(selectedNode, siblingNode, parentNode); + if (NS_FAILED(result)) return result; + // selectedNode will remain after the join, siblingNode is removed + // set selection + result = aSelection->Collapse(siblingNode, selectedNodeLength); } } } @@ -795,23 +802,24 @@ nsTextEditRules:: DidUndo(nsIDOMSelection *aSelection, nsresult aResult) nsCOMPtrnode; PRInt32 offset; result = aSelection->GetAnchorNode(getter_AddRefs(node)); - if (NS_SUCCEEDED(result) && NS_SUCCEEDED(aSelection->GetAnchorOffset(&offset)) && node) + if (NS_FAILED(result)) return result; + if (!node) return NS_ERROR_NULL_POINTER; + result = aSelection->GetAnchorOffset(&offset); + if (NS_FAILED(result)) return result; + nsCOMPtrelement; + element = do_QueryInterface(node); + if (element) { - nsCOMPtrelement; - element = do_QueryInterface(node); - if (element) - { - nsAutoString att(nsEditor::kMOZEditorBogusNodeAttr); - nsAutoString val; - (void)element->GetAttribute(att, val); - if (val.Equals(nsEditor::kMOZEditorBogusNodeValue)) { - mBogusNode = do_QueryInterface(element); - } + nsAutoString att(nsEditor::kMOZEditorBogusNodeAttr); + nsAutoString val; + (void)element->GetAttribute(att, val); + if (val.Equals(nsEditor::kMOZEditorBogusNodeValue)) { + mBogusNode = do_QueryInterface(element); } - nsCOMPtr temp; - result = node->GetParentNode(getter_AddRefs(temp)); - node = do_QueryInterface(temp); } + nsCOMPtr temp; + result = node->GetParentNode(getter_AddRefs(temp)); + node = do_QueryInterface(temp); } } return result; @@ -842,23 +850,24 @@ nsTextEditRules::DidRedo(nsIDOMSelection *aSelection, nsresult aResult) nsCOMPtrnode; PRInt32 offset; result = aSelection->GetAnchorNode(getter_AddRefs(node)); - if (NS_SUCCEEDED(result) && NS_SUCCEEDED(aSelection->GetAnchorOffset(&offset)) && node) + if (NS_FAILED(result)) return result; + if (!node) return NS_ERROR_NULL_POINTER; + result = aSelection->GetAnchorOffset(&offset); + if (NS_FAILED(result)) return result; + nsCOMPtrelement; + element = do_QueryInterface(node); + if (element) { - nsCOMPtrelement; - element = do_QueryInterface(node); - if (element) - { - nsAutoString att(nsEditor::kMOZEditorBogusNodeAttr); - nsAutoString val; - (void)element->GetAttribute(att, val); - if (val.Equals(nsEditor::kMOZEditorBogusNodeValue)) { - mBogusNode = do_QueryInterface(element); - } + nsAutoString att(nsEditor::kMOZEditorBogusNodeAttr); + nsAutoString val; + (void)element->GetAttribute(att, val); + if (val.Equals(nsEditor::kMOZEditorBogusNodeValue)) { + mBogusNode = do_QueryInterface(element); } - nsCOMPtr temp; - result = node->GetParentNode(getter_AddRefs(temp)); - node = do_QueryInterface(temp); } + nsCOMPtr temp; + result = node->GetParentNode(getter_AddRefs(temp)); + node = do_QueryInterface(temp); } } return result; @@ -895,86 +904,63 @@ nsTextEditRules::CreateBogusNodeIfNeeded(nsIDOMSelection *aSelection) { if (!aSelection) { return NS_ERROR_NULL_POINTER; } if (!mEditor) { return NS_ERROR_NULL_POINTER; } - nsCOMPtrdoc; - mEditor->GetDocument(getter_AddRefs(doc)); - nsCOMPtrnodeList; - nsAutoString bodyTag = "body"; - nsresult result = doc->GetElementsByTagName(bodyTag, getter_AddRefs(nodeList)); - if ((NS_SUCCEEDED(result)) && nodeList) + + nsCOMPtr bodyElement; + nsresult result = mEditor->GetBodyElement(getter_AddRefs(bodyElement)); + if (NS_FAILED(result)) return result; + if (!bodyElement) return NS_ERROR_NULL_POINTER; + nsCOMPtrbodyNode = do_QueryInterface(bodyElement); + + // now we've got the body tag. + // iterate the body tag, looking for editable content + // if no editable content is found, insert the bogus node + PRBool needsBogusContent=PR_TRUE; + nsCOMPtrbodyChild; + result = bodyNode->GetFirstChild(getter_AddRefs(bodyChild)); + while ((NS_SUCCEEDED(result)) && bodyChild) + { + if (PR_TRUE==mEditor->IsEditable(bodyChild)) + { + needsBogusContent = PR_FALSE; + break; + } + nsCOMPtrtemp; + bodyChild->GetNextSibling(getter_AddRefs(temp)); + bodyChild = do_QueryInterface(temp); + } + if (PR_TRUE==needsBogusContent) { - PRUint32 count; - nodeList->GetLength(&count); - NS_ASSERTION(1==count, "there is not exactly 1 body in the document!"); - nsCOMPtrbodyNode; - result = nodeList->Item(0, getter_AddRefs(bodyNode)); - if ((NS_SUCCEEDED(result)) && bodyNode) - { // now we've got the body tag. - // iterate the body tag, looking for editable content - // if no editable content is found, insert the bogus node - PRBool needsBogusContent=PR_TRUE; - nsCOMPtrbodyChild; - result = bodyNode->GetFirstChild(getter_AddRefs(bodyChild)); - while ((NS_SUCCEEDED(result)) && bodyChild) - { - if (PR_TRUE==mEditor->IsEditable(bodyChild)) - { - needsBogusContent = PR_FALSE; - break; - } - nsCOMPtrtemp; - bodyChild->GetNextSibling(getter_AddRefs(temp)); - bodyChild = do_QueryInterface(temp); - } - if (PR_TRUE==needsBogusContent) - { - // set mBogusNode to be the newly created

- result = mEditor->CreateNode(nsAutoString("P"), bodyNode, 0, - getter_AddRefs(mBogusNode)); - if ((NS_SUCCEEDED(result)) && mBogusNode) - { - nsCOMPtrnewTNode; - result = mEditor->CreateNode(nsEditor::GetTextNodeTag(), mBogusNode, 0, - getter_AddRefs(newTNode)); - if ((NS_SUCCEEDED(result)) && newTNode) - { - nsCOMPtrnewNodeAsText; - newNodeAsText = do_QueryInterface(newTNode); - if (newNodeAsText) - { - nsAutoString data; - data += 160; - newNodeAsText->SetData(data); - aSelection->Collapse(newTNode, 0); - } - } - // make sure we know the PNode is bogus - nsCOMPtrnewPElement; - newPElement = do_QueryInterface(mBogusNode); - if (newPElement) - { - nsAutoString att(nsEditor::kMOZEditorBogusNodeAttr); - nsAutoString val(nsEditor::kMOZEditorBogusNodeValue); - newPElement->SetAttribute(att, val); - } - } - } + // set mBogusNode to be the newly created

+ result = mEditor->CreateNode(nsAutoString("P"), bodyNode, 0, + getter_AddRefs(mBogusNode)); + if (NS_FAILED(result)) return result; + if (!mBogusNode) return NS_ERROR_NULL_POINTER; + + nsCOMPtrnewTNode; + result = mEditor->CreateNode(nsEditor::GetTextNodeTag(), mBogusNode, 0, + getter_AddRefs(newTNode)); + if (NS_FAILED(result)) return result; + if (!newTNode) return NS_ERROR_NULL_POINTER; + + nsCOMPtrnewNodeAsText; + newNodeAsText = do_QueryInterface(newTNode); + if (newNodeAsText) + { + nsAutoString data; + data += 160; + newNodeAsText->SetData(data); + aSelection->Collapse(newTNode, 0); + } + // make sure we know the PNode is bogus + nsCOMPtrnewPElement; + newPElement = do_QueryInterface(mBogusNode); + if (newPElement) + { + nsAutoString att(nsEditor::kMOZEditorBogusNodeAttr); + nsAutoString val(nsEditor::kMOZEditorBogusNodeValue); + newPElement->SetAttribute(att, val); } } return result; } - - - - - - - - - - - - - - - diff --git a/editor/base/nsTextEditor.cpp b/editor/base/nsTextEditor.cpp index bd62e0141dda..340689d7abb2 100644 --- a/editor/base/nsTextEditor.cpp +++ b/editor/base/nsTextEditor.cpp @@ -400,108 +400,108 @@ NS_IMETHODIMP nsTextEditor::SetTextProperty(nsIAtom *aProperty, nsresult result=NS_ERROR_NOT_INITIALIZED; nsCOMPtrselection; result = nsEditor::GetSelection(getter_AddRefs(selection)); - if ((NS_SUCCEEDED(result)) && selection) + if (NS_FAILED(result)) return result; + if (!selection) return NS_ERROR_NULL_POINTER; + + PRBool cancel; + nsTextRulesInfo ruleInfo(nsTextEditRules::kSetTextProperty); + result = mRules->WillDoAction(selection, &ruleInfo, &cancel); + if ((PR_FALSE==cancel) && (NS_SUCCEEDED(result))) { - PRBool cancel; - nsTextRulesInfo ruleInfo(nsTextEditRules::kSetTextProperty); - result = mRules->WillDoAction(selection, &ruleInfo, &cancel); - if ((PR_FALSE==cancel) && (NS_SUCCEEDED(result))) + PRBool isCollapsed; + selection->GetIsCollapsed(&isCollapsed); + if (PR_TRUE==isCollapsed) { - PRBool isCollapsed; - selection->GetIsCollapsed(&isCollapsed); - if (PR_TRUE==isCollapsed) - { - // manipulating text attributes on a collapsed selection only sets state for the next text insertion - SetTypeInStateForProperty(*mTypeInState, aProperty, aAttribute, aValue); + // manipulating text attributes on a collapsed selection only sets state for the next text insertion + SetTypeInStateForProperty(*mTypeInState, aProperty, aAttribute, aValue); + } + else + { + // set the text property for all selected ranges + nsEditor::BeginTransaction(); + nsCOMPtr enumerator; + result = selection->GetEnumerator(getter_AddRefs(enumerator)); + if (NS_FAILED(result)) return result; + if (!enumerator) return NS_ERROR_NULL_POINTER; + enumerator->First(); + + nsCOMPtr currentItem; + result = enumerator->CurrentItem(getter_AddRefs(currentItem)); + if (NS_FAILED(result)) return result; + if (!currentItem) return NS_ERROR_NULL_POINTER; + + nsCOMPtr range( do_QueryInterface(currentItem) ); + nsCOMPtrcommonParent; + result = range->GetCommonParent(getter_AddRefs(commonParent)); + if (NS_FAILED(result)) return result; + if (!commonParent) return NS_ERROR_NULL_POINTER; + + PRInt32 startOffset, endOffset; + range->GetStartOffset(&startOffset); + range->GetEndOffset(&endOffset); + nsCOMPtr startParent; nsCOMPtr endParent; + range->GetStartParent(getter_AddRefs(startParent)); + range->GetEndParent(getter_AddRefs(endParent)); + PRBool startIsText = IsTextNode(startParent); + PRBool endIsText = IsTextNode(endParent); + if ((PR_TRUE==startIsText) && (PR_TRUE==endIsText) && + (startParent.get()==endParent.get())) + { // the range is entirely contained within a single text node + // commonParent==aStartParent, so get the "real" parent of the selection + startParent->GetParentNode(getter_AddRefs(commonParent)); + result = SetTextPropertiesForNode(startParent, commonParent, + startOffset, endOffset, + aProperty, aAttribute, aValue); } else { - // set the text property for all selected ranges - nsEditor::BeginTransaction(); - nsCOMPtr enumerator; - result = selection->GetEnumerator(getter_AddRefs(enumerator)); - if (NS_SUCCEEDED(result) && enumerator) + nsCOMPtr startGrandParent; + startParent->GetParentNode(getter_AddRefs(startGrandParent)); + nsCOMPtr endGrandParent; + endParent->GetParentNode(getter_AddRefs(endGrandParent)); + if (NS_SUCCEEDED(result)) { - enumerator->First(); - nsCOMPtr currentItem; - result = enumerator->CurrentItem(getter_AddRefs(currentItem)); - if ((NS_SUCCEEDED(result)) && (currentItem)) + PRBool canCollapseStyleNode = PR_FALSE; + if ((PR_TRUE==startIsText) && (PR_TRUE==endIsText) && + endGrandParent.get()==startGrandParent.get()) { - nsCOMPtr range( do_QueryInterface(currentItem) ); - nsCOMPtrcommonParent; - result = range->GetCommonParent(getter_AddRefs(commonParent)); - if ((NS_SUCCEEDED(result)) && commonParent) - { - PRInt32 startOffset, endOffset; - range->GetStartOffset(&startOffset); - range->GetEndOffset(&endOffset); - nsCOMPtr startParent; nsCOMPtr endParent; - range->GetStartParent(getter_AddRefs(startParent)); - range->GetEndParent(getter_AddRefs(endParent)); - PRBool startIsText = IsTextNode(startParent); - PRBool endIsText = IsTextNode(endParent); - if ((PR_TRUE==startIsText) && (PR_TRUE==endIsText) && - (startParent.get()==endParent.get())) - { // the range is entirely contained within a single text node - // commonParent==aStartParent, so get the "real" parent of the selection - startParent->GetParentNode(getter_AddRefs(commonParent)); - result = SetTextPropertiesForNode(startParent, commonParent, - startOffset, endOffset, - aProperty, aAttribute, aValue); - } - else - { - nsCOMPtr startGrandParent; - startParent->GetParentNode(getter_AddRefs(startGrandParent)); - nsCOMPtr endGrandParent; - endParent->GetParentNode(getter_AddRefs(endGrandParent)); - if (NS_SUCCEEDED(result)) - { - PRBool canCollapseStyleNode = PR_FALSE; - if ((PR_TRUE==startIsText) && (PR_TRUE==endIsText) && - endGrandParent.get()==startGrandParent.get()) - { - result = IntermediateNodesAreInline(range, startParent, startOffset, - endParent, endOffset, - canCollapseStyleNode); - } - if (NS_SUCCEEDED(result)) - { - if (PR_TRUE==canCollapseStyleNode) - { // the range is between 2 nodes that have a common (immediate) grandparent, - // and any intermediate nodes are just inline style nodes - result = SetTextPropertiesForNodesWithSameParent(startParent,startOffset, - endParent, endOffset, - commonParent, - aProperty, aAttribute, aValue); - } - else - { // the range is between 2 nodes that have no simple relationship - result = SetTextPropertiesForNodeWithDifferentParents(range, - startParent,startOffset, - endParent, endOffset, - commonParent, - aProperty, aAttribute, aValue); - } - } - } - } - if (NS_SUCCEEDED(result)) - { // compute a range for the selection - // don't want to actually do anything with selection, because - // we are still iterating through it. Just want to create and remember - // an nsIDOMRange, and later add the range to the selection after clearing it. - // XXX: I'm blocked here because nsIDOMSelection doesn't provide a mechanism - // for setting a compound selection yet. - } + result = IntermediateNodesAreInline(range, startParent, startOffset, + endParent, endOffset, + canCollapseStyleNode); + } + if (NS_SUCCEEDED(result)) + { + if (PR_TRUE==canCollapseStyleNode) + { // the range is between 2 nodes that have a common (immediate) grandparent, + // and any intermediate nodes are just inline style nodes + result = SetTextPropertiesForNodesWithSameParent(startParent,startOffset, + endParent, endOffset, + commonParent, + aProperty, aAttribute, aValue); + } + else + { // the range is between 2 nodes that have no simple relationship + result = SetTextPropertiesForNodeWithDifferentParents(range, + startParent,startOffset, + endParent, endOffset, + commonParent, + aProperty, aAttribute, aValue); } } } - nsEditor::EndTransaction(); } - // post-process - result = mRules->DidDoAction(selection, &ruleInfo, result); + if (NS_SUCCEEDED(result)) + { // compute a range for the selection + // don't want to actually do anything with selection, because + // we are still iterating through it. Just want to create and remember + // an nsIDOMRange, and later add the range to the selection after clearing it. + // XXX: I'm blocked here because nsIDOMSelection doesn't provide a mechanism + // for setting a compound selection yet. + } + nsEditor::EndTransaction(); } + // post-process + result = mRules->DidDoAction(selection, &ruleInfo, result); } if (gNoisy) {DebugDumpContent(); } // DEBUG if (gNoisy) @@ -522,16 +522,7 @@ NS_IMETHODIMP nsTextEditor::GetTextProperty(nsIAtom *aProperty, { if (!aProperty) return NS_ERROR_NULL_POINTER; -/* - if (gNoisy) - { - nsAutoString propString; - aProperty->ToString(propString); - char *propCString = propString.ToNewCString(); - if (gNoisy) { printf("nsTextEditor::GetTextProperty %s\n", propCString); } - delete [] propCString; - } -*/ + nsresult result=NS_ERROR_NOT_INITIALIZED; aAny=PR_FALSE; aAll=PR_TRUE; @@ -539,93 +530,93 @@ NS_IMETHODIMP nsTextEditor::GetTextProperty(nsIAtom *aProperty, PRBool first=PR_TRUE; nsCOMPtrselection; result = nsEditor::GetSelection(getter_AddRefs(selection)); - if ((NS_SUCCEEDED(result)) && selection) + if (NS_FAILED(result)) return result; + if (!selection) return NS_ERROR_NULL_POINTER; + + PRBool isCollapsed; + selection->GetIsCollapsed(&isCollapsed); + nsCOMPtr enumerator; + result = selection->GetEnumerator(getter_AddRefs(enumerator)); + if (NS_FAILED(result)) return result; + if (!enumerator) return NS_ERROR_NULL_POINTER; + enumerator->First(); + nsCOMPtr currentItem; + result = enumerator->CurrentItem(getter_AddRefs(currentItem)); + if (NS_FAILED(result)) return result; + if (!currentItem) return NS_ERROR_NULL_POINTER; + // XXX: should be a while loop, to get each separate range + if (currentItem) { - PRBool isCollapsed; - selection->GetIsCollapsed(&isCollapsed); - nsCOMPtr enumerator; - result = selection->GetEnumerator(getter_AddRefs(enumerator)); - if (NS_SUCCEEDED(result) && enumerator) + PRBool firstNodeInRange = PR_TRUE; // for each range, set a flag + nsCOMPtr range( do_QueryInterface(currentItem) ); + nsCOMPtr iter; + result = nsComponentManager::CreateInstance(kCContentIteratorCID, nsnull, + nsIContentIterator::GetIID(), + getter_AddRefs(iter)); + if (NS_FAILED(result)) return result; + if (!iter) return NS_ERROR_NULL_POINTER; + iter->Init(range); + nsCOMPtr content; + result = iter->CurrentNode(getter_AddRefs(content)); + while (NS_COMFALSE == iter->IsDone()) { - enumerator->First(); - nsCOMPtr currentItem; - result = enumerator->CurrentItem(getter_AddRefs(currentItem)); - // XXX: should be a while loop, to get each separate range - if ((NS_SUCCEEDED(result)) && currentItem) + //if (gNoisy) { printf(" checking node %p\n", content.get()); } + nsCOMPtrtext; + text = do_QueryInterface(content); + PRBool skipNode = PR_FALSE; + if (text) { - PRBool firstNodeInRange = PR_TRUE; // for each range, set a flag - nsCOMPtr range( do_QueryInterface(currentItem) ); - nsCOMPtr iter; - result = nsComponentManager::CreateInstance(kCContentIteratorCID, nsnull, - nsIContentIterator::GetIID(), - getter_AddRefs(iter)); - if ((NS_SUCCEEDED(result)) && iter) + if (PR_FALSE==isCollapsed && PR_TRUE==first && PR_TRUE==firstNodeInRange) { - iter->Init(range); - nsCOMPtr content; - result = iter->CurrentNode(getter_AddRefs(content)); - while (NS_COMFALSE == iter->IsDone()) + firstNodeInRange = PR_FALSE; + PRInt32 startOffset; + range->GetStartOffset(&startOffset); + PRUint32 count; + text->GetLength(&count); + if (startOffset==(PRInt32)count) { - //if (gNoisy) { printf(" checking node %p\n", content.get()); } - nsCOMPtrtext; - text = do_QueryInterface(content); - PRBool skipNode = PR_FALSE; - if (text) - { - if (PR_FALSE==isCollapsed && PR_TRUE==first && PR_TRUE==firstNodeInRange) - { - firstNodeInRange = PR_FALSE; - PRInt32 startOffset; - range->GetStartOffset(&startOffset); - PRUint32 count; - text->GetLength(&count); - if (startOffset==(PRInt32)count) - { - //if (gNoisy) { printf(" skipping node %p\n", content.get()); } - skipNode = PR_TRUE; - } - } - } - else - { // handle non-text leaf nodes here - PRBool canContainChildren; - content->CanContainChildren(canContainChildren); - if (PR_TRUE==canContainChildren) - { - //if (gNoisy) { printf(" skipping non-leaf node %p\n", content.get()); } - skipNode = PR_TRUE; - } - else { - //if (gNoisy) { printf(" testing non-text leaf node %p\n", content.get()); } - } - } - if (PR_FALSE==skipNode) - { - nsCOMPtrnode; - node = do_QueryInterface(content); - if (node) - { - PRBool isSet; - nsCOMPtrresultNode; - IsTextPropertySetByContent(node, aProperty, aAttribute, aValue, isSet, getter_AddRefs(resultNode)); - if (PR_TRUE==first) - { - aFirst = isSet; - first = PR_FALSE; - } - if (PR_TRUE==isSet) { - aAny = PR_TRUE; - } - else { - aAll = PR_FALSE; - } - } - } - iter->Next(); - iter->CurrentNode(getter_AddRefs(content)); + //if (gNoisy) { printf(" skipping node %p\n", content.get()); } + skipNode = PR_TRUE; } } } + else + { // handle non-text leaf nodes here + PRBool canContainChildren; + content->CanContainChildren(canContainChildren); + if (PR_TRUE==canContainChildren) + { + //if (gNoisy) { printf(" skipping non-leaf node %p\n", content.get()); } + skipNode = PR_TRUE; + } + else { + //if (gNoisy) { printf(" testing non-text leaf node %p\n", content.get()); } + } + } + if (PR_FALSE==skipNode) + { + nsCOMPtrnode; + node = do_QueryInterface(content); + if (node) + { + PRBool isSet; + nsCOMPtrresultNode; + IsTextPropertySetByContent(node, aProperty, aAttribute, aValue, isSet, getter_AddRefs(resultNode)); + if (PR_TRUE==first) + { + aFirst = isSet; + first = PR_FALSE; + } + if (PR_TRUE==isSet) { + aAny = PR_TRUE; + } + else { + aAll = PR_FALSE; + } + } + } + iter->Next(); + iter->CurrentNode(getter_AddRefs(content)); } } if (PR_FALSE==aAny) { // make sure that if none of the selection is set, we don't report all is set @@ -741,88 +732,85 @@ NS_IMETHODIMP nsTextEditor::RemoveTextProperty(nsIAtom *aProperty, const nsStrin delete [] propCString; } - nsresult result=NS_ERROR_NOT_INITIALIZED; + nsresult result; nsCOMPtrselection; result = nsEditor::GetSelection(getter_AddRefs(selection)); - if ((NS_SUCCEEDED(result)) && selection) + if (NS_FAILED(result)) return result; + if (!selection) return NS_ERROR_NULL_POINTER; + + PRBool cancel; + nsTextRulesInfo ruleInfo(nsTextEditRules::kRemoveTextProperty); + result = mRules->WillDoAction(selection, &ruleInfo, &cancel); + if ((PR_FALSE==cancel) && (NS_SUCCEEDED(result))) { - PRBool cancel; - nsTextRulesInfo ruleInfo(nsTextEditRules::kRemoveTextProperty); - result = mRules->WillDoAction(selection, &ruleInfo, &cancel); - if ((PR_FALSE==cancel) && (NS_SUCCEEDED(result))) + PRBool isCollapsed; + selection->GetIsCollapsed(&isCollapsed); + if (PR_TRUE==isCollapsed) { - PRBool isCollapsed; - selection->GetIsCollapsed(&isCollapsed); - if (PR_TRUE==isCollapsed) - { - // manipulating text attributes on a collapsed selection only sets state for the next text insertion - SetTypeInStateForProperty(*mTypeInState, aProperty, aAttribute, nsnull); + // manipulating text attributes on a collapsed selection only sets state for the next text insertion + SetTypeInStateForProperty(*mTypeInState, aProperty, aAttribute, nsnull); + } + else + { + // removing text properties can really shuffle text nodes around + // so we need to keep some extra state to restore a reasonable selection + // after we're done + nsCOMPtr parentForSelection; // selection's block parent + PRInt32 rangeStartOffset, rangeEndOffset; + GetTextSelectionOffsetsForRange(selection, getter_AddRefs(parentForSelection), + rangeStartOffset, rangeEndOffset); + nsEditor::BeginTransaction(); + nsCOMPtr startParent, endParent; + PRInt32 startOffset, endOffset; + nsCOMPtr enumerator; + result = selection->GetEnumerator(getter_AddRefs(enumerator)); + if (NS_FAILED(result)) return result; + if (!enumerator) return NS_ERROR_NULL_POINTER; + enumerator->First(); + nsCOMPtrcurrentItem; + result = enumerator->CurrentItem(getter_AddRefs(currentItem)); + if (NS_FAILED(result)) return result; + if (!currentItem) return NS_ERROR_NULL_POINTER; + nsCOMPtr range( do_QueryInterface(currentItem) ); + nsCOMPtrcommonParent; + result = range->GetCommonParent(getter_AddRefs(commonParent)); + if (NS_FAILED(result)) return result; + if (!commonParent) return NS_ERROR_NULL_POINTER; + range->GetStartOffset(&startOffset); + range->GetEndOffset(&endOffset); + range->GetStartParent(getter_AddRefs(startParent)); + range->GetEndParent(getter_AddRefs(endParent)); + if (startParent.get()==endParent.get()) + { // the range is entirely contained within a single text node + // commonParent==aStartParent, so get the "real" parent of the selection + startParent->GetParentNode(getter_AddRefs(commonParent)); + result = RemoveTextPropertiesForNode(startParent, commonParent, + startOffset, endOffset, + aProperty, nsnull); } else { - // removing text properties can really shuffle text nodes around - // so we need to keep some extra state to restore a reasonable selection - // after we're done - nsCOMPtr parentForSelection; // selection's block parent - PRInt32 rangeStartOffset, rangeEndOffset; - GetTextSelectionOffsetsForRange(selection, getter_AddRefs(parentForSelection), - rangeStartOffset, rangeEndOffset); - nsEditor::BeginTransaction(); - nsCOMPtr startParent, endParent; - PRInt32 startOffset, endOffset; - nsCOMPtr enumerator; - result = selection->GetEnumerator(getter_AddRefs(enumerator)); - if (NS_SUCCEEDED(result) && enumerator) - { - enumerator->First(); - nsCOMPtrcurrentItem; - result = enumerator->CurrentItem(getter_AddRefs(currentItem)); - if ((NS_SUCCEEDED(result)) && (currentItem)) - { - nsCOMPtr range( do_QueryInterface(currentItem) ); - nsCOMPtrcommonParent; - result = range->GetCommonParent(getter_AddRefs(commonParent)); - if ((NS_SUCCEEDED(result)) && commonParent) - { - range->GetStartOffset(&startOffset); - range->GetEndOffset(&endOffset); - range->GetStartParent(getter_AddRefs(startParent)); - range->GetEndParent(getter_AddRefs(endParent)); - if (startParent.get()==endParent.get()) - { // the range is entirely contained within a single text node - // commonParent==aStartParent, so get the "real" parent of the selection - startParent->GetParentNode(getter_AddRefs(commonParent)); - result = RemoveTextPropertiesForNode(startParent, commonParent, - startOffset, endOffset, - aProperty, nsnull); - } - else - { - result = RemoveTextPropertiesForNodeWithDifferentParents(startParent,startOffset, - endParent, endOffset, - commonParent, - aProperty, nsnull); - } - if (NS_SUCCEEDED(result)) - { // compute a range for the selection - // don't want to actually do anything with selection, because - // we are still iterating through it. Just want to create and remember - // an nsIDOMRange, and later add the range to the selection after clearing it. - // XXX: I'm blocked here because nsIDOMSelection doesn't provide a mechanism - // for setting a compound selection yet. - } - } - } - } - nsEditor::EndTransaction(); - if (NS_SUCCEEDED(result)) - { - ResetTextSelectionForRange(parentForSelection, rangeStartOffset, rangeEndOffset, selection); - } + result = RemoveTextPropertiesForNodeWithDifferentParents(startParent,startOffset, + endParent, endOffset, + commonParent, + aProperty, nsnull); + } + if (NS_SUCCEEDED(result)) + { // compute a range for the selection + // don't want to actually do anything with selection, because + // we are still iterating through it. Just want to create and remember + // an nsIDOMRange, and later add the range to the selection after clearing it. + // XXX: I'm blocked here because nsIDOMSelection doesn't provide a mechanism + // for setting a compound selection yet. + } + nsEditor::EndTransaction(); + if (NS_SUCCEEDED(result)) + { + ResetTextSelectionForRange(parentForSelection, rangeStartOffset, rangeEndOffset, selection); } - // post-process - result = mRules->DidDoAction(selection, &ruleInfo, result); } + // post-process + result = mRules->DidDoAction(selection, &ruleInfo, result); } if (gNoisy) { @@ -835,6 +823,7 @@ NS_IMETHODIMP nsTextEditor::RemoveTextProperty(nsIAtom *aProperty, const nsStrin return result; } +// XXX: should return nsresult void nsTextEditor::GetTextSelectionOffsetsForRange(nsIDOMSelection *aSelection, nsIDOMNode **aParent, PRInt32 &aStartOffset, @@ -901,6 +890,7 @@ void nsTextEditor::GetTextSelectionOffsetsForRange(nsIDOMSelection *aSelection, } } +// XXX: should return nsresult void nsTextEditor::ResetTextSelectionForRange(nsIDOMNode *aParent, PRInt32 aStartOffset, PRInt32 aEndOffset, @@ -1232,21 +1222,16 @@ NS_IMETHODIMP nsTextEditor::SaveDocument(PRBool saveAs, PRBool saveCopy) { nsCOMPtr fileWidget; rv = nsComponentManager::CreateInstance(kCFileWidgetCID, nsnull, kIFileWidgetIID, getter_AddRefs(fileWidget)); - if (NS_SUCCEEDED(rv) && fileWidget) - { - nsAutoString promptString("Save this document as:"); // XXX i18n, l10n - nsFileDlgResults dialogResult; - dialogResult = fileWidget->PutFile(nsnull, promptString, docFileSpec); - if (dialogResult == nsFileDlgResults_Cancel) - return NS_OK; - - replacing = (dialogResult == nsFileDlgResults_Replace); - } - else - { - NS_ASSERTION(0, "Failed to get file widget"); - return rv; - } + NS_ASSERTION((NS_SUCCEEDED(result) && fileWidget), "Failed to get file widget"); + if (NS_FAILED(result)) return result; + if (!fileWidget) return NS_ERROR_NULL_POINTER; + nsAutoString promptString("Save this document as:"); // XXX i18n, l10n + nsFileDlgResults dialogResult; + dialogResult = fileWidget->PutFile(nsnull, promptString, docFileSpec); + if (dialogResult == nsFileDlgResults_Cancel) + return NS_OK; + + replacing = (dialogResult == nsFileDlgResults_Replace); } nsAutoString charsetStr(""); @@ -1554,6 +1539,7 @@ NS_IMETHODIMP nsTextEditor::OutputToString(nsString& aOutputString, { nsCOMPtr selection; rv = GetSelection(getter_AddRefs(selection)); + // XXX: should we return here if we can't get the selection? if (NS_SUCCEEDED(rv) && selection) encoder->SetSelection(selection); } @@ -1633,6 +1619,7 @@ NS_IMETHODIMP nsTextEditor::OutputToStream(nsIOutputStream* aOutputStream, nsCOMPtr selection; rv = GetSelection(getter_AddRefs(selection)); if (NS_SUCCEEDED(rv) && selection) + //XXX: should we return here if we can't get selection? encoder->SetSelection(selection); } @@ -1715,48 +1702,48 @@ NS_IMETHODIMP nsTextEditor::SetTextPropertiesForNode(nsIDOMNode *aNode, { nsCOMPtrnewStyleNode; result = nsEditor::CreateNode(tag, aParent, 0, getter_AddRefs(newStyleNode)); - if (NS_SUCCEEDED(result) && newStyleNode) + if (NS_FAILED(result)) return result; + if (!newStyleNode) return NS_ERROR_NULL_POINTER; + + nsCOMPtrnodeAsChar; + nodeAsChar = do_QueryInterface(aNode); + if (nodeAsChar) { - nsCOMPtrnodeAsChar; - nodeAsChar = do_QueryInterface(aNode); - if (nodeAsChar) - { - result = MoveContentOfNodeIntoNewParent(aNode, newStyleNode, aStartOffset, aEndOffset); - } - else - { // handle non-text selection - nsCOMPtr parent; // used just to make the code easier to understand - nsCOMPtr child; - parent = do_QueryInterface(aNode); - child = GetChildAt(parent, aStartOffset); - // XXX: need to loop for aStartOffset!=aEndOffset-1? - PRInt32 offsetInParent = aStartOffset; // remember where aNode was in aParent - if (NS_SUCCEEDED(result)) - { // remove child from parent - result = nsEditor::DeleteNode(child); + result = MoveContentOfNodeIntoNewParent(aNode, newStyleNode, aStartOffset, aEndOffset); + } + else + { // handle non-text selection + nsCOMPtr parent; // used just to make the code easier to understand + nsCOMPtr child; + parent = do_QueryInterface(aNode); + child = GetChildAt(parent, aStartOffset); + // XXX: need to loop for aStartOffset!=aEndOffset-1? + PRInt32 offsetInParent = aStartOffset; // remember where aNode was in aParent + if (NS_SUCCEEDED(result)) + { // remove child from parent + result = nsEditor::DeleteNode(child); + if (NS_SUCCEEDED(result)) + { // put child into the newStyleNode + result = nsEditor::InsertNode(child, newStyleNode, 0); if (NS_SUCCEEDED(result)) - { // put child into the newStyleNode - result = nsEditor::InsertNode(child, newStyleNode, 0); - if (NS_SUCCEEDED(result)) - { // put newStyleNode in parent where child was - result = nsEditor::InsertNode(newStyleNode, parent, offsetInParent); - } + { // put newStyleNode in parent where child was + result = nsEditor::InsertNode(newStyleNode, parent, offsetInParent); } } } - if (NS_SUCCEEDED(result)) + } + if (NS_SUCCEEDED(result)) + { + if (aAttribute && 0!=aAttribute->Length()) { - if (aAttribute && 0!=aAttribute->Length()) - { - nsCOMPtr newStyleElement; - newStyleElement = do_QueryInterface(newStyleNode); - nsAutoString value; - if (aValue) { - value = *aValue; - } - // XXX should be a call to editor to change attribute! - result = newStyleElement->SetAttribute(*aAttribute, value); + nsCOMPtr newStyleElement; + newStyleElement = do_QueryInterface(newStyleNode); + nsAutoString value; + if (aValue) { + value = *aValue; } + // XXX should be a call to editor to change attribute! + result = newStyleElement->SetAttribute(*aAttribute, value); } } } @@ -1907,28 +1894,25 @@ nsTextEditor::SetTextPropertiesForNodesWithSameParent(nsIDOMNode *aStartNode, nsCOMPtrnewStyleNode; nsCOMPtrdoc; result = GetDocument(getter_AddRefs(doc)); - if (NS_SUCCEEDED(result) && doc) + if (NS_FAILED(result)) return result; + if (!doc) return NS_ERROR_NULL_POINTER; + + nsCOMPtrnewElement; + result = doc->CreateElement(tag, getter_AddRefs(newElement)); + if (NS_FAILED(result)) return result; + if (!newElement) return NS_ERROR_NULL_POINTER; + newStyleNode = do_QueryInterface(newElement); + if (!newStyleNode) return NS_ERROR_NULL_POINTER; + result = MoveContiguousContentIntoNewParent(aStartNode, aStartOffset, aEndNode, aEndOffset, aParent, newStyleNode); + if (NS_SUCCEEDED(result) && aAttribute && 0!=aAttribute->Length()) { - nsCOMPtrnewElement; - result = doc->CreateElement(tag, getter_AddRefs(newElement)); - if (NS_SUCCEEDED(result) && newElement) - { - newStyleNode = do_QueryInterface(newElement); - } - } - if (NS_SUCCEEDED(result) && newStyleNode) - { - result = MoveContiguousContentIntoNewParent(aStartNode, aStartOffset, aEndNode, aEndOffset, aParent, newStyleNode); - if (NS_SUCCEEDED(result) && aAttribute && 0!=aAttribute->Length()) - { - nsCOMPtr newStyleElement; - newStyleElement = do_QueryInterface(newStyleNode); - nsAutoString value; - if (aValue) { - value = *aValue; - } - result = newStyleElement->SetAttribute(*aAttribute, value); + nsCOMPtr newStyleElement; + newStyleElement = do_QueryInterface(newStyleNode); + nsAutoString value; + if (aValue) { + value = *aValue; } + result = newStyleElement->SetAttribute(*aAttribute, value); } } return result; @@ -2116,164 +2100,164 @@ nsTextEditor::SetTextPropertiesForNodeWithDifferentParents(nsIDOMRange *aRange, nsCOMPtriter; result = nsComponentManager::CreateInstance(kCContentIteratorCID, nsnull, nsIContentIterator::GetIID(), getter_AddRefs(iter)); - if ((NS_SUCCEEDED(result)) && iter) + if (NS_FAILED(result)) return result; + if (!iter) return NS_ERROR_NULL_POINTER; + + // find our starting point + PRBool startIsText = IsTextNode(aStartNode); + nsCOMPtrstartContent; + if (PR_TRUE==startIsText) { + startContent = do_QueryInterface(aStartNode); + } + else { + nsCOMPtrnode = GetChildAt(aStartNode, aStartOffset); + startContent = do_QueryInterface(node); + } + + // find our ending point + PRBool endIsText = IsTextNode(aEndNode); + nsCOMPtrendContent; + if (PR_TRUE==endIsText) { + endContent = do_QueryInterface(aEndNode); + } + else { - // find our starting point - PRBool startIsText = IsTextNode(aStartNode); - nsCOMPtrstartContent; - if (PR_TRUE==startIsText) { - startContent = do_QueryInterface(aStartNode); + nsCOMPtrtheEndNode; + if (aEndOffset>0) + { + theEndNode = GetChildAt(aEndNode, aEndOffset-1); } else { - nsCOMPtrnode = GetChildAt(aStartNode, aStartOffset); - startContent = do_QueryInterface(node); + // XXX: we need to find the previous node and set the selection correctly + NS_ASSERTION(0, "unexpected selection"); + return NS_ERROR_NOT_IMPLEMENTED; } + endContent = do_QueryInterface(theEndNode); + } - // find our ending point - PRBool endIsText = IsTextNode(aEndNode); - nsCOMPtrendContent; - if (PR_TRUE==endIsText) { - endContent = do_QueryInterface(aEndNode); - } - else + if (!startContent || !endContent) { return NS_ERROR_NULL_POINTER; } + // iterate over the nodes between the starting and ending points + iter->Init(aRange); + nsCOMPtr content; + iter->CurrentNode(getter_AddRefs(content)); + nsAutoString tag; + aPropName->ToString(tag); + while (NS_COMFALSE == iter->IsDone()) + { + if ((content.get() != startContent.get()) && + (content.get() != endContent.get())) { - nsCOMPtrtheEndNode; - if (aEndOffset>0) + nsCOMPtrnode; + node = do_QueryInterface(content); + if (IsEditable(node)) { - theEndNode = GetChildAt(aEndNode, aEndOffset-1); - } - else { - // XXX: we need to find the previous node and set the selection correctly - NS_ASSERTION(0, "unexpected selection"); - return NS_ERROR_NOT_IMPLEMENTED; - } - endContent = do_QueryInterface(theEndNode); - } - - if (!startContent || !endContent) { return NS_ERROR_NULL_POINTER; } - // iterate over the nodes between the starting and ending points - iter->Init(aRange); - nsCOMPtr content; - iter->CurrentNode(getter_AddRefs(content)); - nsAutoString tag; - aPropName->ToString(tag); - while (NS_COMFALSE == iter->IsDone()) - { - if ((content.get() != startContent.get()) && - (content.get() != endContent.get())) - { - nsCOMPtrnode; - node = do_QueryInterface(content); - if (IsEditable(node)) - { - PRBool canContainChildren; - content->CanContainChildren(canContainChildren); - if (PR_FALSE==canContainChildren) - { - nsEditor::GetTagString(node,tag); - if (tag != "br") // skip
, even though it's a leaf - { // only want to wrap the text node in a new style node if it doesn't already have that style - if (gNoisy) { printf("node %p is an editable leaf.\n", node.get()); } - PRBool textPropertySet; - nsCOMPtrresultNode; - IsTextPropertySetByContent(node, aPropName, aAttribute, aValue, textPropertySet, getter_AddRefs(resultNode)); - if (PR_FALSE==textPropertySet) + PRBool canContainChildren; + content->CanContainChildren(canContainChildren); + if (PR_FALSE==canContainChildren) + { + nsEditor::GetTagString(node,tag); + if (tag != "br") // skip
, even though it's a leaf + { // only want to wrap the text node in a new style node if it doesn't already have that style + if (gNoisy) { printf("node %p is an editable leaf.\n", node.get()); } + PRBool textPropertySet; + nsCOMPtrresultNode; + IsTextPropertySetByContent(node, aPropName, aAttribute, aValue, textPropertySet, getter_AddRefs(resultNode)); + if (PR_FALSE==textPropertySet) + { + if (gNoisy) { printf("property not set\n"); } + node->GetParentNode(getter_AddRefs(parent)); + if (!parent) { return NS_ERROR_NULL_POINTER; } + nsCOMPtrparentContent; + parentContent = do_QueryInterface(parent); + nsCOMPtrparentNode = do_QueryInterface(parent); + if (PR_TRUE==IsTextNode(node)) { - if (gNoisy) { printf("property not set\n"); } - node->GetParentNode(getter_AddRefs(parent)); - if (!parent) { return NS_ERROR_NULL_POINTER; } - nsCOMPtrparentContent; - parentContent = do_QueryInterface(parent); - nsCOMPtrparentNode = do_QueryInterface(parent); - if (PR_TRUE==IsTextNode(node)) - { - startOffset = 0; - result = GetLengthOfDOMNode(node, (PRUint32&)endOffset); - } - else - { - parentContent->IndexOf(content, startOffset); - endOffset = startOffset+1; - } - if (gNoisy) { printf("start/end = %d %d\n", startOffset, endOffset); } - if (NS_SUCCEEDED(result)) { - result = SetTextPropertiesForNode(node, parentNode, startOffset, endOffset, aPropName, aAttribute, aValue); - } + startOffset = 0; + result = GetLengthOfDOMNode(node, (PRUint32&)endOffset); + } + else + { + parentContent->IndexOf(content, startOffset); + endOffset = startOffset+1; + } + if (gNoisy) { printf("start/end = %d %d\n", startOffset, endOffset); } + if (NS_SUCCEEDED(result)) { + result = SetTextPropertiesForNode(node, parentNode, startOffset, endOffset, aPropName, aAttribute, aValue); } } } } - // XXX: shouldn't there be an else here for non-text leaf nodes? } - // note we don't check the result, we just rely on iter->IsDone - iter->Next(); - iter->CurrentNode(getter_AddRefs(content)); + // XXX: shouldn't there be an else here for non-text leaf nodes? } - // handle endpoints + // note we don't check the result, we just rely on iter->IsDone + iter->Next(); + iter->CurrentNode(getter_AddRefs(content)); + } + // handle endpoints + if (NS_SUCCEEDED(result)) + { + // create a style node for the text in the start parent + nsCOMPtrstartNode = do_QueryInterface(startContent); + result = startNode->GetParentNode(getter_AddRefs(parent)); + if (NS_FAILED(result)) { + return result; + } + nsCOMPtrnodeAsChar; + nodeAsChar = do_QueryInterface(startNode); + if (nodeAsChar) + { + nodeAsChar->GetLength(&count); + if (gNoisy) { printf("processing start node %p.\n", nodeAsChar.get()); } + result = SetTextPropertiesForNode(startNode, parent, aStartOffset, count, aPropName, aAttribute, aValue); + startOffset = 0; + } + else + { + nsCOMPtrgrandParent; + result = parent->GetParentNode(getter_AddRefs(grandParent)); + if (gNoisy) { printf("processing start node %p.\n", parent.get()); } + result = SetTextPropertiesForNode(parent, grandParent, aStartOffset, aStartOffset+1, aPropName, aAttribute, aValue); + startNode = do_QueryInterface(parent); + startOffset = aStartOffset; + } + + if (NS_SUCCEEDED(result)) { - // create a style node for the text in the start parent - nsCOMPtrstartNode = do_QueryInterface(startContent); - result = startNode->GetParentNode(getter_AddRefs(parent)); + // create a style node for the text in the end parent + nsCOMPtrendNode = do_QueryInterface(endContent); + result = endNode->GetParentNode(getter_AddRefs(parent)); if (NS_FAILED(result)) { return result; } - nsCOMPtrnodeAsChar; - nodeAsChar = do_QueryInterface(startNode); + nodeAsChar = do_QueryInterface(endNode); if (nodeAsChar) - { + { nodeAsChar->GetLength(&count); - if (gNoisy) { printf("processing start node %p.\n", nodeAsChar.get()); } - result = SetTextPropertiesForNode(startNode, parent, aStartOffset, count, aPropName, aAttribute, aValue); - startOffset = 0; + if (gNoisy) { printf("processing end node %p.\n", nodeAsChar.get()); } + result = SetTextPropertiesForNode(endNode, parent, 0, aEndOffset, aPropName, aAttribute, aValue); + // SetTextPropertiesForNode kindly computed the proper selection focus node and offset for us, + // remember them here + selection->GetFocusOffset(&endOffset); + selection->GetFocusNode(getter_AddRefs(endNode)); } else { + NS_ASSERTION(0!=aEndOffset, "unexpected selection end offset"); + if (0==aEndOffset) { return NS_ERROR_NOT_IMPLEMENTED; } nsCOMPtrgrandParent; result = parent->GetParentNode(getter_AddRefs(grandParent)); - if (gNoisy) { printf("processing start node %p.\n", parent.get()); } - result = SetTextPropertiesForNode(parent, grandParent, aStartOffset, aStartOffset+1, aPropName, aAttribute, aValue); - startNode = do_QueryInterface(parent); - startOffset = aStartOffset; + if (gNoisy) { printf("processing end node %p.\n", parent.get()); } + result = SetTextPropertiesForNode(parent, grandParent, aEndOffset-1, aEndOffset, aPropName, aAttribute, aValue); + endNode = do_QueryInterface(parent); + endOffset = 0; } - - if (NS_SUCCEEDED(result)) { - // create a style node for the text in the end parent - nsCOMPtrendNode = do_QueryInterface(endContent); - result = endNode->GetParentNode(getter_AddRefs(parent)); - if (NS_FAILED(result)) { - return result; - } - nodeAsChar = do_QueryInterface(endNode); - if (nodeAsChar) - { - nodeAsChar->GetLength(&count); - if (gNoisy) { printf("processing end node %p.\n", nodeAsChar.get()); } - result = SetTextPropertiesForNode(endNode, parent, 0, aEndOffset, aPropName, aAttribute, aValue); - // SetTextPropertiesForNode kindly computed the proper selection focus node and offset for us, - // remember them here - selection->GetFocusOffset(&endOffset); - selection->GetFocusNode(getter_AddRefs(endNode)); - } - else - { - NS_ASSERTION(0!=aEndOffset, "unexpected selection end offset"); - if (0==aEndOffset) { return NS_ERROR_NOT_IMPLEMENTED; } - nsCOMPtrgrandParent; - result = parent->GetParentNode(getter_AddRefs(grandParent)); - if (gNoisy) { printf("processing end node %p.\n", parent.get()); } - result = SetTextPropertiesForNode(parent, grandParent, aEndOffset-1, aEndOffset, aPropName, aAttribute, aValue); - endNode = do_QueryInterface(parent); - endOffset = 0; - } - if (NS_SUCCEEDED(result)) - { - selection->Collapse(startNode, startOffset); - selection->Extend(endNode, aEndOffset); - } + selection->Collapse(startNode, startOffset); + selection->Extend(endNode, aEndOffset); } } } @@ -2336,157 +2320,156 @@ NS_IMETHODIMP nsTextEditor::RemoveTextPropertiesForNode(nsIDOMNode *aNode, newMiddleNode = do_QueryInterface(aNode); parent = do_QueryInterface(aParent); } - if (NS_SUCCEEDED(result) && newMiddleNode) + if (NS_FAILED(result)) return result; + if (!newMiddleNode) return NS_ERROR_NULL_POINTER; + + // split every ancestor until we find the node that is giving us the style we want to remove + // then split the style node and promote the selected content to the style node's parent + while (NS_SUCCEEDED(result) && parent) { - // split every ancestor until we find the node that is giving us the style we want to remove - // then split the style node and promote the selected content to the style node's parent - while (NS_SUCCEEDED(result) && parent) + if (gNoisy) { printf("* looking at parent %p\n", parent.get());} + // get the tag from parent and see if we're done + nsCOMPtrtemp; + nsCOMPtrelement; + element = do_QueryInterface(parent); + if (element) { - if (gNoisy) { printf("* looking at parent %p\n", parent.get());} - // get the tag from parent and see if we're done - nsCOMPtrtemp; - nsCOMPtrelement; - element = do_QueryInterface(parent); - if (element) + nsAutoString tag; + result = element->GetTagName(tag); + if (gNoisy) { printf("* parent has tag %s\n", tag.ToNewCString()); } // XXX leak! + if (NS_SUCCEEDED(result)) { - nsAutoString tag; - result = element->GetTagName(tag); - if (gNoisy) { printf("* parent has tag %s\n", tag.ToNewCString()); } // XXX leak! - if (NS_SUCCEEDED(result)) + if (PR_FALSE==tag.EqualsIgnoreCase(aPropName->GetUnicode())) { - if (PR_FALSE==tag.EqualsIgnoreCase(aPropName->GetUnicode())) + PRInt32 offsetInParent; + result = GetChildOffset(newMiddleNode, parent, offsetInParent); + if (NS_SUCCEEDED(result)) { - PRInt32 offsetInParent; - result = GetChildOffset(newMiddleNode, parent, offsetInParent); - if (NS_SUCCEEDED(result)) - { - if (0!=offsetInParent) { - if (gNoisy) { printf("* splitting parent %p at offset %d\n", parent.get(), offsetInParent);} - result = nsEditor::SplitNode(parent, offsetInParent, getter_AddRefs(newLeftNode)); - if (gNoisy) { printf("* split created left node %p sibling of parent\n", newLeftNode.get());} - if (gNoisy) {DebugDumpContent(); } // DEBUG - } - if (NS_SUCCEEDED(result)) - { - nsCOMPtrchildNodes; - result = parent->GetChildNodes(getter_AddRefs(childNodes)); - if (NS_SUCCEEDED(result) && childNodes) - { - childNodes->GetLength(&count); - NS_ASSERTION(count>0, "bad child count in newly split node"); - if ((PRInt32)count!=1) - { - if (gNoisy) { printf("* splitting parent %p at offset %d\n", parent.get(), 1);} - result = nsEditor::SplitNode(parent, 1, getter_AddRefs(newMiddleNode)); - if (gNoisy) { printf("* split created middle node %p sibling of parent\n", newMiddleNode.get());} - if (gNoisy) {DebugDumpContent(); } // DEBUG - } - else { - if (gNoisy) { printf("* no need to split parent, newMiddleNode=parent\n");} - newMiddleNode = do_QueryInterface(parent); - } - NS_ASSERTION(newMiddleNode, "no middle node created"); - parent->GetParentNode(getter_AddRefs(temp)); - parent = do_QueryInterface(temp); - } - } + if (0!=offsetInParent) { + if (gNoisy) { printf("* splitting parent %p at offset %d\n", parent.get(), offsetInParent);} + result = nsEditor::SplitNode(parent, offsetInParent, getter_AddRefs(newLeftNode)); + if (gNoisy) { printf("* split created left node %p sibling of parent\n", newLeftNode.get());} + if (gNoisy) {DebugDumpContent(); } // DEBUG } - } - // else we've found the style tag (referred to by "parent") - // newMiddleNode is the node that is an ancestor to the selection - else - { - if (gNoisy) { printf("* this is the style node\n");} - PRInt32 offsetInParent; - result = GetChildOffset(newMiddleNode, parent, offsetInParent); if (NS_SUCCEEDED(result)) { nsCOMPtrchildNodes; result = parent->GetChildNodes(getter_AddRefs(childNodes)); - if (NS_SUCCEEDED(result) && childNodes) + if (NS_FAILED(result)) return result; + if (!childNodes) return NS_ERROR_NULL_POINTER; + + childNodes->GetLength(&count); + NS_ASSERTION(count>0, "bad child count in newly split node"); + if ((PRInt32)count!=1) { + if (gNoisy) { printf("* splitting parent %p at offset %d\n", parent.get(), 1);} + result = nsEditor::SplitNode(parent, 1, getter_AddRefs(newMiddleNode)); + if (gNoisy) { printf("* split created middle node %p sibling of parent\n", newMiddleNode.get());} + if (gNoisy) {DebugDumpContent(); } // DEBUG + } + else { + if (gNoisy) { printf("* no need to split parent, newMiddleNode=parent\n");} + newMiddleNode = do_QueryInterface(parent); + } + NS_ASSERTION(newMiddleNode, "no middle node created"); + parent->GetParentNode(getter_AddRefs(temp)); + parent = do_QueryInterface(temp); + } + } + } + // else we've found the style tag (referred to by "parent") + // newMiddleNode is the node that is an ancestor to the selection + else + { + if (gNoisy) { printf("* this is the style node\n");} + PRInt32 offsetInParent; + result = GetChildOffset(newMiddleNode, parent, offsetInParent); + if (NS_SUCCEEDED(result)) + { + nsCOMPtrchildNodes; + result = parent->GetChildNodes(getter_AddRefs(childNodes)); + if (NS_FAILED(result)) return result; + if (!childNodes) return NS_ERROR_NULL_POINTER; + childNodes->GetLength(&count); + // if there are siblings to the right, split parent at offsetInParent+1 + if ((PRInt32)count!=offsetInParent+1) + { + nsCOMPtrnewRightNode; + //nsCOMPtrtemp; + if (gNoisy) { printf("* splitting parent %p at offset %d for right side\n", parent.get(), offsetInParent+1);} + result = nsEditor::SplitNode(parent, offsetInParent+1, getter_AddRefs(temp)); + if (NS_SUCCEEDED(result)) + { + newRightNode = do_QueryInterface(parent); + parent = do_QueryInterface(temp); + if (gNoisy) { printf("* split created right node %p sibling of parent %p\n", newRightNode.get(), parent.get());} + if (gNoisy) {DebugDumpContent(); } // DEBUG + } + } + if (NS_SUCCEEDED(result) && 0!=offsetInParent) { + if (gNoisy) { printf("* splitting parent %p at offset %d for left side\n", parent.get(), offsetInParent);} + result = nsEditor::SplitNode(parent, offsetInParent, getter_AddRefs(newLeftNode)); + if (gNoisy) { printf("* split created left node %p sibling of parent %p\n", newLeftNode.get(), parent.get());} + if (gNoisy) {DebugDumpContent(); } // DEBUG + } + if (NS_SUCCEEDED(result)) + { // promote the selection to the grandparent + // first, determine the child's position in it's parent + PRInt32 childPositionInParent; + GetChildOffset(newMiddleNode, parent, childPositionInParent); + // compare childPositionInParent to the number of children in parent + //PRUint32 count=0; + //nsCOMPtrchildNodes; + result = parent->GetChildNodes(getter_AddRefs(childNodes)); + if (NS_SUCCEEDED(result) && childNodes) { childNodes->GetLength(&count); - // if there are siblings to the right, split parent at offsetInParent+1 - if ((PRInt32)count!=offsetInParent+1) + } + PRBool insertAfter = PR_FALSE; + // if they're equal, we'll insert newMiddleNode in grandParent after the parent + if ((PRInt32)count==childPositionInParent) { + insertAfter = PR_TRUE; + } + // now that we know where to put newMiddleNode, do it. + nsCOMPtrgrandParent; + result = parent->GetParentNode(getter_AddRefs(grandParent)); + if (NS_FAILED(result)) return result; + if (!grandParent) return NS_ERROR_NULL_POINTER; + + if (gNoisy) { printf("* deleting middle node %p\n", newMiddleNode.get());} + result = nsEditor::DeleteNode(newMiddleNode); + if (gNoisy) {DebugDumpContent(); } // DEBUG + if (NS_SUCCEEDED(result)) + { + PRInt32 position; + result = GetChildOffset(parent, grandParent, position); + if (NS_SUCCEEDED(result)) { - nsCOMPtrnewRightNode; - //nsCOMPtrtemp; - if (gNoisy) { printf("* splitting parent %p at offset %d for right side\n", parent.get(), offsetInParent+1);} - result = nsEditor::SplitNode(parent, offsetInParent+1, getter_AddRefs(temp)); - if (NS_SUCCEEDED(result)) + if (PR_TRUE==insertAfter) { - newRightNode = do_QueryInterface(parent); - parent = do_QueryInterface(temp); - if (gNoisy) { printf("* split created right node %p sibling of parent %p\n", newRightNode.get(), parent.get());} - if (gNoisy) {DebugDumpContent(); } // DEBUG + if (gNoisy) {printf("insertAfter=PR_TRUE, incr. position\n"); } + position++; } - } - if (NS_SUCCEEDED(result) && 0!=offsetInParent) { - if (gNoisy) { printf("* splitting parent %p at offset %d for left side\n", parent.get(), offsetInParent);} - result = nsEditor::SplitNode(parent, offsetInParent, getter_AddRefs(newLeftNode)); - if (gNoisy) { printf("* split created left node %p sibling of parent %p\n", newLeftNode.get(), parent.get());} + if (gNoisy) { + printf("* inserting node %p in grandparent %p at offset %d\n", + newMiddleNode.get(), grandParent.get(), position); + } + result = nsEditor::InsertNode(newMiddleNode, grandParent, position); if (gNoisy) {DebugDumpContent(); } // DEBUG - } - if (NS_SUCCEEDED(result)) - { // promote the selection to the grandparent - // first, determine the child's position in it's parent - PRInt32 childPositionInParent; - GetChildOffset(newMiddleNode, parent, childPositionInParent); - // compare childPositionInParent to the number of children in parent - //PRUint32 count=0; - //nsCOMPtrchildNodes; - result = parent->GetChildNodes(getter_AddRefs(childNodes)); - if (NS_SUCCEEDED(result) && childNodes) { - childNodes->GetLength(&count); - } - PRBool insertAfter = PR_FALSE; - // if they're equal, we'll insert newMiddleNode in grandParent after the parent - if ((PRInt32)count==childPositionInParent) { - insertAfter = PR_TRUE; - } - // now that we know where to put newMiddleNode, do it. - nsCOMPtrgrandParent; - result = parent->GetParentNode(getter_AddRefs(grandParent)); - if (NS_SUCCEEDED(result) && grandParent) + if (NS_SUCCEEDED(result)) { - if (gNoisy) { printf("* deleting middle node %p\n", newMiddleNode.get());} - result = nsEditor::DeleteNode(newMiddleNode); - if (gNoisy) {DebugDumpContent(); } // DEBUG - if (NS_SUCCEEDED(result)) - { - PRInt32 position; - result = GetChildOffset(parent, grandParent, position); - if (NS_SUCCEEDED(result)) - { - if (PR_TRUE==insertAfter) - { - if (gNoisy) {printf("insertAfter=PR_TRUE, incr. position\n"); } - position++; - } - if (gNoisy) { - printf("* inserting node %p in grandparent %p at offset %d\n", - newMiddleNode.get(), grandParent.get(), position); - } - result = nsEditor::InsertNode(newMiddleNode, grandParent, position); - if (gNoisy) {DebugDumpContent(); } // DEBUG - if (NS_SUCCEEDED(result)) - { - PRBool hasChildren=PR_TRUE; - parent->HasChildNodes(&hasChildren); - if (PR_FALSE==hasChildren) { - if (gNoisy) { printf("* deleting empty style node %p\n", parent.get());} - result = nsEditor::DeleteNode(parent); - if (gNoisy) {DebugDumpContent(); } // DEBUG - } - } - } + PRBool hasChildren=PR_TRUE; + parent->HasChildNodes(&hasChildren); + if (PR_FALSE==hasChildren) { + if (gNoisy) { printf("* deleting empty style node %p\n", parent.get());} + result = nsEditor::DeleteNode(parent); + if (gNoisy) {DebugDumpContent(); } // DEBUG } } } } } - break; } + break; } } } @@ -2516,7 +2499,8 @@ nsTextEditor::RemoveTextPropertiesForNodesWithSameParent(nsIDOMNode *aStartNode, nsCOMPtrsiblingNode; nsCOMPtrnextSiblingNode; // temp to hold the next node in the list result = aStartNode->GetNextSibling(getter_AddRefs(siblingNode)); - while (siblingNode && NS_SUCCEEDED(result)) + if (NS_FAILED(result)) return result; + while (siblingNode) { // get next sibling right away, before we move siblingNode! siblingNode->GetNextSibling(getter_AddRefs(nextSiblingNode)); @@ -2542,40 +2526,35 @@ nsTextEditor::RemoveTextPropertiesForNodesWithSameParent(nsIDOMNode *aStartNode, // XXX: for now, I think that's ok. just pass in 0 } } - if (NS_SUCCEEDED(result)) { - siblingNode->GetParentNode(getter_AddRefs(parentNode)); - result = RemoveTextPropertiesForNode(siblingNode, parentNode, 0, childCount, aPropName, aAttribute); - } + if (NS_FAILED(result)) return result; + siblingNode->GetParentNode(getter_AddRefs(parentNode)); + result = RemoveTextPropertiesForNode(siblingNode, parentNode, 0, childCount, aPropName, aAttribute); + if (NS_FAILED(result)) return result; } siblingNode = do_QueryInterface(nextSiblingNode); } - if (NS_SUCCEEDED(result)) - { - // remove aPropName from aStartNode - //nsCOMPtrnodeAsChar; - nodeAsChar = do_QueryInterface(aStartNode); - if (nodeAsChar) { - nodeAsChar->GetLength((PRUint32 *)&endOffset); - } - else - { - if (gNoisy) { printf("not yet supported\n");} - return NS_ERROR_NOT_IMPLEMENTED; - } - result = aStartNode->GetParentNode(getter_AddRefs(parentNode)); - if (NS_SUCCEEDED(result)) { - result = RemoveTextPropertiesForNode(aStartNode, parentNode, startOffset, endOffset, aPropName, aAttribute); - } + // remove aPropName from aStartNode + //nsCOMPtrnodeAsChar; + nodeAsChar = do_QueryInterface(aStartNode); + if (nodeAsChar) { + nodeAsChar->GetLength((PRUint32 *)&endOffset); } - if (NS_SUCCEEDED(result)) + else { - // remove aPropName from the end node - startOffset = 0; - endOffset = aEndOffset; - result = aEndNode->GetParentNode(getter_AddRefs(parentNode)); - if (NS_SUCCEEDED(result)) { - result = RemoveTextPropertiesForNode(aEndNode, parentNode, startOffset, endOffset, aPropName, aAttribute); - } + if (gNoisy) { printf("not yet supported\n");} + return NS_ERROR_NOT_IMPLEMENTED; + } + result = aStartNode->GetParentNode(getter_AddRefs(parentNode)); + if (NS_SUCCEEDED(result)) { + result = RemoveTextPropertiesForNode(aStartNode, parentNode, startOffset, endOffset, aPropName, aAttribute); + } + if (NS_FAILED(result)) return result; + // remove aPropName from the end node + startOffset = 0; + endOffset = aEndOffset; + result = aEndNode->GetParentNode(getter_AddRefs(parentNode)); + if (NS_SUCCEEDED(result)) { + result = RemoveTextPropertiesForNode(aEndNode, parentNode, startOffset, endOffset, aPropName, aAttribute); } return result; } @@ -2716,106 +2695,101 @@ nsTextEditor::RemoveTextPropertiesForNodeWithDifferentParents(nsIDOMNode *aStar nsCOMPtriter; result = nsComponentManager::CreateInstance(kCContentIteratorCID, nsnull, nsIContentIterator::GetIID(), getter_AddRefs(iter)); - if ((NS_SUCCEEDED(result)) && iter) + if (NS_FAILED(result)) return result; + if (!iter) return NS_ERROR_NULL_POINTER; + + nsCOMPtrstartContent; + startContent = do_QueryInterface(startNode); + nsCOMPtrendContent; + endContent = do_QueryInterface(endNode); + if (startContent && endContent) { - nsCOMPtrstartContent; - startContent = do_QueryInterface(startNode); - nsCOMPtrendContent; - endContent = do_QueryInterface(endNode); - if (startContent && endContent) + iter->Init(range); + nsCOMPtr content; + iter->CurrentNode(getter_AddRefs(content)); + nsAutoString propName; // the property we are removing + aPropName->ToString(propName); + while (NS_COMFALSE == iter->IsDone()) { - iter->Init(range); - nsCOMPtr content; - iter->CurrentNode(getter_AddRefs(content)); - nsAutoString propName; // the property we are removing - aPropName->ToString(propName); - while (NS_COMFALSE == iter->IsDone()) + if ((content.get() != startContent.get()) && + (content.get() != endContent.get())) { - if ((content.get() != startContent.get()) && - (content.get() != endContent.get())) + nsCOMPtrelement; + element = do_QueryInterface(content); + if (element) { - nsCOMPtrelement; - element = do_QueryInterface(content); - if (element) + nsString tag; + element->GetTagName(tag); + if (propName.EqualsIgnoreCase(tag)) { - nsString tag; - element->GetTagName(tag); - if (propName.EqualsIgnoreCase(tag)) - { - if (-1==nodeList.IndexOf(content.get())) { - nodeList.AppendElement((void *)(content.get())); - } + if (-1==nodeList.IndexOf(content.get())) { + nodeList.AppendElement((void *)(content.get())); } } } - // note we don't check the result, we just rely on iter->IsDone - iter->Next(); - iter->CurrentNode(getter_AddRefs(content)); } + // note we don't check the result, we just rely on iter->IsDone + iter->Next(); + iter->CurrentNode(getter_AddRefs(content)); } } // now delete all the style nodes we found - if (NS_SUCCEEDED(result)) + nsIContent *contentPtr; + contentPtr = (nsIContent*)(nodeList.ElementAt(0)); + while (contentPtr) { - nsIContent *contentPtr; - contentPtr = (nsIContent*)(nodeList.ElementAt(0)); - while (NS_SUCCEEDED(result) && contentPtr) - { - nsCOMPtrstyleNode; - styleNode = do_QueryInterface(contentPtr); - // promote the children of styleNode - nsCOMPtrparentNode; - result = styleNode->GetParentNode(getter_AddRefs(parentNode)); - if (NS_SUCCEEDED(result) && parentNode) - { - PRInt32 position; - result = GetChildOffset(styleNode, parentNode, position); - if (NS_SUCCEEDED(result)) - { - nsCOMPtrpreviousSiblingNode; - nsCOMPtrchildNode; - result = styleNode->GetLastChild(getter_AddRefs(childNode)); - while (NS_SUCCEEDED(result) && childNode) - { - childNode->GetPreviousSibling(getter_AddRefs(previousSiblingNode)); - // explicitly delete of childNode from styleNode - // can't just rely on DOM semantics of InsertNode doing the delete implicitly, doesn't undo! - result = nsEditor::DeleteNode(childNode); - if (NS_SUCCEEDED(result)) - { - result = nsEditor::InsertNode(childNode, parentNode, position); - if (gNoisy) - { - printf("deleted next sibling node %p\n", childNode.get()); - DebugDumpContent(); // DEBUG - } - } - childNode = do_QueryInterface(previousSiblingNode); - } // end while loop - // delete styleNode - result = nsEditor::DeleteNode(styleNode); - if (gNoisy) - { - printf("deleted style node %p\n", styleNode.get()); - DebugDumpContent(); // DEBUG - } - } - } + nsCOMPtrstyleNode; + styleNode = do_QueryInterface(contentPtr); + // promote the children of styleNode + nsCOMPtrparentNode; + result = styleNode->GetParentNode(getter_AddRefs(parentNode)); + if (NS_FAILED(result)) return result; + if (!parentNode) return NS_ERROR_NULL_POINTER; - // get next content ptr - nodeList.RemoveElementAt(0); - contentPtr = (nsIContent*)(nodeList.ElementAt(0)); + PRInt32 position; + result = GetChildOffset(styleNode, parentNode, position); + if (NS_FAILED(result)) return result; + + nsCOMPtrpreviousSiblingNode; + nsCOMPtrchildNode; + result = styleNode->GetLastChild(getter_AddRefs(childNode)); + if (NS_FAILED(result)) return result; + while (childNode) + { + childNode->GetPreviousSibling(getter_AddRefs(previousSiblingNode)); + // explicitly delete of childNode from styleNode + // can't just rely on DOM semantics of InsertNode doing the delete implicitly, doesn't undo! + result = nsEditor::DeleteNode(childNode); + if (NS_FAILED(result)) return result; + result = nsEditor::InsertNode(childNode, parentNode, position); + if (gNoisy) + { + printf("deleted next sibling node %p\n", childNode.get()); + DebugDumpContent(); // DEBUG + } + childNode = do_QueryInterface(previousSiblingNode); + } // end while loop + // delete styleNode + result = nsEditor::DeleteNode(styleNode); + if (NS_FAILED(result)) return result; + if (gNoisy) + { + printf("deleted style node %p\n", styleNode.get()); + DebugDumpContent(); // DEBUG } + + // get next content ptr + nodeList.RemoveElementAt(0); + contentPtr = (nsIContent*)(nodeList.ElementAt(0)); } nsCOMPtrselection; result = nsEditor::GetSelection(getter_AddRefs(selection)); - if (NS_SUCCEEDED(result)) - { - selection->Collapse(startNode, rangeStartOffset); - selection->Extend(endNode, rangeEndOffset); - if (gNoisy) { printf("RTPFNWDP set selection.\n"); } - } + if (NS_FAILED(result)) return result; + if (!selection) return NS_ERROR_NULL_POINTER; + selection->Collapse(startNode, rangeStartOffset); + selection->Extend(endNode, rangeEndOffset); + if (gNoisy) { printf("RTPFNWDP set selection.\n"); } } if (gNoisy) { @@ -2912,11 +2886,11 @@ NS_IMETHODIMP nsTextEditor::SetBackgroundColor(const nsString& aColor) // Set the background color attribute on the body tag nsCOMPtr bodyElement; res = nsEditor::GetBodyElement(getter_AddRefs(bodyElement)); - if (NS_SUCCEEDED(res) && bodyElement) - { - nsAutoEditBatch beginBatching(this); - bodyElement->SetAttribute("bgcolor", aColor); - } + if (NS_FAILED(res)) return res; + if (!bodyElement) return NS_ERROR_NULL_POINTER; + + nsAutoEditBatch beginBatching(this); + bodyElement->SetAttribute("bgcolor", aColor); return res; } diff --git a/editor/libeditor/base/ChangeAttributeTxn.cpp b/editor/libeditor/base/ChangeAttributeTxn.cpp index 54773f5fe693..ee7b5dd0ff94 100644 --- a/editor/libeditor/base/ChangeAttributeTxn.cpp +++ b/editor/libeditor/base/ChangeAttributeTxn.cpp @@ -35,23 +35,24 @@ NS_IMETHODIMP ChangeAttributeTxn::Init(nsIEditor *aEditor, const nsString& aValue, PRBool aRemoveAttribute) { - if (nsnull!=aEditor && nsnull!=aElement) - { - mEditor = aEditor; - mElement = do_QueryInterface(aElement); - mAttribute = aAttribute; - mValue = aValue; - mRemoveAttribute = aRemoveAttribute; - mAttributeWasSet=PR_FALSE; - mUndoValue=""; - return NS_OK; - } - else - return NS_ERROR_NULL_POINTER; + NS_ASSERTION(aEditor && aElement, "bad arg"); + if (!aEditor || !aElement) { return NS_ERROR_NULL_POINTER; } + + mEditor = aEditor; + mElement = do_QueryInterface(aElement); + mAttribute = aAttribute; + mValue = aValue; + mRemoveAttribute = aRemoveAttribute; + mAttributeWasSet=PR_FALSE; + mUndoValue=""; + return NS_OK; } NS_IMETHODIMP ChangeAttributeTxn::Do(void) { + NS_ASSERTION(mEditor && mElement, "bad state"); + if (!mEditor || !mElement) { return NS_ERROR_NOT_INITIALIZED; } + // need to get the current value of the attribute and save it, and set mAttributeWasSet nsresult result = mEditor->GetAttributeValue(mElement, mAttribute, mUndoValue, mAttributeWasSet); // XXX: hack until attribute-was-set code is implemented @@ -70,6 +71,9 @@ NS_IMETHODIMP ChangeAttributeTxn::Do(void) NS_IMETHODIMP ChangeAttributeTxn::Undo(void) { + NS_ASSERTION(mEditor && mElement, "bad state"); + if (!mEditor || !mElement) { return NS_ERROR_NOT_INITIALIZED; } + nsresult result=NS_OK; if (PR_TRUE==mAttributeWasSet) result = mElement->SetAttribute(mAttribute, mUndoValue); @@ -81,6 +85,9 @@ NS_IMETHODIMP ChangeAttributeTxn::Undo(void) NS_IMETHODIMP ChangeAttributeTxn::Redo(void) { + NS_ASSERTION(mEditor && mElement, "bad state"); + if (!mEditor || !mElement) { return NS_ERROR_NOT_INITIALIZED; } + nsresult result; if (PR_FALSE==mRemoveAttribute) diff --git a/editor/libeditor/base/CreateElementTxn.cpp b/editor/libeditor/base/CreateElementTxn.cpp index 930a59ec7599..d86043e4d284 100644 --- a/editor/libeditor/base/CreateElementTxn.cpp +++ b/editor/libeditor/base/CreateElementTxn.cpp @@ -41,24 +41,21 @@ NS_IMETHODIMP CreateElementTxn::Init(nsIEditor *aEditor, PRUint32 aOffsetInParent) { NS_ASSERTION(aEditor&&aParent, "null args"); - if (aEditor && aParent) - { - mEditor = aEditor; - mTag = aTag; - mParent = do_QueryInterface(aParent); - mOffsetInParent = aOffsetInParent; + if (!aEditor || !aParent) { return NS_ERROR_NULL_POINTER; } + + mEditor = aEditor; + mTag = aTag; + mParent = do_QueryInterface(aParent); + mOffsetInParent = aOffsetInParent; #ifdef NS_DEBUG - { - nsCOMPtr testChildNodes; - nsresult testResult = mParent->GetChildNodes(getter_AddRefs(testChildNodes)); - NS_ASSERTION(testChildNodes, "bad parent type, can't have children."); - NS_ASSERTION(NS_SUCCEEDED(testResult), "bad result."); - } -#endif - return NS_OK; + { + nsCOMPtr testChildNodes; + nsresult testResult = mParent->GetChildNodes(getter_AddRefs(testChildNodes)); + NS_ASSERTION(testChildNodes, "bad parent type, can't have children."); + NS_ASSERTION(NS_SUCCEEDED(testResult), "bad result."); } - else - return NS_ERROR_NULL_POINTER; +#endif + return NS_OK; } @@ -70,69 +67,69 @@ NS_IMETHODIMP CreateElementTxn::Do(void) { if (gNoisy) { printf("Do Create Element parent = %p, offset = %d\n", mParent.get(), mOffsetInParent); } - NS_ASSERTION(mEditor, "bad state -- null editor"); - nsresult result = NS_ERROR_NULL_POINTER; - if (mEditor) + NS_ASSERTION(mEditor && mParent, "bad state"); + if (!mEditor || !mParent) return NS_ERROR_NOT_INITIALIZED; + nsresult result; + // create a new node + nsCOMPtrdoc; + result = mEditor->GetDocument(getter_AddRefs(doc)); + if (NS_FAILED(result)) return result; + if (!doc) return NS_ERROR_NULL_POINTER; + + if (nsEditor::GetTextNodeTag() == mTag) { - // create a new node - nsCOMPtrdoc; - result = mEditor->GetDocument(getter_AddRefs(doc)); - if ((NS_SUCCEEDED(result)) && (doc)) + const nsString stringData; + nsCOMPtrnewTextNode; + result = doc->CreateTextNode(stringData, getter_AddRefs(newTextNode)); + if (NS_FAILED(result)) return result; + if (!newTextNode) return NS_ERROR_NULL_POINTER; + mNewNode = do_QueryInterface(newTextNode); + } + else + { + nsCOMPtrnewElement; + result = doc->CreateElement(mTag, getter_AddRefs(newElement)); + if (NS_FAILED(result)) return result; + if (!newElement) return NS_ERROR_NULL_POINTER; + mNewNode = do_QueryInterface(newElement); + } + NS_ASSERTION(((NS_SUCCEEDED(result)) && (mNewNode)), "could not create element."); + if (!mNewNode) return NS_ERROR_NULL_POINTER; + + if (gNoisy) { printf(" newNode = %p\n", mNewNode.get()); } + // insert the new node + nsCOMPtr resultNode; + if (CreateElementTxn::eAppend==(PRInt32)mOffsetInParent) + { + result = mParent->AppendChild(mNewNode, getter_AddRefs(resultNode)); + } + else + { + nsCOMPtr childNodes; + result = mParent->GetChildNodes(getter_AddRefs(childNodes)); + if ((NS_SUCCEEDED(result)) && (childNodes)) { - if (nsEditor::GetTextNodeTag() == mTag) + PRUint32 count; + childNodes->GetLength(&count); + if (mOffsetInParent>count) + mOffsetInParent = count; + result = childNodes->Item(mOffsetInParent, getter_AddRefs(mRefNode)); + if (NS_SUCCEEDED(result)) // note, it's ok for mRefNode to be null. that means append { - const nsString stringData; - nsCOMPtrnewTextNode; - result = doc->CreateTextNode(stringData, getter_AddRefs(newTextNode)); - if (NS_SUCCEEDED(result) && newTextNode) { - mNewNode = do_QueryInterface(newTextNode); - } - } - else - { - nsCOMPtrnewElement; - result = doc->CreateElement(mTag, getter_AddRefs(newElement)); - if (NS_SUCCEEDED(result) && newElement) { - mNewNode = do_QueryInterface(newElement); - } - } - NS_ASSERTION(((NS_SUCCEEDED(result)) && (mNewNode)), "could not create element."); - if ((NS_SUCCEEDED(result)) && (mNewNode)) - { - if (gNoisy) { printf(" newNode = %p\n", mNewNode.get()); } - // insert the new node - nsCOMPtr resultNode; - if (CreateElementTxn::eAppend==(PRInt32)mOffsetInParent) + result = mParent->InsertBefore(mNewNode, mRefNode, getter_AddRefs(resultNode)); + if (NS_SUCCEEDED(result)) { - result = mParent->AppendChild(mNewNode, getter_AddRefs(resultNode)); - } - else - { - nsCOMPtr childNodes; - result = mParent->GetChildNodes(getter_AddRefs(childNodes)); - if ((NS_SUCCEEDED(result)) && (childNodes)) - { - PRUint32 count; - childNodes->GetLength(&count); - if (mOffsetInParent>count) - mOffsetInParent = count; - result = childNodes->Item(mOffsetInParent, getter_AddRefs(mRefNode)); - if (NS_SUCCEEDED(result)) // note, it's ok for mRefNode to be null. that means append - { - result = mParent->InsertBefore(mNewNode, mRefNode, getter_AddRefs(resultNode)); - if (NS_SUCCEEDED(result)) - { - nsCOMPtr selection; - nsresult selectionResult = mEditor->GetSelection(getter_AddRefs(selection)); - if (NS_SUCCEEDED(selectionResult) && selection) { - PRInt32 offset=0; - nsEditor::GetChildOffset(mNewNode, mParent, offset); - selectionResult = selection->Collapse(mParent, offset+1); - NS_ASSERTION((NS_SUCCEEDED(selectionResult)), "selection could not be collapsed after insert."); - } - } - } - } + nsCOMPtr selection; + result = mEditor->GetSelection(getter_AddRefs(selection)); + if (NS_FAILED(result)) return result; + if (!selection) return NS_ERROR_NULL_POINTER; + + PRInt32 offset=0; + result = nsEditor::GetChildOffset(mNewNode, mParent, offset); + if (NS_FAILED(result)) return result; + + result = selection->Collapse(mParent, offset+1); + NS_ASSERTION((NS_SUCCEEDED(result)), "selection could not be collapsed after insert."); } } } @@ -144,20 +141,24 @@ NS_IMETHODIMP CreateElementTxn::Undo(void) { if (gNoisy) { printf("Undo Create Element, mParent = %p, node = %p\n", mParent.get(), mNewNode.get()); } + NS_ASSERTION(mEditor && mParent, "bad state"); + if (!mEditor || !mParent) return NS_ERROR_NOT_INITIALIZED; + nsCOMPtr resultNode; nsresult result = mParent->RemoveChild(mNewNode, getter_AddRefs(resultNode)); if (NS_SUCCEEDED(result)) { nsCOMPtr selection; - nsresult selectionResult = mEditor->GetSelection(getter_AddRefs(selection)); - if (NS_SUCCEEDED(selectionResult) && selection) { - PRInt32 offset=0; - if (mRefNode) { - nsEditor::GetChildOffset(mRefNode, mParent, offset); - } - selectionResult = selection->Collapse(mParent, offset); - NS_ASSERTION((NS_SUCCEEDED(selectionResult)), "selection could not be collapsed after undo of insert."); + result = mEditor->GetSelection(getter_AddRefs(selection)); + if (NS_FAILED(result)) return result; + if (!selection) return NS_ERROR_NULL_POINTER; + + PRInt32 offset=0; + if (mRefNode) { + nsEditor::GetChildOffset(mRefNode, mParent, offset); } + result = selection->Collapse(mParent, offset); + NS_ASSERTION((NS_SUCCEEDED(result)), "selection could not be collapsed after undo of insert."); } return result; } @@ -165,6 +166,8 @@ NS_IMETHODIMP CreateElementTxn::Undo(void) NS_IMETHODIMP CreateElementTxn::Redo(void) { if (gNoisy) { printf("Redo Create Element\n"); } + NS_ASSERTION(mEditor && mParent, "bad state"); + if (!mEditor || !mParent) return NS_ERROR_NOT_INITIALIZED; // first, reset mNewNode so it has no attributes or content nsCOMPtrnodeAsText; @@ -182,12 +185,12 @@ NS_IMETHODIMP CreateElementTxn::Redo(void) { nsCOMPtr selection; result = mEditor->GetSelection(getter_AddRefs(selection)); - if (NS_SUCCEEDED(result) && selection) { - PRInt32 offset=0; - nsEditor::GetChildOffset(mNewNode, mParent, offset); - nsresult selectionResult = selection->Collapse(mParent, offset); - NS_ASSERTION((NS_SUCCEEDED(selectionResult)), "selection could not be collapsed after undo of insert."); - } + if (NS_FAILED(result)) return result; + if (!selection) return NS_ERROR_NULL_POINTER; + PRInt32 offset=0; + nsEditor::GetChildOffset(mNewNode, mParent, offset); + result = selection->Collapse(mParent, offset); + NS_ASSERTION((NS_SUCCEEDED(result)), "selection could not be collapsed after undo of insert."); } return result; } diff --git a/editor/libeditor/base/DeleteElementTxn.cpp b/editor/libeditor/base/DeleteElementTxn.cpp index 771c0f26849a..bfe55418fb85 100644 --- a/editor/libeditor/base/DeleteElementTxn.cpp +++ b/editor/libeditor/base/DeleteElementTxn.cpp @@ -51,16 +51,11 @@ DeleteElementTxn::~DeleteElementTxn() NS_IMETHODIMP DeleteElementTxn::Do(void) { if (gNoisy) { printf("%p Do Delete Element element = %p\n", this, mElement.get()); } - if (!mElement) - return NS_ERROR_NULL_POINTER; + if (!mElement) return NS_ERROR_NOT_INITIALIZED; nsresult result = mElement->GetParentNode(getter_AddRefs(mParent)); - if (NS_FAILED(result)) { - return result; - } - if (!mParent) { - return NS_OK; // this is a no-op, there's no parent to delete mElement from - } + if (NS_FAILED(result)) { return result; } + if (!mParent) { return NS_OK; } // this is a no-op, there's no parent to delete mElement from #ifdef NS_DEBUG // begin debug output diff --git a/editor/libeditor/base/DeleteRangeTxn.cpp b/editor/libeditor/base/DeleteRangeTxn.cpp index 816264ab4ea6..8cc9dbf21d45 100644 --- a/editor/libeditor/base/DeleteRangeTxn.cpp +++ b/editor/libeditor/base/DeleteRangeTxn.cpp @@ -46,21 +46,22 @@ DeleteRangeTxn::DeleteRangeTxn() NS_IMETHODIMP DeleteRangeTxn::Init(nsIEditor *aEditor, nsIDOMRange *aRange) { - if (aEditor && aRange) - { - mEditor = aEditor; - mRange = do_QueryInterface(aRange); - - nsresult result = aRange->GetStartParent(getter_AddRefs(mStartParent)); - NS_ASSERTION((NS_SUCCEEDED(result)), "GetStartParent failed."); - result = aRange->GetEndParent(getter_AddRefs(mEndParent)); - NS_ASSERTION((NS_SUCCEEDED(result)), "GetEndParent failed."); - result = aRange->GetStartOffset(&mStartOffset); - NS_ASSERTION((NS_SUCCEEDED(result)), "GetStartOffset failed."); - result = aRange->GetEndOffset(&mEndOffset); - NS_ASSERTION((NS_SUCCEEDED(result)), "GetEndOffset failed."); - result = aRange->GetCommonParent(getter_AddRefs(mCommonParent)); - NS_ASSERTION((NS_SUCCEEDED(result)), "GetCommonParent failed."); + NS_ASSERTION(aEditor && aRange, "bad state"); + if (!aEditor || !aRange) { return NS_ERROR_NOT_INITIALIZED; } + + mEditor = aEditor; + mRange = do_QueryInterface(aRange); + + nsresult result = aRange->GetStartParent(getter_AddRefs(mStartParent)); + NS_ASSERTION((NS_SUCCEEDED(result)), "GetStartParent failed."); + result = aRange->GetEndParent(getter_AddRefs(mEndParent)); + NS_ASSERTION((NS_SUCCEEDED(result)), "GetEndParent failed."); + result = aRange->GetStartOffset(&mStartOffset); + NS_ASSERTION((NS_SUCCEEDED(result)), "GetStartOffset failed."); + result = aRange->GetEndOffset(&mEndOffset); + NS_ASSERTION((NS_SUCCEEDED(result)), "GetEndOffset failed."); + result = aRange->GetCommonParent(getter_AddRefs(mCommonParent)); + NS_ASSERTION((NS_SUCCEEDED(result)), "GetCommonParent failed."); #ifdef NS_DEBUG { @@ -96,10 +97,8 @@ NS_IMETHODIMP DeleteRangeTxn::Init(nsIEditor *aEditor, nsIDOMRange *aRange) } } #endif - return result; - } - else - return NS_ERROR_NULL_POINTER; + return result; + } DeleteRangeTxn::~DeleteRangeTxn() @@ -109,11 +108,10 @@ DeleteRangeTxn::~DeleteRangeTxn() NS_IMETHODIMP DeleteRangeTxn::Do(void) { if (gNoisy) { printf("Do Delete Range\n"); } - if (!mStartParent || !mEndParent || !mCommonParent) - return NS_ERROR_NULL_POINTER; + if (!mStartParent || !mEndParent || !mCommonParent || !mEditor) + return NS_ERROR_NOT_INITIALIZED; nsresult result; - // build the child transactions if (mStartParent==mEndParent) @@ -145,9 +143,9 @@ NS_IMETHODIMP DeleteRangeTxn::Do(void) // set the resulting selection nsCOMPtr selection; result = mEditor->GetSelection(getter_AddRefs(selection)); - if (NS_SUCCEEDED(result)) { - result = selection->Collapse(mStartParent, mStartOffset); - } + if (NS_FAILED(result)) return result; + if (!selection) return NS_ERROR_NULL_POINTER; + result = selection->Collapse(mStartParent, mStartOffset); } return result; @@ -156,19 +154,21 @@ NS_IMETHODIMP DeleteRangeTxn::Do(void) NS_IMETHODIMP DeleteRangeTxn::Undo(void) { if (gNoisy) { printf("Undo Delete Range\n"); } - if (!mStartParent || !mEndParent || !mCommonParent) - return NS_ERROR_NULL_POINTER; + if (!mStartParent || !mEndParent || !mCommonParent || !mEditor) + return NS_ERROR_NOT_INITIALIZED; nsresult result = EditAggregateTxn::Undo(); - if (NS_SUCCEEDED(result)) { + if (NS_SUCCEEDED(result)) + { // set the resulting selection nsCOMPtr selection; result = mEditor->GetSelection(getter_AddRefs(selection)); - if (NS_SUCCEEDED(result)) { - selection->Collapse(mStartParent, mStartOffset); - selection->Extend(mEndParent, mEndOffset); - } + if (NS_FAILED(result)) return result; + if (!selection) return NS_ERROR_NULL_POINTER; + result = selection->Collapse(mStartParent, mStartOffset); + if (NS_FAILED(result)) return result; + result = selection->Extend(mEndParent, mEndOffset); } return result; @@ -177,8 +177,8 @@ NS_IMETHODIMP DeleteRangeTxn::Undo(void) NS_IMETHODIMP DeleteRangeTxn::Redo(void) { if (gNoisy) { printf("Redo Delete Range\n"); } - if (!mStartParent || !mEndParent || !mCommonParent) - return NS_ERROR_NULL_POINTER; + if (!mStartParent || !mEndParent || !mCommonParent || !mEditor) + return NS_ERROR_NOT_INITIALIZED; nsresult result = EditAggregateTxn::Redo(); @@ -186,9 +186,9 @@ NS_IMETHODIMP DeleteRangeTxn::Redo(void) // set the resulting selection nsCOMPtr selection; result = mEditor->GetSelection(getter_AddRefs(selection)); - if (NS_SUCCEEDED(result)) { - result = selection->Collapse(mStartParent, mStartOffset); - } + if (NS_FAILED(result)) return result; + if (!selection) return NS_ERROR_NULL_POINTER; + result = selection->Collapse(mStartParent, mStartOffset); } return result; @@ -224,9 +224,10 @@ NS_IMETHODIMP DeleteRangeTxn::GetRedoString(nsString *aString) return NS_OK; } -NS_IMETHODIMP DeleteRangeTxn::CreateTxnsToDeleteBetween(nsIDOMNode *aStartParent, - PRUint32 aStartOffset, - PRUint32 aEndOffset) +NS_IMETHODIMP +DeleteRangeTxn::CreateTxnsToDeleteBetween(nsIDOMNode *aStartParent, + PRUint32 aStartOffset, + PRUint32 aEndOffset) { nsresult result; // see what kind of node we have @@ -236,44 +237,42 @@ NS_IMETHODIMP DeleteRangeTxn::CreateTxnsToDeleteBetween(nsIDOMNode *aStartParent { // if the node is a text node, then delete text content DeleteTextTxn *txn; result = TransactionFactory::GetNewTransaction(DeleteTextTxn::GetCID(), (EditTxn **)&txn); - if (nsnull!=txn) - { - PRInt32 numToDel; - if (aStartOffset==aEndOffset) - numToDel = 1; - else - numToDel = aEndOffset-aStartOffset; - txn->Init(mEditor, textNode, aStartOffset, numToDel); - AppendChild(txn); - } + if (NS_FAILED(result)) return result; + if (!txn) return NS_ERROR_NULL_POINTER; + + PRInt32 numToDel; + if (aStartOffset==aEndOffset) + numToDel = 1; + else + numToDel = aEndOffset-aStartOffset; + txn->Init(mEditor, textNode, aStartOffset, numToDel); + AppendChild(txn); } else { PRUint32 childCount; nsCOMPtr children; result = aStartParent->GetChildNodes(getter_AddRefs(children)); - if ((NS_SUCCEEDED(result)) && children) + if (NS_FAILED(result)) return result; + if (!children) return NS_ERROR_NULL_POINTER; + + children->GetLength(&childCount); + NS_ASSERTION(aEndOffset<=childCount, "bad aEndOffset"); + PRUint32 i; + for (i=aStartOffset; iGetLength(&childCount); - NS_ASSERTION(aEndOffset<=childCount, "bad aEndOffset"); - PRUint32 i; - for (i=aStartOffset; i child; - result = children->Item(i, getter_AddRefs(child)); - if ((NS_SUCCEEDED(result)) && child) - { - DeleteElementTxn *txn; - result = TransactionFactory::GetNewTransaction(DeleteElementTxn::GetCID(), (EditTxn **)&txn); - if (nsnull!=txn) - { - txn->Init(child); - AppendChild(txn); - } - else - return NS_ERROR_NULL_POINTER; - } - } + nsCOMPtr child; + result = children->Item(i, getter_AddRefs(child)); + if (NS_FAILED(result)) return result; + if (!child) return NS_ERROR_NULL_POINTER; + + DeleteElementTxn *txn; + result = TransactionFactory::GetNewTransaction(DeleteElementTxn::GetCID(), (EditTxn **)&txn); + if (NS_FAILED(result)) return result; + if (!txn) return NS_ERROR_NULL_POINTER; + + txn->Init(child); + AppendChild(txn); } } return result; @@ -306,13 +305,11 @@ NS_IMETHODIMP DeleteRangeTxn::CreateTxnsToDeleteContent(nsIDOMNode *aParent, { DeleteTextTxn *txn; result = TransactionFactory::GetNewTransaction(DeleteTextTxn::GetCID(), (EditTxn **)&txn); - if (nsnull!=txn) - { - txn->Init(mEditor, textNode, start, numToDelete); - AppendChild(txn); - } - else - return NS_ERROR_NULL_POINTER; + if (NS_FAILED(result)) return result; + if (!txn) return NS_ERROR_NULL_POINTER; + + txn->Init(mEditor, textNode, start, numToDelete); + AppendChild(txn); } } @@ -332,11 +329,11 @@ NS_IMETHODIMP DeleteRangeTxn::CreateTxnsToDeleteNodesBetween() nsnull, nsIContentIterator::GetIID(), getter_AddRefs(iter)); - if (!NS_SUCCEEDED(result)) - return result; + if (NS_FAILED(result)) return result; + if (!iter) return NS_ERROR_NULL_POINTER; + result = iter->Init(mRange); - if (!NS_SUCCEEDED(result)) - return result; + if (NS_FAILED(result)) return result; while (NS_COMFALSE == iter->IsDone()) { @@ -344,18 +341,16 @@ NS_IMETHODIMP DeleteRangeTxn::CreateTxnsToDeleteNodesBetween() nsCOMPtr content; result = iter->CurrentNode(getter_AddRefs(content)); node = do_QueryInterface(content); - if ((NS_SUCCEEDED(result)) && node) - { - DeleteElementTxn *txn; - result = TransactionFactory::GetNewTransaction(DeleteElementTxn::GetCID(), (EditTxn **)&txn); - if (nsnull!=txn) - { - txn->Init(node); - AppendChild(txn); - } - else - return NS_ERROR_NULL_POINTER; - } + if (NS_FAILED(result)) return result; + if (!node) return NS_ERROR_NULL_POINTER; + + DeleteElementTxn *txn; + result = TransactionFactory::GetNewTransaction(DeleteElementTxn::GetCID(), (EditTxn **)&txn); + if (NS_FAILED(result)) return result; + if (!txn) return NS_ERROR_NULL_POINTER; + + txn->Init(node); + AppendChild(txn); iter->Next(); } return result; diff --git a/editor/libeditor/base/DeleteTextTxn.cpp b/editor/libeditor/base/DeleteTextTxn.cpp index cf7139391813..811242077bfc 100644 --- a/editor/libeditor/base/DeleteTextTxn.cpp +++ b/editor/libeditor/base/DeleteTextTxn.cpp @@ -41,6 +41,8 @@ NS_IMETHODIMP DeleteTextTxn::Init(nsIEditor *aEditor, PRUint32 aNumCharsToDelete) { NS_ASSERTION(aEditor&&aElement, "bad arg"); + if (!aEditor || !aElement) { return NS_ERROR_NULL_POINTER; } + mEditor = aEditor; mElement = do_QueryInterface(aElement); mOffset = aOffset; @@ -57,22 +59,20 @@ NS_IMETHODIMP DeleteTextTxn::Init(nsIEditor *aEditor, NS_IMETHODIMP DeleteTextTxn::Do(void) { if (gNoisy) { printf("Do Delete Text\n"); } - nsresult result = NS_ERROR_NULL_POINTER; - if (mEditor && mElement) + NS_ASSERTION(mEditor && mElement, "bad state"); + if (!mEditor || !mElement) { return NS_ERROR_NOT_INITIALIZED; } + // get the text that we're about to delete + nsresult result = mElement->SubstringData(mOffset, mNumCharsToDelete, mDeletedText); + NS_ASSERTION(NS_SUCCEEDED(result), "could not get text to delete."); + result = mElement->DeleteData(mOffset, mNumCharsToDelete); + if (NS_SUCCEEDED(result)) { - // get the text that we're about to delete - result = mElement->SubstringData(mOffset, mNumCharsToDelete, mDeletedText); - NS_ASSERTION(NS_SUCCEEDED(result), "could not get text to delete."); - result = mElement->DeleteData(mOffset, mNumCharsToDelete); - if (NS_SUCCEEDED(result)) - { - nsCOMPtr selection; - nsresult selectionResult = mEditor->GetSelection(getter_AddRefs(selection)); - if (NS_SUCCEEDED(selectionResult) && selection) { - selectionResult = selection->Collapse(mElement, mOffset); - NS_ASSERTION((NS_SUCCEEDED(selectionResult)), "selection could not be collapsed after undo of insert."); - } - } + nsCOMPtr selection; + result = mEditor->GetSelection(getter_AddRefs(selection)); + if (NS_FAILED(result)) return result; + if (!selection) return NS_ERROR_NULL_POINTER; + result = selection->Collapse(mElement, mOffset); + NS_ASSERTION((NS_SUCCEEDED(result)), "selection could not be collapsed after undo of insert."); } return result; } @@ -82,19 +82,19 @@ NS_IMETHODIMP DeleteTextTxn::Do(void) NS_IMETHODIMP DeleteTextTxn::Undo(void) { if (gNoisy) { printf("Undo Delete Text\n"); } - nsresult result = NS_ERROR_NULL_POINTER; - if (mEditor && mElement) + NS_ASSERTION(mEditor && mElement, "bad state"); + if (!mEditor || !mElement) { return NS_ERROR_NOT_INITIALIZED; } + + nsresult result; + result = mElement->InsertData(mOffset, mDeletedText); + if (NS_SUCCEEDED(result)) { - result = mElement->InsertData(mOffset, mDeletedText); - if (NS_SUCCEEDED(result)) - { - nsCOMPtr selection; - nsresult selectionResult = mEditor->GetSelection(getter_AddRefs(selection)); - if (NS_SUCCEEDED(selectionResult) && selection) { - selectionResult = selection->Collapse(mElement, mOffset); - NS_ASSERTION((NS_SUCCEEDED(selectionResult)), "selection could not be collapsed after undo of insert."); - } - } + nsCOMPtr selection; + nsresult selectionResult = mEditor->GetSelection(getter_AddRefs(selection)); + if (NS_FAILED(result)) return result; + if (!selection) return NS_ERROR_NULL_POINTER; + result = selection->Collapse(mElement, mOffset); + NS_ASSERTION((NS_SUCCEEDED(result)), "selection could not be collapsed after undo of insert."); } return result; } diff --git a/editor/libeditor/base/InsertElementTxn.cpp b/editor/libeditor/base/InsertElementTxn.cpp index 213d298a2962..d107dfc95b22 100644 --- a/editor/libeditor/base/InsertElementTxn.cpp +++ b/editor/libeditor/base/InsertElementTxn.cpp @@ -64,8 +64,7 @@ NS_IMETHODIMP InsertElementTxn::Do(void) printf("%p Do Insert Element of %p into parent %p at offset %d\n", this, nodeAsContent.get(), parentAsContent.get(), mOffset); } - if (!mNode || !mParent) - return NS_ERROR_NULL_POINTER; + if (!mNode || !mParent) return NS_ERROR_NOT_INITIALIZED; nsresult result; nsCOMPtrrefNode; @@ -92,16 +91,16 @@ NS_IMETHODIMP InsertElementTxn::Do(void) nsCOMPtr resultNode; result = mParent->InsertBefore(mNode, refNode, getter_AddRefs(resultNode)); - if (NS_SUCCEEDED(result) && resultNode) - { - nsCOMPtr selection; - result = mEditor->GetSelection(getter_AddRefs(selection)); - if ((NS_SUCCEEDED(result)) && selection) - { // place the selection just after the inserted element - selection->Collapse(mParent, mOffset+1); - //selection->Extend(mParent, mOffset+1); - } - } + if (NS_FAILED(result)) return result; + if (!resultNode) return NS_ERROR_NULL_POINTER; + + nsCOMPtr selection; + result = mEditor->GetSelection(getter_AddRefs(selection)); + if (NS_FAILED(result)) return result; + if (!selection) return NS_ERROR_NULL_POINTER; + // place the selection just after the inserted element + selection->Collapse(mParent, mOffset+1); + //selection->Extend(mParent, mOffset+1); return result; } @@ -109,8 +108,7 @@ NS_IMETHODIMP InsertElementTxn::Undo(void) { if (gNoisy) { printf("%p Undo Insert Element of %p into parent %p at offset %d\n", this, mNode.get(), mParent.get(), mOffset); } - if (!mNode || !mParent) - return NS_ERROR_NULL_POINTER; + if (!mNode || !mParent) return NS_ERROR_NOT_INITIALIZED; nsCOMPtr resultNode; nsresult result = mParent->RemoveChild(mNode, getter_AddRefs(resultNode)); diff --git a/editor/libeditor/base/InsertTextTxn.cpp b/editor/libeditor/base/InsertTextTxn.cpp index 9f7a45912472..5f3a9442a314 100644 --- a/editor/libeditor/base/InsertTextTxn.cpp +++ b/editor/libeditor/base/InsertTextTxn.cpp @@ -62,6 +62,9 @@ NS_IMETHODIMP InsertTextTxn::Init(nsIDOMCharacterData *aElement, printf("\n"); #endif + NS_ASSERTION(aElement&&aPresShell, "bad args"); + if (!aElement || !aPresShell) return NS_ERROR_NULL_POINTER; + mElement = do_QueryInterface(aElement); mOffset = aOffset; mStringToInsert = aStringToInsert; @@ -72,16 +75,19 @@ NS_IMETHODIMP InsertTextTxn::Init(nsIDOMCharacterData *aElement, NS_IMETHODIMP InsertTextTxn::Do(void) { if (gNoisy) { printf("Do Insert Text element = %p\n", mElement.get()); } + NS_ASSERTION(mElement && mPresShell, "bad state"); + if (!mElement || !mPresShell) { return NS_ERROR_NOT_INITIALIZED; } + // advance caret: This requires the presentation shell to get the selection. nsCOMPtr selection; nsresult result = mPresShell->GetSelection(SELECTION_NORMAL, getter_AddRefs(selection)); - NS_ASSERTION(selection,"Could not get selection in InsertTextTxn::Do\n"); - if (NS_SUCCEEDED(result) && selection) { - result = mElement->InsertData(mOffset, mStringToInsert); - if (NS_SUCCEEDED(result)) { - result = selection->Collapse(mElement, mOffset+mStringToInsert.Length()); - NS_ASSERTION((NS_SUCCEEDED(result)), "selection could not be collapsed after insert."); - } + if (NS_FAILED(result)) return result; + if (!selection) return NS_ERROR_NULL_POINTER; + result = mElement->InsertData(mOffset, mStringToInsert); + if (NS_SUCCEEDED(result)) + { + result = selection->Collapse(mElement, mOffset+mStringToInsert.Length()); + NS_ASSERTION((NS_SUCCEEDED(result)), "selection could not be collapsed after insert."); } return result; } @@ -89,6 +95,9 @@ NS_IMETHODIMP InsertTextTxn::Do(void) NS_IMETHODIMP InsertTextTxn::Undo(void) { if (gNoisy) { printf("Undo Insert Text element = %p\n", mElement.get()); } + NS_ASSERTION(mElement && mPresShell, "bad state"); + if (!mElement || !mPresShell) { return NS_ERROR_NOT_INITIALIZED; } + nsresult result; PRUint32 length = mStringToInsert.Length(); result = mElement->DeleteData(mOffset, length); @@ -96,10 +105,10 @@ NS_IMETHODIMP InsertTextTxn::Undo(void) { // set the selection to the insertion point where the string was removed nsCOMPtr selection; result = mPresShell->GetSelection(SELECTION_NORMAL, getter_AddRefs(selection)); - if (NS_SUCCEEDED(result) && selection) { - result = selection->Collapse(mElement, mOffset); - NS_ASSERTION((NS_SUCCEEDED(result)), "selection could not be collapsed after undo of insert."); - } + if (NS_FAILED(result)) return result; + if (!selection) return NS_ERROR_NULL_POINTER; + result = selection->Collapse(mElement, mOffset); + NS_ASSERTION((NS_SUCCEEDED(result)), "selection could not be collapsed after undo of insert."); } return result; } diff --git a/editor/libeditor/base/JoinElementTxn.cpp b/editor/libeditor/base/JoinElementTxn.cpp index c6d3902fbda3..62869cfa5b41 100644 --- a/editor/libeditor/base/JoinElementTxn.cpp +++ b/editor/libeditor/base/JoinElementTxn.cpp @@ -37,6 +37,8 @@ NS_IMETHODIMP JoinElementTxn::Init(nsIEditor *aEditor, nsIDOMNode *aLeftNode, nsIDOMNode *aRightNode) { + NS_PRECONDITION((aEditor && aLeftNode && aRightNode), "null arg"); + if (!aEditor || !aLeftNode || !aRightNode) { return NS_ERROR_NULL_POINTER; } mEditor = aEditor; mLeftNode = do_QueryInterface(aLeftNode); mRightNode = do_QueryInterface(aRightNode); @@ -52,54 +54,54 @@ JoinElementTxn::~JoinElementTxn() NS_IMETHODIMP JoinElementTxn::Do(void) { if (gNoisy) { printf("%p Do Join of %p and %p\n", this, mLeftNode.get(), mRightNode.get()); } - nsresult result; + NS_PRECONDITION((mEditor && mLeftNode && mRightNode), "null arg"); + if (!mEditor || !mLeftNode || !mRightNode) { return NS_ERROR_NOT_INITIALIZED; } - if ((mLeftNode) && (mRightNode)) - { // get the parent node - nsCOMPtrleftParent; - result = mLeftNode->GetParentNode(getter_AddRefs(leftParent)); - if ((NS_SUCCEEDED(result)) && (leftParent)) - { // verify that mLeftNode and mRightNode have the same parent - nsCOMPtrrightParent; - result = mRightNode->GetParentNode(getter_AddRefs(rightParent)); - if ((NS_SUCCEEDED(result)) && (rightParent)) - { - if (leftParent==rightParent) - { - mParent= do_QueryInterface(leftParent); // set this instance mParent. - // Other methods will see a non-null mParent and know all is well - nsCOMPtr childNodes; - result = mLeftNode->GetChildNodes(getter_AddRefs(childNodes)); - if ((NS_SUCCEEDED(result)) && (childNodes)) { - childNodes->GetLength(&mOffset); - } - else - { - nsCOMPtr leftNodeAsText; - leftNodeAsText = do_QueryInterface(mLeftNode); - if (leftNodeAsText) { - leftNodeAsText->GetLength(&mOffset); - } - } - result = nsEditor::JoinNodesImpl(mRightNode, mLeftNode, mParent, PR_FALSE); - if (NS_SUCCEEDED(result)) - { - if (gNoisy) { printf(" left node = %p removed\n", mLeftNode.get()); } - nsCOMPtrselection; - mEditor->GetSelection(getter_AddRefs(selection)); - if (selection) - { - selection->Collapse(mRightNode, mOffset); - } - } - } - else - { - NS_ASSERTION(PR_FALSE, "2 nodes do not have same parent"); - return NS_ERROR_INVALID_ARG; - } + // get the parent node + nsCOMPtrleftParent; + nsresult result = mLeftNode->GetParentNode(getter_AddRefs(leftParent)); + if (NS_FAILED(result)) return result; + if (!leftParent) return NS_ERROR_NULL_POINTER; + + // verify that mLeftNode and mRightNode have the same parent + nsCOMPtrrightParent; + result = mRightNode->GetParentNode(getter_AddRefs(rightParent)); + if (NS_FAILED(result)) return result; + if (!rightParent) return NS_ERROR_NULL_POINTER; + + if (leftParent==rightParent) + { + mParent= do_QueryInterface(leftParent); // set this instance mParent. + // Other methods will see a non-null mParent and know all is well + nsCOMPtr childNodes; + result = mLeftNode->GetChildNodes(getter_AddRefs(childNodes)); + if (NS_FAILED(result)) return result; + if (childNodes) { + childNodes->GetLength(&mOffset); + } + else + { + nsCOMPtr leftNodeAsText; + leftNodeAsText = do_QueryInterface(mLeftNode); + if (leftNodeAsText) { + leftNodeAsText->GetLength(&mOffset); } } + result = nsEditor::JoinNodesImpl(mRightNode, mLeftNode, mParent, PR_FALSE); + if (NS_SUCCEEDED(result)) + { + if (gNoisy) { printf(" left node = %p removed\n", mLeftNode.get()); } + nsCOMPtrselection; + result = mEditor->GetSelection(getter_AddRefs(selection)); + if (NS_FAILED(result)) return result; + if (!selection) return NS_ERROR_NULL_POINTER; + selection->Collapse(mRightNode, mOffset); + } + } + else + { + NS_ASSERTION(PR_FALSE, "2 nodes do not have same parent"); + return NS_ERROR_INVALID_ARG; } return result; } @@ -110,9 +112,7 @@ NS_IMETHODIMP JoinElementTxn::Undo(void) { if (gNoisy) { printf("%p Undo Join, right node = %p\n", this, mRightNode.get()); } NS_ASSERTION(mRightNode && mLeftNode && mParent, "bad state"); - if (!mRightNode || !mLeftNode || !mParent) { - return NS_ERROR_NOT_INITIALIZED; - } + if (!mRightNode || !mLeftNode || !mParent) { return NS_ERROR_NOT_INITIALIZED; } nsresult result; nsCOMPtrresultNode; // first, massage the existing node so it is in its post-split state diff --git a/editor/libeditor/base/SplitElementTxn.cpp b/editor/libeditor/base/SplitElementTxn.cpp index 179c1231f233..8ee8bec46284 100644 --- a/editor/libeditor/base/SplitElementTxn.cpp +++ b/editor/libeditor/base/SplitElementTxn.cpp @@ -39,6 +39,9 @@ NS_IMETHODIMP SplitElementTxn::Init(nsIEditor *aEditor, nsIDOMNode *aNode, PRInt32 aOffset) { + NS_ASSERTION(aEditor && aNode, "bad args"); + if (!aEditor || !aNode) { return NS_ERROR_NOT_INITIALIZED; } + mEditor = aEditor; mExistingRightNode = do_QueryInterface(aNode); mOffset = aOffset; @@ -52,36 +55,33 @@ SplitElementTxn::~SplitElementTxn() NS_IMETHODIMP SplitElementTxn::Do(void) { if (gNoisy) { printf("%p Do Split of node %p offset %d\n", this, mExistingRightNode.get(), mOffset); } - NS_ASSERTION(mExistingRightNode, "bad state"); - if (!mExistingRightNode) { - return NS_ERROR_NOT_INITIALIZED; - } + NS_ASSERTION(mExistingRightNode && mEditor, "bad state"); + if (!mExistingRightNode || !mEditor) { return NS_ERROR_NOT_INITIALIZED; } + // create a new node nsresult result = mExistingRightNode->CloneNode(PR_FALSE, getter_AddRefs(mNewLeftNode)); NS_ASSERTION(((NS_SUCCEEDED(result)) && (mNewLeftNode)), "could not create element."); + if (NS_FAILED(result)) return result; + if (!mNewLeftNode) return NS_ERROR_NULL_POINTER; - if ((NS_SUCCEEDED(result)) && (mNewLeftNode)) + if (gNoisy) { printf(" created left node = %p\n", mNewLeftNode.get()); } + // get the parent node + result = mExistingRightNode->GetParentNode(getter_AddRefs(mParent)); + if (NS_FAILED(result)) return result; + if (!mParent) return NS_ERROR_NULL_POINTER; + + // insert the new node + result = nsEditor::SplitNodeImpl(mExistingRightNode, mOffset, mNewLeftNode, mParent); + if (NS_SUCCEEDED(result) && mNewLeftNode) { - if (gNoisy) { printf(" created left node = %p\n", mNewLeftNode.get()); } - // get the parent node - result = mExistingRightNode->GetParentNode(getter_AddRefs(mParent)); - // insert the new node - if ((NS_SUCCEEDED(result)) && (mParent)) - { - result = nsEditor::SplitNodeImpl(mExistingRightNode, mOffset, mNewLeftNode, mParent); - if (NS_SUCCEEDED(result) && mNewLeftNode) - { - nsCOMPtrselection; - mEditor->GetSelection(getter_AddRefs(selection)); - if (selection) - { - selection->Collapse(mNewLeftNode, mOffset); - } - } - else { - result = NS_ERROR_NOT_IMPLEMENTED; - } - } + nsCOMPtrselection; + mEditor->GetSelection(getter_AddRefs(selection)); + if (NS_FAILED(result)) return result; + if (!selection) return NS_ERROR_NULL_POINTER; + result = selection->Collapse(mNewLeftNode, mOffset); + } + else { + result = NS_ERROR_NOT_IMPLEMENTED; } return result; } @@ -92,8 +92,8 @@ NS_IMETHODIMP SplitElementTxn::Undo(void) printf("%p Undo Split of existing node %p and new node %p offset %d\n", this, mExistingRightNode.get(), mNewLeftNode.get(), mOffset); } - NS_ASSERTION(mExistingRightNode && mNewLeftNode && mParent, "bad state"); - if (!mExistingRightNode || !mNewLeftNode || !mParent) { + NS_ASSERTION(mEditor && mExistingRightNode && mNewLeftNode && mParent, "bad state"); + if (!mEditor || !mExistingRightNode || !mNewLeftNode || !mParent) { return NS_ERROR_NOT_INITIALIZED; } @@ -110,10 +110,9 @@ NS_IMETHODIMP SplitElementTxn::Undo(void) if (gNoisy) { printf(" left node = %p removed\n", mNewLeftNode.get()); } nsCOMPtrselection; mEditor->GetSelection(getter_AddRefs(selection)); - if (selection) - { - selection->Collapse(mExistingRightNode, mOffset); - } + if (NS_FAILED(result)) return result; + if (!selection) return NS_ERROR_NULL_POINTER; + result = selection->Collapse(mExistingRightNode, mOffset); } else { result = NS_ERROR_NOT_IMPLEMENTED; @@ -126,8 +125,8 @@ NS_IMETHODIMP SplitElementTxn::Undo(void) */ NS_IMETHODIMP SplitElementTxn::Redo(void) { - NS_ASSERTION(mExistingRightNode && mNewLeftNode && mParent, "bad state"); - if (!mExistingRightNode || !mNewLeftNode || !mParent) { + NS_ASSERTION(mEditor && mExistingRightNode && mNewLeftNode && mParent, "bad state"); + if (!mEditor || !mExistingRightNode || !mNewLeftNode || !mParent) { return NS_ERROR_NOT_INITIALIZED; } if (gNoisy) { @@ -146,7 +145,7 @@ NS_IMETHODIMP SplitElementTxn::Redo(void) if (gNoisy) { printf("** after delete of text in right text node %p offset %d\n", rightNodeAsText.get(), mOffset); - if (gNoisy) {mEditor->DebugDumpContent(); } // DEBUG + mEditor->DebugDumpContent(); // DEBUG } } else diff --git a/editor/libeditor/base/nsEditor.cpp b/editor/libeditor/base/nsEditor.cpp index 01adf94ad49d..e69eca6ff05b 100644 --- a/editor/libeditor/base/nsEditor.cpp +++ b/editor/libeditor/base/nsEditor.cpp @@ -239,6 +239,7 @@ nsEditor::Init(nsIDOMDocument *aDoc, nsIPresShell* aPresShell, PRUint32 aFlags) // disable links nsCOMPtr context; mPresShell->GetPresContext(getter_AddRefs(context)); + if (!context) return NS_ERROR_NULL_POINTER; context->SetLinkHandler(0); // Set up the DTD @@ -252,9 +253,9 @@ nsEditor::Init(nsIDOMDocument *aDoc, nsIPresShell* aPresShell, PRUint32 aFlags) if (!mEditProperty) {return NS_ERROR_NULL_POINTER;} mPresShell->GetViewManager(&mViewManager); - if (mViewManager){ - mViewManager->Release(); //we want a weak link - } + if (!mViewManager) {return NS_ERROR_NULL_POINTER;} + mViewManager->Release(); //we want a weak link + mPresShell->SetDisplayNonTextSelection(PR_TRUE);//we want to see all the selection reflected to user mUpdateCount=0; InsertTextTxn::ClassInit(); @@ -267,22 +268,25 @@ nsEditor::Init(nsIDOMDocument *aDoc, nsIPresShell* aPresShell, PRUint32 aFlags) mIMEBufferLength = 0; /* Show the caret */ + // XXX: I suppose it's legal to fail to get a caret, so don't propogate the + // result of GetCaret nsCOMPtr caret; if (NS_SUCCEEDED(mPresShell->GetCaret(getter_AddRefs(caret))) && caret) { caret->SetCaretVisible(PR_TRUE); caret->SetCaretReadOnly(PR_FALSE); } + // NOTE: We don't fail if we can't get prefs or string bundles // since we could still be used as the text edit widget without prefs // Get the prefs service (Note: can't use nsCOMPtr for service pointers) - result = nsServiceManager::GetService(kPrefCID, - nsIPref::GetIID(), - (nsISupports**)&mPrefs); - if (NS_FAILED(result) || !mPrefs) + nsresult ignoredResult = nsServiceManager::GetService(kPrefCID, + nsIPref::GetIID(), + (nsISupports**)&mPrefs); + if (NS_FAILED(ignoredResult) || !mPrefs) { - printf("ERROR: Failed to get Prefs Service instance.\n"); + if (gNoisy) { printf("ERROR: Failed to get Prefs Service instance.\n");} } // TODO: Cache basic preferences? @@ -290,20 +294,21 @@ nsEditor::Init(nsIDOMDocument *aDoc, nsIPresShell* aPresShell, PRUint32 aFlags) // respond to while running nsIStringBundleService* service; - result = nsServiceManager::GetService(kStringBundleServiceCID, - nsIStringBundleService::GetIID(), - (nsISupports**)&service); + ignoredResult = nsServiceManager::GetService(kStringBundleServiceCID, + nsIStringBundleService::GetIID(), + (nsISupports**)&service); - if (NS_SUCCEEDED(result) && service) + if (NS_SUCCEEDED(ignoredResult) && service) { nsILocale* locale = nsnull; - result = service->CreateBundle(EDITOR_BUNDLE_URL, locale, - getter_AddRefs(mStringBundle)); + ignoredResult = service->CreateBundle(EDITOR_BUNDLE_URL, locale, + getter_AddRefs(mStringBundle)); // We don't need to keep service around once we created the bundle nsServiceManager::ReleaseService(kStringBundleServiceCID, service); } else { - printf("ERROR: Failed to get StringBundle Service instance.\n"); + if (gNoisy) printf("ERROR: Failed to get StringBundle Service instance.\n"); } + /* Example of getting a string: nsString value; @@ -374,8 +379,8 @@ NS_IMETHODIMP nsEditor::SaveDocument(PRBool saveAs, PRBool saveCopy) // get the document nsCOMPtr doc; rv = GetDocument(getter_AddRefs(doc)); - if (NS_FAILED(rv) || !doc) - return rv; + if (NS_FAILED(rv)) return rv; + if (!doc) return NS_ERROR_NULL_POINTER; nsCOMPtr diskDoc = do_QueryInterface(doc); if (!diskDoc) @@ -1238,7 +1243,6 @@ nsEditor::SetCompositionString(const nsString& aCompositionString, nsIPrivateTex return result; } - #ifdef XP_MAC #pragma mark - #pragma mark --- public nsEditor methods --- diff --git a/editor/libeditor/base/nsEditor.h b/editor/libeditor/base/nsEditor.h index 82420966c538..03e2b2b92b2b 100644 --- a/editor/libeditor/base/nsEditor.h +++ b/editor/libeditor/base/nsEditor.h @@ -387,7 +387,7 @@ public: * @param aNodeToKeep The node that will remain after the join. * @param aNodeToJoin The node that will be joined with aNodeToKeep. * There is no requirement that the two nodes be of the same type. - * @param aParent The parent of aExistingRightNode + * @param aParent The parent of aNodeToKeep * @param aNodeToKeepIsFirst if PR_TRUE, the contents|children of aNodeToKeep come before the * contents|children of aNodeToJoin, otherwise their positions are switched. */ diff --git a/editor/libeditor/html/nsHTMLEditor.cpp b/editor/libeditor/html/nsHTMLEditor.cpp index a1ca754660f1..c003726c549e 100644 --- a/editor/libeditor/html/nsHTMLEditor.cpp +++ b/editor/libeditor/html/nsHTMLEditor.cpp @@ -102,7 +102,7 @@ static NS_DEFINE_CID(kCClipboardCID, NS_CLIPBOARD_CID); static NS_DEFINE_CID(kCTransferableCID, NS_TRANSFERABLE_CID); #ifdef NS_DEBUG -static PRBool gNoisy = PR_FALSE; +static PRBool gNoisy = PR_TRUE; #else static const PRBool gNoisy = PR_FALSE; #endif @@ -164,7 +164,8 @@ nsHTMLEditor::~nsHTMLEditor() //the autopointers will clear themselves up. //but we need to also remove the listeners or we have a leak nsCOMPtrselection; - nsresult result = nsEditor::GetSelection(getter_AddRefs(selection)); + nsresult result = GetSelection(getter_AddRefs(selection)); + // if we don't get the selection, just skip this if (NS_SUCCEEDED(result) && selection) { nsCOMPtrlistener; @@ -255,7 +256,7 @@ NS_IMETHODIMP nsHTMLEditor::Init(nsIDOMDocument *aDoc, nsresult result = NS_ERROR_NULL_POINTER; // Init the base editor result = nsEditor::Init(aDoc, aPresShell, aFlags); - if (NS_OK != result) { return result; } + if (NS_FAILED(result)) { return result; } // init the type-in state mTypeInState = new TypeInState(); @@ -263,8 +264,8 @@ NS_IMETHODIMP nsHTMLEditor::Init(nsIDOMDocument *aDoc, NS_ADDREF(mTypeInState); nsCOMPtrselection; - result = nsEditor::GetSelection(getter_AddRefs(selection)); - if (NS_OK != result) { return result; } + result = GetSelection(getter_AddRefs(selection)); + if (NS_FAILED(result)) { return result; } if (selection) { nsCOMPtrlistener; @@ -279,22 +280,21 @@ NS_IMETHODIMP nsHTMLEditor::Init(nsIDOMDocument *aDoc, // get a key listener result = NS_NewEditorKeyListener(getter_AddRefs(mKeyListenerP), this); - if (NS_OK != result) { + if (NS_FAILED(result)) { HandleEventListenerError(); return result; } // get a mouse listener result = NS_NewEditorMouseListener(getter_AddRefs(mMouseListenerP), this); - if (NS_OK != result) { + if (NS_FAILED(result)) { HandleEventListenerError(); return result; } // get a text listener result = NS_NewEditorTextListener(getter_AddRefs(mTextListenerP),this); - if (NS_OK !=result) - { + if (NS_FAILED(result)) { #ifdef DEBUG_TAGUE printf("nsTextEditor.cpp: failed to get TextEvent Listener\n"); #endif @@ -304,8 +304,7 @@ printf("nsTextEditor.cpp: failed to get TextEvent Listener\n"); // get a composition listener result = NS_NewEditorCompositionListener(getter_AddRefs(mCompositionListenerP),this); - if (NS_OK!=result) - { + if (NS_FAILED(result)) { #ifdef DEBUG_TAGUE printf("nsTextEditor.cpp: failed to get TextEvent Listener\n"); #endif @@ -315,16 +314,14 @@ printf("nsTextEditor.cpp: failed to get TextEvent Listener\n"); // get a drag listener result = NS_NewEditorDragListener(getter_AddRefs(mDragListenerP), this); - if (NS_OK != result) - { + if (NS_FAILED(result)) { HandleEventListenerError(); - //return result; // XXX: why is this return commented out? + return result; } // get a focus listener result = NS_NewEditorFocusListener(getter_AddRefs(mFocusListenerP), this); - if (NS_OK != result) - { + if (NS_FAILED(result)) { HandleEventListenerError(); return result; } @@ -332,8 +329,7 @@ printf("nsTextEditor.cpp: failed to get TextEvent Listener\n"); // get the DOM event receiver nsCOMPtr erP; result = aDoc->QueryInterface(nsIDOMEventReceiver::GetIID(), getter_AddRefs(erP)); - if (!NS_SUCCEEDED(result)) - { + if (NS_FAILED(result)) { HandleEventListenerError(); return result; } @@ -341,16 +337,35 @@ printf("nsTextEditor.cpp: failed to get TextEvent Listener\n"); // register the event listeners with the DOM event reveiver result = erP->AddEventListenerByIID(mKeyListenerP, nsIDOMKeyListener::GetIID()); NS_ASSERTION(NS_SUCCEEDED(result), "failed to register key listener"); - result = erP->AddEventListenerByIID(mMouseListenerP, nsIDOMMouseListener::GetIID()); - NS_ASSERTION(NS_SUCCEEDED(result), "failed to register mouse listener"); - result = erP->AddEventListenerByIID(mFocusListenerP, nsIDOMFocusListener::GetIID()); - NS_ASSERTION(NS_SUCCEEDED(result), "failed to register focus listener"); - result = erP->AddEventListenerByIID(mTextListenerP, nsIDOMTextListener::GetIID()); - NS_ASSERTION(NS_SUCCEEDED(result), "failed to register text listener"); - result = erP->AddEventListenerByIID(mCompositionListenerP, nsIDOMCompositionListener::GetIID()); - NS_ASSERTION(NS_SUCCEEDED(result), "failed to register composition listener"); - result = erP->AddEventListenerByIID(mDragListenerP, nsIDOMDragListener::GetIID()); - NS_ASSERTION(NS_SUCCEEDED(result), "failed to register drag listener"); + if (NS_SUCCEEDED(result)) + { + result = erP->AddEventListenerByIID(mMouseListenerP, nsIDOMMouseListener::GetIID()); + NS_ASSERTION(NS_SUCCEEDED(result), "failed to register mouse listener"); + if (NS_SUCCEEDED(result)) + { + result = erP->AddEventListenerByIID(mFocusListenerP, nsIDOMFocusListener::GetIID()); + NS_ASSERTION(NS_SUCCEEDED(result), "failed to register focus listener"); + if (NS_SUCCEEDED(result)) + { + result = erP->AddEventListenerByIID(mTextListenerP, nsIDOMTextListener::GetIID()); + NS_ASSERTION(NS_SUCCEEDED(result), "failed to register text listener"); + if (NS_SUCCEEDED(result)) + { + result = erP->AddEventListenerByIID(mCompositionListenerP, nsIDOMCompositionListener::GetIID()); + NS_ASSERTION(NS_SUCCEEDED(result), "failed to register composition listener"); + if (NS_SUCCEEDED(result)) + { + result = erP->AddEventListenerByIID(mDragListenerP, nsIDOMDragListener::GetIID()); + NS_ASSERTION(NS_SUCCEEDED(result), "failed to register drag listener"); + } + } + } + } + } + if (NS_FAILED(result)) { + HandleEventListenerError(); + return result; + } result = NS_OK; EnableUndo(PR_TRUE); @@ -418,109 +433,110 @@ NS_IMETHODIMP nsHTMLEditor::SetInlineProperty(nsIAtom *aProperty, nsresult result=NS_ERROR_NOT_INITIALIZED; nsCOMPtrselection; - result = nsEditor::GetSelection(getter_AddRefs(selection)); - if ((NS_SUCCEEDED(result)) && selection) + result = GetSelection(getter_AddRefs(selection)); + if (NS_FAILED(result)) return result; + if (!selection) return NS_ERROR_NULL_POINTER; + PRBool cancel; + nsTextRulesInfo ruleInfo(nsTextEditRules::kSetTextProperty); + result = mRules->WillDoAction(selection, &ruleInfo, &cancel); + if ((PR_FALSE==cancel) && (NS_SUCCEEDED(result))) { - PRBool cancel; - nsTextRulesInfo ruleInfo(nsTextEditRules::kSetTextProperty); - result = mRules->WillDoAction(selection, &ruleInfo, &cancel); - if ((PR_FALSE==cancel) && (NS_SUCCEEDED(result))) + PRBool isCollapsed; + selection->GetIsCollapsed(&isCollapsed); + if (PR_TRUE==isCollapsed) { - PRBool isCollapsed; - selection->GetIsCollapsed(&isCollapsed); - if (PR_TRUE==isCollapsed) - { - // manipulating text attributes on a collapsed selection only sets state for the next text insertion - SetTypeInStateForProperty(*mTypeInState, aProperty, aAttribute, aValue); + // manipulating text attributes on a collapsed selection only sets state for the next text insertion + SetTypeInStateForProperty(*mTypeInState, aProperty, aAttribute, aValue); + } + else + { + // set the text property for all selected ranges + nsEditor::BeginTransaction(); + nsCOMPtr enumerator; + result = selection->GetEnumerator(getter_AddRefs(enumerator)); + if (NS_FAILED(result)) return result; + if (!enumerator) return NS_ERROR_NULL_POINTER; + + enumerator->First(); + nsCOMPtr currentItem; + result = enumerator->CurrentItem(getter_AddRefs(currentItem)); + if (NS_FAILED(result)) return result; + if (!currentItem) return NS_ERROR_NULL_POINTER; + + nsCOMPtr range( do_QueryInterface(currentItem) ); + nsCOMPtrcommonParent; + result = range->GetCommonParent(getter_AddRefs(commonParent)); + if (NS_FAILED(result)) return result; + if (!commonParent) return NS_ERROR_NULL_POINTER; + + PRInt32 startOffset, endOffset; + range->GetStartOffset(&startOffset); + range->GetEndOffset(&endOffset); + nsCOMPtr startParent; nsCOMPtr endParent; + range->GetStartParent(getter_AddRefs(startParent)); + range->GetEndParent(getter_AddRefs(endParent)); + PRBool startIsText = IsTextNode(startParent); + PRBool endIsText = IsTextNode(endParent); + if ((PR_TRUE==startIsText) && (PR_TRUE==endIsText) && + (startParent.get()==endParent.get())) + { // the range is entirely contained within a single text node + // commonParent==aStartParent, so get the "real" parent of the selection + startParent->GetParentNode(getter_AddRefs(commonParent)); + result = SetTextPropertiesForNode(startParent, commonParent, + startOffset, endOffset, + aProperty, aAttribute, aValue); } else { - // set the text property for all selected ranges - nsEditor::BeginTransaction(); - nsCOMPtr enumerator; - result = selection->GetEnumerator(getter_AddRefs(enumerator)); - if (NS_SUCCEEDED(result) && enumerator) + nsCOMPtr startGrandParent; + result = startParent->GetParentNode(getter_AddRefs(startGrandParent)); + if (NS_FAILED(result)) return result; + if (!startGrandParent) return NS_ERROR_NULL_POINTER; + nsCOMPtr endGrandParent; + result = endParent->GetParentNode(getter_AddRefs(endGrandParent)); + if (NS_FAILED(result)) return result; + if (!endGrandParent) return NS_ERROR_NULL_POINTER; + + PRBool canCollapseStyleNode = PR_FALSE; + if ((PR_TRUE==startIsText) && (PR_TRUE==endIsText) && + endGrandParent.get()==startGrandParent.get()) { - enumerator->First(); - nsCOMPtr currentItem; - result = enumerator->CurrentItem(getter_AddRefs(currentItem)); - if ((NS_SUCCEEDED(result)) && (currentItem)) - { - nsCOMPtr range( do_QueryInterface(currentItem) ); - nsCOMPtrcommonParent; - result = range->GetCommonParent(getter_AddRefs(commonParent)); - if ((NS_SUCCEEDED(result)) && commonParent) - { - PRInt32 startOffset, endOffset; - range->GetStartOffset(&startOffset); - range->GetEndOffset(&endOffset); - nsCOMPtr startParent; nsCOMPtr endParent; - range->GetStartParent(getter_AddRefs(startParent)); - range->GetEndParent(getter_AddRefs(endParent)); - PRBool startIsText = IsTextNode(startParent); - PRBool endIsText = IsTextNode(endParent); - if ((PR_TRUE==startIsText) && (PR_TRUE==endIsText) && - (startParent.get()==endParent.get())) - { // the range is entirely contained within a single text node - // commonParent==aStartParent, so get the "real" parent of the selection - startParent->GetParentNode(getter_AddRefs(commonParent)); - result = SetTextPropertiesForNode(startParent, commonParent, - startOffset, endOffset, - aProperty, aAttribute, aValue); - } - else - { - nsCOMPtr startGrandParent; - startParent->GetParentNode(getter_AddRefs(startGrandParent)); - nsCOMPtr endGrandParent; - endParent->GetParentNode(getter_AddRefs(endGrandParent)); - if (NS_SUCCEEDED(result)) - { - PRBool canCollapseStyleNode = PR_FALSE; - if ((PR_TRUE==startIsText) && (PR_TRUE==endIsText) && - endGrandParent.get()==startGrandParent.get()) - { - result = IntermediateNodesAreInline(range, startParent, startOffset, - endParent, endOffset, - canCollapseStyleNode); - } - if (NS_SUCCEEDED(result)) - { - if (PR_TRUE==canCollapseStyleNode) - { // the range is between 2 nodes that have a common (immediate) grandparent, - // and any intermediate nodes are just inline style nodes - result = SetTextPropertiesForNodesWithSameParent(startParent,startOffset, - endParent, endOffset, - commonParent, - aProperty, aAttribute, aValue); - } - else - { // the range is between 2 nodes that have no simple relationship - result = SetTextPropertiesForNodeWithDifferentParents(range, - startParent,startOffset, - endParent, endOffset, - commonParent, - aProperty, aAttribute, aValue); - } - } - } - } - if (NS_SUCCEEDED(result)) - { // compute a range for the selection - // don't want to actually do anything with selection, because - // we are still iterating through it. Just want to create and remember - // an nsIDOMRange, and later add the range to the selection after clearing it. - // XXX: I'm blocked here because nsIDOMSelection doesn't provide a mechanism - // for setting a compound selection yet. - } - } + result = IntermediateNodesAreInline(range, startParent, startOffset, + endParent, endOffset, + canCollapseStyleNode); + } + if (NS_SUCCEEDED(result)) + { + if (PR_TRUE==canCollapseStyleNode) + { // the range is between 2 nodes that have a common (immediate) grandparent, + // and any intermediate nodes are just inline style nodes + result = SetTextPropertiesForNodesWithSameParent(startParent,startOffset, + endParent, endOffset, + commonParent, + aProperty, aAttribute, aValue); + } + else + { // the range is between 2 nodes that have no simple relationship + result = SetTextPropertiesForNodeWithDifferentParents(range, + startParent,startOffset, + endParent, endOffset, + commonParent, + aProperty, aAttribute, aValue); } } - nsEditor::EndTransaction(); } - // post-process - result = mRules->DidDoAction(selection, &ruleInfo, result); + if (NS_SUCCEEDED(result)) + { // compute a range for the selection + // don't want to actually do anything with selection, because + // we are still iterating through it. Just want to create and remember + // an nsIDOMRange, and later add the range to the selection after clearing it. + // XXX: I'm blocked here because nsIDOMSelection doesn't provide a mechanism + // for setting a compound selection yet. + } + nsEditor::EndTransaction(); } + // post-process + result = mRules->DidDoAction(selection, &ruleInfo, result); } if (gNoisy) {DebugDumpContent(); } // DEBUG if (gNoisy) @@ -535,9 +551,9 @@ NS_IMETHODIMP nsHTMLEditor::SetInlineProperty(nsIAtom *aProperty, } NS_IMETHODIMP nsHTMLEditor::GetInlineProperty(nsIAtom *aProperty, - const nsString *aAttribute, - const nsString *aValue, - PRBool &aFirst, PRBool &aAny, PRBool &aAll) + const nsString *aAttribute, + const nsString *aValue, + PRBool &aFirst, PRBool &aAny, PRBool &aAll) { if (!aProperty) return NS_ERROR_NULL_POINTER; @@ -551,100 +567,101 @@ NS_IMETHODIMP nsHTMLEditor::GetInlineProperty(nsIAtom *aProperty, delete [] propCString; } */ - nsresult result=NS_ERROR_NOT_INITIALIZED; + nsresult result; aAny=PR_FALSE; aAll=PR_TRUE; aFirst=PR_FALSE; PRBool first=PR_TRUE; nsCOMPtrselection; - result = nsEditor::GetSelection(getter_AddRefs(selection)); - if ((NS_SUCCEEDED(result)) && selection) + result = GetSelection(getter_AddRefs(selection)); + if (NS_FAILED(result)) return result; + if (!selection) return NS_ERROR_NULL_POINTER; + + PRBool isCollapsed; + selection->GetIsCollapsed(&isCollapsed); + nsCOMPtr enumerator; + result = selection->GetEnumerator(getter_AddRefs(enumerator)); + if (NS_FAILED(result)) return result; + if (!enumerator) return NS_ERROR_NULL_POINTER; + + enumerator->First(); + nsCOMPtr currentItem; + result = enumerator->CurrentItem(getter_AddRefs(currentItem)); + // XXX: should be a while loop, to get each separate range + // XXX: ERROR_HANDLING can currentItem be null? + if ((NS_SUCCEEDED(result)) && currentItem) { - PRBool isCollapsed; - selection->GetIsCollapsed(&isCollapsed); - nsCOMPtr enumerator; - result = selection->GetEnumerator(getter_AddRefs(enumerator)); - if (NS_SUCCEEDED(result) && enumerator) + PRBool firstNodeInRange = PR_TRUE; // for each range, set a flag + nsCOMPtr range( do_QueryInterface(currentItem) ); + nsCOMPtr iter; + result = nsComponentManager::CreateInstance(kCContentIteratorCID, nsnull, + nsIContentIterator::GetIID(), + getter_AddRefs(iter)); + if (NS_FAILED(result)) return result; + if (!iter) return NS_ERROR_NULL_POINTER; + + iter->Init(range); + nsCOMPtr content; + result = iter->CurrentNode(getter_AddRefs(content)); + while (NS_COMFALSE == iter->IsDone()) { - enumerator->First(); - nsCOMPtr currentItem; - result = enumerator->CurrentItem(getter_AddRefs(currentItem)); - // XXX: should be a while loop, to get each separate range - if ((NS_SUCCEEDED(result)) && currentItem) + //if (gNoisy) { printf(" checking node %p\n", content.get()); } + nsCOMPtrtext; + text = do_QueryInterface(content); + PRBool skipNode = PR_FALSE; + if (text) { - PRBool firstNodeInRange = PR_TRUE; // for each range, set a flag - nsCOMPtr range( do_QueryInterface(currentItem) ); - nsCOMPtr iter; - result = nsComponentManager::CreateInstance(kCContentIteratorCID, nsnull, - nsIContentIterator::GetIID(), - getter_AddRefs(iter)); - if ((NS_SUCCEEDED(result)) && iter) + if (PR_FALSE==isCollapsed && PR_TRUE==first && PR_TRUE==firstNodeInRange) { - iter->Init(range); - nsCOMPtr content; - result = iter->CurrentNode(getter_AddRefs(content)); - while (NS_COMFALSE == iter->IsDone()) + firstNodeInRange = PR_FALSE; + PRInt32 startOffset; + range->GetStartOffset(&startOffset); + PRUint32 count; + text->GetLength(&count); + if (startOffset==(PRInt32)count) { - //if (gNoisy) { printf(" checking node %p\n", content.get()); } - nsCOMPtrtext; - text = do_QueryInterface(content); - PRBool skipNode = PR_FALSE; - if (text) - { - if (PR_FALSE==isCollapsed && PR_TRUE==first && PR_TRUE==firstNodeInRange) - { - firstNodeInRange = PR_FALSE; - PRInt32 startOffset; - range->GetStartOffset(&startOffset); - PRUint32 count; - text->GetLength(&count); - if (startOffset==(PRInt32)count) - { - //if (gNoisy) { printf(" skipping node %p\n", content.get()); } - skipNode = PR_TRUE; - } - } - } - else - { // handle non-text leaf nodes here - PRBool canContainChildren; - content->CanContainChildren(canContainChildren); - if (PR_TRUE==canContainChildren) - { - //if (gNoisy) { printf(" skipping non-leaf node %p\n", content.get()); } - skipNode = PR_TRUE; - } - else { - //if (gNoisy) { printf(" testing non-text leaf node %p\n", content.get()); } - } - } - if (PR_FALSE==skipNode) - { - nsCOMPtrnode; - node = do_QueryInterface(content); - if (node) - { - PRBool isSet; - nsCOMPtrresultNode; - IsTextPropertySetByContent(node, aProperty, aAttribute, aValue, isSet, getter_AddRefs(resultNode)); - if (PR_TRUE==first) - { - aFirst = isSet; - first = PR_FALSE; - } - if (PR_TRUE==isSet) { - aAny = PR_TRUE; - } - else { - aAll = PR_FALSE; - } - } - } - iter->Next(); - iter->CurrentNode(getter_AddRefs(content)); + //if (gNoisy) { printf(" skipping node %p\n", content.get()); } + skipNode = PR_TRUE; } } } + else + { // handle non-text leaf nodes here + PRBool canContainChildren; + content->CanContainChildren(canContainChildren); + if (PR_TRUE==canContainChildren) + { + //if (gNoisy) { printf(" skipping non-leaf node %p\n", content.get()); } + skipNode = PR_TRUE; + } + else { + //if (gNoisy) { printf(" testing non-text leaf node %p\n", content.get()); } + } + } + if (PR_FALSE==skipNode) + { + nsCOMPtrnode; + node = do_QueryInterface(content); + if (node) + { + PRBool isSet; + nsCOMPtrresultNode; + IsTextPropertySetByContent(node, aProperty, aAttribute, aValue, isSet, getter_AddRefs(resultNode)); + if (PR_TRUE==first) + { + aFirst = isSet; + first = PR_FALSE; + } + if (PR_TRUE==isSet) { + aAny = PR_TRUE; + } + else { + aAll = PR_FALSE; + } + } + } + iter->Next(); + iter->CurrentNode(getter_AddRefs(content)); } } if (PR_FALSE==aAny) { // make sure that if none of the selection is set, we don't report all is set @@ -664,99 +681,113 @@ NS_IMETHODIMP nsHTMLEditor::RemoveInlineProperty(nsIAtom *aProperty, const nsStr nsAutoString propString; aProperty->ToString(propString); char *propCString = propString.ToNewCString(); - if (gNoisy) { printf("---------- start nsTextEditor::RemoveTextProperty %s ----------\n", propCString); } + if (gNoisy) { printf("---------- start nsTextEditor::RemoveInlineProperty %s ----------\n", propCString); } delete [] propCString; } - nsresult result=NS_ERROR_NOT_INITIALIZED; + nsresult result; nsCOMPtrselection; - result = nsEditor::GetSelection(getter_AddRefs(selection)); - if ((NS_SUCCEEDED(result)) && selection) + result = GetSelection(getter_AddRefs(selection)); + if (NS_FAILED(result)) return result; + if (!selection) return NS_ERROR_NULL_POINTER; + + PRBool cancel; + nsTextRulesInfo ruleInfo(nsTextEditRules::kRemoveTextProperty); + result = mRules->WillDoAction(selection, &ruleInfo, &cancel); + if (NS_FAILED(result)) return result; + if (PR_FALSE==cancel) { - PRBool cancel; - nsTextRulesInfo ruleInfo(nsTextEditRules::kRemoveTextProperty); - result = mRules->WillDoAction(selection, &ruleInfo, &cancel); - if ((PR_FALSE==cancel) && (NS_SUCCEEDED(result))) + PRBool isCollapsed; + selection->GetIsCollapsed(&isCollapsed); + if (PR_TRUE==isCollapsed) { - PRBool isCollapsed; - selection->GetIsCollapsed(&isCollapsed); - if (PR_TRUE==isCollapsed) - { - // manipulating text attributes on a collapsed selection only sets state for the next text insertion - SetTypeInStateForProperty(*mTypeInState, aProperty, aAttribute, nsnull); - } - else - { - // removing text properties can really shuffle text nodes around - // so we need to keep some extra state to restore a reasonable selection - // after we're done - nsCOMPtr parentForSelection; // selection's block parent - PRInt32 rangeStartOffset, rangeEndOffset; - GetTextSelectionOffsetsForRange(selection, getter_AddRefs(parentForSelection), - rangeStartOffset, rangeEndOffset); - nsEditor::BeginTransaction(); - nsCOMPtr startParent, endParent; - PRInt32 startOffset, endOffset; - nsCOMPtr enumerator; - result = selection->GetEnumerator(getter_AddRefs(enumerator)); - if (NS_SUCCEEDED(result) && enumerator) - { - enumerator->First(); - nsCOMPtrcurrentItem; - result = enumerator->CurrentItem(getter_AddRefs(currentItem)); - if ((NS_SUCCEEDED(result)) && (currentItem)) - { - nsCOMPtr range( do_QueryInterface(currentItem) ); - nsCOMPtrcommonParent; - result = range->GetCommonParent(getter_AddRefs(commonParent)); - if ((NS_SUCCEEDED(result)) && commonParent) - { - range->GetStartOffset(&startOffset); - range->GetEndOffset(&endOffset); - range->GetStartParent(getter_AddRefs(startParent)); - range->GetEndParent(getter_AddRefs(endParent)); - if (startParent.get()==endParent.get()) - { // the range is entirely contained within a single text node - // commonParent==aStartParent, so get the "real" parent of the selection - startParent->GetParentNode(getter_AddRefs(commonParent)); - result = RemoveTextPropertiesForNode(startParent, commonParent, - startOffset, endOffset, - aProperty, nsnull); - } - else - { - result = RemoveTextPropertiesForNodeWithDifferentParents(startParent,startOffset, - endParent, endOffset, - commonParent, - aProperty, nsnull); - } - if (NS_SUCCEEDED(result)) - { // compute a range for the selection - // don't want to actually do anything with selection, because - // we are still iterating through it. Just want to create and remember - // an nsIDOMRange, and later add the range to the selection after clearing it. - // XXX: I'm blocked here because nsIDOMSelection doesn't provide a mechanism - // for setting a compound selection yet. - } - } - } - } - nsEditor::EndTransaction(); - if (NS_SUCCEEDED(result)) - { - ResetTextSelectionForRange(parentForSelection, rangeStartOffset, rangeEndOffset, selection); - } - } - // post-process - result = mRules->DidDoAction(selection, &ruleInfo, result); + // manipulating text attributes on a collapsed selection only sets state for the next text insertion + SetTypeInStateForProperty(*mTypeInState, aProperty, aAttribute, nsnull); } + else + { + // removing text properties can really shuffle text nodes around + // so we need to keep some extra state to restore a reasonable selection + // after we're done + nsCOMPtr parentForSelection; // selection's block parent + PRInt32 rangeStartOffset, rangeEndOffset; + GetTextSelectionOffsetsForRange(selection, getter_AddRefs(parentForSelection), + rangeStartOffset, rangeEndOffset); + nsEditor::BeginTransaction(); + nsCOMPtr startParent, endParent; + PRInt32 startOffset, endOffset; + nsCOMPtr enumerator; + result = selection->GetEnumerator(getter_AddRefs(enumerator)); + if (NS_FAILED(result)) return result; + if (!enumerator) return NS_ERROR_NULL_POINTER; + + enumerator->First(); + nsCOMPtrcurrentItem; + result = enumerator->CurrentItem(getter_AddRefs(currentItem)); + if (NS_FAILED(result)) return result; + //XXX: should be a while loop to get all ranged in selection + if (currentItem) + { + nsCOMPtr range( do_QueryInterface(currentItem) ); + nsCOMPtrcommonParent; + result = range->GetCommonParent(getter_AddRefs(commonParent)); + if (NS_FAILED(result)) return result; + if (!commonParent) return NS_ERROR_NULL_POINTER; + + range->GetStartOffset(&startOffset); + range->GetEndOffset(&endOffset); + result = range->GetStartParent(getter_AddRefs(startParent)); + if (NS_FAILED(result)) return result; + if (!startParent) return NS_ERROR_NULL_POINTER; + result = range->GetEndParent(getter_AddRefs(endParent)); + if (NS_FAILED(result)) return result; + if (!endParent) return NS_ERROR_NULL_POINTER; + + if (startParent.get()==endParent.get()) + { // the range is entirely contained within a single text node + // commonParent==aStartParent, so get the "real" parent of the selection + startParent->GetParentNode(getter_AddRefs(commonParent)); + result = RemoveTextPropertiesForNode(startParent, commonParent, + startOffset, endOffset, + aProperty, nsnull); + } + else + { + result = RemoveTextPropertiesForNodeWithDifferentParents(startParent,startOffset, + endParent, endOffset, + commonParent, + aProperty, nsnull); + } + if (NS_FAILED(result)) return result; + + { // compute a range for the selection + // don't want to actually do anything with selection, because + // we are still iterating through it. Just want to create and remember + // an nsIDOMRange, and later add the range to the selection after clearing it. + // XXX: I'm blocked here because nsIDOMSelection doesn't provide a mechanism + // for setting a compound selection yet. + } + } + if (NS_SUCCEEDED(result)) + { + result = CollapseAdjacentTextNodes(selection); // we may have created wasteful consecutive text nodes. collapse them. + } + nsEditor::EndTransaction(); + if (NS_SUCCEEDED(result)) + { + // XXX: ERROR_HANDLING should get a result and validate it + ResetTextSelectionForRange(parentForSelection, rangeStartOffset, rangeEndOffset, selection); + } + } + // post-process + result = mRules->DidDoAction(selection, &ruleInfo, result); } if (gNoisy) { nsAutoString propString; aProperty->ToString(propString); char *propCString = propString.ToNewCString(); - if (gNoisy) { printf("---------- end nsTextEditor::RemoveTextProperty %s ----------\n", propCString); } + if (gNoisy) { printf("---------- end nsTextEditor::RemoveInlineProperty %s ----------\n", propCString); } delete [] propCString; } return result; @@ -773,7 +804,10 @@ NS_IMETHODIMP nsHTMLEditor::DeleteSelection(nsIEditor::ESelectionCollapseDirecti if (NS_FAILED(result)) { return result; } // pre-process - nsEditor::GetSelection(getter_AddRefs(selection)); + result = GetSelection(getter_AddRefs(selection)); + if (NS_FAILED(result)) return result; + if (!selection) return NS_ERROR_NULL_POINTER; + nsTextRulesInfo ruleInfo(nsTextEditRules::kDeleteSelection); ruleInfo.collapsedAction = aAction; result = mRules->WillDoAction(selection, &ruleInfo, &cancel); @@ -784,6 +818,7 @@ NS_IMETHODIMP nsHTMLEditor::DeleteSelection(nsIEditor::ESelectionCollapseDirecti result = mRules->DidDoAction(selection, &ruleInfo, result); } + // XXX: ERROR_HANDLING is there any reason to not consider this a serious error? nsresult endTxnResult = nsEditor::EndTransaction(); // don't return this result! NS_ASSERTION ((NS_SUCCEEDED(endTxnResult)), "bad end transaction result"); @@ -798,7 +833,9 @@ NS_IMETHODIMP nsHTMLEditor::InsertText(const nsString& aStringToInsert) PRBool cancel= PR_FALSE; // pre-process - nsEditor::GetSelection(getter_AddRefs(selection)); + nsresult result = GetSelection(getter_AddRefs(selection)); + if (NS_FAILED(result)) return result; + if (!selection) return NS_ERROR_NULL_POINTER; nsString resultString; PlaceholderTxn *placeholderTxn=nsnull; nsTextRulesInfo ruleInfo(nsTextEditRules::kInsertText); @@ -808,7 +845,7 @@ NS_IMETHODIMP nsHTMLEditor::InsertText(const nsString& aStringToInsert) ruleInfo.typeInState = *mTypeInState; ruleInfo.maxLength = mMaxTextLength; - nsresult result = mRules->WillDoAction(selection, &ruleInfo, &cancel); + result = mRules->WillDoAction(selection, &ruleInfo, &cancel); if ((PR_FALSE==cancel) && (NS_SUCCEEDED(result))) { result = InsertTextImpl(resultString); @@ -833,8 +870,8 @@ NS_IMETHODIMP nsHTMLEditor::InsertHTML(const nsString& aInputString) nsCOMPtrselection; res = GetSelection(getter_AddRefs(selection)); - if (NS_FAILED(res)) - return res; + if (NS_FAILED(res)) return res; + if (!selection) return NS_ERROR_NULL_POINTER; // Get the first range in the selection, for context: nsCOMPtr range; @@ -887,6 +924,7 @@ NS_IMETHODIMP nsHTMLEditor::InsertHTML(const nsString& aInputString) { nsCOMPtr parent; PRInt32 offset; + // XXX: ERROR_HANDLING error return codes are lost if (NS_SUCCEEDED(saverange->GetEndParent(getter_AddRefs(parent)))) if (NS_SUCCEEDED(saverange->GetEndOffset(&offset))) selection->Collapse(parent, offset); @@ -933,7 +971,10 @@ NS_IMETHODIMP nsHTMLEditor::InsertBreak() nsAutoEditBatch beginBatching(this); // pre-process - nsEditor::GetSelection(getter_AddRefs(selection)); + res = GetSelection(getter_AddRefs(selection)); + if (NS_FAILED(res)) return res; + if (!selection) return NS_ERROR_NULL_POINTER; + nsTextRulesInfo ruleInfo(nsHTMLEditRules::kInsertBreak); res = mRules->WillDoAction(selection, &ruleInfo, &cancel); if ((PR_FALSE==cancel) && (NS_SUCCEEDED(res))) @@ -942,12 +983,14 @@ NS_IMETHODIMP nsHTMLEditor::InsertBreak() nsCOMPtr newNode; nsAutoString tag("BR"); res = DeleteSelectionAndCreateNode(tag, getter_AddRefs(newNode)); - if (NS_SUCCEEDED(res) && newNode) + if (!newNode) res = NS_ERROR_NULL_POINTER; // don't return here, so DidDoAction is called + if (NS_SUCCEEDED(res)) { // set the selection to the new node nsCOMPtrparent; res = newNode->GetParentNode(getter_AddRefs(parent)); - if (NS_SUCCEEDED(res) && parent) + if (!parent) res = NS_ERROR_NULL_POINTER; // don't return here, so DidDoAction is called + if (NS_SUCCEEDED(res)) { PRInt32 offsetInParent=-1; // we use the -1 as a marker to see if we need to compute this or not nsCOMPtrnextNode; @@ -966,7 +1009,8 @@ NS_IMETHODIMP nsHTMLEditor::InsertBreak() else { nextNode = do_QueryInterface(newNode); } - res = nsEditor::GetSelection(getter_AddRefs(selection)); + res = GetSelection(getter_AddRefs(selection)); + if (!selection) res = NS_ERROR_NULL_POINTER; // don't return here, so DidDoAction is called if (NS_SUCCEEDED(res)) { if (-1==offsetInParent) @@ -974,12 +1018,12 @@ NS_IMETHODIMP nsHTMLEditor::InsertBreak() nextNode->GetParentNode(getter_AddRefs(parent)); res = GetChildOffset(nextNode, parent, offsetInParent); if (NS_SUCCEEDED(res)) { - selection->Collapse(parent, offsetInParent+1); // +1 to insert just after the break + res = selection->Collapse(parent, offsetInParent+1); // +1 to insert just after the break } } else { - selection->Collapse(nextNode, offsetInParent); + res = selection->Collapse(nextNode, offsetInParent); } } } @@ -1005,7 +1049,7 @@ nsHTMLEditor::InsertElement(nsIDOMElement* aElement, PRBool aDeleteSelection) //PRBool setCaretAfterElement = PR_TRUE; nsCOMPtrselection; - res = nsEditor::GetSelection(getter_AddRefs(selection)); + res = GetSelection(getter_AddRefs(selection)); if (!NS_SUCCEEDED(res) || !selection) return NS_ERROR_FAILURE; @@ -1039,9 +1083,11 @@ nsHTMLEditor::InsertElement(nsIDOMElement* aElement, PRBool aDeleteSelection) // TODO: Move this logic to a new method nsIDOMSelection::CollapseToStart()??? nsCOMPtr firstRange; res = selection->GetRangeAt(0, getter_AddRefs(firstRange)); + // XXX: ERROR_HANDLING can firstRange legally be null? if (NS_SUCCEEDED(res) && firstRange) { nsCOMPtr parent; + // XXX: ERROR_HANDLING bad XPCOM usage, should check for null parent separately res = firstRange->GetCommonParent(getter_AddRefs(parent)); if (NS_SUCCEEDED(res) && parent) { @@ -1059,6 +1105,7 @@ nsHTMLEditor::InsertElement(nsIDOMElement* aElement, PRBool aDeleteSelection) nsCOMPtr parentSelectedNode; PRInt32 offsetForInsert; res = selection->GetAnchorNode(getter_AddRefs(parentSelectedNode)); + // XXX: ERROR_HANDLING bad XPCOM usage if (NS_SUCCEEDED(res) && NS_SUCCEEDED(selection->GetAnchorOffset(&offsetForInsert)) && parentSelectedNode) { #ifdef DEBUG_cmanske @@ -1127,10 +1174,10 @@ nsHTMLEditor::InsertElement(nsIDOMElement* aElement, PRBool aDeleteSelection) return res; } - +// XXX: error handling in this routine needs to be cleaned up! NS_IMETHODIMP nsHTMLEditor::DeleteSelectionAndCreateNode(const nsString& aTag, - nsIDOMNode ** aNewNode) + nsIDOMNode ** aNewNode) { nsCOMPtr parentSelectedNode; PRInt32 offsetOfNewNode; @@ -1142,14 +1189,15 @@ nsHTMLEditor::DeleteSelectionAndCreateNode(const nsString& aTag, nsCOMPtr newNode; result = CreateNode(aTag, parentSelectedNode, offsetOfNewNode, getter_AddRefs(newNode)); - + // XXX: ERROR_HANDLING check result, and make sure aNewNode is set correctly in success/failure cases *aNewNode = newNode; // we want the selection to be just after the new node nsCOMPtr selection; result = GetSelection(getter_AddRefs(selection)); - if ((NS_SUCCEEDED(result)) && selection) - selection->Collapse(parentSelectedNode, offsetOfNewNode+1); + if (NS_FAILED(result)) return result; + if (!selection) return NS_ERROR_NULL_POINTER; + result = selection->Collapse(parentSelectedNode, offsetOfNewNode+1); return result; } @@ -1163,23 +1211,24 @@ nsHTMLEditor::SelectElement(nsIDOMElement* aElement) if (IsElementInBody(aElement)) { nsCOMPtr selection; - res = nsEditor::GetSelection(getter_AddRefs(selection)); - if (NS_SUCCEEDED(res) && selection) + res = GetSelection(getter_AddRefs(selection)); + if (NS_FAILED(res)) return res; + if (!selection) return NS_ERROR_NULL_POINTER; + nsCOMPtrparent; + res = aElement->GetParentNode(getter_AddRefs(parent)); + if (NS_SUCCEEDED(res) && parent) { - nsCOMPtrparent; - res = aElement->GetParentNode(getter_AddRefs(parent)); - if (NS_SUCCEEDED(res) && parent) - { - PRInt32 offsetInParent; - res = GetChildOffset(aElement, parent, offsetInParent); + PRInt32 offsetInParent; + res = GetChildOffset(aElement, parent, offsetInParent); - if (NS_SUCCEEDED(res)) - { - // Collapse selection to just before desired element, - selection->Collapse(parent, offsetInParent); - // then extend it to just after - selection->Extend(parent, offsetInParent+1); - } + if (NS_SUCCEEDED(res)) + { + // Collapse selection to just before desired element, + res = selection->Collapse(parent, offsetInParent); + if (NS_SUCCEEDED(res)) { + // then extend it to just after + res = selection->Extend(parent, offsetInParent+1); + } } } } @@ -1195,34 +1244,32 @@ nsHTMLEditor::SetCaretAfterElement(nsIDOMElement* aElement) if (aElement && IsElementInBody(aElement)) { nsCOMPtr selection; - res = nsEditor::GetSelection(getter_AddRefs(selection)); - if (NS_SUCCEEDED(res) && selection) + res = GetSelection(getter_AddRefs(selection)); + if (NS_FAILED(res)) return res; + if (!selection) return NS_ERROR_NULL_POINTER; + nsCOMPtrparent; + res = aElement->GetParentNode(getter_AddRefs(parent)); + if (NS_FAILED(res)) return res; + if (!parent) return NS_ERROR_NULL_POINTER; + PRInt32 offsetInParent; + res = GetChildOffset(aElement, parent, offsetInParent); + if (NS_SUCCEEDED(res)) { - nsCOMPtrparent; - res = aElement->GetParentNode(getter_AddRefs(parent)); - if (NS_SUCCEEDED(res) && parent) - { - PRInt32 offsetInParent; - res = GetChildOffset(aElement, parent, offsetInParent); - if (NS_SUCCEEDED(res)) - { - // Collapse selection to just after desired element, - selection->Collapse(parent, offsetInParent+1); + // Collapse selection to just after desired element, + res = selection->Collapse(parent, offsetInParent+1); #ifdef DEBUG_cmanske - { - nsAutoString name; - parent->GetNodeName(name); - printf("SetCaretAfterElement: Parent node: "); - wprintf(name.GetUnicode()); - printf(" Offset: %d\n\nHTML:\n", offsetInParent+1); - nsString Format("text/html"); - nsString ContentsAs; - OutputToString(ContentsAs, Format, 2); - wprintf(ContentsAs.GetUnicode()); - } -#endif - } + { + nsAutoString name; + parent->GetNodeName(name); + printf("SetCaretAfterElement: Parent node: "); + wprintf(name.GetUnicode()); + printf(" Offset: %d\n\nHTML:\n", offsetInParent+1); + nsString Format("text/html"); + nsString ContentsAs; + OutputToString(ContentsAs, Format, 2); + wprintf(ContentsAs.GetUnicode()); } +#endif } } return res; @@ -1259,6 +1306,8 @@ NS_IMETHODIMP nsHTMLEditor::SetParagraphFormat(const nsString& aParagraphFormat) // get the paragraph style(s) for the selection +// XXX: ERROR_HANDLING -- this method needs a little work to ensure all error codes are +// checked properly, all null pointers are checked, and no memory leaks occur NS_IMETHODIMP nsHTMLEditor::GetParagraphStyle(nsStringArray *aTagList) { @@ -1267,58 +1316,61 @@ nsHTMLEditor::GetParagraphStyle(nsStringArray *aTagList) nsresult res; nsCOMPtrselection; - res = nsEditor::GetSelection(getter_AddRefs(selection)); - if ((NS_SUCCEEDED(res)) && selection) + res = GetSelection(getter_AddRefs(selection)); + if (NS_FAILED(res)) return res; + if (!selection) return NS_ERROR_NULL_POINTER; + + nsCOMPtr enumerator; + res = selection->GetEnumerator(getter_AddRefs(enumerator)); + if (NS_FAILED(res)) return res; + if (!enumerator) return NS_ERROR_NULL_POINTER; + + enumerator->First(); + nsCOMPtr currentItem; + res = enumerator->CurrentItem(getter_AddRefs(currentItem)); + if (NS_FAILED(res)) return res; + //XXX: should be while loop? + if (currentItem) { - nsCOMPtr enumerator; - res = selection->GetEnumerator(getter_AddRefs(enumerator)); - if (NS_SUCCEEDED(res) && enumerator) + nsCOMPtr range( do_QueryInterface(currentItem) ); + // scan the range for all the independent block content blockSections + // and get the block parent of each + nsISupportsArray *blockSections; + res = NS_NewISupportsArray(&blockSections); + if (NS_FAILED(res)) return res; + if (!blockSections) return NS_ERROR_NULL_POINTER; + res = GetBlockSectionsForRange(range, blockSections); + if (NS_SUCCEEDED(res)) { - enumerator->First(); - nsCOMPtr currentItem; - res = enumerator->CurrentItem(getter_AddRefs(currentItem)); - if ((NS_SUCCEEDED(res)) && (currentItem)) + nsIDOMRange *subRange; + subRange = (nsIDOMRange *)(blockSections->ElementAt(0)); + while (subRange) { - nsCOMPtr range( do_QueryInterface(currentItem) ); - // scan the range for all the independent block content blockSections - // and get the block parent of each - nsISupportsArray *blockSections; - res = NS_NewISupportsArray(&blockSections); - if ((NS_SUCCEEDED(res)) && blockSections) + nsCOMPtrstartParent; + res = subRange->GetStartParent(getter_AddRefs(startParent)); + if (NS_SUCCEEDED(res) && startParent) { - res = GetBlockSectionsForRange(range, blockSections); - if (NS_SUCCEEDED(res)) + nsCOMPtr blockParent; + res = GetBlockParent(startParent, getter_AddRefs(blockParent)); + if (NS_SUCCEEDED(res) && blockParent) { - nsIDOMRange *subRange; - subRange = (nsIDOMRange *)(blockSections->ElementAt(0)); - while (subRange && (NS_SUCCEEDED(res))) - { - nsCOMPtrstartParent; - res = subRange->GetStartParent(getter_AddRefs(startParent)); - if (NS_SUCCEEDED(res) && startParent) - { - nsCOMPtr blockParent; - res = GetBlockParent(startParent, getter_AddRefs(blockParent)); - if (NS_SUCCEEDED(res) && blockParent) - { - nsAutoString blockParentTag; - blockParent->GetTagName(blockParentTag); - PRBool isRoot; - IsRootTag(blockParentTag, isRoot); - if ((PR_FALSE==isRoot) && (-1==aTagList->IndexOf(blockParentTag))) { - aTagList->AppendString(blockParentTag); - } - } - } - NS_RELEASE(subRange); - blockSections->RemoveElementAt(0); - subRange = (nsIDOMRange *)(blockSections->ElementAt(0)); + nsAutoString blockParentTag; + blockParent->GetTagName(blockParentTag); + PRBool isRoot; + IsRootTag(blockParentTag, isRoot); + if ((PR_FALSE==isRoot) && (-1==aTagList->IndexOf(blockParentTag))) { + aTagList->AppendString(blockParentTag); } } - NS_RELEASE(blockSections); } + NS_RELEASE(subRange); + if (NS_FAILED(res)) + break; // don't return here, need to release blockSections + blockSections->RemoveElementAt(0); + subRange = (nsIDOMRange *)(blockSections->ElementAt(0)); } } + NS_RELEASE(blockSections); } return res; @@ -1337,32 +1389,33 @@ nsHTMLEditor::AddBlockParent(nsString& aParentTag) nsresult res=NS_ERROR_NOT_INITIALIZED; nsCOMPtrselection; - res = nsEditor::GetSelection(getter_AddRefs(selection)); - if ((NS_SUCCEEDED(res)) && selection) + res = GetSelection(getter_AddRefs(selection)); + if (NS_FAILED(res)) return res; + if (!selection) return NS_ERROR_NULL_POINTER; + + // set the block parent for all selected ranges + nsAutoSelectionReset selectionResetter(selection); + nsAutoEditBatch beginBatching(this); + nsCOMPtr enumerator; + enumerator = do_QueryInterface(selection); + if (enumerator) { - // set the block parent for all selected ranges - nsAutoSelectionReset selectionResetter(selection); - nsAutoEditBatch beginBatching(this); - nsCOMPtr enumerator; - enumerator = do_QueryInterface(selection); - if (enumerator) + enumerator->First(); + nsCOMPtr currentItem; + res = enumerator->CurrentItem(getter_AddRefs(currentItem)); + // XXX: ERROR_HANDLING can currentItem be null? + if ((NS_SUCCEEDED(res)) && (currentItem)) { - enumerator->First(); - nsCOMPtr currentItem; - res = enumerator->CurrentItem(getter_AddRefs(currentItem)); - if ((NS_SUCCEEDED(res)) && (currentItem)) - { - nsCOMPtr range( do_QueryInterface(currentItem) ); - // scan the range for all the independent block content blockSections - // and apply the transformation to them - res = ReParentContentOfRange(range, aParentTag, eInsertParent); - } - } - if (NS_SUCCEEDED(res)) - { // set the selection - // XXX: can't do anything until I can create ranges + nsCOMPtr range( do_QueryInterface(currentItem) ); + // scan the range for all the independent block content blockSections + // and apply the transformation to them + res = ReParentContentOfRange(range, aParentTag, eInsertParent); } } + if (NS_SUCCEEDED(res)) + { // set the selection + // XXX: can't do anything until I can create ranges + } if (gNoisy) {printf("Finished nsHTMLEditor::AddBlockParent with this content:\n"); DebugDumpContent(); } // DEBUG return res; @@ -1381,27 +1434,28 @@ nsHTMLEditor::ReplaceBlockParent(nsString& aParentTag) nsresult res=NS_ERROR_NOT_INITIALIZED; nsCOMPtrselection; - res = nsEditor::GetSelection(getter_AddRefs(selection)); - if ((NS_SUCCEEDED(res)) && selection) + res = GetSelection(getter_AddRefs(selection)); + if (NS_FAILED(res)) return res; + if (!selection) return NS_ERROR_NULL_POINTER; + + nsAutoSelectionReset selectionResetter(selection); + // set the block parent for all selected ranges + nsAutoEditBatch beginBatching(this); + nsCOMPtr enumerator; + res = selection->GetEnumerator(getter_AddRefs(enumerator)); + if (NS_FAILED(res)) return res; + if (!enumerator) return NS_ERROR_NULL_POINTER; + + enumerator->First(); + nsCOMPtr currentItem; + res = enumerator->CurrentItem(getter_AddRefs(currentItem)); + // XXX: ERROR_HANDLING can currentItem be null? + if ((NS_SUCCEEDED(res)) && (currentItem)) { - nsAutoSelectionReset selectionResetter(selection); - // set the block parent for all selected ranges - nsAutoEditBatch beginBatching(this); - nsCOMPtr enumerator; - res = selection->GetEnumerator(getter_AddRefs(enumerator)); - if (NS_SUCCEEDED(res) && enumerator) - { - enumerator->First(); - nsCOMPtr currentItem; - res = enumerator->CurrentItem(getter_AddRefs(currentItem)); - if ((NS_SUCCEEDED(res)) && (currentItem)) - { - nsCOMPtr range( do_QueryInterface(currentItem) ); - // scan the range for all the independent block content blockSections - // and apply the transformation to them - res = ReParentContentOfRange(range, aParentTag, eReplaceParent); - } - } + nsCOMPtr range( do_QueryInterface(currentItem) ); + // scan the range for all the independent block content blockSections + // and apply the transformation to them + res = ReParentContentOfRange(range, aParentTag, eReplaceParent); } if (gNoisy) {printf("Finished nsHTMLEditor::AddBlockParent with this content:\n"); DebugDumpContent(); } // DEBUG @@ -1418,24 +1472,25 @@ nsHTMLEditor::RemoveParagraphStyle() nsresult res=NS_ERROR_NOT_INITIALIZED; nsCOMPtrselection; - res = nsEditor::GetSelection(getter_AddRefs(selection)); - if ((NS_SUCCEEDED(res)) && selection) + res = GetSelection(getter_AddRefs(selection)); + if (NS_FAILED(res)) return res; + if (!selection) return NS_ERROR_NULL_POINTER; + + nsAutoSelectionReset selectionResetter(selection); + nsAutoEditBatch beginBatching(this); + nsCOMPtr enumerator; + res = selection->GetEnumerator(getter_AddRefs(enumerator)); + if (NS_FAILED(res)) return res; + if (!enumerator) return NS_ERROR_NULL_POINTER; + + enumerator->First(); + nsCOMPtr currentItem; + res = enumerator->CurrentItem(getter_AddRefs(currentItem)); + // XXX: ERROR_HANDLING can currentItem be null? + if ((NS_SUCCEEDED(res)) && (currentItem)) { - nsAutoSelectionReset selectionResetter(selection); - nsAutoEditBatch beginBatching(this); - nsCOMPtr enumerator; - res = selection->GetEnumerator(getter_AddRefs(enumerator)); - if (NS_SUCCEEDED(res) && enumerator) - { - enumerator->First(); - nsCOMPtr currentItem; - res = enumerator->CurrentItem(getter_AddRefs(currentItem)); - if ((NS_SUCCEEDED(res)) && (currentItem)) - { - nsCOMPtr range( do_QueryInterface(currentItem) ); - res = RemoveParagraphStyleFromRange(range); - } - } + nsCOMPtr range( do_QueryInterface(currentItem) ); + res = RemoveParagraphStyleFromRange(range); } return res; } @@ -1447,26 +1502,27 @@ nsHTMLEditor::RemoveParent(const nsString &aParentTag) printf("---------- nsHTMLEditor::RemoveParent ----------\n"); } - nsresult res=NS_ERROR_NOT_INITIALIZED; + nsresult res; nsCOMPtrselection; - res = nsEditor::GetSelection(getter_AddRefs(selection)); - if ((NS_SUCCEEDED(res)) && selection) + res = GetSelection(getter_AddRefs(selection)); + if (NS_FAILED(res)) return res; + if (!selection) return NS_ERROR_NULL_POINTER; + + nsAutoSelectionReset selectionResetter(selection); + nsAutoEditBatch beginBatching(this); + nsCOMPtr enumerator; + res = selection->GetEnumerator(getter_AddRefs(enumerator)); + if (NS_FAILED(res)) return res; + if (!enumerator) return NS_ERROR_NULL_POINTER; + + enumerator->First(); + nsCOMPtr currentItem; + res = enumerator->CurrentItem(getter_AddRefs(currentItem)); + // XXX: ERROR_HANDLING can currentItem be null? + if ((NS_SUCCEEDED(res)) && (currentItem)) { - nsAutoSelectionReset selectionResetter(selection); - nsAutoEditBatch beginBatching(this); - nsCOMPtr enumerator; - res = selection->GetEnumerator(getter_AddRefs(enumerator)); - if (NS_SUCCEEDED(res) && enumerator) - { - enumerator->First(); - nsCOMPtr currentItem; - res = enumerator->CurrentItem(getter_AddRefs(currentItem)); - if ((NS_SUCCEEDED(res)) && (currentItem)) - { - nsCOMPtr range( do_QueryInterface(currentItem) ); - res = RemoveParentFromRange(aParentTag, range); - } - } + nsCOMPtr range( do_QueryInterface(currentItem) ); + res = RemoveParentFromRange(aParentTag, range); } return res; } @@ -1483,7 +1539,10 @@ nsHTMLEditor::InsertList(const nsString& aListType) nsAutoEditBatch beginBatching(this); // pre-process - nsEditor::GetSelection(getter_AddRefs(selection)); + res = GetSelection(getter_AddRefs(selection)); + if (NS_FAILED(res)) return res; + if (!selection) return NS_ERROR_NULL_POINTER; + nsTextRulesInfo ruleInfo(nsHTMLEditRules::kMakeList); if (aListType == "ol") ruleInfo.bOrdered = PR_TRUE; else ruleInfo.bOrdered = PR_FALSE; @@ -1491,8 +1550,6 @@ nsHTMLEditor::InsertList(const nsString& aListType) if (cancel || (NS_FAILED(res))) return res; // Find out if the selection is collapsed: - if (NS_FAILED(res) || !selection) return res; - PRBool isCollapsed; res = selection->GetIsCollapsed(&isCollapsed); if (NS_FAILED(res)) return res; @@ -1567,15 +1624,15 @@ nsHTMLEditor::InsertBasicBlock(const nsString& aBlockType) nsAutoEditBatch beginBatching(this); // pre-process - nsEditor::GetSelection(getter_AddRefs(selection)); + res = GetSelection(getter_AddRefs(selection)); + if (NS_FAILED(res)) return res; + if (!selection) return NS_ERROR_NULL_POINTER; nsTextRulesInfo ruleInfo(nsHTMLEditRules::kMakeBasicBlock); ruleInfo.blockType = &aBlockType; res = mRules->WillDoAction(selection, &ruleInfo, &cancel); if (cancel || (NS_FAILED(res))) return res; // Find out if the selection is collapsed: - if (NS_FAILED(res) || !selection) return res; - PRBool isCollapsed; res = selection->GetIsCollapsed(&isCollapsed); if (NS_FAILED(res)) return res; @@ -1645,7 +1702,10 @@ nsHTMLEditor::Indent(const nsString& aIndent) // pre-process nsCOMPtr selection; - nsEditor::GetSelection(getter_AddRefs(selection)); + res = GetSelection(getter_AddRefs(selection)); + if (NS_FAILED(res)) return res; + if (!selection) return NS_ERROR_NULL_POINTER; + nsTextRulesInfo ruleInfo(nsHTMLEditRules::kIndent); if (aIndent == "outdent") ruleInfo.action = nsHTMLEditRules::kOutdent; @@ -1666,7 +1726,6 @@ nsHTMLEditor::Indent(const nsString& aIndent) nsAutoString inward("indent"); if (aIndent == inward) { - if (isCollapsed) { // have to find a place to put the blockquote @@ -1722,7 +1781,8 @@ nsHTMLEditor::Align(const nsString& aAlignType) // Find out if the selection is collapsed: nsCOMPtr selection; nsresult res = GetSelection(getter_AddRefs(selection)); - if (NS_FAILED(res) || !selection) return res; + if (NS_FAILED(res)) return res; + if (!selection) return NS_ERROR_NULL_POINTER; nsTextRulesInfo ruleInfo(nsHTMLEditRules::kAlign); ruleInfo.alignType = &aAlignType; res = mRules->WillDoAction(selection, &ruleInfo, &cancel); @@ -1742,9 +1802,9 @@ nsHTMLEditor::GetElementOrParentByTagName(const nsString &aTagName, nsIDOMNode * if (!aNode) { nsCOMPtrselection; - res = nsEditor::GetSelection(getter_AddRefs(selection)); - if (NS_FAILED(res) || !selection) - return res; + res = GetSelection(getter_AddRefs(selection)); + if (NS_FAILED(res)) return res; + if (!selection) return NS_ERROR_NULL_POINTER; //TODO: Do I need to release the node? if(NS_FAILED(selection->GetAnchorNode(&aNode))) @@ -1790,6 +1850,7 @@ nsHTMLEditor::GetElementOrParentByTagName(const nsString &aTagName, nsIDOMNode * } // Search up the parent chain // We should never fail because of root test below, but lets be safe + // XXX: ERROR_HANDLING error return code lost if (!NS_SUCCEEDED(currentNode->GetParentNode(getter_AddRefs(parent))) || !parent) break; @@ -1837,10 +1898,10 @@ nsHTMLEditor::GetSelectedElement(const nsString& aTagName, nsIDOMElement** aRetu nsresult res=NS_ERROR_NOT_INITIALIZED; //PRBool first=PR_TRUE; nsCOMPtrselection; - res = nsEditor::GetSelection(getter_AddRefs(selection)); - if (NS_FAILED(res) || !selection) - return res; - + res = GetSelection(getter_AddRefs(selection)); + if (NS_FAILED(res)) return res; + if (!selection) return NS_ERROR_NULL_POINTER; + PRBool isCollapsed; selection->GetIsCollapsed(&isCollapsed); nsCOMPtr selectedElement; @@ -1853,12 +1914,14 @@ nsHTMLEditor::GetSelectedElement(const nsString& aTagName, nsIDOMElement** aRetu // included a collapsed selection (just a caret in a link) nsCOMPtr anchorNode; res = selection->GetAnchorNode(getter_AddRefs(anchorNode)); + if (NS_FAILED(res)) return res; PRInt32 anchorOffset = -1; if (anchorNode) selection->GetAnchorOffset(&anchorOffset); nsCOMPtr focusNode; - selection->GetFocusNode(getter_AddRefs(focusNode)); + res = selection->GetFocusNode(getter_AddRefs(focusNode)); + if (NS_FAILED(res)) return res; PRInt32 focusOffset = -1; if (focusNode) selection->GetFocusOffset(&focusOffset); @@ -1881,6 +1944,7 @@ nsHTMLEditor::GetSelectedElement(const nsString& aTagName, nsIDOMElement** aRetu #endif nsCOMPtr parentLinkOfAnchor; res = GetElementOrParentByTagName("href", anchorNode, getter_AddRefs(parentLinkOfAnchor)); + // XXX: ERROR_HANDLING can parentLinkOfAnchor be null? if (NS_SUCCEEDED(res) && parentLinkOfAnchor) { if (isCollapsed) @@ -1920,6 +1984,7 @@ nsHTMLEditor::GetSelectedElement(const nsString& aTagName, nsIDOMElement** aRetu { nsCOMPtr enumerator; res = selection->GetEnumerator(getter_AddRefs(enumerator)); + // XXX: ERROR_HANDLING unclear what to do here, should an error just be returned if enumerator is null or res failed? if (NS_SUCCEEDED(res) && enumerator) { enumerator->First(); @@ -1932,6 +1997,7 @@ nsHTMLEditor::GetSelectedElement(const nsString& aTagName, nsIDOMElement** aRetu res = nsComponentManager::CreateInstance(kCContentIteratorCID, nsnull, nsIContentIterator::GetIID(), getter_AddRefs(iter)); + // XXX: ERROR_HANDLING XPCOM usage if ((NS_SUCCEEDED(res)) && iter) { iter->Init(range); @@ -2050,6 +2116,7 @@ nsHTMLEditor::CreateElementWithDefaults(const nsString& aTagName, nsIDOMElement* char buf[16]; PRInt32 iAlign; // Currently using 0=left, 1=center, and 2=right + // XXX: ERROR_HANDLING if these results are intentionally thrown away, it should be documented here if( NS_SUCCEEDED(mPrefs->GetIntPref("editor.hrule.align", &iAlign))) { switch (iAlign) { @@ -2121,11 +2188,11 @@ nsHTMLEditor::CreateElementWithDefaults(const nsString& aTagName, nsIDOMElement* space += nbsp; // If we fail here, we return NS_OK anyway, since we have an OK cell node nsresult result = mDoc->CreateTextNode(space, getter_AddRefs(newTextNode)); - if (NS_SUCCEEDED(result) && newTextNode) - { - nsCOMPtrresultNode; - result = newCellNode->AppendChild(newTextNode, getter_AddRefs(resultNode)); - } + if (NS_FAILED(result)) return result; + if (!newTextNode) return NS_ERROR_NULL_POINTER; + + nsCOMPtrresultNode; + result = newCellNode->AppendChild(newTextNode, getter_AddRefs(resultNode)); } } // ADD OTHER DEFAULT ATTRIBUTES HERE @@ -2147,6 +2214,9 @@ nsHTMLEditor::SaveHLineSettings(nsIDOMElement* aElement) nsAutoString align, width, height, noshade; res = NS_ERROR_UNEXPECTED; + // XXX: ERROR_HANDLING if return codes are intentionally thrown away, it should be documented here + // it looks like if any GetAttribute call failes, an error is returned + // is that the desired behavior? if (NS_SUCCEEDED(aElement->GetAttribute("align", align)) && NS_SUCCEEDED(aElement->GetAttribute("height", height)) && NS_SUCCEEDED(aElement->GetAttribute("width", width)) && @@ -2190,6 +2260,10 @@ nsHTMLEditor::InsertLinkAroundSelection(nsIDOMElement* aAnchorElement) // We must have a real selection res = GetSelection(getter_AddRefs(selection)); + if (!selection) + { + res = NS_ERROR_NULL_POINTER; + } if (NS_FAILED(res) || !selection) goto DELETE_ANCHOR; @@ -2208,6 +2282,7 @@ nsHTMLEditor::InsertLinkAroundSelection(nsIDOMElement* aAnchorElement) if (anchor) { nsAutoString href; + // XXX: ERROR_HANDLING return code lost if (NS_SUCCEEDED(anchor->GetHref(href)) && href.GetUnicode() && href.Length() > 0) { nsAutoEditBatch beginBatching(this); @@ -2228,7 +2303,8 @@ DELETE_ANCHOR: return res; } - +// XXX: this method sets the attribute on the body element directly, +// and is not undoable. It should go through the transaction system! NS_IMETHODIMP nsHTMLEditor::SetBackgroundColor(const nsString& aColor) { // nsresult result; @@ -2243,9 +2319,11 @@ NS_IMETHODIMP nsHTMLEditor::SetBackgroundColor(const nsString& aColor) // Set the background color attribute on the body tag nsCOMPtr bodyElement; nsresult res = nsEditor::GetBodyElement(getter_AddRefs(bodyElement)); - if (NS_SUCCEEDED(res) && bodyElement) + if (!bodyElement) res = NS_ERROR_NULL_POINTER; + if (NS_SUCCEEDED(res)) { nsAutoEditBatch beginBatching(this); + // XXX: ERROR_HANDLING should this be "res = SetAttribute..." bodyElement->SetAttribute("bgcolor", aColor); } @@ -2263,9 +2341,11 @@ NS_IMETHODIMP nsHTMLEditor::SetBodyAttribute(const nsString& aAttribute, const n nsCOMPtr bodyElement; res = nsEditor::GetBodyElement(getter_AddRefs(bodyElement)); - if (NS_SUCCEEDED(res) && bodyElement) + if (!bodyElement) res = NS_ERROR_NULL_POINTER; + if (NS_SUCCEEDED(res)) { // Use the editor's method which goes through the transaction system + // XXX: ERROR_HANDLING should this be "res = SetAttribute..." SetAttribute(bodyElement, aAttribute, aValue); } return res; @@ -2330,21 +2410,21 @@ nsHTMLEditor::GetDocumentLength(PRInt32 *aCount) nsCOMPtr sel; result = GetSelection(getter_AddRefs(sel)); - if ((NS_SUCCEEDED(result)) && sel) + if (NS_FAILED(result)) return result; + if (!sel) return NS_ERROR_NULL_POINTER; + + nsAutoSelectionReset selectionResetter(sel); + result = SelectAll(); + if (NS_SUCCEEDED(result)) { - nsAutoSelectionReset selectionResetter(sel); - result = SelectAll(); + PRInt32 start, end; + result = GetTextSelectionOffsets(sel, start, end); if (NS_SUCCEEDED(result)) { - PRInt32 start, end; - result = GetTextSelectionOffsets(sel, start, end); - if (NS_SUCCEEDED(result)) - { - NS_ASSERTION(0==start, "GetTextSelectionOffsets failed to set start correctly."); - NS_ASSERTION(0<=end, "GetTextSelectionOffsets failed to set end correctly."); - if (0<=end) { - *aCount = end; - } + NS_ASSERTION(0==start, "GetTextSelectionOffsets failed to set start correctly."); + NS_ASSERTION(0<=end, "GetTextSelectionOffsets failed to set end correctly."); + if (0<=end) { + *aCount = end; } } } @@ -2374,11 +2454,12 @@ NS_IMETHODIMP nsHTMLEditor::GetMaxTextLength(PRInt32& aMaxTextLength) NS_IMETHODIMP nsHTMLEditor::AddStyleSheet(nsICSSStyleSheet* aSheet) { - AddStyleSheetTxn* aTxn; - nsresult rv = CreateTxnForAddStyleSheet(aSheet, &aTxn); - if (NS_SUCCEEDED(rv) && aTxn) + AddStyleSheetTxn* txn; + nsresult rv = CreateTxnForAddStyleSheet(aSheet, &txn); + if (!txn) rv = NS_ERROR_NULL_POINTER; + if (NS_SUCCEEDED(rv)) { - rv = Do(aTxn); + rv = Do(txn); if (NS_SUCCEEDED(rv)) { mLastStyleSheet = do_QueryInterface(aSheet); // save it so we can remove before applying the next one @@ -2392,11 +2473,12 @@ nsHTMLEditor::AddStyleSheet(nsICSSStyleSheet* aSheet) NS_IMETHODIMP nsHTMLEditor::RemoveStyleSheet(nsICSSStyleSheet* aSheet) { - RemoveStyleSheetTxn* aTxn; - nsresult rv = CreateTxnForRemoveStyleSheet(aSheet, &aTxn); - if (NS_SUCCEEDED(rv) && aTxn) + RemoveStyleSheetTxn* txn; + nsresult rv = CreateTxnForRemoveStyleSheet(aSheet, &txn); + if (!txn) rv = NS_ERROR_NULL_POINTER; + if (NS_SUCCEEDED(rv)) { - rv = Do(aTxn); + rv = Do(txn); if (NS_SUCCEEDED(rv)) { mLastStyleSheet = nsnull; // forget it @@ -2588,8 +2670,8 @@ NS_IMETHODIMP nsHTMLEditor::PasteAsCitedQuotation(const nsString& aCitation) nsCOMPtr newNode; nsAutoString tag("blockquote"); nsresult res = DeleteSelectionAndCreateNode(tag, getter_AddRefs(newNode)); - if (NS_FAILED(res) || !newNode) - return res; + if (NS_FAILED(res)) return res; + if (!newNode) return NS_ERROR_NULL_POINTER; // Try to set type=cite. Ignore it if this fails. nsCOMPtr newElement (do_QueryInterface(newNode)); @@ -2609,6 +2691,8 @@ NS_IMETHODIMP nsHTMLEditor::PasteAsCitedQuotation(const nsString& aCitation) printf("Can't get selection!"); #endif } + if (NS_FAILED(res)) return res; + if (!selection) return NS_ERROR_NULL_POINTER; res = selection->Collapse(newNode, 0); if (NS_FAILED(res)) @@ -2616,6 +2700,7 @@ NS_IMETHODIMP nsHTMLEditor::PasteAsCitedQuotation(const nsString& aCitation) #ifdef DEBUG_akkana printf("Couldn't collapse"); #endif + // XXX: error result: should res be returned here? } res = Paste(); @@ -2715,8 +2800,8 @@ NS_IMETHODIMP nsHTMLEditor::InsertAsCitedQuotation(const nsString& aQuotedText, nsCOMPtr newNode; nsAutoString tag("blockquote"); nsresult res = DeleteSelectionAndCreateNode(tag, getter_AddRefs(newNode)); - if (NS_FAILED(res) || !newNode) - return res; + if (NS_FAILED(res)) return res; + if (!newNode) return NS_ERROR_NULL_POINTER; // Try to set type=cite. Ignore it if this fails. nsCOMPtr newElement (do_QueryInterface(newNode)); @@ -2744,15 +2829,15 @@ nsHTMLEditor::GetEmbeddedObjects(nsISupportsArray** aNodeList) nsresult res; res = NS_NewISupportsArray(aNodeList); - if (NS_FAILED(res) || !*aNodeList) - return res; - //NS_ADDREF(*aNodeList); + if (NS_FAILED(res)) return res; + if (!*aNodeList) return NS_ERROR_NULL_POINTER; nsCOMPtr iter; res = nsComponentManager::CreateInstance(kCContentIteratorCID, nsnull, nsIContentIterator::GetIID(), getter_AddRefs(iter)); - if ((NS_SUCCEEDED(res)) && iter) + if (!iter) return NS_ERROR_NULL_POINTER; + if ((NS_SUCCEEDED(res))) { // get the root content nsCOMPtr rootContent; @@ -3114,6 +3199,7 @@ nsHTMLEditor::ReplaceStyleSheet(nsICSSStyleSheet *aNewSheet) if (mLastStyleSheet) { rv = RemoveStyleSheet(mLastStyleSheet); + //XXX: rv is ignored here, why? } rv = AddStyleSheet(aNewSheet); @@ -3136,7 +3222,7 @@ void nsHTMLEditor::ApplyStyleSheetToPresShellDocument(nsICSSStyleSheet* aSheet, rv = editor->ReplaceStyleSheet(aSheet); } - // we lose the return value here. Set a flag in the editor? + // XXX: we lose the return value here. Set a flag in the editor? } @@ -3248,7 +3334,8 @@ void nsHTMLEditor::IsTextPropertySetByContent(nsIDOMNode *aNode, aProperty->ToString(propName); nsCOMPtrparent; result = aNode->GetParentNode(getter_AddRefs(parent)); - while (NS_SUCCEEDED(result) && parent) + if (NS_FAILED(result)) return; + while (parent) { nsCOMPtrelement; element = do_QueryInterface(parent); @@ -3324,6 +3411,7 @@ nsresult nsHTMLEditor::GetTextSelectionOffsets(nsIDOMSelection *aSelection, PRInt32 &aStartOffset, PRInt32 &aEndOffset) { + if(!aSelection) { return NS_ERROR_NULL_POINTER; } nsresult result; // initialize out params aStartOffset = 0; // default to first char in selection @@ -3338,115 +3426,46 @@ nsresult nsHTMLEditor::GetTextSelectionOffsets(nsIDOMSelection *aSelection, nsCOMPtr enumerator; result = aSelection->GetEnumerator(getter_AddRefs(enumerator)); - if (NS_SUCCEEDED(result) && enumerator) + if (NS_FAILED(result)) return result; + if (!enumerator) return NS_ERROR_NULL_POINTER; + + // don't use "result" in this block + enumerator->First(); + nsCOMPtr currentItem; + nsresult findParentResult = enumerator->CurrentItem(getter_AddRefs(currentItem)); + if ((NS_SUCCEEDED(findParentResult)) && (currentItem)) { - // don't use "result" in this block - enumerator->First(); - nsCOMPtr currentItem; - nsresult findParentResult = enumerator->CurrentItem(getter_AddRefs(currentItem)); - if ((NS_SUCCEEDED(findParentResult)) && (currentItem)) - { - nsCOMPtr range( do_QueryInterface(currentItem) ); - range->GetCommonParent(getter_AddRefs(parentNode)); - } - else parentNode = do_QueryInterface(startNode); + nsCOMPtr range( do_QueryInterface(currentItem) ); + range->GetCommonParent(getter_AddRefs(parentNode)); } + else { + parentNode = do_QueryInterface(startNode); + } + nsCOMPtr iter; result = nsComponentManager::CreateInstance(kCContentIteratorCID, nsnull, nsIContentIterator::GetIID(), getter_AddRefs(iter)); - if ((NS_SUCCEEDED(result)) && iter) + if (NS_FAILED(result)) return result; + if (!iter) return NS_ERROR_NULL_POINTER; + + PRUint32 totalLength=0; + nsCOMPtrtextNode; + nsCOMPtrblockParentContent = do_QueryInterface(parentNode); + iter->Init(blockParentContent); + // loop through the content iterator for each content node + nsCOMPtr content; + result = iter->CurrentNode(getter_AddRefs(content)); + while (NS_COMFALSE == iter->IsDone()) { - PRUint32 totalLength=0; - nsCOMPtrtextNode; - nsCOMPtrblockParentContent = do_QueryInterface(parentNode); - iter->Init(blockParentContent); - // loop through the content iterator for each content node - nsCOMPtr content; - result = iter->CurrentNode(getter_AddRefs(content)); - while (NS_COMFALSE == iter->IsDone()) + textNode = do_QueryInterface(content); + if (textNode) { - textNode = do_QueryInterface(content); - if (textNode) + nsCOMPtrcurrentNode = do_QueryInterface(textNode); + if (!currentNode) {return NS_ERROR_NO_INTERFACE;} + if (PR_TRUE==IsEditable(currentNode)) { - nsCOMPtrcurrentNode = do_QueryInterface(textNode); - if (!currentNode) {return NS_ERROR_NO_INTERFACE;} - if (PR_TRUE==IsEditable(currentNode)) - { - if (currentNode.get() == startNode.get()) - { - aStartOffset = totalLength + startOffset; - } - if (currentNode.get() == endNode.get()) - { - aEndOffset = totalLength + endOffset; - break; - } - PRUint32 length; - textNode->GetLength(&length); - totalLength += length; - } - } - iter->Next(); - iter->CurrentNode(getter_AddRefs(content)); - } - if (-1==aEndOffset) { - aEndOffset = totalLength; - } - } - return result; -} - - - -void nsHTMLEditor::GetTextSelectionOffsetsForRange(nsIDOMSelection *aSelection, - nsIDOMNode **aParent, - PRInt32 &aStartOffset, - PRInt32 &aEndOffset) -{ - nsresult result; - - nsCOMPtr startNode, endNode; - PRInt32 startOffset, endOffset; - aSelection->GetAnchorNode(getter_AddRefs(startNode)); - aSelection->GetAnchorOffset(&startOffset); - aSelection->GetFocusNode(getter_AddRefs(endNode)); - aSelection->GetFocusOffset(&endOffset); - - nsCOMPtr enumerator; - result = aSelection->GetEnumerator(getter_AddRefs(enumerator)); - if (NS_SUCCEEDED(result) && enumerator) - { - enumerator->First(); - nsCOMPtr currentItem; - result = enumerator->CurrentItem(getter_AddRefs(currentItem)); - if ((NS_SUCCEEDED(result)) && currentItem) - { - nsCOMPtr range( do_QueryInterface(currentItem) ); - range->GetCommonParent(aParent); - } - } - - nsCOMPtr iter; - result = nsComponentManager::CreateInstance(kCContentIteratorCID, nsnull, - nsIContentIterator::GetIID(), - getter_AddRefs(iter)); - if ((NS_SUCCEEDED(result)) && iter) - { - PRUint32 totalLength=0; - nsCOMPtrtextNode; - nsCOMPtrblockParentContent = do_QueryInterface(*aParent); - iter->Init(blockParentContent); - // loop through the content iterator for each content node - nsCOMPtr content; - result = iter->CurrentNode(getter_AddRefs(content)); - while (NS_COMFALSE == iter->IsDone()) - { - textNode = do_QueryInterface(content); - if (textNode) - { - nsCOMPtrcurrentNode = do_QueryInterface(textNode); if (currentNode.get() == startNode.get()) { aStartOffset = totalLength + startOffset; @@ -3460,10 +3479,84 @@ void nsHTMLEditor::GetTextSelectionOffsetsForRange(nsIDOMSelection *aSelection, textNode->GetLength(&length); totalLength += length; } - iter->Next(); - iter->CurrentNode(getter_AddRefs(content)); } + iter->Next(); + iter->CurrentNode(getter_AddRefs(content)); } + if (-1==aEndOffset) { + aEndOffset = totalLength; + } + return result; +} + + +NS_IMETHODIMP +nsHTMLEditor::GetTextSelectionOffsetsForRange(nsIDOMSelection *aSelection, + nsIDOMNode **aParent, + PRInt32 &aStartOffset, + PRInt32 &aEndOffset) +{ + if (!aSelection) { return NS_ERROR_NULL_POINTER; } + aStartOffset = aEndOffset = 0; + nsresult result; + + nsCOMPtr startNode, endNode; + PRInt32 startOffset, endOffset; + aSelection->GetAnchorNode(getter_AddRefs(startNode)); + aSelection->GetAnchorOffset(&startOffset); + aSelection->GetFocusNode(getter_AddRefs(endNode)); + aSelection->GetFocusOffset(&endOffset); + + nsCOMPtr enumerator; + result = aSelection->GetEnumerator(getter_AddRefs(enumerator)); + if (NS_FAILED(result)) return result; + if (!enumerator) return NS_ERROR_NULL_POINTER; + enumerator->First(); + nsCOMPtr currentItem; + result = enumerator->CurrentItem(getter_AddRefs(currentItem)); + if ((NS_SUCCEEDED(result)) && currentItem) + { + nsCOMPtr range( do_QueryInterface(currentItem) ); + range->GetCommonParent(aParent); + } + + nsCOMPtr iter; + result = nsComponentManager::CreateInstance(kCContentIteratorCID, nsnull, + nsIContentIterator::GetIID(), + getter_AddRefs(iter)); + if (NS_FAILED(result)) return result; + if (!iter) return NS_ERROR_NULL_POINTER; + + PRUint32 totalLength=0; + nsCOMPtrtextNode; + nsCOMPtrblockParentContent = do_QueryInterface(*aParent); + iter->Init(blockParentContent); + // loop through the content iterator for each content node + nsCOMPtr content; + result = iter->CurrentNode(getter_AddRefs(content)); + while (NS_COMFALSE == iter->IsDone()) + { + textNode = do_QueryInterface(content); + if (textNode) + { + nsCOMPtrcurrentNode = do_QueryInterface(textNode); + if (currentNode.get() == startNode.get()) + { + aStartOffset = totalLength + startOffset; + } + if (currentNode.get() == endNode.get()) + { + aEndOffset = totalLength + endOffset; + break; + } + PRUint32 length; + textNode->GetLength(&length); + totalLength += length; + } + iter->Next(); + iter->CurrentNode(getter_AddRefs(content)); + } + return result; } void nsHTMLEditor::ResetTextSelectionForRange(nsIDOMNode *aParent, @@ -3471,6 +3564,7 @@ void nsHTMLEditor::ResetTextSelectionForRange(nsIDOMNode *aParent, PRInt32 aEndOffset, nsIDOMSelection *aSelection) { + if (!aParent || !aSelection) { return; } // XXX: should return an error nsCOMPtr startNode, endNode; PRInt32 startOffset, endOffset; @@ -3479,43 +3573,42 @@ void nsHTMLEditor::ResetTextSelectionForRange(nsIDOMNode *aParent, result = nsComponentManager::CreateInstance(kCContentIteratorCID, nsnull, nsIContentIterator::GetIID(), getter_AddRefs(iter)); - if ((NS_SUCCEEDED(result)) && iter) + if (NS_FAILED(result)) return; + if (!iter) return; + PRBool setStart = PR_FALSE; + PRUint32 totalLength=0; + nsCOMPtrtextNode; + nsCOMPtrblockParentContent = do_QueryInterface(aParent); + iter->Init(blockParentContent); + // loop through the content iterator for each content node + nsCOMPtr content; + result = iter->CurrentNode(getter_AddRefs(content)); + while (NS_COMFALSE == iter->IsDone()) { - PRBool setStart = PR_FALSE; - PRUint32 totalLength=0; - nsCOMPtrtextNode; - nsCOMPtrblockParentContent = do_QueryInterface(aParent); - iter->Init(blockParentContent); - // loop through the content iterator for each content node - nsCOMPtr content; - result = iter->CurrentNode(getter_AddRefs(content)); - while (NS_COMFALSE == iter->IsDone()) + textNode = do_QueryInterface(content); + if (textNode) { - textNode = do_QueryInterface(content); - if (textNode) + PRUint32 length; + textNode->GetLength(&length); + if ((PR_FALSE==setStart) && aStartOffset<=(PRInt32)(totalLength+length)) { - PRUint32 length; - textNode->GetLength(&length); - if ((PR_FALSE==setStart) && aStartOffset<=(PRInt32)(totalLength+length)) - { - setStart = PR_TRUE; - startNode = do_QueryInterface(textNode); - startOffset = aStartOffset-totalLength; - } - if (aEndOffset<=(PRInt32)(totalLength+length)) - { - endNode = do_QueryInterface(textNode); - endOffset = aEndOffset-totalLength; - break; - } - totalLength += length; + setStart = PR_TRUE; + startNode = do_QueryInterface(textNode); + startOffset = aStartOffset-totalLength; } - iter->Next(); - iter->CurrentNode(getter_AddRefs(content)); + if (aEndOffset<=(PRInt32)(totalLength+length)) + { + endNode = do_QueryInterface(textNode); + endOffset = aEndOffset-totalLength; + break; + } + totalLength += length; } - aSelection->Collapse(startNode, startOffset); - aSelection->Extend(endNode, endOffset); - } + iter->Next(); + iter->CurrentNode(getter_AddRefs(content)); + } + aSelection->Collapse(startNode, startOffset); + aSelection->Extend(endNode, endOffset); } #pragma mark - @@ -3651,8 +3744,9 @@ nsHTMLEditor::ReParentBlockContent(nsIDOMNode *aNode, PRBool removeBreakAfter = PR_FALSE; nsCOMPtrancestor; nsresult res = aNode->GetParentNode(getter_AddRefs(ancestor)); + if (NS_FAILED(res)) return res; nsCOMPtrpreviousAncestor = do_QueryInterface(aNode); - while (NS_SUCCEEDED(res) && ancestor) + while (ancestor) { nsCOMPtrancestorElement = do_QueryInterface(ancestor); nsAutoString ancestorTag; @@ -3663,118 +3757,136 @@ nsHTMLEditor::ReParentBlockContent(nsIDOMNode *aNode, } previousAncestor = do_QueryInterface(ancestor); res = ancestorElement->GetParentNode(getter_AddRefs(ancestor)); + if (NS_FAILED(res)) return res; } // now, previousAncestor is the node we are operating on nsCOMPtrleftNode, rightNode; res = GetBlockSection(previousAncestor, - getter_AddRefs(leftNode), - getter_AddRefs(rightNode)); - if ((NS_SUCCEEDED(res)) && leftNode && rightNode) + getter_AddRefs(leftNode), + getter_AddRefs(rightNode)); + if (NS_FAILED(res)) return res; + if (!leftNode || !rightNode) return NS_ERROR_NULL_POINTER; + + // determine some state for managing
s around the new block + PRBool isSubordinateBlock = PR_FALSE; // if true, the content is already in a subordinate block + PRBool isRootBlock = PR_FALSE; // if true, the content is in a root block + nsCOMPtrblockParentElement = do_QueryInterface(blockParentNode); + if (blockParentElement) { - // determine some state for managing
s around the new block - PRBool isSubordinateBlock = PR_FALSE; // if true, the content is already in a subordinate block - PRBool isRootBlock = PR_FALSE; // if true, the content is in a root block - nsCOMPtrblockParentElement = do_QueryInterface(blockParentNode); - if (blockParentElement) - { - nsAutoString blockParentTag; - blockParentElement->GetTagName(blockParentTag); - IsSubordinateBlock(blockParentTag, isSubordinateBlock); - IsRootTag(blockParentTag, isRootBlock); - } + nsAutoString blockParentTag; + blockParentElement->GetTagName(blockParentTag); + IsSubordinateBlock(blockParentTag, isSubordinateBlock); + IsRootTag(blockParentTag, isRootBlock); + } - if (PR_TRUE==isRootBlock) - { // we're creating a block element where a block element did not previously exist - removeBreakBefore = PR_TRUE; - removeBreakAfter = PR_TRUE; - } + if (PR_TRUE==isRootBlock) + { // we're creating a block element where a block element did not previously exist + removeBreakBefore = PR_TRUE; + removeBreakAfter = PR_TRUE; + } - // apply the transformation - PRInt32 offsetInParent=0; - if (eInsertParent==aTransformation || PR_TRUE==isRootBlock) + // apply the transformation + PRInt32 offsetInParent=0; + if (eInsertParent==aTransformation || PR_TRUE==isRootBlock) + { + res = GetChildOffset(leftNode, blockParentNode, offsetInParent); + NS_ASSERTION((NS_SUCCEEDED(res)), "bad res from GetChildOffset"); + res = CreateNode(aParentTag, blockParentNode, offsetInParent, aNewParentNode); + if (gNoisy) { printf("created a node in blockParentNode at offset %d\n", offsetInParent); } + } + else + { + nsCOMPtr grandParent; + res = blockParentNode->GetParentNode(getter_AddRefs(grandParent)); + if (NS_FAILED(res)) return res; + if (!grandParent) return NS_ERROR_NULL_POINTER; + nsCOMPtrfirstChildNode, lastChildNode; + blockParentNode->GetFirstChild(getter_AddRefs(firstChildNode)); + blockParentNode->GetLastChild(getter_AddRefs(lastChildNode)); + if (firstChildNode==leftNode && lastChildNode==rightNode) { + res = GetChildOffset(blockParentNode, grandParent, offsetInParent); + NS_ASSERTION((NS_SUCCEEDED(res)), "bad res from GetChildOffset"); + res = CreateNode(aParentTag, grandParent, offsetInParent, aNewParentNode); + if (gNoisy) { printf("created a node in grandParent at offset %d\n", offsetInParent); } + } + else + { + // We're in the case where the content of blockParentNode is separated by
's, + // creating multiple block content ranges. + // Split blockParentNode around the blockContent + if (gNoisy) { printf("splitting a node because of
s\n"); } + nsCOMPtr newLeftNode; + if (firstChildNode!=leftNode) + { + res = GetChildOffset(leftNode, blockParentNode, offsetInParent); + if (gNoisy) { printf("splitting left at %d\n", offsetInParent); } + res = SplitNode(blockParentNode, offsetInParent, getter_AddRefs(newLeftNode)); + // after this split, blockParentNode still contains leftNode and rightNode + } + if (lastChildNode!=rightNode) + { + res = GetChildOffset(rightNode, blockParentNode, offsetInParent); + offsetInParent++; + if (gNoisy) { printf("splitting right at %d\n", offsetInParent); } + res = SplitNode(blockParentNode, offsetInParent, getter_AddRefs(newLeftNode)); + blockParentNode = do_QueryInterface(newLeftNode); + } res = GetChildOffset(leftNode, blockParentNode, offsetInParent); NS_ASSERTION((NS_SUCCEEDED(res)), "bad res from GetChildOffset"); res = CreateNode(aParentTag, blockParentNode, offsetInParent, aNewParentNode); if (gNoisy) { printf("created a node in blockParentNode at offset %d\n", offsetInParent); } + // what we need to do here is remove the existing block parent when we're all done. + removeBlockParent = PR_TRUE; } - else + } + if ((NS_SUCCEEDED(res)) && *aNewParentNode) + { // move all the children/contents of blockParentNode to aNewParentNode + nsCOMPtrchildNode = do_QueryInterface(rightNode); + nsCOMPtrpreviousSiblingNode; + while (NS_SUCCEEDED(res) && childNode) { - nsCOMPtr grandParent; - res = blockParentNode->GetParentNode(getter_AddRefs(grandParent)); - if ((NS_SUCCEEDED(res)) && grandParent) + childNode->GetPreviousSibling(getter_AddRefs(previousSiblingNode)); + // explicitly delete of childNode from it's current parent + // can't just rely on DOM semantics of InsertNode doing the delete implicitly, doesn't undo! + res = nsEditor::DeleteNode(childNode); + if (NS_SUCCEEDED(res)) { - nsCOMPtrfirstChildNode, lastChildNode; - blockParentNode->GetFirstChild(getter_AddRefs(firstChildNode)); - blockParentNode->GetLastChild(getter_AddRefs(lastChildNode)); - if (firstChildNode==leftNode && lastChildNode==rightNode) + res = nsEditor::InsertNode(childNode, *aNewParentNode, 0); + if (gNoisy) { - res = GetChildOffset(blockParentNode, grandParent, offsetInParent); - NS_ASSERTION((NS_SUCCEEDED(res)), "bad res from GetChildOffset"); - res = CreateNode(aParentTag, grandParent, offsetInParent, aNewParentNode); - if (gNoisy) { printf("created a node in grandParent at offset %d\n", offsetInParent); } + printf("re-parented sibling node %p\n", childNode.get()); } - else - { - // We're in the case where the content of blockParentNode is separated by
's, - // creating multiple block content ranges. - // Split blockParentNode around the blockContent - if (gNoisy) { printf("splitting a node because of
s\n"); } - nsCOMPtr newLeftNode; - if (firstChildNode!=leftNode) - { - res = GetChildOffset(leftNode, blockParentNode, offsetInParent); - if (gNoisy) { printf("splitting left at %d\n", offsetInParent); } - res = SplitNode(blockParentNode, offsetInParent, getter_AddRefs(newLeftNode)); - // after this split, blockParentNode still contains leftNode and rightNode - } - if (lastChildNode!=rightNode) - { - res = GetChildOffset(rightNode, blockParentNode, offsetInParent); - offsetInParent++; - if (gNoisy) { printf("splitting right at %d\n", offsetInParent); } - res = SplitNode(blockParentNode, offsetInParent, getter_AddRefs(newLeftNode)); - blockParentNode = do_QueryInterface(newLeftNode); - } - res = GetChildOffset(leftNode, blockParentNode, offsetInParent); - NS_ASSERTION((NS_SUCCEEDED(res)), "bad res from GetChildOffset"); - res = CreateNode(aParentTag, blockParentNode, offsetInParent, aNewParentNode); - if (gNoisy) { printf("created a node in blockParentNode at offset %d\n", offsetInParent); } - // what we need to do here is remove the existing block parent when we're all done. - removeBlockParent = PR_TRUE; + } + if (childNode==leftNode || rightNode==leftNode) { + break; + } + childNode = do_QueryInterface(previousSiblingNode); + } // end while loop + } + // clean up the surrounding content to maintain vertical whitespace + if (NS_SUCCEEDED(res)) + { + // if the prior node is a
and we did something to change vertical whitespacing, delete the
+ nsCOMPtr brNode; + res = GetPriorNode(leftNode, PR_TRUE, getter_AddRefs(brNode)); + if (NS_SUCCEEDED(res) && brNode) + { + nsCOMPtr brContent = do_QueryInterface(brNode); + if (brContent) + { + nsCOMPtr brContentTag; + brContent->GetTag(*getter_AddRefs(brContentTag)); + if (nsIEditProperty::br==brContentTag.get()) { + res = DeleteNode(brNode); } } } - if ((NS_SUCCEEDED(res)) && *aNewParentNode) - { // move all the children/contents of blockParentNode to aNewParentNode - nsCOMPtrchildNode = do_QueryInterface(rightNode); - nsCOMPtrpreviousSiblingNode; - while (NS_SUCCEEDED(res) && childNode) - { - childNode->GetPreviousSibling(getter_AddRefs(previousSiblingNode)); - // explicitly delete of childNode from it's current parent - // can't just rely on DOM semantics of InsertNode doing the delete implicitly, doesn't undo! - res = nsEditor::DeleteNode(childNode); - if (NS_SUCCEEDED(res)) - { - res = nsEditor::InsertNode(childNode, *aNewParentNode, 0); - if (gNoisy) - { - printf("re-parented sibling node %p\n", childNode.get()); - } - } - if (childNode==leftNode || rightNode==leftNode) { - break; - } - childNode = do_QueryInterface(previousSiblingNode); - } // end while loop - } - // clean up the surrounding content to maintain vertical whitespace + + // if the next node is a
and we did something to change vertical whitespacing, delete the
if (NS_SUCCEEDED(res)) { - // if the prior node is a
and we did something to change vertical whitespacing, delete the
- nsCOMPtr brNode; - res = GetPriorNode(leftNode, PR_TRUE, getter_AddRefs(brNode)); + res = GetNextNode(rightNode, PR_TRUE, getter_AddRefs(brNode)); if (NS_SUCCEEDED(res) && brNode) { nsCOMPtr brContent = do_QueryInterface(brNode); @@ -3787,54 +3899,36 @@ nsHTMLEditor::ReParentBlockContent(nsIDOMNode *aNode, } } } - - // if the next node is a
and we did something to change vertical whitespacing, delete the
- if (NS_SUCCEEDED(res)) - { - res = GetNextNode(rightNode, PR_TRUE, getter_AddRefs(brNode)); - if (NS_SUCCEEDED(res) && brNode) - { - nsCOMPtr brContent = do_QueryInterface(brNode); - if (brContent) - { - nsCOMPtr brContentTag; - brContent->GetTag(*getter_AddRefs(brContentTag)); - if (nsIEditProperty::br==brContentTag.get()) { - res = DeleteNode(brNode); - } - } - } - } } - if ((NS_SUCCEEDED(res)) && (PR_TRUE==removeBlockParent)) - { // we determined we need to remove the previous block parent. Do it! - // go through list backwards so deletes don't interfere with the iteration - nsCOMPtr childNodes; - res = blockParentNode->GetChildNodes(getter_AddRefs(childNodes)); - if ((NS_SUCCEEDED(res)) && (childNodes)) + } + if ((NS_SUCCEEDED(res)) && (PR_TRUE==removeBlockParent)) + { // we determined we need to remove the previous block parent. Do it! + // go through list backwards so deletes don't interfere with the iteration + nsCOMPtr childNodes; + res = blockParentNode->GetChildNodes(getter_AddRefs(childNodes)); + if ((NS_SUCCEEDED(res)) && (childNodes)) + { + nsCOMPtrgrandParent; + blockParentNode->GetParentNode(getter_AddRefs(grandParent)); + //PRInt32 offsetInParent; + res = GetChildOffset(blockParentNode, grandParent, offsetInParent); + PRUint32 childCount; + childNodes->GetLength(&childCount); + PRInt32 i=childCount-1; + for ( ; ((NS_SUCCEEDED(res)) && (0<=i)); i--) { - nsCOMPtrgrandParent; - blockParentNode->GetParentNode(getter_AddRefs(grandParent)); - //PRInt32 offsetInParent; - res = GetChildOffset(blockParentNode, grandParent, offsetInParent); - PRUint32 childCount; - childNodes->GetLength(&childCount); - PRInt32 i=childCount-1; - for ( ; ((NS_SUCCEEDED(res)) && (0<=i)); i--) + nsCOMPtr childNode; + res = childNodes->Item(i, getter_AddRefs(childNode)); + if ((NS_SUCCEEDED(res)) && (childNode)) { - nsCOMPtr childNode; - res = childNodes->Item(i, getter_AddRefs(childNode)); - if ((NS_SUCCEEDED(res)) && (childNode)) - { - res = DeleteNode(childNode); - if (NS_SUCCEEDED(res)) { - res = InsertNode(childNode, grandParent, offsetInParent); - } + res = DeleteNode(childNode); + if (NS_SUCCEEDED(res)) { + res = InsertNode(childNode, grandParent, offsetInParent); } } - if (gNoisy) { printf("removing the old block parent %p\n", blockParentNode.get()); } - res = DeleteNode(blockParentNode); } + if (gNoisy) { printf("removing the old block parent %p\n", blockParentNode.get()); } + res = DeleteNode(blockParentNode); } } return res; @@ -3849,29 +3943,34 @@ nsHTMLEditor::ReParentContentOfRange(nsIDOMRange *aRange, nsresult res; nsISupportsArray *blockSections; res = NS_NewISupportsArray(&blockSections); - if ((NS_SUCCEEDED(res)) && blockSections) + if (NS_FAILED(res)) return res; + if (!blockSections) return NS_ERROR_NULL_POINTER; + + res = GetBlockSectionsForRange(aRange, blockSections); + if (NS_FAILED(res)) return res; + + // no embedded returns allowed below here in this method, or you'll get a space leak + nsIDOMRange *subRange; + subRange = (nsIDOMRange *)(blockSections->ElementAt(0)); + while (subRange) { - res = GetBlockSectionsForRange(aRange, blockSections); - if (NS_SUCCEEDED(res)) + nsCOMPtrstartParent; + res = subRange->GetStartParent(getter_AddRefs(startParent)); + if (NS_SUCCEEDED(res) && startParent) { - nsIDOMRange *subRange; - subRange = (nsIDOMRange *)(blockSections->ElementAt(0)); - while (subRange && (NS_SUCCEEDED(res))) - { - nsCOMPtrstartParent; - res = subRange->GetStartParent(getter_AddRefs(startParent)); - if (NS_SUCCEEDED(res) && startParent) - { - if (gNoisy) { printf("ReParentContentOfRange calling ReParentContentOfNode\n"); } - res = ReParentContentOfNode(startParent, aParentTag, aTranformation); - } - NS_RELEASE(subRange); - blockSections->RemoveElementAt(0); - subRange = (nsIDOMRange *)(blockSections->ElementAt(0)); - } + if (gNoisy) { printf("ReParentContentOfRange calling ReParentContentOfNode\n"); } + res = ReParentContentOfNode(startParent, aParentTag, aTranformation); } - NS_RELEASE(blockSections); + NS_RELEASE(subRange); + if (NS_FAILED(res)) + { // be sure to break after free of subRange + break; + } + blockSections->RemoveElementAt(0); + subRange = (nsIDOMRange *)(blockSections->ElementAt(0)); } + NS_RELEASE(blockSections); + return res; } @@ -3883,23 +3982,27 @@ nsHTMLEditor::RemoveParagraphStyleFromRange(nsIDOMRange *aRange) nsresult res; nsISupportsArray *blockSections; res = NS_NewISupportsArray(&blockSections); - if ((NS_SUCCEEDED(res)) && blockSections) + if (NS_FAILED(res)) return res; + if (!blockSections) return NS_ERROR_NULL_POINTER; + + res = GetBlockSectionsForRange(aRange, blockSections); + if (NS_FAILED(res)) return res; + + nsIDOMRange *subRange; + subRange = (nsIDOMRange *)(blockSections->ElementAt(0)); + while (subRange) { - res = GetBlockSectionsForRange(aRange, blockSections); - if (NS_SUCCEEDED(res)) - { - nsIDOMRange *subRange; - subRange = (nsIDOMRange *)(blockSections->ElementAt(0)); - while (subRange && (NS_SUCCEEDED(res))) - { - res = RemoveParagraphStyleFromBlockContent(subRange); - NS_RELEASE(subRange); - blockSections->RemoveElementAt(0); - subRange = (nsIDOMRange *)(blockSections->ElementAt(0)); - } - } - NS_RELEASE(blockSections); + res = RemoveParagraphStyleFromBlockContent(subRange); + NS_RELEASE(subRange); + if (NS_FAILED(res)) + { // be sure to break after subrange is released + break; + } + blockSections->RemoveElementAt(0); + subRange = (nsIDOMRange *)(blockSections->ElementAt(0)); } + NS_RELEASE(blockSections); + return res; } @@ -3912,7 +4015,9 @@ nsHTMLEditor::RemoveParagraphStyleFromBlockContent(nsIDOMRange *aRange) aRange->GetStartParent(getter_AddRefs(startParent)); nsCOMPtrblockParentElement; res = GetBlockParent(startParent, getter_AddRefs(blockParentElement)); - while ((NS_SUCCEEDED(res)) && blockParentElement) + if (NS_FAILED(res)) return res; + + while (blockParentElement) { nsAutoString blockParentTag; blockParentElement->GetTagName(blockParentTag); @@ -3930,6 +4035,9 @@ nsHTMLEditor::RemoveParagraphStyleFromBlockContent(nsIDOMRange *aRange) { nsCOMPtrgrandParent; blockParentElement->GetParentNode(getter_AddRefs(grandParent)); + if (NS_FAILED(res)) return res; + if (!grandParent) return NS_ERROR_NULL_POINTER; + PRInt32 offsetInParent; res = GetChildOffset(blockParentElement, grandParent, offsetInParent); PRUint32 childCount; @@ -3942,17 +4050,22 @@ nsHTMLEditor::RemoveParagraphStyleFromBlockContent(nsIDOMRange *aRange) if ((NS_SUCCEEDED(res)) && (childNode)) { res = DeleteNode(childNode); - if (NS_SUCCEEDED(res)) { + if (NS_SUCCEEDED(res)) + { res = InsertNode(childNode, grandParent, offsetInParent); - } + if (NS_FAILED(res)) return res; + } } } - if (NS_SUCCEEDED(res)) { + if (NS_SUCCEEDED(res)) + { res = DeleteNode(blockParentElement); + if (NS_FAILED(res)) return res; } } } res = GetBlockParent(startParent, getter_AddRefs(blockParentElement)); + if (NS_FAILED(res)) return res; } return res; } @@ -3965,23 +4078,27 @@ nsHTMLEditor::RemoveParentFromRange(const nsString &aParentTag, nsIDOMRange *aRa nsresult res; nsISupportsArray *blockSections; res = NS_NewISupportsArray(&blockSections); - if ((NS_SUCCEEDED(res)) && blockSections) + if (NS_FAILED(res)) return res; + if (!blockSections) return NS_ERROR_NULL_POINTER; + res = GetBlockSectionsForRange(aRange, blockSections); + if (NS_SUCCEEDED(res)) { - res = GetBlockSectionsForRange(aRange, blockSections); - if (NS_SUCCEEDED(res)) + nsIDOMRange *subRange; + subRange = (nsIDOMRange *)(blockSections->ElementAt(0)); + while (subRange && (NS_SUCCEEDED(res))) { - nsIDOMRange *subRange; + res = RemoveParentFromBlockContent(aParentTag, subRange); + NS_RELEASE(subRange); + if (NS_FAILED(res)) + { + break; + } + blockSections->RemoveElementAt(0); subRange = (nsIDOMRange *)(blockSections->ElementAt(0)); - while (subRange && (NS_SUCCEEDED(res))) - { - res = RemoveParentFromBlockContent(aParentTag, subRange); - NS_RELEASE(subRange); - blockSections->RemoveElementAt(0); - subRange = (nsIDOMRange *)(blockSections->ElementAt(0)); - } } - NS_RELEASE(blockSections); } + NS_RELEASE(blockSections); + return res; } @@ -3992,55 +4109,59 @@ nsHTMLEditor::RemoveParentFromBlockContent(const nsString &aParentTag, nsIDOMRan nsresult res; nsCOMPtrstartParent; res = aRange->GetStartParent(getter_AddRefs(startParent)); - if ((NS_SUCCEEDED(res)) && startParent) - { - nsCOMPtrparentNode; - nsCOMPtrparentElement; - res = startParent->GetParentNode(getter_AddRefs(parentNode)); - while ((NS_SUCCEEDED(res)) && parentNode) + if (NS_FAILED(res)) return res; + if (!startParent) return NS_ERROR_NULL_POINTER; + + nsCOMPtrparentNode; + nsCOMPtrparentElement; + res = startParent->GetParentNode(getter_AddRefs(parentNode)); + if (NS_FAILED(res)) return res; + + while (parentNode) + { + parentElement = do_QueryInterface(parentNode); + nsAutoString parentTag; + parentElement->GetTagName(parentTag); + PRBool isRoot; + IsRootTag(parentTag, isRoot); + if (aParentTag.EqualsIgnoreCase(parentTag)) { - parentElement = do_QueryInterface(parentNode); - nsAutoString parentTag; - parentElement->GetTagName(parentTag); - PRBool isRoot; - IsRootTag(parentTag, isRoot); - if (aParentTag.EqualsIgnoreCase(parentTag)) + // go through list backwards so deletes don't interfere with the iteration + nsCOMPtr childNodes; + res = parentElement->GetChildNodes(getter_AddRefs(childNodes)); + if (NS_FAILED(res)) return res; + if (!childNodes) return NS_ERROR_NULL_POINTER; + + nsCOMPtrgrandParent; + parentElement->GetParentNode(getter_AddRefs(grandParent)); + PRInt32 offsetInParent; + res = GetChildOffset(parentElement, grandParent, offsetInParent); + if (NS_FAILED(res)) return res; + + PRUint32 childCount; + childNodes->GetLength(&childCount); + PRInt32 i=childCount-1; + for ( ; ((NS_SUCCEEDED(res)) && (0<=i)); i--) { - // go through list backwards so deletes don't interfere with the iteration - nsCOMPtr childNodes; - res = parentElement->GetChildNodes(getter_AddRefs(childNodes)); - if ((NS_SUCCEEDED(res)) && (childNodes)) - { - nsCOMPtrgrandParent; - parentElement->GetParentNode(getter_AddRefs(grandParent)); - PRInt32 offsetInParent; - res = GetChildOffset(parentElement, grandParent, offsetInParent); - PRUint32 childCount; - childNodes->GetLength(&childCount); - PRInt32 i=childCount-1; - for ( ; ((NS_SUCCEEDED(res)) && (0<=i)); i--) - { - nsCOMPtr childNode; - res = childNodes->Item(i, getter_AddRefs(childNode)); - if ((NS_SUCCEEDED(res)) && (childNode)) - { - res = DeleteNode(childNode); - if (NS_SUCCEEDED(res)) { - res = InsertNode(childNode, grandParent, offsetInParent); - } - } - } - if (NS_SUCCEEDED(res)) { - res = DeleteNode(parentElement); - } - } - break; + nsCOMPtr childNode; + res = childNodes->Item(i, getter_AddRefs(childNode)); + if (NS_FAILED(res)) return res; + if (!childNode) return NS_ERROR_NULL_POINTER; + res = DeleteNode(childNode); + if (NS_FAILED(res)) return res; + res = InsertNode(childNode, grandParent, offsetInParent); + if (NS_FAILED(res)) return res; } - else if (PR_TRUE==isRoot) { // hit a local root node, terminate loop - break; - } - res = parentElement->GetParentNode(getter_AddRefs(parentNode)); + res = DeleteNode(parentElement); + if (NS_FAILED(res)) { return res; } + + break; } + else if (PR_TRUE==isRoot) { // hit a local root node, terminate loop + break; + } + res = parentElement->GetParentNode(getter_AddRefs(parentNode)); + if (NS_FAILED(res)) return res; } return res; } @@ -4053,23 +4174,22 @@ PRBool nsHTMLEditor::IsElementInBody(nsIDOMElement* aElement) { nsIDOMElement* bodyElement = nsnull; nsresult res = nsEditor::GetBodyElement(&bodyElement); - if (NS_SUCCEEDED(res) && bodyElement) + if (NS_FAILED(res)) return res; + if (!bodyElement) return NS_ERROR_NULL_POINTER; + nsCOMPtr parent; + nsCOMPtr currentElement = do_QueryInterface(aElement); + if (currentElement) { - nsCOMPtr parent; - nsCOMPtr currentElement = do_QueryInterface(aElement); - if (currentElement) - { - do { - currentElement->GetParentNode(getter_AddRefs(parent)); - if (parent) - { - if (parent == bodyElement) - return PR_TRUE; + do { + currentElement->GetParentNode(getter_AddRefs(parent)); + if (parent) + { + if (parent == bodyElement) + return PR_TRUE; - currentElement = parent; - } - } while(parent); - } + currentElement = parent; + } + } while(parent); } } return PR_FALSE; @@ -4134,7 +4254,7 @@ nsHTMLEditor::SetCaretInTableCell(nsIDOMElement* aElement) // Set selection at beginning of deepest node // Should we set nsCOMPtr selection; - res = nsEditor::GetSelection(getter_AddRefs(selection)); + res = GetSelection(getter_AddRefs(selection)); if (NS_SUCCEEDED(res) && selection) { res = selection->Collapse(parent, offset); @@ -4211,141 +4331,141 @@ nsHTMLEditor::DeleteSelectionAndPrepareToCreateNode(nsCOMPtr &parent nsresult result=NS_ERROR_NOT_INITIALIZED; nsCOMPtr selection; result = GetSelection(getter_AddRefs(selection)); - if ((NS_SUCCEEDED(result)) && selection) + if (NS_FAILED(result)) return result; + if (!selection) return NS_ERROR_NULL_POINTER; + + PRBool collapsed; + result = selection->GetIsCollapsed(&collapsed); + if (NS_SUCCEEDED(result) && !collapsed) { - PRBool collapsed; - result = selection->GetIsCollapsed(&collapsed); - if (NS_SUCCEEDED(result) && !collapsed) - { - result = DeleteSelection(nsIEditor::eDoNothing); - if (NS_FAILED(result)) { - return result; - } - // get the new selection - result = GetSelection(getter_AddRefs(selection)); - if (NS_FAILED(result)) { - return result; - } + result = DeleteSelection(nsIEditor::eDoNothing); + if (NS_FAILED(result)) { + return result; + } + // get the new selection + result = GetSelection(getter_AddRefs(selection)); + if (NS_FAILED(result)) { + return result; + } #ifdef NS_DEBUG - nsCOMPtrtestSelectedNode; - nsresult debugResult = selection->GetAnchorNode(getter_AddRefs(testSelectedNode)); - // no selection is ok. - // if there is a selection, it must be collapsed - if (testSelectedNode) - { - PRBool testCollapsed; - debugResult = selection->GetIsCollapsed(&testCollapsed); - NS_ASSERTION((NS_SUCCEEDED(result)), "couldn't get a selection after deletion"); - NS_ASSERTION(PR_TRUE==testCollapsed, "selection not reset after deletion"); - } -#endif - } - // split the selected node - PRInt32 offsetOfSelectedNode; - result = selection->GetAnchorNode(getter_AddRefs(parentSelectedNode)); - if (NS_SUCCEEDED(result) && NS_SUCCEEDED(selection->GetAnchorOffset(&offsetOfSelectedNode)) && parentSelectedNode) + nsCOMPtrtestSelectedNode; + nsresult debugResult = selection->GetAnchorNode(getter_AddRefs(testSelectedNode)); + // no selection is ok. + // if there is a selection, it must be collapsed + if (testSelectedNode) { - nsCOMPtr selectedNode; - PRUint32 selectedNodeContentCount=0; - nsCOMPtrselectedParentNodeAsText; - selectedParentNodeAsText = do_QueryInterface(parentSelectedNode); + PRBool testCollapsed; + debugResult = selection->GetIsCollapsed(&testCollapsed); + NS_ASSERTION((NS_SUCCEEDED(result)), "couldn't get a selection after deletion"); + NS_ASSERTION(PR_TRUE==testCollapsed, "selection not reset after deletion"); + } +#endif + } + // split the selected node + PRInt32 offsetOfSelectedNode; + result = selection->GetAnchorNode(getter_AddRefs(parentSelectedNode)); + if (NS_SUCCEEDED(result) && NS_SUCCEEDED(selection->GetAnchorOffset(&offsetOfSelectedNode)) && parentSelectedNode) + { + nsCOMPtr selectedNode; + PRUint32 selectedNodeContentCount=0; + nsCOMPtrselectedParentNodeAsText; + selectedParentNodeAsText = do_QueryInterface(parentSelectedNode); - /* if the selection is a text node, split the text node if necesary - and compute where to put the new node - */ - if (selectedParentNodeAsText) - { - PRInt32 indexOfTextNodeInParent; - selectedNode = do_QueryInterface(parentSelectedNode); - selectedNode->GetParentNode(getter_AddRefs(parentSelectedNode)); - selectedParentNodeAsText->GetLength(&selectedNodeContentCount); - GetChildOffset(selectedNode, parentSelectedNode, indexOfTextNodeInParent); + /* if the selection is a text node, split the text node if necesary + and compute where to put the new node + */ + if (selectedParentNodeAsText) + { + PRInt32 indexOfTextNodeInParent; + selectedNode = do_QueryInterface(parentSelectedNode); + selectedNode->GetParentNode(getter_AddRefs(parentSelectedNode)); + selectedParentNodeAsText->GetLength(&selectedNodeContentCount); + GetChildOffset(selectedNode, parentSelectedNode, indexOfTextNodeInParent); - if ((offsetOfSelectedNode!=0) && (((PRUint32)offsetOfSelectedNode)!=selectedNodeContentCount)) - { - nsCOMPtr newSiblingNode; - result = SplitNode(selectedNode, offsetOfSelectedNode, getter_AddRefs(newSiblingNode)); - // now get the node's offset in it's parent, and insert the new tag there - if (NS_SUCCEEDED(result)) { - result = GetChildOffset(selectedNode, parentSelectedNode, offsetOfNewNode); - } - } - else - { // determine where to insert the new node - if (0==offsetOfSelectedNode) { - offsetOfNewNode = indexOfTextNodeInParent; // insert new node as previous sibling to selection parent - } - else { // insert new node as last child - GetChildOffset(selectedNode, parentSelectedNode, offsetOfNewNode); - offsetOfNewNode++; // offsets are 0-based, and we need the index of the new node - } + if ((offsetOfSelectedNode!=0) && (((PRUint32)offsetOfSelectedNode)!=selectedNodeContentCount)) + { + nsCOMPtr newSiblingNode; + result = SplitNode(selectedNode, offsetOfSelectedNode, getter_AddRefs(newSiblingNode)); + // now get the node's offset in it's parent, and insert the new tag there + if (NS_SUCCEEDED(result)) { + result = GetChildOffset(selectedNode, parentSelectedNode, offsetOfNewNode); } } - /* if the selection is not a text node, split the parent node if necesary - and compute where to put the new node - */ - else - { // it's an interior node - nsCOMPtrparentChildList; - parentSelectedNode->GetChildNodes(getter_AddRefs(parentChildList)); - if ((NS_SUCCEEDED(result)) && parentChildList) + else + { // determine where to insert the new node + if (0==offsetOfSelectedNode) { + offsetOfNewNode = indexOfTextNodeInParent; // insert new node as previous sibling to selection parent + } + else { // insert new node as last child + GetChildOffset(selectedNode, parentSelectedNode, offsetOfNewNode); + offsetOfNewNode++; // offsets are 0-based, and we need the index of the new node + } + } + } + /* if the selection is not a text node, split the parent node if necesary + and compute where to put the new node + */ + else + { // it's an interior node + nsCOMPtrparentChildList; + parentSelectedNode->GetChildNodes(getter_AddRefs(parentChildList)); + if ((NS_SUCCEEDED(result)) && parentChildList) + { + result = parentChildList->Item(offsetOfSelectedNode, getter_AddRefs(selectedNode)); + if ((NS_SUCCEEDED(result)) && selectedNode) { - result = parentChildList->Item(offsetOfSelectedNode, getter_AddRefs(selectedNode)); - if ((NS_SUCCEEDED(result)) && selectedNode) + nsCOMPtrselectedNodeAsText; + selectedNodeAsText = do_QueryInterface(selectedNode); + nsCOMPtrchildList; + //CM: I added "result =" + result = selectedNode->GetChildNodes(getter_AddRefs(childList)); + if (NS_SUCCEEDED(result)) { - nsCOMPtrselectedNodeAsText; - selectedNodeAsText = do_QueryInterface(selectedNode); - nsCOMPtrchildList; - //CM: I added "result =" - result = selectedNode->GetChildNodes(getter_AddRefs(childList)); - if (NS_SUCCEEDED(result)) + if (childList) { - if (childList) - { - childList->GetLength(&selectedNodeContentCount); - } - else - { - // This is the case where the collapsed selection offset - // points to an inline node with no children - // This must also be where the new node should be inserted - // and there is no splitting necessary - offsetOfNewNode = offsetOfSelectedNode; - return NS_OK; - } - } + childList->GetLength(&selectedNodeContentCount); + } else { - return NS_ERROR_FAILURE; + // This is the case where the collapsed selection offset + // points to an inline node with no children + // This must also be where the new node should be inserted + // and there is no splitting necessary + offsetOfNewNode = offsetOfSelectedNode; + return NS_OK; } - if ((offsetOfSelectedNode!=0) && (((PRUint32)offsetOfSelectedNode)!=selectedNodeContentCount)) - { - nsCOMPtr newSiblingNode; - result = SplitNode(selectedNode, offsetOfSelectedNode, getter_AddRefs(newSiblingNode)); - // now get the node's offset in it's parent, and insert the new tag there - if (NS_SUCCEEDED(result)) { - result = GetChildOffset(selectedNode, parentSelectedNode, offsetOfNewNode); - } + } + else + { + return NS_ERROR_FAILURE; + } + if ((offsetOfSelectedNode!=0) && (((PRUint32)offsetOfSelectedNode)!=selectedNodeContentCount)) + { + nsCOMPtr newSiblingNode; + result = SplitNode(selectedNode, offsetOfSelectedNode, getter_AddRefs(newSiblingNode)); + // now get the node's offset in it's parent, and insert the new tag there + if (NS_SUCCEEDED(result)) { + result = GetChildOffset(selectedNode, parentSelectedNode, offsetOfNewNode); } - else - { // determine where to insert the new node - if (0==offsetOfSelectedNode) { - offsetOfNewNode = 0; // insert new node as first child - } - else { // insert new node as last child - GetChildOffset(selectedNode, parentSelectedNode, offsetOfNewNode); - offsetOfNewNode++; // offsets are 0-based, and we need the index of the new node - } + } + else + { // determine where to insert the new node + if (0==offsetOfSelectedNode) { + offsetOfNewNode = 0; // insert new node as first child + } + else { // insert new node as last child + GetChildOffset(selectedNode, parentSelectedNode, offsetOfNewNode); + offsetOfNewNode++; // offsets are 0-based, and we need the index of the new node } } } } + } - // Here's where the new node was inserted - } - else { - printf("InsertBreak into an empty document is not yet supported\n"); - } + // Here's where the new node was inserted + } + else { + printf("InsertBreak into an empty document is not yet supported\n"); } return result; } @@ -4384,7 +4504,7 @@ nsCOMPtr nsHTMLEditor::FindPreElement() void nsHTMLEditor::HandleEventListenerError() { - printf("failed to add event listener\n"); + if (gNoisy) { printf("failed to add event listener\n"); } // null out the nsCOMPtrs mKeyListenerP = nsnull; mMouseListenerP = nsnull; @@ -4430,48 +4550,48 @@ nsHTMLEditor::SetTextPropertiesForNode(nsIDOMNode *aNode, { nsCOMPtrnewStyleNode; result = nsEditor::CreateNode(tag, aParent, 0, getter_AddRefs(newStyleNode)); - if (NS_SUCCEEDED(result) && newStyleNode) + if (NS_FAILED(result)) return result; + if (!newStyleNode) return NS_ERROR_NULL_POINTER; + + nsCOMPtrnodeAsChar; + nodeAsChar = do_QueryInterface(aNode); + if (nodeAsChar) { - nsCOMPtrnodeAsChar; - nodeAsChar = do_QueryInterface(aNode); - if (nodeAsChar) - { - result = MoveContentOfNodeIntoNewParent(aNode, newStyleNode, aStartOffset, aEndOffset); - } - else - { // handle non-text selection - nsCOMPtr parent; // used just to make the code easier to understand - nsCOMPtr child; - parent = do_QueryInterface(aNode); - child = GetChildAt(parent, aStartOffset); - // XXX: need to loop for aStartOffset!=aEndOffset-1? - PRInt32 offsetInParent = aStartOffset; // remember where aNode was in aParent - if (NS_SUCCEEDED(result)) - { // remove child from parent - result = nsEditor::DeleteNode(child); + result = MoveContentOfNodeIntoNewParent(aNode, newStyleNode, aStartOffset, aEndOffset); + } + else + { // handle non-text selection + nsCOMPtr parent; // used just to make the code easier to understand + nsCOMPtr child; + parent = do_QueryInterface(aNode); + child = GetChildAt(parent, aStartOffset); + // XXX: need to loop for aStartOffset!=aEndOffset-1? + PRInt32 offsetInParent = aStartOffset; // remember where aNode was in aParent + if (NS_SUCCEEDED(result)) + { // remove child from parent + result = nsEditor::DeleteNode(child); + if (NS_SUCCEEDED(result)) + { // put child into the newStyleNode + result = nsEditor::InsertNode(child, newStyleNode, 0); if (NS_SUCCEEDED(result)) - { // put child into the newStyleNode - result = nsEditor::InsertNode(child, newStyleNode, 0); - if (NS_SUCCEEDED(result)) - { // put newStyleNode in parent where child was - result = nsEditor::InsertNode(newStyleNode, parent, offsetInParent); - } + { // put newStyleNode in parent where child was + result = nsEditor::InsertNode(newStyleNode, parent, offsetInParent); } } } - if (NS_SUCCEEDED(result)) + } + if (NS_SUCCEEDED(result)) + { + if (aAttribute && 0!=aAttribute->Length()) { - if (aAttribute && 0!=aAttribute->Length()) - { - nsCOMPtr newStyleElement; - newStyleElement = do_QueryInterface(newStyleNode); - nsAutoString value; - if (aValue) { - value = *aValue; - } - // XXX should be a call to editor to change attribute! - result = newStyleElement->SetAttribute(*aAttribute, value); + nsCOMPtr newStyleElement; + newStyleElement = do_QueryInterface(newStyleNode); + nsAutoString value; + if (aValue) { + value = *aValue; } + // XXX should be a call to editor to change attribute! + result = newStyleElement->SetAttribute(*aAttribute, value); } } } @@ -4571,13 +4691,12 @@ NS_IMETHODIMP nsHTMLEditor::MoveContentOfNodeIntoNewParent(nsIDOMNode *aNode, if (NS_SUCCEEDED(result)) { // set the selection nsCOMPtrselection; - result = nsEditor::GetSelection(getter_AddRefs(selection)); - if (NS_SUCCEEDED(result)) - { - selection->Collapse(newChildNode, 0); - PRInt32 endOffset = aEndOffset-aStartOffset; - selection->Extend(newChildNode, endOffset); - } + result = GetSelection(getter_AddRefs(selection)); + if (NS_FAILED(result)) return result; + if (!selection) return NS_ERROR_NULL_POINTER; + selection->Collapse(newChildNode, 0); + PRInt32 endOffset = aEndOffset-aStartOffset; + selection->Extend(newChildNode, endOffset); } } } @@ -4603,54 +4722,50 @@ nsHTMLEditor::SetTextPropertiesForNodesWithSameParent(nsIDOMNode *aStartNode, const nsString *aAttribute, const nsString *aValue) { - if (gNoisy) { printf("nsTextEditor::SetTextPropertiesForNodesWithSameParent\n"); } + if (gNoisy) { printf("---------- start nsTextEditor::SetTextPropertiesForNodesWithSameParent ----------\n"); } nsresult result=NS_OK; PRBool textPropertySet; nsCOMPtrresultNode; IsTextPropertySetByContent(aStartNode, aPropName, aAttribute, aValue, textPropertySet, getter_AddRefs(resultNode)); if (PR_FALSE==textPropertySet) { - if (aValue && 0!=aValue->Length()) - { - result = RemoveTextPropertiesForNodesWithSameParent(aStartNode, aStartOffset, - aEndNode, aEndOffset, - aParent, aPropName, aAttribute); - } + result = RemoveTextPropertiesForNodeWithDifferentParents(aStartNode, aStartOffset, + aEndNode, aEndOffset, + aParent, aPropName, aAttribute); + if (NS_FAILED(result)) return result; + nsAutoString tag; aPropName->ToString(tag); // create the new style node, which will be the new parent for the selected nodes nsCOMPtrnewStyleNode; nsCOMPtrdoc; result = GetDocument(getter_AddRefs(doc)); - if (NS_SUCCEEDED(result) && doc) + if (NS_FAILED(result)) return result; + if (!doc) return NS_ERROR_NULL_POINTER; + + nsCOMPtrnewElement; + result = doc->CreateElement(tag, getter_AddRefs(newElement)); + if (NS_FAILED(result)) return result; + if (!newElement) return NS_ERROR_NULL_POINTER; + + newStyleNode = do_QueryInterface(newElement); + if (!newStyleNode) return NS_ERROR_NULL_POINTER; + result = MoveContiguousContentIntoNewParent(aStartNode, aStartOffset, aEndNode, aEndOffset, aParent, newStyleNode); + if (NS_SUCCEEDED(result) && aAttribute && 0!=aAttribute->Length()) { - nsCOMPtrnewElement; - result = doc->CreateElement(tag, getter_AddRefs(newElement)); - if (NS_SUCCEEDED(result) && newElement) - { - newStyleNode = do_QueryInterface(newElement); - } - } - if (NS_SUCCEEDED(result) && newStyleNode) - { - result = MoveContiguousContentIntoNewParent(aStartNode, aStartOffset, aEndNode, aEndOffset, aParent, newStyleNode); - if (NS_SUCCEEDED(result) && aAttribute && 0!=aAttribute->Length()) - { - nsCOMPtr newStyleElement; - newStyleElement = do_QueryInterface(newStyleNode); - nsAutoString value; - if (aValue) { - value = *aValue; - } - result = newStyleElement->SetAttribute(*aAttribute, value); + nsCOMPtr newStyleElement; + newStyleElement = do_QueryInterface(newStyleNode); + nsAutoString value; + if (aValue) { + value = *aValue; } + result = newStyleElement->SetAttribute(*aAttribute, value); } } + if (gNoisy) { printf("---------- end nsTextEditor::SetTextPropertiesForNodesWithSameParent ----------\n"); } return result; } -//XXX won't work for selections that are not leaf nodes! -// should fix up the end points to make sure they are leaf nodes NS_IMETHODIMP nsHTMLEditor::MoveContiguousContentIntoNewParent(nsIDOMNode *aStartNode, PRInt32 aStartOffset, @@ -4660,7 +4775,8 @@ nsHTMLEditor::MoveContiguousContentIntoNewParent(nsIDOMNode *aStartNode, nsIDOMNode *aNewParentNode) { if (!aStartNode || !aEndNode || !aNewParentNode) { return NS_ERROR_NULL_POINTER; } - if (gNoisy) { printf("nsTextEditor::MoveContiguousContentIntoNewParent\n"); } + if (gNoisy) { printf("--- start nsTextEditor::MoveContiguousContentIntoNewParent ---\n"); } + if (gNoisy) {DebugDumpContent(); } // DEBUG nsresult result = NS_OK; nsCOMPtrstartNode, endNode; @@ -4676,6 +4792,7 @@ nsHTMLEditor::MoveContiguousContentIntoNewParent(nsIDOMNode *aStartNode, { result = nsEditor::SplitNode(aStartNode, aStartOffset, getter_AddRefs(newLeftNode)); if (gNoisy) { printf("split aStartNode, newLeftNode = %p\n", newLeftNode.get()); } + if (gNoisy) {DebugDumpContent(); } // DEBUG } else { if (gNoisy) { printf("did not split aStartNode\n"); } @@ -4698,6 +4815,7 @@ nsHTMLEditor::MoveContiguousContentIntoNewParent(nsIDOMNode *aStartNode, { result = nsEditor::SplitNode(aEndNode, aEndOffset, getter_AddRefs(newRightNode)); if (gNoisy) { printf("split aEndNode, newRightNode = %p\n", newRightNode.get()); } + if (gNoisy) {DebugDumpContent(); } // DEBUG } else { newRightNode = do_QueryInterface(aEndNode); @@ -4726,6 +4844,8 @@ nsHTMLEditor::MoveContiguousContentIntoNewParent(nsIDOMNode *aStartNode, { // insert aNewParentNode into aGrandParentNode result = nsEditor::InsertNode(aNewParentNode, aGrandParentNode, offsetInParent); + if (gNoisy) printf("just after InsertNode 1\n"); + if (gNoisy) {DebugDumpContent(); } // DEBUG if (NS_SUCCEEDED(result)) { // move the right half of the start node into the new parent node nsCOMPtrintermediateNode; @@ -4733,10 +4853,14 @@ nsHTMLEditor::MoveContiguousContentIntoNewParent(nsIDOMNode *aStartNode, if (NS_SUCCEEDED(result)) { result = nsEditor::DeleteNode(startNode); + if (gNoisy) printf("just after DeleteNode 1\n"); + if (gNoisy) {DebugDumpContent(); } // DEBUG if (NS_SUCCEEDED(result)) { PRInt32 childIndex=0; result = nsEditor::InsertNode(startNode, aNewParentNode, childIndex); + if (gNoisy) printf("just after InsertNode 2\n"); + if (gNoisy) {DebugDumpContent(); } // DEBUG childIndex++; if (NS_SUCCEEDED(result)) { // move all the intermediate nodes into the new parent node @@ -4751,8 +4875,13 @@ nsHTMLEditor::MoveContiguousContentIntoNewParent(nsIDOMNode *aStartNode, // get the next sibling before moving the current child!!! intermediateNode->GetNextSibling(getter_AddRefs(nextSibling)); result = nsEditor::DeleteNode(intermediateNode); - if (NS_SUCCEEDED(result)) { + if (gNoisy) printf("just after DeleteNode 3\n"); + if (gNoisy) {DebugDumpContent(); } // DEBUG + if (NS_SUCCEEDED(result)) + { result = nsEditor::InsertNode(intermediateNode, aNewParentNode, childIndex); + if (gNoisy) printf("just after InsertNode 4\n"); + if (gNoisy) {DebugDumpContent(); } // DEBUG childIndex++; } intermediateNode = do_QueryInterface(nextSibling); @@ -4760,19 +4889,22 @@ nsHTMLEditor::MoveContiguousContentIntoNewParent(nsIDOMNode *aStartNode, if (NS_SUCCEEDED(result)) { // move the left half of the end node into the new parent node result = nsEditor::DeleteNode(newRightNode); + if (gNoisy) printf("just after DeleteNode 5\n"); + if (gNoisy) {DebugDumpContent(); } // DEBUG if (NS_SUCCEEDED(result)) { result = nsEditor::InsertNode(newRightNode, aNewParentNode, childIndex); + if (gNoisy) printf("just after InsertNode 5\n"); + if (gNoisy) {DebugDumpContent(); } // DEBUG // now set the selection if (NS_SUCCEEDED(result)) { nsCOMPtrselection; - result = nsEditor::GetSelection(getter_AddRefs(selection)); - if (NS_SUCCEEDED(result)) - { - selection->Collapse(startNode, startOffset); - selection->Extend(newRightNode, endOffset); - } + result = GetSelection(getter_AddRefs(selection)); + if (NS_FAILED(result)) return result; + if (!selection) return NS_ERROR_NULL_POINTER; + selection->Collapse(startNode, startOffset); + selection->Extend(newRightNode, endOffset); } } } @@ -4783,6 +4915,8 @@ nsHTMLEditor::MoveContiguousContentIntoNewParent(nsIDOMNode *aStartNode, } } } + if (gNoisy) { printf("--- end nsTextEditor::MoveContiguousContentIntoNewParent ---\n"); } + if (gNoisy) {DebugDumpContent(); } // DEBUG return result; } @@ -4822,7 +4956,7 @@ nsHTMLEditor::SetTextPropertiesForNodeWithDifferentParents(nsIDOMRange *aRange, // RemoveTextProperties... might have changed selection endpoints, get new ones nsCOMPtrselection; - result = nsEditor::GetSelection(getter_AddRefs(selection)); + result = GetSelection(getter_AddRefs(selection)); if (NS_FAILED(result)) { return result; } if (!selection) { return NS_ERROR_NULL_POINTER; } selection->GetAnchorOffset(&aStartOffset); @@ -4832,164 +4966,174 @@ nsHTMLEditor::SetTextPropertiesForNodeWithDifferentParents(nsIDOMRange *aRange, nsCOMPtriter; result = nsComponentManager::CreateInstance(kCContentIteratorCID, nsnull, nsIContentIterator::GetIID(), getter_AddRefs(iter)); - if ((NS_SUCCEEDED(result)) && iter) + if (NS_FAILED(result)) return result; + if (!iter) return NS_ERROR_NULL_POINTER; + + // find our starting point + PRBool startIsText = IsTextNode(aStartNode); + nsCOMPtrstartContent; + if (PR_TRUE==startIsText) { + startContent = do_QueryInterface(aStartNode); + } + else { + nsCOMPtrnode = GetChildAt(aStartNode, aStartOffset); + startContent = do_QueryInterface(node); + } + + // find our ending point + PRBool endIsText = IsTextNode(aEndNode); + nsCOMPtrendContent; + if (PR_TRUE==endIsText) { + endContent = do_QueryInterface(aEndNode); + } + else { - // find our starting point - PRBool startIsText = IsTextNode(aStartNode); - nsCOMPtrstartContent; - if (PR_TRUE==startIsText) { - startContent = do_QueryInterface(aStartNode); + nsCOMPtrtheEndNode; + if (aEndOffset>0) + { + theEndNode = GetChildAt(aEndNode, aEndOffset-1); } else { - nsCOMPtrnode = GetChildAt(aStartNode, aStartOffset); - startContent = do_QueryInterface(node); + // XXX: we need to find the previous node and set the selection correctly + NS_ASSERTION(0, "unexpected selection"); + return NS_ERROR_NOT_IMPLEMENTED; } + endContent = do_QueryInterface(theEndNode); + } - // find our ending point - PRBool endIsText = IsTextNode(aEndNode); - nsCOMPtrendContent; - if (PR_TRUE==endIsText) { - endContent = do_QueryInterface(aEndNode); - } - else + if (!startContent || !endContent) { return NS_ERROR_NULL_POINTER; } + // iterate over the nodes between the starting and ending points + iter->Init(aRange); + nsCOMPtr content; + iter->CurrentNode(getter_AddRefs(content)); + nsAutoString tag; + aPropName->ToString(tag); + while (NS_COMFALSE == iter->IsDone()) + { + if ((content.get() != startContent.get()) && + (content.get() != endContent.get())) { - nsCOMPtrtheEndNode; - if (aEndOffset>0) + nsCOMPtrnode; + node = do_QueryInterface(content); + if (IsEditable(node)) { - theEndNode = GetChildAt(aEndNode, aEndOffset-1); - } - else { - // XXX: we need to find the previous node and set the selection correctly - NS_ASSERTION(0, "unexpected selection"); - return NS_ERROR_NOT_IMPLEMENTED; - } - endContent = do_QueryInterface(theEndNode); - } - - if (!startContent || !endContent) { return NS_ERROR_NULL_POINTER; } - // iterate over the nodes between the starting and ending points - iter->Init(aRange); - nsCOMPtr content; - iter->CurrentNode(getter_AddRefs(content)); - nsAutoString tag; - aPropName->ToString(tag); - while (NS_COMFALSE == iter->IsDone()) - { - if ((content.get() != startContent.get()) && - (content.get() != endContent.get())) - { - nsCOMPtrnode; - node = do_QueryInterface(content); - if (IsEditable(node)) - { - PRBool canContainChildren; - content->CanContainChildren(canContainChildren); - if (PR_FALSE==canContainChildren) - { - nsEditor::GetTagString(node,tag); - if (tag != "br") // skip
, even though it's a leaf - { // only want to wrap the text node in a new style node if it doesn't already have that style - if (gNoisy) { printf("node %p is an editable leaf.\n", node.get()); } - PRBool textPropertySet; - nsCOMPtrresultNode; - IsTextPropertySetByContent(node, aPropName, aAttribute, aValue, textPropertySet, getter_AddRefs(resultNode)); - if (PR_FALSE==textPropertySet) + PRBool canContainChildren; + content->CanContainChildren(canContainChildren); + if (PR_FALSE==canContainChildren) + { + nsEditor::GetTagString(node,tag); + if (tag != "br") // skip
, even though it's a leaf + { // only want to wrap the text node in a new style node if it doesn't already have that style + if (gNoisy) { printf("node %p is an editable leaf.\n", node.get()); } + PRBool textPropertySet; + nsCOMPtrresultNode; + IsTextPropertySetByContent(node, aPropName, aAttribute, aValue, textPropertySet, getter_AddRefs(resultNode)); + if (PR_FALSE==textPropertySet) + { + if (gNoisy) { printf("property not set\n"); } + node->GetParentNode(getter_AddRefs(parent)); + if (!parent) { return NS_ERROR_NULL_POINTER; } + nsCOMPtrparentContent; + parentContent = do_QueryInterface(parent); + nsCOMPtrparentNode = do_QueryInterface(parent); + if (PR_TRUE==IsTextNode(node)) { - if (gNoisy) { printf("property not set\n"); } - node->GetParentNode(getter_AddRefs(parent)); - if (!parent) { return NS_ERROR_NULL_POINTER; } - nsCOMPtrparentContent; - parentContent = do_QueryInterface(parent); - nsCOMPtrparentNode = do_QueryInterface(parent); - if (PR_TRUE==IsTextNode(node)) - { - startOffset = 0; - result = GetLengthOfDOMNode(node, (PRUint32&)endOffset); - } - else - { - parentContent->IndexOf(content, startOffset); - endOffset = startOffset+1; - } - if (gNoisy) { printf("start/end = %d %d\n", startOffset, endOffset); } - if (NS_SUCCEEDED(result)) { - result = SetTextPropertiesForNode(node, parentNode, startOffset, endOffset, aPropName, aAttribute, aValue); - } + startOffset = 0; + result = GetLengthOfDOMNode(node, (PRUint32&)endOffset); + } + else + { + parentContent->IndexOf(content, startOffset); + endOffset = startOffset+1; + } + if (gNoisy) { printf("start/end = %d %d\n", startOffset, endOffset); } + if (NS_SUCCEEDED(result)) { + result = SetTextPropertiesForNode(node, parentNode, startOffset, endOffset, aPropName, aAttribute, aValue); } } } } - // XXX: shouldn't there be an else here for non-text leaf nodes? } - // note we don't check the result, we just rely on iter->IsDone - iter->Next(); - iter->CurrentNode(getter_AddRefs(content)); + // XXX: shouldn't there be an else here for non-text leaf nodes? } - // handle endpoints + // note we don't check the result, we just rely on iter->IsDone + iter->Next(); + iter->CurrentNode(getter_AddRefs(content)); + } + // handle endpoints + if (NS_SUCCEEDED(result)) + { + // create a style node for the text in the start parent + nsCOMPtrstartNode = do_QueryInterface(startContent); + result = startNode->GetParentNode(getter_AddRefs(parent)); + if (NS_FAILED(result)) return result; + if (!parent) return NS_ERROR_NULL_POINTER; + + nsCOMPtrnodeAsChar; + nodeAsChar = do_QueryInterface(startNode); + if (nodeAsChar) + { + nodeAsChar->GetLength(&count); + if (gNoisy) { printf("processing start node %p.\n", nodeAsChar.get()); } + if (aStartOffset!=(PRInt32)count) + { + result = SetTextPropertiesForNode(startNode, parent, aStartOffset, count, aPropName, aAttribute, aValue); + startOffset = 0; + } + } + else + { + nsCOMPtrgrandParent; + result = parent->GetParentNode(getter_AddRefs(grandParent)); + if (NS_FAILED(result)) return result; + if (!grandParent) return NS_ERROR_NULL_POINTER; + if (gNoisy) { printf("processing start node %p.\n", parent.get()); } + result = SetTextPropertiesForNode(parent, grandParent, aStartOffset, aStartOffset+1, aPropName, aAttribute, aValue); + startNode = do_QueryInterface(parent); + startOffset = aStartOffset; + } + + if (NS_SUCCEEDED(result)) { - // create a style node for the text in the start parent - nsCOMPtrstartNode = do_QueryInterface(startContent); - result = startNode->GetParentNode(getter_AddRefs(parent)); + // create a style node for the text in the end parent + nsCOMPtrendNode = do_QueryInterface(endContent); + result = endNode->GetParentNode(getter_AddRefs(parent)); if (NS_FAILED(result)) { return result; } - nsCOMPtrnodeAsChar; - nodeAsChar = do_QueryInterface(startNode); + nodeAsChar = do_QueryInterface(endNode); if (nodeAsChar) - { + { nodeAsChar->GetLength(&count); - if (gNoisy) { printf("processing start node %p.\n", nodeAsChar.get()); } - result = SetTextPropertiesForNode(startNode, parent, aStartOffset, count, aPropName, aAttribute, aValue); - startOffset = 0; + if (gNoisy) { printf("processing end node %p.\n", nodeAsChar.get()); } + if (0!=aEndOffset) + { + result = SetTextPropertiesForNode(endNode, parent, 0, aEndOffset, aPropName, aAttribute, aValue); + // SetTextPropertiesForNode kindly computed the proper selection focus node and offset for us, + // remember them here + selection->GetFocusOffset(&endOffset); + selection->GetFocusNode(getter_AddRefs(endNode)); + } } else { + NS_ASSERTION(0!=aEndOffset, "unexpected selection end offset"); + if (0==aEndOffset) { return NS_ERROR_NOT_IMPLEMENTED; } nsCOMPtrgrandParent; result = parent->GetParentNode(getter_AddRefs(grandParent)); - if (gNoisy) { printf("processing start node %p.\n", parent.get()); } - result = SetTextPropertiesForNode(parent, grandParent, aStartOffset, aStartOffset+1, aPropName, aAttribute, aValue); - startNode = do_QueryInterface(parent); - startOffset = aStartOffset; + if (NS_FAILED(result)) return result; + if (!grandParent) return NS_ERROR_NULL_POINTER; + if (gNoisy) { printf("processing end node %p.\n", parent.get()); } + result = SetTextPropertiesForNode(parent, grandParent, aEndOffset-1, aEndOffset, aPropName, aAttribute, aValue); + endNode = do_QueryInterface(parent); + endOffset = 0; } - - if (NS_SUCCEEDED(result)) { - // create a style node for the text in the end parent - nsCOMPtrendNode = do_QueryInterface(endContent); - result = endNode->GetParentNode(getter_AddRefs(parent)); - if (NS_FAILED(result)) { - return result; - } - nodeAsChar = do_QueryInterface(endNode); - if (nodeAsChar) - { - nodeAsChar->GetLength(&count); - if (gNoisy) { printf("processing end node %p.\n", nodeAsChar.get()); } - result = SetTextPropertiesForNode(endNode, parent, 0, aEndOffset, aPropName, aAttribute, aValue); - // SetTextPropertiesForNode kindly computed the proper selection focus node and offset for us, - // remember them here - selection->GetFocusOffset(&endOffset); - selection->GetFocusNode(getter_AddRefs(endNode)); - } - else - { - NS_ASSERTION(0!=aEndOffset, "unexpected selection end offset"); - if (0==aEndOffset) { return NS_ERROR_NOT_IMPLEMENTED; } - nsCOMPtrgrandParent; - result = parent->GetParentNode(getter_AddRefs(grandParent)); - if (gNoisy) { printf("processing end node %p.\n", parent.get()); } - result = SetTextPropertiesForNode(parent, grandParent, aEndOffset-1, aEndOffset, aPropName, aAttribute, aValue); - endNode = do_QueryInterface(parent); - endOffset = 0; - } - if (NS_SUCCEEDED(result)) - { - selection->Collapse(startNode, startOffset); - selection->Extend(endNode, aEndOffset); - } + selection->Collapse(startNode, startOffset); + selection->Extend(endNode, aEndOffset); } } } @@ -5222,79 +5366,8 @@ nsHTMLEditor::RemoveTextPropertiesForNodesWithSameParent(nsIDOMNode *aStartNode, nsIAtom *aPropName, const nsString *aAttribute) { - if (gNoisy) { printf("nsTextEditor::RemoveTextPropertiesForNodesWithSameParent\n"); } - nsresult result=NS_OK; - PRInt32 startOffset = aStartOffset; - PRInt32 endOffset; - nsCOMPtrnodeAsChar; - nsCOMPtrparentNode = do_QueryInterface(aParent); - - // remove aPropName from all intermediate nodes - nsCOMPtrsiblingNode; - nsCOMPtrnextSiblingNode; // temp to hold the next node in the list - result = aStartNode->GetNextSibling(getter_AddRefs(siblingNode)); - while (siblingNode && NS_SUCCEEDED(result)) - { - // get next sibling right away, before we move siblingNode! - siblingNode->GetNextSibling(getter_AddRefs(nextSiblingNode)); - if (aEndNode==siblingNode.get()) { // found the end node, handle that below - break; - } - else - { // found a sibling node between aStartNode and aEndNode, remove the style node - PRUint32 childCount=0; - nodeAsChar = do_QueryInterface(siblingNode); - if (nodeAsChar) { - nodeAsChar->GetLength(&childCount); - } - else - { - nsCOMPtrgrandChildNodes; - result = siblingNode->GetChildNodes(getter_AddRefs(grandChildNodes)); - if (NS_SUCCEEDED(result) && grandChildNodes) { - grandChildNodes->GetLength(&childCount); - } - if (0==childCount) - { // node has no children - // XXX: for now, I think that's ok. just pass in 0 - } - } - if (NS_SUCCEEDED(result)) { - siblingNode->GetParentNode(getter_AddRefs(parentNode)); - result = RemoveTextPropertiesForNode(siblingNode, parentNode, 0, childCount, aPropName, aAttribute); - } - } - siblingNode = do_QueryInterface(nextSiblingNode); - } - if (NS_SUCCEEDED(result)) - { - // remove aPropName from aStartNode - //nsCOMPtrnodeAsChar; - nodeAsChar = do_QueryInterface(aStartNode); - if (nodeAsChar) { - nodeAsChar->GetLength((PRUint32 *)&endOffset); - } - else - { - if (gNoisy) { printf("not yet supported\n");} - return NS_ERROR_NOT_IMPLEMENTED; - } - result = aStartNode->GetParentNode(getter_AddRefs(parentNode)); - if (NS_SUCCEEDED(result)) { - result = RemoveTextPropertiesForNode(aStartNode, parentNode, startOffset, endOffset, aPropName, aAttribute); - } - } - if (NS_SUCCEEDED(result)) - { - // remove aPropName from the end node - startOffset = 0; - endOffset = aEndOffset; - result = aEndNode->GetParentNode(getter_AddRefs(parentNode)); - if (NS_SUCCEEDED(result)) { - result = RemoveTextPropertiesForNode(aEndNode, parentNode, startOffset, endOffset, aPropName, aAttribute); - } - } - return result; + NS_ASSERTION(0, "obsolete"); + return NS_ERROR_NOT_IMPLEMENTED; } NS_IMETHODIMP @@ -5306,7 +5379,7 @@ nsHTMLEditor::RemoveTextPropertiesForNodeWithDifferentParents(nsIDOMNode *aStar nsIAtom *aPropName, const nsString *aAttribute) { - if (gNoisy) { printf("start nsTextEditor::RemoveTextPropertiesForNodeWithDifferentParents\n"); } + if (gNoisy) { printf("----- start nsTextEditor::RemoveTextPropertiesForNodeWithDifferentParents-----\n"); } nsresult result=NS_OK; if (!aStartNode || !aEndNode || !aParent || !aPropName) return NS_ERROR_NULL_POINTER; @@ -5323,6 +5396,7 @@ nsHTMLEditor::RemoveTextPropertiesForNodeWithDifferentParents(nsIDOMNode *aStar nsCOMPtrendNode = do_QueryInterface(aEndNode); // use computed endpoint based on end points passed in nsCOMPtrparent; // the parent of the node we're operating on PRBool skippedStartNode = PR_FALSE; // we skip the start node if aProp is not set on it + PRBool skippedEndNode = PR_FALSE; // we skip the end node if aProp is not set on it PRUint32 count; nsCOMPtrnodeAsChar; nodeAsChar = do_QueryInterface(startNode); @@ -5377,7 +5451,8 @@ nsHTMLEditor::RemoveTextPropertiesForNodeWithDifferentParents(nsIDOMNode *aStar if (nodeAsChar) { result = endNode->GetParentNode(getter_AddRefs(parent)); - if (NS_FAILED(result)) { return result; } + if (NS_FAILED(result)) return result; + if (!parent) return NS_ERROR_NULL_POINTER; nodeAsChar->GetLength(&count); if (aEndOffset!=0) { // only do this if at least one child is selected @@ -5385,20 +5460,37 @@ nsHTMLEditor::RemoveTextPropertiesForNodeWithDifferentParents(nsIDOMNode *aStar if (PR_TRUE==textPropertySet) { result = RemoveTextPropertiesForNode(endNode, parent, 0, aEndOffset, aPropName, aAttribute); - if (0!=aEndOffset) { + if (0!=aEndOffset && (((PRInt32)count)!=aEndOffset)) { rangeEndOffset = 0; // we split endNode at aEndOffset and it is the right node now } } - else { if (gNoisy) { printf("skipping end node because aProperty not set.\n"); } } + else + { + skippedEndNode = PR_TRUE; + if (gNoisy) { printf("skipping end node because aProperty not set.\n"); } + } } - else { if (gNoisy) { printf("skipping end node because aEndOffset==0\n"); } } + else + { + skippedEndNode = PR_TRUE; + if (gNoisy) { printf("skipping end node because aEndOffset==0\n"); } + } } else { endNode = GetChildAt(aEndNode, aEndOffset); parent = do_QueryInterface(aEndNode); if (!endNode || !parent) {return NS_ERROR_NULL_POINTER;} - result = RemoveTextPropertiesForNode(endNode, parent, aEndOffset, aEndOffset+1, aPropName, aAttribute); + IsTextPropertySetByContent(endNode, aPropName, aAttribute, nsnull, textPropertySet, getter_AddRefs(resultNode)); + if (PR_TRUE==textPropertySet) + { + result = RemoveTextPropertiesForNode(endNode, parent, aEndOffset, aEndOffset+1, aPropName, aAttribute); + } + else + { + skippedEndNode = PR_TRUE; + if (gNoisy) { printf("skipping end node because property not set\n"); } + } } } @@ -5433,42 +5525,42 @@ nsHTMLEditor::RemoveTextPropertiesForNodeWithDifferentParents(nsIDOMNode *aStar nsCOMPtriter; result = nsComponentManager::CreateInstance(kCContentIteratorCID, nsnull, nsIContentIterator::GetIID(), getter_AddRefs(iter)); - if ((NS_SUCCEEDED(result)) && iter) + if (NS_FAILED(result)) return result; + if (!iter) return NS_ERROR_NULL_POINTER; + + nsCOMPtrstartContent; + startContent = do_QueryInterface(startNode); + nsCOMPtrendContent; + endContent = do_QueryInterface(endNode); + if (startContent && endContent) { - nsCOMPtrstartContent; - startContent = do_QueryInterface(startNode); - nsCOMPtrendContent; - endContent = do_QueryInterface(endNode); - if (startContent && endContent) + iter->Init(range); + nsCOMPtr content; + iter->CurrentNode(getter_AddRefs(content)); + nsAutoString propName; // the property we are removing + aPropName->ToString(propName); + while (NS_COMFALSE == iter->IsDone()) { - iter->Init(range); - nsCOMPtr content; - iter->CurrentNode(getter_AddRefs(content)); - nsAutoString propName; // the property we are removing - aPropName->ToString(propName); - while (NS_COMFALSE == iter->IsDone()) + if ((content.get() != startContent.get()) && + (content.get() != endContent.get())) { - if ((content.get() != startContent.get()) && - (content.get() != endContent.get())) + nsCOMPtrelement; + element = do_QueryInterface(content); + if (element) { - nsCOMPtrelement; - element = do_QueryInterface(content); - if (element) + nsString tag; + element->GetTagName(tag); + if (propName.EqualsIgnoreCase(tag)) { - nsString tag; - element->GetTagName(tag); - if (propName.EqualsIgnoreCase(tag)) - { - if (-1==nodeList.IndexOf(content.get())) { - nodeList.AppendElement((void *)(content.get())); - } + if (-1==nodeList.IndexOf(content.get())) { + nodeList.AppendElement((void *)(content.get())); } } } - // note we don't check the result, we just rely on iter->IsDone - iter->Next(); - iter->CurrentNode(getter_AddRefs(content)); } + // note we don't check the result, we just rely on iter->IsDone + iter->Next(); + iter->CurrentNode(getter_AddRefs(content)); } } @@ -5505,7 +5597,6 @@ nsHTMLEditor::RemoveTextPropertiesForNodeWithDifferentParents(nsIDOMNode *aStar if (gNoisy) { printf("deleted next sibling node %p\n", childNode.get()); - DebugDumpContent(); // DEBUG } } childNode = do_QueryInterface(previousSiblingNode); @@ -5515,7 +5606,6 @@ nsHTMLEditor::RemoveTextPropertiesForNodeWithDifferentParents(nsIDOMNode *aStar if (gNoisy) { printf("deleted style node %p\n", styleNode.get()); - DebugDumpContent(); // DEBUG } } } @@ -5526,20 +5616,209 @@ nsHTMLEditor::RemoveTextPropertiesForNodeWithDifferentParents(nsIDOMNode *aStar } } nsCOMPtrselection; - result = nsEditor::GetSelection(getter_AddRefs(selection)); - if (NS_SUCCEEDED(result)) - { - selection->Collapse(startNode, rangeStartOffset); - selection->Extend(endNode, rangeEndOffset); - if (gNoisy) { printf("RTPFNWDP set selection.\n"); } - } + result = GetSelection(getter_AddRefs(selection)); + if (NS_FAILED(result)) return result; + if (!selection) return NS_ERROR_NULL_POINTER; + + // set the sel. start point. if we skipped the start node, just use it + if (PR_TRUE==skippedStartNode) + startNode = do_QueryInterface(aStartNode); + result = selection->Collapse(startNode, rangeStartOffset); + if (NS_FAILED(result)) return result; + + // set the sel. end point. if we skipped the end node, just use it + if (PR_TRUE==skippedEndNode) + endNode = do_QueryInterface(aEndNode); + result = selection->Extend(endNode, rangeEndOffset); + if (NS_FAILED(result)) return result; + if (gNoisy) { printf("RTPFNWDP set selection.\n"); } } if (gNoisy) { - printf("end nsTextEditor::RemoveTextPropertiesForNodeWithDifferentParents, dumping content...\n"); + printf("----- end nsTextEditor::RemoveTextPropertiesForNodeWithDifferentParents, dumping content...-----\n"); DebugDumpContent(); } return result; } +/* this method scans the selection for adjacent text nodes and collapses them into a single text node + * "adjacent" means literally adjacent siblings of the same parent + * In all cases, the content of the right text node is moved into + * the left node, and the right node is deleted. + * Uses nsEditor::JoinNodes so action is undoable. Should be called within the context of a batch transaction + */ + /* + XXX: TODO: use a helper function of next/prev sibling that only deals with editable content + */ +NS_IMETHODIMP +nsHTMLEditor::CollapseAdjacentTextNodes(nsIDOMSelection *aInSelection) +{ + if (gNoisy) + { + printf("---------- start nsTextEditor::CollapseAdjacentTextNodes ----------\n"); + DebugDumpContent(); + } + if (!aInSelection) return NS_ERROR_NULL_POINTER; + + nsVoidArray textNodes; // we can't actually do anything during iteration, so store the text nodes in an array + // don't bother ref counting them because we know we can hold them for the + // lifetime of this method + + PRBool isCollapsed; + aInSelection->GetIsCollapsed(&isCollapsed); + if (PR_TRUE==isCollapsed) { return NS_OK; } // no need to scan collapsed selection + + // store info about selection endpoints so we can re-establish selection after collapsing text nodes + // XXX: won't work for multiple selections (this will create a single selection from anchor to focus) + nsCOMPtr parentForSelection; // selection's block parent + PRInt32 rangeStartOffset, rangeEndOffset; // selection offsets + nsresult result = GetTextSelectionOffsetsForRange(aInSelection, getter_AddRefs(parentForSelection), + rangeStartOffset, rangeEndOffset); + if (NS_FAILED(result)) return result; + if (!parentForSelection) return NS_ERROR_NULL_POINTER; + + // first, do the endpoints of the selection, so we don't rely on the iteration to include them + nsCOMPtranchor, focus; + nsCOMPtranchorText, focusText; + aInSelection->GetAnchorNode(getter_AddRefs(anchor)); + anchorText = do_QueryInterface(anchor); + if (anchorText) + { + textNodes.AppendElement((void*)(anchorText.get())); + } + aInSelection->GetFocusNode(getter_AddRefs(focus)); + focusText = do_QueryInterface(focus); + + // for all the ranges in the selection, build a list of text nodes + nsCOMPtr enumerator; + result = aInSelection->GetEnumerator(getter_AddRefs(enumerator)); + if (NS_FAILED(result)) return result; + if (!enumerator) return NS_ERROR_NULL_POINTER; + + enumerator->First(); + nsCOMPtr currentItem; + result = enumerator->CurrentItem(getter_AddRefs(currentItem)); + if (NS_FAILED(result)) return result; + if (!currentItem) return NS_OK; // there are no ranges in the selection, so nothing to do + + while ((NS_COMFALSE == enumerator->IsDone())) + { + nsCOMPtr range( do_QueryInterface(currentItem) ); + nsCOMPtr iter; + result = nsComponentManager::CreateInstance(kCContentIteratorCID, nsnull, + nsIContentIterator::GetIID(), + getter_AddRefs(iter)); + if (NS_FAILED(result)) return result; + if (!iter) return NS_ERROR_NULL_POINTER; + + iter->Init(range); + nsCOMPtr content; + result = iter->CurrentNode(getter_AddRefs(content)); + while (NS_COMFALSE == iter->IsDone()) + { + nsCOMPtr text = do_QueryInterface(content); + if (text && anchorText.get() != text.get() && focusText.get() != text.get()) + { + textNodes.AppendElement((void*)(text.get())); + } + iter->Next(); + iter->CurrentNode(getter_AddRefs(content)); + } + enumerator->Next(); + enumerator->CurrentItem(getter_AddRefs(currentItem)); + } + // now add the focus to the list, if it's a text node + if (focusText) + { + textNodes.AppendElement((void*)(focusText.get())); + } + + + // now that I have a list of text nodes, collapse adjacent text nodes + PRInt32 count = textNodes.Count(); + const PRInt32 initialCount = count; + while (1 prevSiblingOfLeftTextNode; + result = leftTextNode->GetPreviousSibling(getter_AddRefs(prevSiblingOfLeftTextNode)); + if (NS_FAILED(result)) return result; + if (prevSiblingOfLeftTextNode) + { + nsCOMPtrprevSiblingAsText = do_QueryInterface(prevSiblingOfLeftTextNode); + if (prevSiblingAsText) + { + nsCOMPtr parent; + result = leftTextNode->GetParentNode(getter_AddRefs(parent)); + if (NS_FAILED(result)) return result; + if (!parent) return NS_ERROR_NULL_POINTER; + result = JoinNodes(prevSiblingOfLeftTextNode, leftTextNode, parent); + if (NS_FAILED(result)) return result; + } + } + } + + // get the prev sibling of the right node, and see if it's leftTextNode + nsCOMPtr prevSiblingOfRightTextNode; + result = rightTextNode->GetPreviousSibling(getter_AddRefs(prevSiblingOfRightTextNode)); + if (NS_FAILED(result)) return result; + if (prevSiblingOfRightTextNode) + { + nsCOMPtrprevSiblingAsText = do_QueryInterface(prevSiblingOfRightTextNode); + if (prevSiblingAsText) + { + if (prevSiblingAsText.get()==leftTextNode) + { + nsCOMPtr parent; + result = rightTextNode->GetParentNode(getter_AddRefs(parent)); + if (NS_FAILED(result)) return result; + if (!parent) return NS_ERROR_NULL_POINTER; + result = JoinNodes(leftTextNode, rightTextNode, parent); + if (NS_FAILED(result)) return result; + } + } + } + + // special case: check next sibling of the rightmost text node + if (2==count) + { + nsCOMPtr nextSiblingOfRightTextNode; + result = rightTextNode->GetNextSibling(getter_AddRefs(nextSiblingOfRightTextNode)); + if (NS_FAILED(result)) return result; + if (nextSiblingOfRightTextNode) + { + nsCOMPtrnextSiblingAsText = do_QueryInterface(nextSiblingOfRightTextNode); + if (nextSiblingAsText) + { + nsCOMPtr parent; + result = rightTextNode->GetParentNode(getter_AddRefs(parent)); + if (NS_FAILED(result)) return result; + if (!parent) return NS_ERROR_NULL_POINTER; + result = JoinNodes(rightTextNode, nextSiblingOfRightTextNode, parent); + if (NS_FAILED(result)) return result; + } + } + } + + // remove the rightmost remaining text node from the array and work our way towards the beginning + textNodes.RemoveElementAt(0); // remove the leftmost text node from the list + count --; + } + + ResetTextSelectionForRange(parentForSelection, rangeStartOffset, rangeEndOffset, aInSelection); + + if (gNoisy) + { + printf("---------- end nsTextEditor::CollapseAdjacentTextNodes ----------\n"); + DebugDumpContent(); + } + + return result; +} diff --git a/editor/libeditor/html/nsHTMLEditor.h b/editor/libeditor/html/nsHTMLEditor.h index 90f448548c38..debfd5ecb8e9 100644 --- a/editor/libeditor/html/nsHTMLEditor.h +++ b/editor/libeditor/html/nsHTMLEditor.h @@ -192,7 +192,15 @@ protected: virtual void InitRules(); - NS_IMETHOD GetLayoutObject(nsIDOMNode *aNode, nsISupports **aLayoutObject); + /** returns the layout object (nsIFrame in the real world) for aNode + * @param aNode the content to get a frame for + * @param aLayoutObject the "primary frame" for aNode, if one exists. May be null + * @return NS_OK whether a frame is found or not + * an error if some serious error occurs + */ + NS_IMETHOD GetLayoutObject(nsIDOMNode *aInNode, nsISupports **aOutLayoutObject); + + NS_IMETHOD CollapseAdjacentTextNodes(nsIDOMSelection *aInSelection); NS_IMETHOD DeleteSelectionAndPrepareToCreateNode(nsCOMPtr &parentSelectedNode, PRInt32& offsetOfNewNode); @@ -382,10 +390,10 @@ protected: const nsString *aAttribute, const nsString *aValue); - void GetTextSelectionOffsetsForRange(nsIDOMSelection *aSelection, - nsIDOMNode **aParent, - PRInt32 &aStartOffset, - PRInt32 &aEndOffset); + NS_IMETHOD GetTextSelectionOffsetsForRange(nsIDOMSelection *aSelection, + nsIDOMNode **aParent, + PRInt32 &aStartOffset, + PRInt32 &aEndOffset); void ResetTextSelectionForRange(nsIDOMNode *aParent, PRInt32 aStartOffset, diff --git a/editor/libeditor/text/nsEditorEventListeners.cpp b/editor/libeditor/text/nsEditorEventListeners.cpp index 7ac517663e53..72a44858842d 100644 --- a/editor/libeditor/text/nsEditorEventListeners.cpp +++ b/editor/libeditor/text/nsEditorEventListeners.cpp @@ -47,12 +47,18 @@ #include "nsIDragSession.h" #include "nsITransferable.h" #include "nsIFormatConverter.h" +#include "nsIContentIterator.h" +#include "nsIContent.h" +#include "nsLayoutCID.h" // Drag & Drop, Clipboard Support static NS_DEFINE_CID(kCDragServiceCID, NS_DRAGSERVICE_CID); static NS_DEFINE_CID(kCTransferableCID, NS_TRANSFERABLE_CID); static NS_DEFINE_IID(kCDataFlavorCID, NS_DATAFLAVOR_CID); -static NS_DEFINE_IID(kCXIFFormatConverterCID, NS_XIFFORMATCONVERTER_CID); +static NS_DEFINE_IID(kContentIteratorCID, NS_CONTENTITERATOR_CID); +static NS_DEFINE_CID(kCClipboardCID, NS_CLIPBOARD_CID); +static NS_DEFINE_IID(kCXIFConverterCID, NS_XIFFORMATCONVERTER_CID); + /* @@ -116,8 +122,7 @@ nsresult nsTextEditorKeyListener::KeyDown(nsIDOMEvent* aKeyEvent) { PRUint32 keyCode; - PRBool isShift; - PRBool ctrlKey; + PRBool isShift, ctrlKey, altKey, metaKey; nsCOMPtruiEvent; uiEvent = do_QueryInterface(aKeyEvent); @@ -126,87 +131,87 @@ nsTextEditorKeyListener::KeyDown(nsIDOMEvent* aKeyEvent) return NS_OK; } - if (NS_SUCCEEDED(uiEvent->GetKeyCode(&keyCode)) && - NS_SUCCEEDED(uiEvent->GetShiftKey(&isShift)) && - NS_SUCCEEDED(uiEvent->GetCtrlKey(&ctrlKey)) - ) { - PRBool keyProcessed; - ProcessShortCutKeys(aKeyEvent, keyProcessed); - if (PR_FALSE==keyProcessed) - { - switch(keyCode) { -// case nsIDOMUIEvent::VK_BACK: -// mEditor->DeleteSelection(nsIEditor::eDeleteLeft); -// break; + PRBool keyProcessed; + ProcessShortCutKeys(aKeyEvent, keyProcessed); + if (PR_FALSE==keyProcessed) + { + if (NS_SUCCEEDED(uiEvent->GetKeyCode(&keyCode)) && + NS_SUCCEEDED(uiEvent->GetShiftKey(&isShift)) && + NS_SUCCEEDED(uiEvent->GetCtrlKey(&ctrlKey)) && + NS_SUCCEEDED(uiEvent->GetAltKey(&altKey)) && + NS_SUCCEEDED(uiEvent->GetMetaKey(&metaKey))) + { + { + switch(keyCode) { + // case nsIDOMUIEvent::VK_BACK: + // mEditor->DeleteSelection(nsIEditor::eDeleteLeft); + // break; - case nsIDOMUIEvent::VK_DELETE: - mEditor->DeleteSelection(nsIEditor::eDeleteNext); - break; + case nsIDOMUIEvent::VK_DELETE: + mEditor->DeleteSelection(nsIEditor::eDeleteNext); + break; -// case nsIDOMUIEvent::VK_RETURN: - //case nsIDOMUIEvent::VK_ENTER: // why does this not exist? - // Need to implement creation of either

or
nodes. -// mEditor->InsertBreak(); -// break; + // case nsIDOMUIEvent::VK_RETURN: + //case nsIDOMUIEvent::VK_ENTER: // why does this not exist? + // Need to implement creation of either

or
nodes. + // mEditor->InsertBreak(); + // break; - case nsIDOMUIEvent::VK_LEFT: - case nsIDOMUIEvent::VK_RIGHT: - case nsIDOMUIEvent::VK_UP: - case nsIDOMUIEvent::VK_DOWN: - // these have already been handled in nsRangeList. Why are we getting them - // again here (Mac)? In switch to avoid putting in bogus chars. + case nsIDOMUIEvent::VK_LEFT: + case nsIDOMUIEvent::VK_RIGHT: + case nsIDOMUIEvent::VK_UP: + case nsIDOMUIEvent::VK_DOWN: + // these have already been handled in nsRangeList. Why are we getting them + // again here (Mac)? In switch to avoid putting in bogus chars. - //return NS_OK to allow page scrolling. - return NS_OK; - break; + //return NS_OK to allow page scrolling. + return NS_OK; + break; - case nsIDOMUIEvent::VK_HOME: - case nsIDOMUIEvent::VK_END: - // who handles these? -#if DEBUG - printf("Key not handled\n"); -#endif - return NS_OK; - break; + case nsIDOMUIEvent::VK_HOME: + case nsIDOMUIEvent::VK_END: + // who handles these? + #if DEBUG + printf("Key not handled\n"); + #endif + return NS_OK; + break; - case nsIDOMUIEvent::VK_PAGE_UP: - case nsIDOMUIEvent::VK_PAGE_DOWN: - //return NS_OK to allow page scrolling. - return NS_OK; - break; + case nsIDOMUIEvent::VK_PAGE_UP: + case nsIDOMUIEvent::VK_PAGE_DOWN: + //return NS_OK to allow page scrolling. + return NS_OK; + break; - case nsIDOMUIEvent::VK_TAB: - { - PRUint32 flags=0; - mEditor->GetFlags(&flags); - if (! (flags & nsIHTMLEditor::eEditorSingleLineMask)) - { - PRBool ctrlKey, altKey, metaKey; - uiEvent->GetCtrlKey(&ctrlKey); - uiEvent->GetAltKey(&altKey); - uiEvent->GetMetaKey(&metaKey); - if (metaKey || altKey) - return NS_OK; // don't consume - // else we insert the tab straight through - nsAutoString key; - key += keyCode; + case nsIDOMUIEvent::VK_TAB: + { + PRUint32 flags=0; + mEditor->GetFlags(&flags); + if (! (flags & nsIHTMLEditor::eEditorSingleLineMask)) + { + if (metaKey || altKey) + return NS_OK; // don't consume + // else we insert the tab straight through + nsAutoString key; + key += keyCode; - nsCOMPtr htmlEditor = do_QueryInterface(mEditor); - if (htmlEditor) - htmlEditor->InsertText(key); - return NS_ERROR_BASE; // this means "I handled the event, don't do default processing" - } - else { - return NS_OK; - } - break; - } + nsCOMPtr htmlEditor = do_QueryInterface(mEditor); + if (htmlEditor) + htmlEditor->InsertText(key); + return NS_ERROR_BASE; // this means "I handled the event, don't do default processing" + } + else { + return NS_OK; + } + break; + } - default: - return NS_OK; // this indicates that we have not handled the keyDown event in any way. - } - } - } + default: + return NS_OK; // this indicates that we have not handled the keyDown event in any way. + } + } + } + } return NS_ERROR_BASE; } @@ -238,19 +243,20 @@ nsTextEditorKeyListener::KeyPress(nsIDOMEvent* aKeyEvent) // eaiser // - PRBool ctrlKey, altKey, metaKey; - uiEvent->GetCtrlKey(&ctrlKey); - uiEvent->GetAltKey(&altKey); - uiEvent->GetMetaKey(&metaKey); - if (metaKey) - return NS_OK; // don't consume - - nsCOMPtr htmlEditor = do_QueryInterface(mEditor); - if (!htmlEditor) return NS_ERROR_NO_INTERFACE; - + PRBool ctrlKey, altKey, metaKey; + uiEvent->GetCtrlKey(&ctrlKey); + uiEvent->GetAltKey(&altKey); + uiEvent->GetMetaKey(&metaKey); + + if (metaKey) + return NS_OK; // don't consume + + nsCOMPtr htmlEditor = do_QueryInterface(mEditor); + if (!htmlEditor) return NS_ERROR_NO_INTERFACE; + if (NS_SUCCEEDED(uiEvent->GetKeyCode(&keyCode))) { - if (nsIDOMUIEvent::VK_BACK==keyCode) { + if (nsIDOMUIEvent::VK_BACK==keyCode) { mEditor->DeleteSelection(nsIEditor::eDeletePrevious); return NS_ERROR_BASE; // consumed } @@ -261,14 +267,14 @@ nsTextEditorKeyListener::KeyPress(nsIDOMEvent* aKeyEvent) } if ((PR_FALSE==altKey) && (PR_FALSE==ctrlKey) && - (NS_SUCCEEDED(uiEvent->GetCharCode(&character)))) + (NS_SUCCEEDED(uiEvent->GetCharCode(&character)))) { - if (nsIDOMUIEvent::VK_TAB==character) { - return NS_OK; // ignore tabs here, they're handled in keyDown if at all - } + if (nsIDOMUIEvent::VK_TAB==character) { + return NS_OK; // ignore tabs here, they're handled in keyDown if at all + } key += character; htmlEditor->InsertText(key); - } + } return NS_ERROR_BASE; // consumed @@ -843,6 +849,62 @@ nsTextEditorMouseListener::HandleEvent(nsIDOMEvent* aEvent) +// XXX: evil global functions, move them to proper support module + +nsresult +IsNodeInSelection(nsIDOMNode *aInNode, nsIDOMSelection *aInSelection, PRBool &aOutIsInSel) +{ + aOutIsInSel = PR_FALSE; // init out-param + if (!aInNode || !aInSelection) { return NS_ERROR_NULL_POINTER; } + + nsCOMPtriter; + nsresult result = nsComponentManager::CreateInstance(kContentIteratorCID, nsnull, + nsIContentIterator::GetIID(), + getter_AddRefs(iter)); + if (NS_FAILED(result)) { return result; } + if (!iter) { return NS_ERROR_OUT_OF_MEMORY; } + + nsCOMPtr enumerator; + result = aInSelection->GetEnumerator(getter_AddRefs(enumerator)); + if (NS_FAILED(result)) { return result; } + if (!enumerator) { return NS_ERROR_OUT_OF_MEMORY; } + + for (enumerator->First(); NS_OK!=enumerator->IsDone(); enumerator->Next()) + { + nsCOMPtr currentItem; + result = enumerator->CurrentItem(getter_AddRefs(currentItem)); + if ((NS_SUCCEEDED(result)) && (currentItem)) + { + nsCOMPtr range( do_QueryInterface(currentItem) ); + + iter->Init(range); + nsCOMPtr currentContent; + iter->CurrentNode(getter_AddRefs(currentContent)); + while (NS_COMFALSE == iter->IsDone()) + { + nsCOMPtrcurrentNode = do_QueryInterface(currentContent); + if (currentNode.get()==aInNode) + { + // if it's a start or end node, need to test whether the (x,y) + // of the event falls within the selection + + // talk to Mike + + aOutIsInSel = PR_TRUE; + return NS_OK; + } + /* do not check result here, and especially do not return the result code. + * we rely on iter->IsDone to tell us when the iteration is complete + */ + iter->Next(); + iter->CurrentNode(getter_AddRefs(currentContent)); + } + } + } + return NS_OK; +} + + nsresult nsTextEditorMouseListener::MouseDown(nsIDOMEvent* aMouseEvent) { @@ -856,49 +918,141 @@ nsTextEditorMouseListener::MouseDown(nsIDOMEvent* aMouseEvent) return NS_OK; } - // We only do anything special for middle-mouse click (paste); - // ignore all other events. + nsCOMPtr editor (do_QueryInterface(mEditor)); + if (!editor) { return NS_OK; } + + + // get the document + nsCOMPtrdomDoc; + editor->GetDocument(getter_AddRefs(domDoc)); + if (!domDoc) { return NS_OK; } + nsCOMPtrdoc = do_QueryInterface(domDoc); + if (!doc) { return NS_OK; } + PRUint16 button = 0; uiEvent->GetButton(&button); - if (button != 2) - return NS_OK; + // left button click might be a drag-start + if (1==button) + { +#ifndef EXPERIMENTAL_DRAG_CODE + return NS_OK; +#else + nsString XIFBuffer; + // get the DOM select here + nsCOMPtr sel; + editor->GetSelection(getter_AddRefs(sel)); + + // convert the DOMselection to XIF + if (sel) + { + // if we are within the selection, start the drag - nsCOMPtr editor (do_QueryInterface(mEditor)); - if (!editor) - return NS_ERROR_FAILURE; + nsCOMPtr target; + nsresult rv = aMouseEvent->GetTarget(getter_AddRefs(target)); + if (NS_FAILED(rv) || !target) { return NS_OK; } + PRBool isInSel; + rv = IsNodeInSelection(target, sel, isInSel); + if (NS_FAILED(rv) || PR_FALSE==isInSel) { return NS_OK; } + doc->CreateXIF(XIFBuffer, sel); - // Set the selection to the point under the mouse cursor: - nsCOMPtr mouseEvent (do_QueryInterface(aMouseEvent)); + // Get the Clipboard + nsIClipboard* clipboard; + rv = nsServiceManager::GetService(kCClipboardCID, + nsIClipboard::GetIID(), + (nsISupports **)&clipboard); + if (NS_OK == rv) + { + // Create a data flavor to tell the transferable + // that it is about to receive XIF + nsAutoString flavor(kXIFMime); - if (!mouseEvent) - return NS_ERROR_BASE; // NS_ERROR_BASE means "We did process the event". - nsCOMPtr parent; - if (!NS_SUCCEEDED(mouseEvent->GetRangeParent(getter_AddRefs(parent)))) - return NS_ERROR_BASE; // NS_ERROR_BASE means "We did process the event". - PRInt32 offset = 0; - if (!NS_SUCCEEDED(mouseEvent->GetRangeOffset(&offset))) - return NS_ERROR_BASE; // NS_ERROR_BASE means "We did process the event". + // Create a transferable for putting data on the Clipboard + nsCOMPtr trans; + rv = nsComponentManager::CreateInstance(kCTransferableCID, nsnull, + nsITransferable::GetIID(), + (void**) getter_AddRefs(trans)); + if (NS_OK == rv) { + // The data on the clipboard will be in "XIF" format + // so give the clipboard transferable a "XIFConverter" for + // converting from XIF to other formats + nsCOMPtr xifConverter; + rv = nsComponentManager::CreateInstance(kCXIFConverterCID, nsnull, + nsIFormatConverter::GetIID(), (void**) getter_AddRefs(xifConverter)); + if (NS_OK == rv) { + // Add the XIF DataFlavor to the transferable + // this tells the transferable that it can handle receiving the XIF format + trans->AddDataFlavor(&flavor); - nsCOMPtr selection; - if (NS_SUCCEEDED(editor->GetSelection(getter_AddRefs(selection)))) - (void)selection->Collapse(parent, offset); + // Add the converter for going from XIF to other formats + trans->SetConverter(xifConverter); - // If the ctrl key is pressed, we'll do paste as quotation. - // Would've used the alt key, but the kde wmgr treats alt-middle specially. - PRBool ctrlKey = PR_FALSE; - uiEvent->GetCtrlKey(&ctrlKey); + // Now add the XIF data to the transferable + // the transferable wants the number bytes for the data and since it is double byte + // we multiply by 2 + trans->SetTransferData(&flavor, XIFBuffer.ToNewUnicode(), XIFBuffer.Length()*2); - if (ctrlKey) - { - nsCOMPtr mailEditor = do_QueryInterface(mEditor); - if (mailEditor) - mailEditor->PasteAsQuotation(); + // Now invoke the drag session + nsIDragService* dragService; + nsresult rv = nsServiceManager::GetService(kCDragServiceCID, + nsIDragService::GetIID(), + (nsISupports **)&dragService); + if (NS_OK == rv) { + nsCOMPtr items; + NS_NewISupportsArray(getter_AddRefs(items)); + if ( items ) { + items->AppendElement(trans); + dragService->InvokeDragSession(items, nsnull, nsIDragService::DRAGDROP_ACTION_COPY | nsIDragService::DRAGDROP_ACTION_MOVE); + } + nsServiceManager::ReleaseService(kCDragServiceCID, dragService); + } + } + } + nsServiceManager::ReleaseService(kCClipboardCID, clipboard); + } + return NS_ERROR_BASE; // return that we've handled the event + } +#endif } - return editor->Paste(); + // middle-mouse click (paste); + else if (button == 2) + { + + // Set the selection to the point under the mouse cursor: + nsCOMPtr mouseEvent (do_QueryInterface(aMouseEvent)); + + if (!mouseEvent) + return NS_ERROR_BASE; // NS_ERROR_BASE means "We did process the event". + nsCOMPtr parent; + if (!NS_SUCCEEDED(mouseEvent->GetRangeParent(getter_AddRefs(parent)))) + return NS_ERROR_BASE; // NS_ERROR_BASE means "We did process the event". + PRInt32 offset = 0; + if (!NS_SUCCEEDED(mouseEvent->GetRangeOffset(&offset))) + return NS_ERROR_BASE; // NS_ERROR_BASE means "We did process the event". + + nsCOMPtr selection; + if (NS_SUCCEEDED(editor->GetSelection(getter_AddRefs(selection)))) + (void)selection->Collapse(parent, offset); + + // If the ctrl key is pressed, we'll do paste as quotation. + // Would've used the alt key, but the kde wmgr treats alt-middle specially. + PRBool ctrlKey = PR_FALSE; + uiEvent->GetCtrlKey(&ctrlKey); + + if (ctrlKey) + { + nsCOMPtr mailEditor = do_QueryInterface(mEditor); + if (mailEditor) + mailEditor->PasteAsQuotation(); + } + editor->Paste(); + return NS_ERROR_BASE; // NS_ERROR_BASE means "We did process the event". + } + return NS_OK; // did not process the event } + nsresult nsTextEditorMouseListener::MouseUp(nsIDOMEvent* aMouseEvent) { @@ -1425,9 +1579,6 @@ nsTextEditorFocusListener::HandleEvent(nsIDOMEvent* aEvent) nsresult nsTextEditorFocusListener::Focus(nsIDOMEvent* aEvent) { - // turn on selection and caret - if (mEditor) - { // turn on selection and caret if (mEditor) { @@ -1474,8 +1625,6 @@ nsTextEditorFocusListener::Focus(nsIDOMEvent* aEvent) } return NS_OK; } - return NS_OK; -} nsresult nsTextEditorFocusListener::Blur(nsIDOMEvent* aEvent) diff --git a/editor/libeditor/text/nsTextEditRules.cpp b/editor/libeditor/text/nsTextEditRules.cpp index f8044504665f..65b8f0be0c04 100644 --- a/editor/libeditor/text/nsTextEditRules.cpp +++ b/editor/libeditor/text/nsTextEditRules.cpp @@ -104,11 +104,10 @@ nsTextEditRules::SetFlags(PRUint32 aFlags) // put a "white-space: pre" style on the body nsCOMPtr bodyElement; nsresult res = mEditor->GetBodyElement(getter_AddRefs(bodyElement)); - if (NS_SUCCEEDED(res) && bodyElement) - { - // not going through the editor to do this. - bodyElement->SetAttribute("style", "white-space: pre"); - } + if (NS_FAILED(res)) return res; + if (!bodyElement) return NS_ERROR_NULL_POINTER; + // not going through the editor to do this. + bodyElement->SetAttribute("style", "white-space: pre"); } } mFlags = aFlags; @@ -394,7 +393,9 @@ nsTextEditRules::CreateStyleForInsertText(nsIDOMSelection *aSelection, TypeInSta // splitting anchor twice sets newTextNode as an empty text node between // two halves of the original text node result = mEditor->SplitNode(anchorAsText, offset, getter_AddRefs(newTextNode)); - result = mEditor->SplitNode(anchorAsText, 0, getter_AddRefs(newTextNode)); + if (NS_SUCCEEDED(result)) { + result = mEditor->SplitNode(anchorAsText, 0, getter_AddRefs(newTextNode)); + } } } // now we have the new text node we are going to insert into. @@ -464,37 +465,30 @@ nsTextEditRules::CreateStyleForInsertText(nsIDOMSelection *aSelection, TypeInSta } else // we have no selection, so insert a style tag in the body { - nsCOMPtrdoc; - mEditor->GetDocument(getter_AddRefs(doc)); - nsCOMPtrnodeList; - nsAutoString bodyTag = "body"; - result = doc->GetElementsByTagName(bodyTag, getter_AddRefs(nodeList)); - if ((NS_SUCCEEDED(result)) && nodeList) - { - PRUint32 count; - nodeList->GetLength(&count); - NS_ASSERTION(1==count, "there is not exactly 1 body in the document!"); - nsCOMPtrbodyNode; - result = nodeList->Item(0, getter_AddRefs(bodyNode)); - if ((NS_SUCCEEDED(result)) && bodyNode) - { // now we've got the body tag. insert the style tag - if (aTypeInState.IsSet(NS_TYPEINSTATE_BOLD)) - { - if (PR_TRUE==aTypeInState.GetBold()) { - InsertStyleAndNewTextNode(bodyNode, nsIEditProperty::b, aSelection); - } + nsCOMPtr bodyElement; + nsresult res = mEditor->GetBodyElement(getter_AddRefs(bodyElement)); + if (NS_FAILED(res)) return res; + if (!bodyElement) return NS_ERROR_NULL_POINTER; + + nsCOMPtrbodyNode = do_QueryInterface(bodyElement); + if (bodyNode) + { // now we've got the body tag. insert the style tag + if (aTypeInState.IsSet(NS_TYPEINSTATE_BOLD)) + { + if (PR_TRUE==aTypeInState.GetBold()) { + InsertStyleAndNewTextNode(bodyNode, nsIEditProperty::b, aSelection); } - if (aTypeInState.IsSet(NS_TYPEINSTATE_ITALIC)) - { - if (PR_TRUE==aTypeInState.GetItalic()) { - InsertStyleAndNewTextNode(bodyNode, nsIEditProperty::i, aSelection); - } + } + if (aTypeInState.IsSet(NS_TYPEINSTATE_ITALIC)) + { + if (PR_TRUE==aTypeInState.GetItalic()) { + InsertStyleAndNewTextNode(bodyNode, nsIEditProperty::i, aSelection); } - if (aTypeInState.IsSet(NS_TYPEINSTATE_UNDERLINE)) - { - if (PR_TRUE==aTypeInState.GetUnderline()) { - InsertStyleAndNewTextNode(bodyNode, nsIEditProperty::u, aSelection); - } + } + if (aTypeInState.IsSet(NS_TYPEINSTATE_UNDERLINE)) + { + if (PR_TRUE==aTypeInState.GetUnderline()) { + InsertStyleAndNewTextNode(bodyNode, nsIEditProperty::u, aSelection); } } } @@ -513,12 +507,11 @@ nsTextEditRules::CreateFontStyleForInsertText(nsIDOMNode *aNewTextNode, if (0!=aValue.Length()) { result = InsertStyleNode(aNewTextNode, nsIEditProperty::font, aSelection, getter_AddRefs(newStyleNode)); - if (NS_SUCCEEDED(result) && newStyleNode) - { - nsCOMPtrelement = do_QueryInterface(newStyleNode); - if (element) { - result = mEditor->SetAttribute(element, aAttr, aValue); - } + if (NS_FAILED(result)) return result; + if (!newStyleNode) return NS_ERROR_NULL_POINTER; + nsCOMPtrelement = do_QueryInterface(newStyleNode); + if (element) { + result = mEditor->SetAttribute(element, aAttr, aValue); } } else @@ -540,21 +533,26 @@ nsTextEditRules::InsertStyleNode(nsIDOMNode *aNode, nsresult result; nsCOMPtrparent; aNode->GetParentNode(getter_AddRefs(parent)); + if (NS_FAILED(result)) return result; + if (!parent) return NS_ERROR_NULL_POINTER; + PRInt32 offsetInParent; - nsEditor::GetChildOffset(aNode, parent, offsetInParent); + result = nsEditor::GetChildOffset(aNode, parent, offsetInParent); + if (NS_FAILED(result)) return result; + nsAutoString tag; aTag->ToString(tag); result = mEditor->CreateNode(tag, parent, offsetInParent, aNewNode); - if ((NS_SUCCEEDED(result)) && *aNewNode) + if (NS_FAILED(result)) return result; + if (!aNewNode) return NS_ERROR_NULL_POINTER; + + result = mEditor->DeleteNode(aNode); + if (NS_SUCCEEDED(result)) { - result = mEditor->DeleteNode(aNode); - if (NS_SUCCEEDED(result)) - { - result = mEditor->InsertNode(aNode, *aNewNode, 0); - if (NS_SUCCEEDED(result)) { - if (aSelection) { - aSelection->Collapse(aNode, 0); - } + result = mEditor->InsertNode(aNode, *aNewNode, 0); + if (NS_SUCCEEDED(result)) { + if (aSelection) { + result = aSelection->Collapse(aNode, 0); } } } @@ -575,16 +573,17 @@ nsTextEditRules::InsertStyleAndNewTextNode(nsIDOMNode *aParentNode, nsIAtom *aTa nsCOMPtranchor; PRInt32 offset; result = aSelection->GetAnchorNode(getter_AddRefs(anchor)); - if (NS_SUCCEEDED(result) && NS_SUCCEEDED(aSelection->GetAnchorOffset(&offset)) && anchor) + if (NS_FAILED(result)) return result; + if (!anchor) return NS_ERROR_NULL_POINTER; + result = aSelection->GetAnchorOffset(&offset); + if (NS_FAILED(result)) return result; + nsCOMPtranchorAsText; + anchorAsText = do_QueryInterface(anchor); + if (anchorAsText) { - nsCOMPtranchorAsText; - anchorAsText = do_QueryInterface(anchor); - if (anchorAsText) - { - nsCOMPtr newStyleNode; - result = InsertStyleNode(anchor, aTag, aSelection, getter_AddRefs(newStyleNode)); - return result; - } + nsCOMPtr newStyleNode; + result = InsertStyleNode(anchor, aTag, aSelection, getter_AddRefs(newStyleNode)); + return result; } } // if we get here, there is no selected text node so we create one. @@ -593,15 +592,15 @@ nsTextEditRules::InsertStyleAndNewTextNode(nsIDOMNode *aParentNode, nsIAtom *aTa nsCOMPtrnewStyleNode; nsCOMPtrnewTextNode; result = mEditor->CreateNode(tag, aParentNode, 0, getter_AddRefs(newStyleNode)); - if (NS_SUCCEEDED(result)) - { - result = mEditor->CreateNode(nsEditor::GetTextNodeTag(), newStyleNode, 0, getter_AddRefs(newTextNode)); - if (NS_SUCCEEDED(result)) - { - if (aSelection) { - aSelection->Collapse(newTextNode, 0); - } - } + if (NS_FAILED(result)) return result; + if (!newStyleNode) return NS_ERROR_NULL_POINTER; + + result = mEditor->CreateNode(nsEditor::GetTextNodeTag(), newStyleNode, 0, getter_AddRefs(newTextNode)); + if (NS_FAILED(result)) return result; + if (!newTextNode) return NS_ERROR_NULL_POINTER; + + if (aSelection) { + result = aSelection->Collapse(newTextNode, 0); } return result; } @@ -707,55 +706,63 @@ nsTextEditRules::DidDeleteSelection(nsIDOMSelection *aSelection, nsCOMPtranchor; PRInt32 offset; result = aSelection->GetAnchorNode(getter_AddRefs(anchor)); - if (NS_SUCCEEDED(result) && NS_SUCCEEDED(aSelection->GetAnchorOffset(&offset)) && anchor) + if (NS_FAILED(result)) return result; + if (!anchor) return NS_ERROR_NULL_POINTER; + result = aSelection->GetAnchorOffset(&offset); + if (NS_FAILED(result)) return result; + + nsCOMPtr anchorChildren; + result = anchor->GetChildNodes(getter_AddRefs(anchorChildren)); + nsCOMPtr selectedNode; + if ((NS_SUCCEEDED(result)) && anchorChildren) { + result = anchorChildren->Item(offset, getter_AddRefs(selectedNode)); + } + else { + selectedNode = do_QueryInterface(anchor); + } + if ((NS_SUCCEEDED(result)) && selectedNode) { - nsCOMPtr anchorChildren; - result = anchor->GetChildNodes(getter_AddRefs(anchorChildren)); - nsCOMPtr selectedNode; - if ((NS_SUCCEEDED(result)) && anchorChildren) { - result = anchorChildren->Item(offset, getter_AddRefs(selectedNode)); - } - else { - selectedNode = do_QueryInterface(anchor); - } - if ((NS_SUCCEEDED(result)) && selectedNode) + nsCOMPtrselectedNodeAsText; + selectedNodeAsText = do_QueryInterface(selectedNode); + if (selectedNodeAsText) { - nsCOMPtrselectedNodeAsText; - selectedNodeAsText = do_QueryInterface(selectedNode); - if (selectedNodeAsText) + nsCOMPtr siblingNode; + selectedNode->GetPreviousSibling(getter_AddRefs(siblingNode)); + if (siblingNode) { - nsCOMPtr siblingNode; - selectedNode->GetPreviousSibling(getter_AddRefs(siblingNode)); - if (siblingNode) + nsCOMPtrsiblingNodeAsText; + siblingNodeAsText = do_QueryInterface(siblingNode); + if (siblingNodeAsText) { - nsCOMPtrsiblingNodeAsText; - siblingNodeAsText = do_QueryInterface(siblingNode); - if (siblingNodeAsText) - { - PRUint32 siblingLength; // the length of siblingNode before the join - siblingNodeAsText->GetLength(&siblingLength); - nsCOMPtr parentNode; - selectedNode->GetParentNode(getter_AddRefs(parentNode)); - result = mEditor->JoinNodes(siblingNode, selectedNode, parentNode); - // selectedNode will remain after the join, siblingNode is removed - } + PRUint32 siblingLength; // the length of siblingNode before the join + siblingNodeAsText->GetLength(&siblingLength); + nsCOMPtr parentNode; + result = selectedNode->GetParentNode(getter_AddRefs(parentNode)); + if (NS_FAILED(result)) return result; + if (!parentNode) return NS_ERROR_NULL_POINTER; + result = mEditor->JoinNodes(siblingNode, selectedNode, parentNode); + // selectedNode will remain after the join, siblingNode is removed } - selectedNode->GetNextSibling(getter_AddRefs(siblingNode)); - if (siblingNode) + } + selectedNode->GetNextSibling(getter_AddRefs(siblingNode)); + if (siblingNode) + { + nsCOMPtrsiblingNodeAsText; + siblingNodeAsText = do_QueryInterface(siblingNode); + if (siblingNodeAsText) { - nsCOMPtrsiblingNodeAsText; - siblingNodeAsText = do_QueryInterface(siblingNode); - if (siblingNodeAsText) - { - PRUint32 selectedNodeLength; // the length of siblingNode before the join - selectedNodeAsText->GetLength(&selectedNodeLength); - nsCOMPtr parentNode; - selectedNode->GetParentNode(getter_AddRefs(parentNode)); - result = mEditor->JoinNodes(selectedNode, siblingNode, parentNode); - // selectedNode will remain after the join, siblingNode is removed - // set selection - aSelection->Collapse(siblingNode, selectedNodeLength); - } + PRUint32 selectedNodeLength; // the length of siblingNode before the join + selectedNodeAsText->GetLength(&selectedNodeLength); + nsCOMPtr parentNode; + result = selectedNode->GetParentNode(getter_AddRefs(parentNode)); + if (NS_FAILED(result)) return result; + if (!parentNode) return NS_ERROR_NULL_POINTER; + + result = mEditor->JoinNodes(selectedNode, siblingNode, parentNode); + if (NS_FAILED(result)) return result; + // selectedNode will remain after the join, siblingNode is removed + // set selection + result = aSelection->Collapse(siblingNode, selectedNodeLength); } } } @@ -795,23 +802,24 @@ nsTextEditRules:: DidUndo(nsIDOMSelection *aSelection, nsresult aResult) nsCOMPtrnode; PRInt32 offset; result = aSelection->GetAnchorNode(getter_AddRefs(node)); - if (NS_SUCCEEDED(result) && NS_SUCCEEDED(aSelection->GetAnchorOffset(&offset)) && node) + if (NS_FAILED(result)) return result; + if (!node) return NS_ERROR_NULL_POINTER; + result = aSelection->GetAnchorOffset(&offset); + if (NS_FAILED(result)) return result; + nsCOMPtrelement; + element = do_QueryInterface(node); + if (element) { - nsCOMPtrelement; - element = do_QueryInterface(node); - if (element) - { - nsAutoString att(nsEditor::kMOZEditorBogusNodeAttr); - nsAutoString val; - (void)element->GetAttribute(att, val); - if (val.Equals(nsEditor::kMOZEditorBogusNodeValue)) { - mBogusNode = do_QueryInterface(element); - } + nsAutoString att(nsEditor::kMOZEditorBogusNodeAttr); + nsAutoString val; + (void)element->GetAttribute(att, val); + if (val.Equals(nsEditor::kMOZEditorBogusNodeValue)) { + mBogusNode = do_QueryInterface(element); } - nsCOMPtr temp; - result = node->GetParentNode(getter_AddRefs(temp)); - node = do_QueryInterface(temp); } + nsCOMPtr temp; + result = node->GetParentNode(getter_AddRefs(temp)); + node = do_QueryInterface(temp); } } return result; @@ -842,23 +850,24 @@ nsTextEditRules::DidRedo(nsIDOMSelection *aSelection, nsresult aResult) nsCOMPtrnode; PRInt32 offset; result = aSelection->GetAnchorNode(getter_AddRefs(node)); - if (NS_SUCCEEDED(result) && NS_SUCCEEDED(aSelection->GetAnchorOffset(&offset)) && node) + if (NS_FAILED(result)) return result; + if (!node) return NS_ERROR_NULL_POINTER; + result = aSelection->GetAnchorOffset(&offset); + if (NS_FAILED(result)) return result; + nsCOMPtrelement; + element = do_QueryInterface(node); + if (element) { - nsCOMPtrelement; - element = do_QueryInterface(node); - if (element) - { - nsAutoString att(nsEditor::kMOZEditorBogusNodeAttr); - nsAutoString val; - (void)element->GetAttribute(att, val); - if (val.Equals(nsEditor::kMOZEditorBogusNodeValue)) { - mBogusNode = do_QueryInterface(element); - } + nsAutoString att(nsEditor::kMOZEditorBogusNodeAttr); + nsAutoString val; + (void)element->GetAttribute(att, val); + if (val.Equals(nsEditor::kMOZEditorBogusNodeValue)) { + mBogusNode = do_QueryInterface(element); } - nsCOMPtr temp; - result = node->GetParentNode(getter_AddRefs(temp)); - node = do_QueryInterface(temp); } + nsCOMPtr temp; + result = node->GetParentNode(getter_AddRefs(temp)); + node = do_QueryInterface(temp); } } return result; @@ -895,86 +904,63 @@ nsTextEditRules::CreateBogusNodeIfNeeded(nsIDOMSelection *aSelection) { if (!aSelection) { return NS_ERROR_NULL_POINTER; } if (!mEditor) { return NS_ERROR_NULL_POINTER; } - nsCOMPtrdoc; - mEditor->GetDocument(getter_AddRefs(doc)); - nsCOMPtrnodeList; - nsAutoString bodyTag = "body"; - nsresult result = doc->GetElementsByTagName(bodyTag, getter_AddRefs(nodeList)); - if ((NS_SUCCEEDED(result)) && nodeList) + + nsCOMPtr bodyElement; + nsresult result = mEditor->GetBodyElement(getter_AddRefs(bodyElement)); + if (NS_FAILED(result)) return result; + if (!bodyElement) return NS_ERROR_NULL_POINTER; + nsCOMPtrbodyNode = do_QueryInterface(bodyElement); + + // now we've got the body tag. + // iterate the body tag, looking for editable content + // if no editable content is found, insert the bogus node + PRBool needsBogusContent=PR_TRUE; + nsCOMPtrbodyChild; + result = bodyNode->GetFirstChild(getter_AddRefs(bodyChild)); + while ((NS_SUCCEEDED(result)) && bodyChild) + { + if (PR_TRUE==mEditor->IsEditable(bodyChild)) + { + needsBogusContent = PR_FALSE; + break; + } + nsCOMPtrtemp; + bodyChild->GetNextSibling(getter_AddRefs(temp)); + bodyChild = do_QueryInterface(temp); + } + if (PR_TRUE==needsBogusContent) { - PRUint32 count; - nodeList->GetLength(&count); - NS_ASSERTION(1==count, "there is not exactly 1 body in the document!"); - nsCOMPtrbodyNode; - result = nodeList->Item(0, getter_AddRefs(bodyNode)); - if ((NS_SUCCEEDED(result)) && bodyNode) - { // now we've got the body tag. - // iterate the body tag, looking for editable content - // if no editable content is found, insert the bogus node - PRBool needsBogusContent=PR_TRUE; - nsCOMPtrbodyChild; - result = bodyNode->GetFirstChild(getter_AddRefs(bodyChild)); - while ((NS_SUCCEEDED(result)) && bodyChild) - { - if (PR_TRUE==mEditor->IsEditable(bodyChild)) - { - needsBogusContent = PR_FALSE; - break; - } - nsCOMPtrtemp; - bodyChild->GetNextSibling(getter_AddRefs(temp)); - bodyChild = do_QueryInterface(temp); - } - if (PR_TRUE==needsBogusContent) - { - // set mBogusNode to be the newly created

- result = mEditor->CreateNode(nsAutoString("P"), bodyNode, 0, - getter_AddRefs(mBogusNode)); - if ((NS_SUCCEEDED(result)) && mBogusNode) - { - nsCOMPtrnewTNode; - result = mEditor->CreateNode(nsEditor::GetTextNodeTag(), mBogusNode, 0, - getter_AddRefs(newTNode)); - if ((NS_SUCCEEDED(result)) && newTNode) - { - nsCOMPtrnewNodeAsText; - newNodeAsText = do_QueryInterface(newTNode); - if (newNodeAsText) - { - nsAutoString data; - data += 160; - newNodeAsText->SetData(data); - aSelection->Collapse(newTNode, 0); - } - } - // make sure we know the PNode is bogus - nsCOMPtrnewPElement; - newPElement = do_QueryInterface(mBogusNode); - if (newPElement) - { - nsAutoString att(nsEditor::kMOZEditorBogusNodeAttr); - nsAutoString val(nsEditor::kMOZEditorBogusNodeValue); - newPElement->SetAttribute(att, val); - } - } - } + // set mBogusNode to be the newly created

+ result = mEditor->CreateNode(nsAutoString("P"), bodyNode, 0, + getter_AddRefs(mBogusNode)); + if (NS_FAILED(result)) return result; + if (!mBogusNode) return NS_ERROR_NULL_POINTER; + + nsCOMPtrnewTNode; + result = mEditor->CreateNode(nsEditor::GetTextNodeTag(), mBogusNode, 0, + getter_AddRefs(newTNode)); + if (NS_FAILED(result)) return result; + if (!newTNode) return NS_ERROR_NULL_POINTER; + + nsCOMPtrnewNodeAsText; + newNodeAsText = do_QueryInterface(newTNode); + if (newNodeAsText) + { + nsAutoString data; + data += 160; + newNodeAsText->SetData(data); + aSelection->Collapse(newTNode, 0); + } + // make sure we know the PNode is bogus + nsCOMPtrnewPElement; + newPElement = do_QueryInterface(mBogusNode); + if (newPElement) + { + nsAutoString att(nsEditor::kMOZEditorBogusNodeAttr); + nsAutoString val(nsEditor::kMOZEditorBogusNodeValue); + newPElement->SetAttribute(att, val); } } return result; } - - - - - - - - - - - - - - -