diff --git a/editor/base/nsEditor.cpp b/editor/base/nsEditor.cpp index 60570b7f8030..3aed9d654b96 100644 --- a/editor/base/nsEditor.cpp +++ b/editor/base/nsEditor.cpp @@ -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 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 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 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 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
  • 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 *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 leftNodeToJoin = do_QueryInterface(aLeftNode); nsCOMPtr rightNodeToJoin = do_QueryInterface(aRightNode); - nsCOMPtr parentNode; - PRInt32 offset; + nsCOMPtr 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)) + { + nsCOMPtrnodeAsText; + 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 nodeAsText; - nsCOMPtr 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 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); + } } } } diff --git a/editor/base/nsEditor.h b/editor/base/nsEditor.h index c0df4d1d14c1..821ec7618a23 100644 --- a/editor/base/nsEditor.h +++ b/editor/base/nsEditor.h @@ -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 *aOutJoinNode, PRInt32 *outOffset); + + nsresult GetString(const nsString& name, nsString& value); nsresult BeginUpdateViewBatch(void); nsresult EndUpdateViewBatch(void); diff --git a/editor/base/nsHTMLEditRules.cpp b/editor/base/nsHTMLEditRules.cpp index b3d2241806ad..5f70ff0e5923 100644 --- a/editor/base/nsHTMLEditRules.cpp +++ b/editor/base/nsHTMLEditRules.cpp @@ -306,8 +306,8 @@ nsHTMLEditRules::WillDeleteSelection(nsIDOMSelection *aSelection, nsIEditor::ESe res = aSelection->GetIsCollapsed(&bCollapsed); if (NS_FAILED(res)) return res; - nsCOMPtr node; - PRInt32 offset; + nsCOMPtr 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 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; + nsCOMPtrnodeAsText; + 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
    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; } } diff --git a/editor/libeditor/base/nsEditor.cpp b/editor/libeditor/base/nsEditor.cpp index 60570b7f8030..3aed9d654b96 100644 --- a/editor/libeditor/base/nsEditor.cpp +++ b/editor/libeditor/base/nsEditor.cpp @@ -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 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 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 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 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
  • 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 *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 leftNodeToJoin = do_QueryInterface(aLeftNode); nsCOMPtr rightNodeToJoin = do_QueryInterface(aRightNode); - nsCOMPtr parentNode; - PRInt32 offset; + nsCOMPtr 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)) + { + nsCOMPtrnodeAsText; + 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 nodeAsText; - nsCOMPtr 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 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); + } } } } diff --git a/editor/libeditor/base/nsEditor.h b/editor/libeditor/base/nsEditor.h index c0df4d1d14c1..821ec7618a23 100644 --- a/editor/libeditor/base/nsEditor.h +++ b/editor/libeditor/base/nsEditor.h @@ -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 *aOutJoinNode, PRInt32 *outOffset); + + nsresult GetString(const nsString& name, nsString& value); nsresult BeginUpdateViewBatch(void); nsresult EndUpdateViewBatch(void); diff --git a/editor/libeditor/html/nsHTMLEditRules.cpp b/editor/libeditor/html/nsHTMLEditRules.cpp index b3d2241806ad..5f70ff0e5923 100644 --- a/editor/libeditor/html/nsHTMLEditRules.cpp +++ b/editor/libeditor/html/nsHTMLEditRules.cpp @@ -306,8 +306,8 @@ nsHTMLEditRules::WillDeleteSelection(nsIDOMSelection *aSelection, nsIEditor::ESe res = aSelection->GetIsCollapsed(&bCollapsed); if (NS_FAILED(res)) return res; - nsCOMPtr node; - PRInt32 offset; + nsCOMPtr 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 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; + nsCOMPtrnodeAsText; + 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
    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; } }