mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-02-18 06:45:33 +00:00
checkpointing some deletion work
This commit is contained in:
parent
6d8c1b766a
commit
743156ab31
@ -2417,6 +2417,85 @@ nsEditor::IntermediateNodesAreInline(nsIDOMRange *aRange,
|
||||
}
|
||||
|
||||
|
||||
nsresult
|
||||
nsEditor::GetPriorNode(nsIDOMNode *aParentNode,
|
||||
PRInt32 aOffset,
|
||||
PRBool aEditableNode,
|
||||
nsIDOMNode **aResultNode)
|
||||
{
|
||||
// just another version of GetPriorNode that takes a {parent, offset}
|
||||
// instead of a node
|
||||
nsresult result = NS_OK;
|
||||
if (!aParentNode || !aResultNode) { return NS_ERROR_NULL_POINTER; }
|
||||
|
||||
// if we are at beginning of node than just look before it
|
||||
if (!aOffset)
|
||||
{
|
||||
return GetPriorNode(aParentNode, aEditableNode, aResultNode);
|
||||
}
|
||||
else
|
||||
{
|
||||
// else look before the child at 'aOffset'
|
||||
nsCOMPtr<nsIDOMNode> child = GetChildAt(aParentNode, aOffset);
|
||||
if (child)
|
||||
return GetPriorNode(child, aEditableNode, aResultNode);
|
||||
// unless there isn't one, in which case we are at the end of the node
|
||||
// and want the deep-right child.
|
||||
else
|
||||
{
|
||||
result = GetRightmostChild(*aResultNode, aResultNode);
|
||||
if (NS_FAILED(result)) return result;
|
||||
if (!aEditableNode) return result;
|
||||
if (IsEditable(*aResultNode)) return result;
|
||||
else
|
||||
{
|
||||
// restart the search from the non-editable node we just found
|
||||
nsCOMPtr<nsIDOMNode> notEditableNode = do_QueryInterface(*aResultNode);
|
||||
return GetPriorNode(notEditableNode, aEditableNode, aResultNode);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
nsresult
|
||||
nsEditor::GetNextNode(nsIDOMNode *aParentNode,
|
||||
PRInt32 aOffset,
|
||||
PRBool aEditableNode,
|
||||
nsIDOMNode **aResultNode)
|
||||
{
|
||||
// just another version of GetNextNode that takes a {parent, offset}
|
||||
// instead of a node
|
||||
nsresult result = NS_OK;
|
||||
if (!aParentNode || !aResultNode) { return NS_ERROR_NULL_POINTER; }
|
||||
|
||||
// look at the child at 'aOffset'
|
||||
nsCOMPtr<nsIDOMNode> child = GetChildAt(aParentNode, aOffset);
|
||||
if (child)
|
||||
{
|
||||
result = GetLeftmostChild(*aResultNode, aResultNode);
|
||||
if (NS_FAILED(result)) return result;
|
||||
if (!aEditableNode) return result;
|
||||
if (IsEditable(*aResultNode)) return result;
|
||||
else
|
||||
{
|
||||
// restart the search from the non-editable node we just found
|
||||
nsCOMPtr<nsIDOMNode> notEditableNode = do_QueryInterface(*aResultNode);
|
||||
return GetNextNode(notEditableNode, aEditableNode, aResultNode);
|
||||
}
|
||||
}
|
||||
|
||||
// unless there isn't one, in which case we are at the end of the node
|
||||
// and want the next one.
|
||||
else
|
||||
{
|
||||
return GetNextNode(aParentNode, aEditableNode, aResultNode);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
nsresult
|
||||
nsEditor::GetPriorNode(nsIDOMNode *aCurrentNode,
|
||||
PRBool aEditableNode,
|
||||
@ -3525,7 +3604,7 @@ nsEditor::SplitNodeDeep(nsIDOMNode *aNode,
|
||||
|
||||
while (nodeToSplit)
|
||||
{
|
||||
// need to insert rules code call here to do thingsa like
|
||||
// need to insert rules code call here to do things like
|
||||
// not split a list if you are after the last <li> or before the first, etc.
|
||||
// for now we just have some smarts about unneccessarily splitting
|
||||
// textnodes, which should be universal enough to put straight in
|
||||
@ -3577,18 +3656,18 @@ nsEditor::SplitNodeDeep(nsIDOMNode *aNode,
|
||||
nsresult
|
||||
nsEditor::JoinNodeDeep(nsIDOMNode *aLeftNode,
|
||||
nsIDOMNode *aRightNode,
|
||||
nsIDOMSelection *aSelection)
|
||||
nsCOMPtr<nsIDOMNode> *aOutJoinNode,
|
||||
PRInt32 *outOffset)
|
||||
{
|
||||
if (!aLeftNode || !aRightNode) return NS_ERROR_NULL_POINTER;
|
||||
if (!aLeftNode || !aRightNode || !aOutJoinNode || !outOffset) return NS_ERROR_NULL_POINTER;
|
||||
|
||||
// while the rightmost children and their descendants of the left node
|
||||
// match the leftmost children and their descendants of the right node
|
||||
// join them up. Can you say that three times fast?
|
||||
|
||||
|
||||
nsCOMPtr<nsIDOMNode> leftNodeToJoin = do_QueryInterface(aLeftNode);
|
||||
nsCOMPtr<nsIDOMNode> rightNodeToJoin = do_QueryInterface(aRightNode);
|
||||
nsCOMPtr<nsIDOMNode> parentNode;
|
||||
PRInt32 offset;
|
||||
nsCOMPtr<nsIDOMNode> parentNode,tmp;
|
||||
nsresult res = NS_OK;
|
||||
|
||||
rightNodeToJoin->GetParentNode(getter_AddRefs(parentNode));
|
||||
@ -3596,23 +3675,51 @@ nsEditor::JoinNodeDeep(nsIDOMNode *aLeftNode,
|
||||
while (leftNodeToJoin && rightNodeToJoin && parentNode &&
|
||||
NodesSameType(leftNodeToJoin, rightNodeToJoin))
|
||||
{
|
||||
res = JoinNodes(leftNodeToJoin,rightNodeToJoin,parentNode);
|
||||
// adjust out params
|
||||
PRUint32 length;
|
||||
if (IsTextNode(leftNodeToJoin))
|
||||
{
|
||||
nsCOMPtr<nsIDOMCharacterData>nodeAsText;
|
||||
nodeAsText = do_QueryInterface(leftNodeToJoin);
|
||||
nodeAsText->GetLength(&length);
|
||||
}
|
||||
else
|
||||
{
|
||||
res = GetLengthOfDOMNode(leftNodeToJoin, length);
|
||||
if (NS_FAILED(res)) return res;
|
||||
}
|
||||
|
||||
*aOutJoinNode = rightNodeToJoin;
|
||||
*outOffset = length;
|
||||
|
||||
// do the join
|
||||
res = JoinNodes(leftNodeToJoin, rightNodeToJoin, parentNode);
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
res = GetStartNodeAndOffset(aSelection, &parentNode, &offset);
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
if (offset == 0) // no new left node; we're done joining
|
||||
return NS_OK;
|
||||
|
||||
if (IsTextNode(parentNode)) // we've joined all the way down to text nodes, we're done!
|
||||
return NS_OK;
|
||||
|
||||
else
|
||||
{
|
||||
// get new left and right nodes, and begin anew
|
||||
leftNodeToJoin = GetChildAt(parentNode, offset-1);
|
||||
rightNodeToJoin = GetChildAt(parentNode, offset);
|
||||
parentNode = rightNodeToJoin;
|
||||
leftNodeToJoin = GetChildAt(parentNode, length-1);
|
||||
rightNodeToJoin = GetChildAt(parentNode, length);
|
||||
|
||||
// skip over non-editable nodes
|
||||
while (leftNodeToJoin && !IsEditable(leftNodeToJoin))
|
||||
{
|
||||
leftNodeToJoin->GetPreviousSibling(getter_AddRefs(tmp));
|
||||
leftNodeToJoin = tmp;
|
||||
}
|
||||
if (!leftNodeToJoin) break;
|
||||
|
||||
while (rightNodeToJoin && !IsEditable(rightNodeToJoin))
|
||||
{
|
||||
rightNodeToJoin->GetNextSibling(getter_AddRefs(tmp));
|
||||
rightNodeToJoin = tmp;
|
||||
}
|
||||
if (!rightNodeToJoin) break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -4021,7 +4128,6 @@ nsEditor::CreateTxnForDeleteInsertionPoint(nsIDOMRange *aRange,
|
||||
|
||||
// determine if the insertion point is at the beginning, middle, or end of the node
|
||||
nsCOMPtr<nsIDOMCharacterData> nodeAsText;
|
||||
nsCOMPtr<nsIDOMNode> selectedNode;
|
||||
nodeAsText = do_QueryInterface(node);
|
||||
|
||||
if (nodeAsText)
|
||||
@ -4040,7 +4146,6 @@ nsEditor::CreateTxnForDeleteInsertionPoint(nsIDOMRange *aRange,
|
||||
if ((NS_SUCCEEDED(result)) && childList)
|
||||
{
|
||||
childList->GetLength(&count);
|
||||
childList->Item(offset, getter_AddRefs(selectedNode));
|
||||
}
|
||||
isFirst = PRBool(0==offset);
|
||||
isLast = PRBool((count-1)==(PRUint32)offset);
|
||||
@ -4140,9 +4245,22 @@ nsEditor::CreateTxnForDeleteInsertionPoint(nsIDOMRange *aRange,
|
||||
else
|
||||
{ // we're deleting a node
|
||||
DeleteElementTxn *txn;
|
||||
result = CreateTxnForDeleteElement(selectedNode, &txn);
|
||||
if (NS_SUCCEEDED(result)) {
|
||||
aTxn->AppendChild(txn);
|
||||
nsCOMPtr<nsIDOMNode> selectedNode;
|
||||
if (eDeletePrevious==aAction)
|
||||
{
|
||||
result = GetPriorNode(node, offset, PR_TRUE, getter_AddRefs(selectedNode));
|
||||
}
|
||||
else if (eDeleteNext==aAction)
|
||||
{
|
||||
result = GetNextNode(node, offset, PR_TRUE, getter_AddRefs(selectedNode));
|
||||
}
|
||||
if (NS_SUCCEEDED(result) && selectedNode)
|
||||
{
|
||||
result = CreateTxnForDeleteElement(selectedNode, &txn);
|
||||
if (NS_SUCCEEDED(result))
|
||||
{
|
||||
aTxn->AppendChild(txn);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -482,6 +482,12 @@ public:
|
||||
PRBool aEditableNode,
|
||||
nsIDOMNode **aResultNode);
|
||||
|
||||
// and another version that takes a {parent,offset} pair rather than a node
|
||||
nsresult GetPriorNode(nsIDOMNode *aParentNode,
|
||||
PRInt32 aOffset,
|
||||
PRBool aEditableNode,
|
||||
nsIDOMNode **aResultNode);
|
||||
|
||||
/** get the node immediately after to aCurrentNode
|
||||
* @param aCurrentNode the node from which we start the search
|
||||
* @param aEditableNode if PR_TRUE, only return an editable node
|
||||
@ -493,6 +499,12 @@ public:
|
||||
PRBool aEditableNode,
|
||||
nsIDOMNode **aResultNode);
|
||||
|
||||
// and another version that takes a {parent,offset} pair rather than a node
|
||||
nsresult GetNextNode(nsIDOMNode *aParentNode,
|
||||
PRInt32 aOffset,
|
||||
PRBool aEditableNode,
|
||||
nsIDOMNode **aResultNode);
|
||||
|
||||
/** Get the rightmost child of aCurrentNode, and return it in aResultNode
|
||||
* aResultNode is set to nsnull if aCurrentNode has no children.
|
||||
*/
|
||||
@ -565,7 +577,9 @@ public:
|
||||
nsresult IsPrevCharWhitespace(nsIDOMNode *aParentNode, PRInt32 aOffset, PRBool *aResult);
|
||||
|
||||
nsresult SplitNodeDeep(nsIDOMNode *aNode, nsIDOMNode *aSplitPointParent, PRInt32 aSplitPointOffset, PRInt32 *outOffset);
|
||||
nsresult JoinNodeDeep(nsIDOMNode *aLeftNode, nsIDOMNode *aRightNode, nsIDOMSelection *aSelection);
|
||||
nsresult JoinNodeDeep(nsIDOMNode *aLeftNode, nsIDOMNode *aRightNode, nsCOMPtr<nsIDOMNode> *aOutJoinNode, PRInt32 *outOffset);
|
||||
|
||||
nsresult GetString(const nsString& name, nsString& value);
|
||||
|
||||
nsresult BeginUpdateViewBatch(void);
|
||||
nsresult EndUpdateViewBatch(void);
|
||||
|
@ -306,8 +306,8 @@ nsHTMLEditRules::WillDeleteSelection(nsIDOMSelection *aSelection, nsIEditor::ESe
|
||||
res = aSelection->GetIsCollapsed(&bCollapsed);
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
nsCOMPtr<nsIDOMNode> node;
|
||||
PRInt32 offset;
|
||||
nsCOMPtr<nsIDOMNode> node, selNode;
|
||||
PRInt32 offset, selOffset;
|
||||
|
||||
res = mEditor->GetStartNodeAndOffset(aSelection, &node, &offset);
|
||||
if (NS_FAILED(res)) return res;
|
||||
@ -356,7 +356,10 @@ nsHTMLEditRules::WillDeleteSelection(nsIDOMSelection *aSelection, nsIEditor::ESe
|
||||
{
|
||||
// join para's, insert break
|
||||
*aCancel = PR_TRUE;
|
||||
res = mEditor->JoinNodeDeep(leftParent,rightParent,aSelection);
|
||||
res = mEditor->JoinNodeDeep(leftParent,rightParent,&selNode,&selOffset);
|
||||
if (NS_FAILED(res)) return res;
|
||||
// fix up selection
|
||||
res = aSelection->Collapse(selNode,selOffset);
|
||||
if (NS_FAILED(res)) return res;
|
||||
res = mEditor->InsertBreak();
|
||||
return res;
|
||||
@ -365,7 +368,10 @@ nsHTMLEditRules::WillDeleteSelection(nsIDOMSelection *aSelection, nsIEditor::ESe
|
||||
{
|
||||
// join blocks
|
||||
*aCancel = PR_TRUE;
|
||||
res = mEditor->JoinNodeDeep(leftParent,rightParent,aSelection);
|
||||
res = mEditor->JoinNodeDeep(leftParent,rightParent,&selNode,&selOffset);
|
||||
if (NS_FAILED(res)) return res;
|
||||
// fix up selection
|
||||
res = aSelection->Collapse(selNode,selOffset);
|
||||
return res;
|
||||
}
|
||||
}
|
||||
@ -409,7 +415,10 @@ nsHTMLEditRules::WillDeleteSelection(nsIDOMSelection *aSelection, nsIEditor::ESe
|
||||
{
|
||||
// join para's, insert break
|
||||
*aCancel = PR_TRUE;
|
||||
res = mEditor->JoinNodeDeep(leftParent,rightParent,aSelection);
|
||||
res = mEditor->JoinNodeDeep(leftParent,rightParent,&selNode,&selOffset);
|
||||
if (NS_FAILED(res)) return res;
|
||||
// fix up selection
|
||||
res = aSelection->Collapse(selNode,selOffset);
|
||||
if (NS_FAILED(res)) return res;
|
||||
res = mEditor->InsertBreak();
|
||||
return res;
|
||||
@ -418,7 +427,10 @@ nsHTMLEditRules::WillDeleteSelection(nsIDOMSelection *aSelection, nsIEditor::ESe
|
||||
{
|
||||
// join blocks
|
||||
*aCancel = PR_TRUE;
|
||||
res = mEditor->JoinNodeDeep(leftParent,rightParent,aSelection);
|
||||
res = mEditor->JoinNodeDeep(leftParent,rightParent,&selNode,&selOffset);
|
||||
if (NS_FAILED(res)) return res;
|
||||
// fix up selection
|
||||
res = aSelection->Collapse(selNode,selOffset);
|
||||
return res;
|
||||
}
|
||||
}
|
||||
@ -428,7 +440,41 @@ nsHTMLEditRules::WillDeleteSelection(nsIDOMSelection *aSelection, nsIEditor::ESe
|
||||
|
||||
}
|
||||
}
|
||||
// else do default
|
||||
// else not in text node; we need to find right place to act on
|
||||
else
|
||||
{
|
||||
|
||||
// XXX add (aAction == nsIEditor::eDeleteNext) case!!
|
||||
|
||||
nsCOMPtr<nsIDOMNode> nodeToBackspace;
|
||||
|
||||
res = mEditor->GetPriorNode(node, offset, PR_TRUE, getter_AddRefs(nodeToBackspace));
|
||||
if (NS_FAILED(res)) return res;
|
||||
if (!nodeToBackspace) return NS_ERROR_NULL_POINTER;
|
||||
|
||||
// if this node is text node, adjust selection
|
||||
if (nsEditor::IsTextNode(nodeToBackspace))
|
||||
{
|
||||
PRUint32 len;
|
||||
nsCOMPtr<nsIDOMCharacterData>nodeAsText;
|
||||
nodeAsText = do_QueryInterface(nodeToBackspace);
|
||||
nodeAsText->GetLength(&len);
|
||||
res = aSelection->Collapse(nodeToBackspace,len);
|
||||
return res;
|
||||
}
|
||||
else
|
||||
{
|
||||
// editable leaf node is not text; delete it.
|
||||
// that's the default behavior
|
||||
res = nsEditor::GetNodeLocation(nodeToBackspace, &node, &offset);
|
||||
if (NS_FAILED(res)) return res;
|
||||
// adjust selection to be right after it, for benefit of
|
||||
// deletion code
|
||||
res = aSelection->Collapse(node, offset+1);
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -491,10 +537,10 @@ nsHTMLEditRules::WillDeleteSelection(nsIDOMSelection *aSelection, nsIEditor::ESe
|
||||
res = mEditor->DeleteSelectionImpl(aAction);
|
||||
if (NS_FAILED(res)) return res;
|
||||
// then join para's, insert break
|
||||
res = mEditor->JoinNodeDeep(leftParent,rightParent,aSelection);
|
||||
res = mEditor->JoinNodeDeep(leftParent,rightParent,&selNode,&selOffset);
|
||||
if (NS_FAILED(res)) return res;
|
||||
//res = mEditor->InsertBreak();
|
||||
// uhh, no, we don't want to have the <br> on a deleted selction across para's
|
||||
// fix up selection
|
||||
res = aSelection->Collapse(selNode,selOffset);
|
||||
return res;
|
||||
}
|
||||
if (IsListItem(leftParent) || IsHeader(leftParent))
|
||||
@ -504,7 +550,10 @@ nsHTMLEditRules::WillDeleteSelection(nsIDOMSelection *aSelection, nsIEditor::ESe
|
||||
res = mEditor->DeleteSelectionImpl(aAction);
|
||||
if (NS_FAILED(res)) return res;
|
||||
// join blocks
|
||||
res = mEditor->JoinNodeDeep(leftParent,rightParent,aSelection);
|
||||
res = mEditor->JoinNodeDeep(leftParent,rightParent,&selNode,&selOffset);
|
||||
if (NS_FAILED(res)) return res;
|
||||
// fix up selection
|
||||
res = aSelection->Collapse(selNode,selOffset);
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
@ -2417,6 +2417,85 @@ nsEditor::IntermediateNodesAreInline(nsIDOMRange *aRange,
|
||||
}
|
||||
|
||||
|
||||
nsresult
|
||||
nsEditor::GetPriorNode(nsIDOMNode *aParentNode,
|
||||
PRInt32 aOffset,
|
||||
PRBool aEditableNode,
|
||||
nsIDOMNode **aResultNode)
|
||||
{
|
||||
// just another version of GetPriorNode that takes a {parent, offset}
|
||||
// instead of a node
|
||||
nsresult result = NS_OK;
|
||||
if (!aParentNode || !aResultNode) { return NS_ERROR_NULL_POINTER; }
|
||||
|
||||
// if we are at beginning of node than just look before it
|
||||
if (!aOffset)
|
||||
{
|
||||
return GetPriorNode(aParentNode, aEditableNode, aResultNode);
|
||||
}
|
||||
else
|
||||
{
|
||||
// else look before the child at 'aOffset'
|
||||
nsCOMPtr<nsIDOMNode> child = GetChildAt(aParentNode, aOffset);
|
||||
if (child)
|
||||
return GetPriorNode(child, aEditableNode, aResultNode);
|
||||
// unless there isn't one, in which case we are at the end of the node
|
||||
// and want the deep-right child.
|
||||
else
|
||||
{
|
||||
result = GetRightmostChild(*aResultNode, aResultNode);
|
||||
if (NS_FAILED(result)) return result;
|
||||
if (!aEditableNode) return result;
|
||||
if (IsEditable(*aResultNode)) return result;
|
||||
else
|
||||
{
|
||||
// restart the search from the non-editable node we just found
|
||||
nsCOMPtr<nsIDOMNode> notEditableNode = do_QueryInterface(*aResultNode);
|
||||
return GetPriorNode(notEditableNode, aEditableNode, aResultNode);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
nsresult
|
||||
nsEditor::GetNextNode(nsIDOMNode *aParentNode,
|
||||
PRInt32 aOffset,
|
||||
PRBool aEditableNode,
|
||||
nsIDOMNode **aResultNode)
|
||||
{
|
||||
// just another version of GetNextNode that takes a {parent, offset}
|
||||
// instead of a node
|
||||
nsresult result = NS_OK;
|
||||
if (!aParentNode || !aResultNode) { return NS_ERROR_NULL_POINTER; }
|
||||
|
||||
// look at the child at 'aOffset'
|
||||
nsCOMPtr<nsIDOMNode> child = GetChildAt(aParentNode, aOffset);
|
||||
if (child)
|
||||
{
|
||||
result = GetLeftmostChild(*aResultNode, aResultNode);
|
||||
if (NS_FAILED(result)) return result;
|
||||
if (!aEditableNode) return result;
|
||||
if (IsEditable(*aResultNode)) return result;
|
||||
else
|
||||
{
|
||||
// restart the search from the non-editable node we just found
|
||||
nsCOMPtr<nsIDOMNode> notEditableNode = do_QueryInterface(*aResultNode);
|
||||
return GetNextNode(notEditableNode, aEditableNode, aResultNode);
|
||||
}
|
||||
}
|
||||
|
||||
// unless there isn't one, in which case we are at the end of the node
|
||||
// and want the next one.
|
||||
else
|
||||
{
|
||||
return GetNextNode(aParentNode, aEditableNode, aResultNode);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
nsresult
|
||||
nsEditor::GetPriorNode(nsIDOMNode *aCurrentNode,
|
||||
PRBool aEditableNode,
|
||||
@ -3525,7 +3604,7 @@ nsEditor::SplitNodeDeep(nsIDOMNode *aNode,
|
||||
|
||||
while (nodeToSplit)
|
||||
{
|
||||
// need to insert rules code call here to do thingsa like
|
||||
// need to insert rules code call here to do things like
|
||||
// not split a list if you are after the last <li> or before the first, etc.
|
||||
// for now we just have some smarts about unneccessarily splitting
|
||||
// textnodes, which should be universal enough to put straight in
|
||||
@ -3577,18 +3656,18 @@ nsEditor::SplitNodeDeep(nsIDOMNode *aNode,
|
||||
nsresult
|
||||
nsEditor::JoinNodeDeep(nsIDOMNode *aLeftNode,
|
||||
nsIDOMNode *aRightNode,
|
||||
nsIDOMSelection *aSelection)
|
||||
nsCOMPtr<nsIDOMNode> *aOutJoinNode,
|
||||
PRInt32 *outOffset)
|
||||
{
|
||||
if (!aLeftNode || !aRightNode) return NS_ERROR_NULL_POINTER;
|
||||
if (!aLeftNode || !aRightNode || !aOutJoinNode || !outOffset) return NS_ERROR_NULL_POINTER;
|
||||
|
||||
// while the rightmost children and their descendants of the left node
|
||||
// match the leftmost children and their descendants of the right node
|
||||
// join them up. Can you say that three times fast?
|
||||
|
||||
|
||||
nsCOMPtr<nsIDOMNode> leftNodeToJoin = do_QueryInterface(aLeftNode);
|
||||
nsCOMPtr<nsIDOMNode> rightNodeToJoin = do_QueryInterface(aRightNode);
|
||||
nsCOMPtr<nsIDOMNode> parentNode;
|
||||
PRInt32 offset;
|
||||
nsCOMPtr<nsIDOMNode> parentNode,tmp;
|
||||
nsresult res = NS_OK;
|
||||
|
||||
rightNodeToJoin->GetParentNode(getter_AddRefs(parentNode));
|
||||
@ -3596,23 +3675,51 @@ nsEditor::JoinNodeDeep(nsIDOMNode *aLeftNode,
|
||||
while (leftNodeToJoin && rightNodeToJoin && parentNode &&
|
||||
NodesSameType(leftNodeToJoin, rightNodeToJoin))
|
||||
{
|
||||
res = JoinNodes(leftNodeToJoin,rightNodeToJoin,parentNode);
|
||||
// adjust out params
|
||||
PRUint32 length;
|
||||
if (IsTextNode(leftNodeToJoin))
|
||||
{
|
||||
nsCOMPtr<nsIDOMCharacterData>nodeAsText;
|
||||
nodeAsText = do_QueryInterface(leftNodeToJoin);
|
||||
nodeAsText->GetLength(&length);
|
||||
}
|
||||
else
|
||||
{
|
||||
res = GetLengthOfDOMNode(leftNodeToJoin, length);
|
||||
if (NS_FAILED(res)) return res;
|
||||
}
|
||||
|
||||
*aOutJoinNode = rightNodeToJoin;
|
||||
*outOffset = length;
|
||||
|
||||
// do the join
|
||||
res = JoinNodes(leftNodeToJoin, rightNodeToJoin, parentNode);
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
res = GetStartNodeAndOffset(aSelection, &parentNode, &offset);
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
if (offset == 0) // no new left node; we're done joining
|
||||
return NS_OK;
|
||||
|
||||
if (IsTextNode(parentNode)) // we've joined all the way down to text nodes, we're done!
|
||||
return NS_OK;
|
||||
|
||||
else
|
||||
{
|
||||
// get new left and right nodes, and begin anew
|
||||
leftNodeToJoin = GetChildAt(parentNode, offset-1);
|
||||
rightNodeToJoin = GetChildAt(parentNode, offset);
|
||||
parentNode = rightNodeToJoin;
|
||||
leftNodeToJoin = GetChildAt(parentNode, length-1);
|
||||
rightNodeToJoin = GetChildAt(parentNode, length);
|
||||
|
||||
// skip over non-editable nodes
|
||||
while (leftNodeToJoin && !IsEditable(leftNodeToJoin))
|
||||
{
|
||||
leftNodeToJoin->GetPreviousSibling(getter_AddRefs(tmp));
|
||||
leftNodeToJoin = tmp;
|
||||
}
|
||||
if (!leftNodeToJoin) break;
|
||||
|
||||
while (rightNodeToJoin && !IsEditable(rightNodeToJoin))
|
||||
{
|
||||
rightNodeToJoin->GetNextSibling(getter_AddRefs(tmp));
|
||||
rightNodeToJoin = tmp;
|
||||
}
|
||||
if (!rightNodeToJoin) break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -4021,7 +4128,6 @@ nsEditor::CreateTxnForDeleteInsertionPoint(nsIDOMRange *aRange,
|
||||
|
||||
// determine if the insertion point is at the beginning, middle, or end of the node
|
||||
nsCOMPtr<nsIDOMCharacterData> nodeAsText;
|
||||
nsCOMPtr<nsIDOMNode> selectedNode;
|
||||
nodeAsText = do_QueryInterface(node);
|
||||
|
||||
if (nodeAsText)
|
||||
@ -4040,7 +4146,6 @@ nsEditor::CreateTxnForDeleteInsertionPoint(nsIDOMRange *aRange,
|
||||
if ((NS_SUCCEEDED(result)) && childList)
|
||||
{
|
||||
childList->GetLength(&count);
|
||||
childList->Item(offset, getter_AddRefs(selectedNode));
|
||||
}
|
||||
isFirst = PRBool(0==offset);
|
||||
isLast = PRBool((count-1)==(PRUint32)offset);
|
||||
@ -4140,9 +4245,22 @@ nsEditor::CreateTxnForDeleteInsertionPoint(nsIDOMRange *aRange,
|
||||
else
|
||||
{ // we're deleting a node
|
||||
DeleteElementTxn *txn;
|
||||
result = CreateTxnForDeleteElement(selectedNode, &txn);
|
||||
if (NS_SUCCEEDED(result)) {
|
||||
aTxn->AppendChild(txn);
|
||||
nsCOMPtr<nsIDOMNode> selectedNode;
|
||||
if (eDeletePrevious==aAction)
|
||||
{
|
||||
result = GetPriorNode(node, offset, PR_TRUE, getter_AddRefs(selectedNode));
|
||||
}
|
||||
else if (eDeleteNext==aAction)
|
||||
{
|
||||
result = GetNextNode(node, offset, PR_TRUE, getter_AddRefs(selectedNode));
|
||||
}
|
||||
if (NS_SUCCEEDED(result) && selectedNode)
|
||||
{
|
||||
result = CreateTxnForDeleteElement(selectedNode, &txn);
|
||||
if (NS_SUCCEEDED(result))
|
||||
{
|
||||
aTxn->AppendChild(txn);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -482,6 +482,12 @@ public:
|
||||
PRBool aEditableNode,
|
||||
nsIDOMNode **aResultNode);
|
||||
|
||||
// and another version that takes a {parent,offset} pair rather than a node
|
||||
nsresult GetPriorNode(nsIDOMNode *aParentNode,
|
||||
PRInt32 aOffset,
|
||||
PRBool aEditableNode,
|
||||
nsIDOMNode **aResultNode);
|
||||
|
||||
/** get the node immediately after to aCurrentNode
|
||||
* @param aCurrentNode the node from which we start the search
|
||||
* @param aEditableNode if PR_TRUE, only return an editable node
|
||||
@ -493,6 +499,12 @@ public:
|
||||
PRBool aEditableNode,
|
||||
nsIDOMNode **aResultNode);
|
||||
|
||||
// and another version that takes a {parent,offset} pair rather than a node
|
||||
nsresult GetNextNode(nsIDOMNode *aParentNode,
|
||||
PRInt32 aOffset,
|
||||
PRBool aEditableNode,
|
||||
nsIDOMNode **aResultNode);
|
||||
|
||||
/** Get the rightmost child of aCurrentNode, and return it in aResultNode
|
||||
* aResultNode is set to nsnull if aCurrentNode has no children.
|
||||
*/
|
||||
@ -565,7 +577,9 @@ public:
|
||||
nsresult IsPrevCharWhitespace(nsIDOMNode *aParentNode, PRInt32 aOffset, PRBool *aResult);
|
||||
|
||||
nsresult SplitNodeDeep(nsIDOMNode *aNode, nsIDOMNode *aSplitPointParent, PRInt32 aSplitPointOffset, PRInt32 *outOffset);
|
||||
nsresult JoinNodeDeep(nsIDOMNode *aLeftNode, nsIDOMNode *aRightNode, nsIDOMSelection *aSelection);
|
||||
nsresult JoinNodeDeep(nsIDOMNode *aLeftNode, nsIDOMNode *aRightNode, nsCOMPtr<nsIDOMNode> *aOutJoinNode, PRInt32 *outOffset);
|
||||
|
||||
nsresult GetString(const nsString& name, nsString& value);
|
||||
|
||||
nsresult BeginUpdateViewBatch(void);
|
||||
nsresult EndUpdateViewBatch(void);
|
||||
|
@ -306,8 +306,8 @@ nsHTMLEditRules::WillDeleteSelection(nsIDOMSelection *aSelection, nsIEditor::ESe
|
||||
res = aSelection->GetIsCollapsed(&bCollapsed);
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
nsCOMPtr<nsIDOMNode> node;
|
||||
PRInt32 offset;
|
||||
nsCOMPtr<nsIDOMNode> node, selNode;
|
||||
PRInt32 offset, selOffset;
|
||||
|
||||
res = mEditor->GetStartNodeAndOffset(aSelection, &node, &offset);
|
||||
if (NS_FAILED(res)) return res;
|
||||
@ -356,7 +356,10 @@ nsHTMLEditRules::WillDeleteSelection(nsIDOMSelection *aSelection, nsIEditor::ESe
|
||||
{
|
||||
// join para's, insert break
|
||||
*aCancel = PR_TRUE;
|
||||
res = mEditor->JoinNodeDeep(leftParent,rightParent,aSelection);
|
||||
res = mEditor->JoinNodeDeep(leftParent,rightParent,&selNode,&selOffset);
|
||||
if (NS_FAILED(res)) return res;
|
||||
// fix up selection
|
||||
res = aSelection->Collapse(selNode,selOffset);
|
||||
if (NS_FAILED(res)) return res;
|
||||
res = mEditor->InsertBreak();
|
||||
return res;
|
||||
@ -365,7 +368,10 @@ nsHTMLEditRules::WillDeleteSelection(nsIDOMSelection *aSelection, nsIEditor::ESe
|
||||
{
|
||||
// join blocks
|
||||
*aCancel = PR_TRUE;
|
||||
res = mEditor->JoinNodeDeep(leftParent,rightParent,aSelection);
|
||||
res = mEditor->JoinNodeDeep(leftParent,rightParent,&selNode,&selOffset);
|
||||
if (NS_FAILED(res)) return res;
|
||||
// fix up selection
|
||||
res = aSelection->Collapse(selNode,selOffset);
|
||||
return res;
|
||||
}
|
||||
}
|
||||
@ -409,7 +415,10 @@ nsHTMLEditRules::WillDeleteSelection(nsIDOMSelection *aSelection, nsIEditor::ESe
|
||||
{
|
||||
// join para's, insert break
|
||||
*aCancel = PR_TRUE;
|
||||
res = mEditor->JoinNodeDeep(leftParent,rightParent,aSelection);
|
||||
res = mEditor->JoinNodeDeep(leftParent,rightParent,&selNode,&selOffset);
|
||||
if (NS_FAILED(res)) return res;
|
||||
// fix up selection
|
||||
res = aSelection->Collapse(selNode,selOffset);
|
||||
if (NS_FAILED(res)) return res;
|
||||
res = mEditor->InsertBreak();
|
||||
return res;
|
||||
@ -418,7 +427,10 @@ nsHTMLEditRules::WillDeleteSelection(nsIDOMSelection *aSelection, nsIEditor::ESe
|
||||
{
|
||||
// join blocks
|
||||
*aCancel = PR_TRUE;
|
||||
res = mEditor->JoinNodeDeep(leftParent,rightParent,aSelection);
|
||||
res = mEditor->JoinNodeDeep(leftParent,rightParent,&selNode,&selOffset);
|
||||
if (NS_FAILED(res)) return res;
|
||||
// fix up selection
|
||||
res = aSelection->Collapse(selNode,selOffset);
|
||||
return res;
|
||||
}
|
||||
}
|
||||
@ -428,7 +440,41 @@ nsHTMLEditRules::WillDeleteSelection(nsIDOMSelection *aSelection, nsIEditor::ESe
|
||||
|
||||
}
|
||||
}
|
||||
// else do default
|
||||
// else not in text node; we need to find right place to act on
|
||||
else
|
||||
{
|
||||
|
||||
// XXX add (aAction == nsIEditor::eDeleteNext) case!!
|
||||
|
||||
nsCOMPtr<nsIDOMNode> nodeToBackspace;
|
||||
|
||||
res = mEditor->GetPriorNode(node, offset, PR_TRUE, getter_AddRefs(nodeToBackspace));
|
||||
if (NS_FAILED(res)) return res;
|
||||
if (!nodeToBackspace) return NS_ERROR_NULL_POINTER;
|
||||
|
||||
// if this node is text node, adjust selection
|
||||
if (nsEditor::IsTextNode(nodeToBackspace))
|
||||
{
|
||||
PRUint32 len;
|
||||
nsCOMPtr<nsIDOMCharacterData>nodeAsText;
|
||||
nodeAsText = do_QueryInterface(nodeToBackspace);
|
||||
nodeAsText->GetLength(&len);
|
||||
res = aSelection->Collapse(nodeToBackspace,len);
|
||||
return res;
|
||||
}
|
||||
else
|
||||
{
|
||||
// editable leaf node is not text; delete it.
|
||||
// that's the default behavior
|
||||
res = nsEditor::GetNodeLocation(nodeToBackspace, &node, &offset);
|
||||
if (NS_FAILED(res)) return res;
|
||||
// adjust selection to be right after it, for benefit of
|
||||
// deletion code
|
||||
res = aSelection->Collapse(node, offset+1);
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -491,10 +537,10 @@ nsHTMLEditRules::WillDeleteSelection(nsIDOMSelection *aSelection, nsIEditor::ESe
|
||||
res = mEditor->DeleteSelectionImpl(aAction);
|
||||
if (NS_FAILED(res)) return res;
|
||||
// then join para's, insert break
|
||||
res = mEditor->JoinNodeDeep(leftParent,rightParent,aSelection);
|
||||
res = mEditor->JoinNodeDeep(leftParent,rightParent,&selNode,&selOffset);
|
||||
if (NS_FAILED(res)) return res;
|
||||
//res = mEditor->InsertBreak();
|
||||
// uhh, no, we don't want to have the <br> on a deleted selction across para's
|
||||
// fix up selection
|
||||
res = aSelection->Collapse(selNode,selOffset);
|
||||
return res;
|
||||
}
|
||||
if (IsListItem(leftParent) || IsHeader(leftParent))
|
||||
@ -504,7 +550,10 @@ nsHTMLEditRules::WillDeleteSelection(nsIDOMSelection *aSelection, nsIEditor::ESe
|
||||
res = mEditor->DeleteSelectionImpl(aAction);
|
||||
if (NS_FAILED(res)) return res;
|
||||
// join blocks
|
||||
res = mEditor->JoinNodeDeep(leftParent,rightParent,aSelection);
|
||||
res = mEditor->JoinNodeDeep(leftParent,rightParent,&selNode,&selOffset);
|
||||
if (NS_FAILED(res)) return res;
|
||||
// fix up selection
|
||||
res = aSelection->Collapse(selNode,selOffset);
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user