From 55fa886458664041323c55a3a69aa0fbfc5200c8 Mon Sep 17 00:00:00 2001 From: "dbaron%dbaron.org" Date: Tue, 4 Apr 2006 00:57:55 +0000 Subject: [PATCH] Fix backspace/delete on non-BMP characters for plaintext editor. b=237585 r=smontagu sr=roc --- editor/libeditor/base/nsEditor.cpp | 52 +++++++++++++++++++++++------- editor/libeditor/base/nsEditor.h | 5 +++ 2 files changed, 45 insertions(+), 12 deletions(-) diff --git a/editor/libeditor/base/nsEditor.cpp b/editor/libeditor/base/nsEditor.cpp index 49c5bd306fa..e085bd43bf1 100644 --- a/editor/libeditor/base/nsEditor.cpp +++ b/editor/libeditor/base/nsEditor.cpp @@ -5023,6 +5023,36 @@ nsEditor::CreateTxnForDeleteSelection(nsIEditor::EDirection aAction, return result; } +nsresult +nsEditor::CreateTxnForDeleteCharacter(nsIDOMCharacterData *aData, + PRUint32 aOffset, + nsIEditor::EDirection aDirection, + DeleteTextTxn **aTxn) +{ + NS_ASSERTION(aDirection == eNext || aDirection == ePrevious, + "invalid direction"); + nsAutoString data; + aData->GetData(data); + PRUint32 segOffset, segLength = 1; + if (aDirection == eNext) { + segOffset = aOffset; + if (IS_HIGH_SURROGATE(data[segOffset]) && + segOffset + 1 < data.Length() && + IS_LOW_SURROGATE(data[segOffset+1])) { + // delete both halves of the surrogate pair + ++segLength; + } + } else { + segOffset = aOffset - 1; + if (IS_LOW_SURROGATE(data[segOffset]) && + segOffset > 0 && + IS_HIGH_SURROGATE(data[segOffset-1])) { + ++segLength; + --segOffset; + } + } + return CreateTxnForDeleteText(aData, segOffset, segLength, aTxn); +} //XXX: currently, this doesn't handle edge conditions because GetNext/GetPrior are not implemented NS_IMETHODIMP @@ -5030,6 +5060,8 @@ nsEditor::CreateTxnForDeleteInsertionPoint(nsIDOMRange *aRange, nsIEditor::EDirection aAction, EditAggregateTxn *aTxn) { + NS_ASSERTION(aAction == eNext || aAction == ePrevious, "invalid action"); + // get the node and offset of the insertion point nsCOMPtr node; nsresult result = aRange->GetStartContainer(getter_AddRefs(node)); @@ -5080,7 +5112,8 @@ nsEditor::CreateTxnForDeleteInsertionPoint(nsIDOMRange *aRange, if (0AppendChild(txn); NS_RELEASE(txn); @@ -5118,7 +5151,7 @@ nsEditor::CreateTxnForDeleteInsertionPoint(nsIDOMRange *aRange, if (0AppendChild(txn); NS_RELEASE(txn); @@ -5145,11 +5178,8 @@ nsEditor::CreateTxnForDeleteInsertionPoint(nsIDOMRange *aRange, { if (nodeAsText) { // we have text, so delete a char at the proper offset - if (nsIEditor::ePrevious==aAction) { - offset --; - } DeleteTextTxn *txn; - result = CreateTxnForDeleteText(nodeAsText, offset, 1, &txn); + result = CreateTxnForDeleteCharacter(nodeAsText, offset, aAction, &txn); if (NS_SUCCEEDED(result)) { aTxn->AppendChild(txn); NS_RELEASE(txn); @@ -5173,16 +5203,14 @@ nsEditor::CreateTxnForDeleteInsertionPoint(nsIDOMRange *aRange, do_QueryInterface(selectedNode); if (selectedNodeAsText) { // we are deleting from a text node, so do a text deletion - PRInt32 begin = 0; // default for forward delete + PRUint32 position = 0; // default for forward delete if (ePrevious==aAction) { - PRUint32 length=0; - selectedNodeAsText->GetLength(&length); - if (0GetLength(&position); } DeleteTextTxn *delTextTxn; - result = CreateTxnForDeleteText(selectedNodeAsText, begin, 1, &delTextTxn); + result = CreateTxnForDeleteCharacter(selectedNodeAsText, position, + aAction, &delTextTxn); if (NS_FAILED(result)) { return result; } if (!delTextTxn) { return NS_ERROR_NULL_POINTER; } aTxn->AppendChild(delTextTxn); diff --git a/editor/libeditor/base/nsEditor.h b/editor/libeditor/base/nsEditor.h index fe87caabf4a..4a86ed93803 100644 --- a/editor/libeditor/base/nsEditor.h +++ b/editor/libeditor/base/nsEditor.h @@ -268,6 +268,11 @@ protected: PRUint32 aOffset, PRUint32 aLength, DeleteTextTxn **aTxn); + + nsresult CreateTxnForDeleteCharacter(nsIDOMCharacterData *aData, + PRUint32 aOffset, + nsIEditor::EDirection aDirection, + DeleteTextTxn **aTxn); NS_IMETHOD CreateTxnForSplitNode(nsIDOMNode *aNode, PRUint32 aOffset,