Bug 1086349 part 5 - Clean up nsEditor::SplitNodeImpl; r=ehsan

This commit is contained in:
Aryeh Gregor 2014-11-02 14:04:13 +02:00
Родитель 8146930fd8
Коммит 7a88b21c2d
3 изменённых файлов: 94 добавлений и 126 удалений

Просмотреть файл

@ -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> selection = mEditor.GetSelection();
NS_ENSURE_TRUE(selection, NS_ERROR_NULL_POINTER);

Просмотреть файл

@ -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<nsISelection> selection;
result = GetSelection(getter_AddRefs(selection));
NS_ENSURE_SUCCESS(result, result);
NS_ENSURE_TRUE(selection, NS_ERROR_NULL_POINTER);
// Get selection
nsRefPtr<Selection> selection = GetSelection();
NS_ENSURE_TRUE(selection, NS_ERROR_NULL_POINTER);
// remember some selection points
nsCOMPtr<nsIDOMNode> 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<nsINode> 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<nsIDOMNode> 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<nsIDOMCharacterData> rightNodeAsText( do_QueryInterface(aExistingRightNode) );
nsCOMPtr<nsIDOMCharacterData> 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<nsIDOMNodeList> 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<nsIDOMNode> 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<nsIDOMNode> firstChild;
aNewLeftNode->GetFirstChild(getter_AddRefs(firstChild));
result = aNewLeftNode->InsertBefore(childNode, firstChild, getter_AddRefs(resultNode));
//printf(" after append\n"); content->List(); // DEBUG
}
}
}
}
}
// handle selection
nsCOMPtr<nsIPresShell> ps = GetPresShell();
if (ps)
ps->FlushPendingNotifications(Flush_Frames);
nsCOMPtr<nsINode> 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<nsINodeList> childNodes = aExistingRightNode.ChildNodes();
for (int32_t i = aOffset - 1; i >= 0; i--) {
nsCOMPtr<nsIContent> childNode = childNodes->Item(i);
if (childNode) {
aExistingRightNode.RemoveChild(*childNode, rv);
if (!rv.Failed()) {
nsCOMPtr<nsIContent> firstChild = aNewLeftNode.GetFirstChild();
aNewLeftNode.InsertBefore(*childNode, firstChild, rv);
}
}
if (rv.Failed()) {
break;
}
}
}
else
result = NS_ERROR_INVALID_ARG;
return result;
// Handle selection
nsCOMPtr<nsIPresShell> 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

Просмотреть файл

@ -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.