diff --git a/editor/libeditor/SplitNodeTxn.cpp b/editor/libeditor/SplitNodeTxn.cpp index 95b390ff3b1f..994704001d10 100644 --- a/editor/libeditor/SplitNodeTxn.cpp +++ b/editor/libeditor/SplitNodeTxn.cpp @@ -58,8 +58,7 @@ SplitNodeTxn::DoTransaction() NS_ENSURE_TRUE(mParent, NS_ERROR_NULL_POINTER); // Insert the new node - rv = mEditor.SplitNodeImpl(mExistingRightNode->AsDOMNode(), mOffset, - mNewLeftNode->AsDOMNode(), mParent->AsDOMNode()); + rv = mEditor.SplitNodeImpl(*mExistingRightNode, mOffset, *mNewLeftNode); if (mEditor.GetShouldTxnSetSelection()) { nsRefPtr selection = mEditor.GetSelection(); NS_ENSURE_TRUE(selection, NS_ERROR_NULL_POINTER); diff --git a/editor/libeditor/nsEditor.cpp b/editor/libeditor/nsEditor.cpp index 4a6c66cae85b..05f65582d76e 100644 --- a/editor/libeditor/nsEditor.cpp +++ b/editor/libeditor/nsEditor.cpp @@ -2602,130 +2602,97 @@ nsEditor::CreateTxnForJoinNode(nsINode& aLeftNode, nsINode& aRightNode) // BEGIN nsEditor public helper methods nsresult -nsEditor::SplitNodeImpl(nsIDOMNode * aExistingRightNode, - int32_t aOffset, - nsIDOMNode* aNewLeftNode, - nsIDOMNode* aParent) +nsEditor::SplitNodeImpl(nsIContent& aExistingRightNode, + int32_t aOffset, + nsIContent& aNewLeftNode) { - NS_ASSERTION(((nullptr!=aExistingRightNode) && - (nullptr!=aNewLeftNode) && - (nullptr!=aParent)), - "null arg"); - nsresult result; - if ((nullptr!=aExistingRightNode) && - (nullptr!=aNewLeftNode) && - (nullptr!=aParent)) - { - // get selection - nsCOMPtr selection; - result = GetSelection(getter_AddRefs(selection)); - NS_ENSURE_SUCCESS(result, result); - NS_ENSURE_TRUE(selection, NS_ERROR_NULL_POINTER); + // Get selection + nsRefPtr selection = GetSelection(); + NS_ENSURE_TRUE(selection, NS_ERROR_NULL_POINTER); - // remember some selection points - nsCOMPtr selStartNode, selEndNode; - int32_t selStartOffset, selEndOffset; - result = GetStartNodeAndOffset(selection, getter_AddRefs(selStartNode), &selStartOffset); - if (NS_FAILED(result)) selStartNode = nullptr; // if selection is cleared, remember that - result = GetEndNodeAndOffset(selection, getter_AddRefs(selEndNode), &selEndOffset); - if (NS_FAILED(result)) selStartNode = nullptr; // if selection is cleared, remember that + // Remember some selection points, if selection is set + nsCOMPtr selStartNode, selEndNode; + int32_t selStartOffset = 0, selEndOffset = 0; + if (selection->GetRangeAt(0)) { + selStartNode = selection->GetRangeAt(0)->GetStartParent(); + selStartOffset = selection->GetRangeAt(0)->StartOffset(); + selEndNode = selection->GetRangeAt(0)->GetEndParent(); + selEndOffset = selection->GetRangeAt(0)->EndOffset(); + } - nsCOMPtr resultNode; - result = aParent->InsertBefore(aNewLeftNode, aExistingRightNode, getter_AddRefs(resultNode)); - //printf(" after insert\n"); content->List(); // DEBUG - if (NS_SUCCEEDED(result)) - { - // split the children between the 2 nodes - // at this point, aExistingRightNode has all the children - // move all the children whose index is < aOffset to aNewLeftNode - if (0<=aOffset) // don't bother unless we're going to move at least one child - { - // if it's a text node, just shuffle around some text - nsCOMPtr rightNodeAsText( do_QueryInterface(aExistingRightNode) ); - nsCOMPtr leftNodeAsText( do_QueryInterface(aNewLeftNode) ); - if (leftNodeAsText && rightNodeAsText) - { - // fix right node - nsAutoString leftText; - rightNodeAsText->SubstringData(0, aOffset, leftText); - rightNodeAsText->DeleteData(0, aOffset); - // fix left node - leftNodeAsText->SetData(leftText); - // moose - } - else - { // otherwise it's an interior node, so shuffle around the children - // go through list backwards so deletes don't interfere with the iteration - nsCOMPtr childNodes; - result = aExistingRightNode->GetChildNodes(getter_AddRefs(childNodes)); - if ((NS_SUCCEEDED(result)) && (childNodes)) - { - int32_t i=aOffset-1; - for ( ; ((NS_SUCCEEDED(result)) && (0<=i)); i--) - { - nsCOMPtr childNode; - result = childNodes->Item(i, getter_AddRefs(childNode)); - if ((NS_SUCCEEDED(result)) && (childNode)) - { - result = aExistingRightNode->RemoveChild(childNode, getter_AddRefs(resultNode)); - //printf(" after remove\n"); content->List(); // DEBUG - if (NS_SUCCEEDED(result)) - { - nsCOMPtr firstChild; - aNewLeftNode->GetFirstChild(getter_AddRefs(firstChild)); - result = aNewLeftNode->InsertBefore(childNode, firstChild, getter_AddRefs(resultNode)); - //printf(" after append\n"); content->List(); // DEBUG - } - } - } - } - } - // handle selection - nsCOMPtr ps = GetPresShell(); - if (ps) - ps->FlushPendingNotifications(Flush_Frames); + nsCOMPtr parent = aExistingRightNode.GetParentNode(); + NS_ENSURE_TRUE(parent, NS_ERROR_NULL_POINTER); - if (GetShouldTxnSetSelection()) - { - // editor wants us to set selection at split point - selection->Collapse(aNewLeftNode, aOffset); - } - else if (selStartNode) - { - // else adjust the selection if needed. if selStartNode is null, then there was no selection. - // HACK: this is overly simplified - multi-range selections need more work than this - if (selStartNode.get() == aExistingRightNode) - { - if (selStartOffset < aOffset) - { - selStartNode = aNewLeftNode; - } - else - { - selStartOffset -= aOffset; - } - } - if (selEndNode.get() == aExistingRightNode) - { - if (selEndOffset < aOffset) - { - selEndNode = aNewLeftNode; - } - else - { - selEndOffset -= aOffset; - } - } - selection->Collapse(selStartNode,selStartOffset); - selection->Extend(selEndNode,selEndOffset); + ErrorResult rv; + parent->InsertBefore(aNewLeftNode, &aExistingRightNode, rv); + NS_ENSURE_SUCCESS(rv.ErrorCode(), rv.ErrorCode()); + + // Split the children between the two nodes. At this point, + // aExistingRightNode has all the children. Move all the children whose + // index is < aOffset to aNewLeftNode. + if (aOffset < 0) { + // This means move no children + return NS_OK; + } + + // If it's a text node, just shuffle around some text + if (aExistingRightNode.GetAsText() && aNewLeftNode.GetAsText()) { + // Fix right node + nsAutoString leftText; + aExistingRightNode.GetAsText()->SubstringData(0, aOffset, leftText); + aExistingRightNode.GetAsText()->DeleteData(0, aOffset); + // Fix left node + aNewLeftNode.GetAsText()->SetData(leftText); + } else { + // Otherwise it's an interior node, so shuffle around the children. Go + // through list backwards so deletes don't interfere with the iteration. + nsCOMPtr childNodes = aExistingRightNode.ChildNodes(); + for (int32_t i = aOffset - 1; i >= 0; i--) { + nsCOMPtr childNode = childNodes->Item(i); + if (childNode) { + aExistingRightNode.RemoveChild(*childNode, rv); + if (!rv.Failed()) { + nsCOMPtr firstChild = aNewLeftNode.GetFirstChild(); + aNewLeftNode.InsertBefore(*childNode, firstChild, rv); } } + if (rv.Failed()) { + break; + } } } - else - result = NS_ERROR_INVALID_ARG; - return result; + // Handle selection + nsCOMPtr ps = GetPresShell(); + if (ps) { + ps->FlushPendingNotifications(Flush_Frames); + } + + if (GetShouldTxnSetSelection()) { + // Editor wants us to set selection at split point + selection->Collapse(&aNewLeftNode, aOffset); + } else if (selStartNode) { + // Else adjust the selection if needed. If selStartNode is null, then + // there was no selection. + if (selStartNode == &aExistingRightNode) { + if (selStartOffset < aOffset) { + selStartNode = &aNewLeftNode; + } else { + selStartOffset -= aOffset; + } + } + if (selEndNode == &aExistingRightNode) { + if (selEndOffset < aOffset) { + selEndNode = &aNewLeftNode; + } else { + selEndOffset -= aOffset; + } + } + selection->Collapse(selStartNode, selStartOffset); + selection->Extend(selEndNode, selEndOffset); + } + + return NS_OK; } nsresult diff --git a/editor/libeditor/nsEditor.h b/editor/libeditor/nsEditor.h index 79fb937d9301..eed7d819d84c 100644 --- a/editor/libeditor/nsEditor.h +++ b/editor/libeditor/nsEditor.h @@ -442,16 +442,18 @@ public: void StopPreservingSelection(); /** - * SplitNode() creates a new node identical to an existing node, and split the contents between the two nodes - * @param aExistingRightNode the node to split. It will become the new node's next sibling. - * @param aOffset the offset of aExistingRightNode's content|children to do the split at - * @param aNewLeftNode [OUT] the new node resulting from the split, becomes aExistingRightNode's previous sibling. - * @param aParent the parent of aExistingRightNode + * SplitNode() creates a new node identical to an existing node, and split + * the contents between the two nodes + * @param aExistingRightNode The node to split. It will become the new + * node's next sibling. + * @param aOffset The offset of aExistingRightNode's + * content|children to do the split at + * @param aNewLeftNode The new node resulting from the split, becomes + * aExistingRightNode's previous sibling. */ - nsresult SplitNodeImpl(nsIDOMNode *aExistingRightNode, - int32_t aOffset, - nsIDOMNode *aNewLeftNode, - nsIDOMNode *aParent); + nsresult SplitNodeImpl(nsIContent& aExistingRightNode, + int32_t aOffset, + nsIContent& aNewLeftNode); /** * JoinNodes() takes 2 nodes and merge their content|children.