зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1086349 part 5 - Clean up nsEditor::SplitNodeImpl; r=ehsan
This commit is contained in:
Родитель
8146930fd8
Коммит
7a88b21c2d
|
@ -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.
|
||||
|
|
Загрузка…
Ссылка в новой задаче