Bug 344423. Backspace notifications off by 1

This commit is contained in:
aaronleventhal%moonset.net 2006-08-30 14:17:05 +00:00
Родитель ca5218736c
Коммит 3d8aea6ee4
2 изменённых файлов: 98 добавлений и 8 удалений

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

@ -1032,6 +1032,7 @@ NS_IMETHODIMP nsHyperTextAccessible::WillInsertNode(nsIDOMNode *aNode, nsIDOMNod
NS_IMETHODIMP nsHyperTextAccessible::DidInsertNode(nsIDOMNode *aNode, nsIDOMNode *aParent,
PRInt32 aPosition, nsresult aResult)
{
InvalidateChildren();
AtkTextChange textData;
textData.add = PR_TRUE;
@ -1067,6 +1068,7 @@ NS_IMETHODIMP nsHyperTextAccessible::WillDeleteNode(nsIDOMNode *aChild)
AtkTextChange textData;
textData.add = PR_FALSE;
textData.length = 1;
nsCOMPtr<nsIContent> content(do_QueryInterface(aChild));
if (content && content->IsNodeOfType(nsINode::eTEXT)) {
textData.length = content->TextLength();
@ -1086,7 +1088,13 @@ NS_IMETHODIMP nsHyperTextAccessible::WillDeleteNode(nsIDOMNode *aChild)
}
}
if (NS_FAILED(DOMPointToOffset(aChild, 0, &textData.start))) {
nsCOMPtr<nsIDOMNode> parentNode;
aChild->GetParentNode(getter_AddRefs(parentNode));
nsCOMPtr<nsIContent> parentContent(do_QueryInterface(parentNode));
NS_ENSURE_TRUE(parentContent, NS_ERROR_FAILURE);
nsCOMPtr<nsIContent> childContent(do_QueryInterface(aChild));
NS_ENSURE_TRUE(childContent, NS_ERROR_FAILURE);
if (NS_FAILED(DOMPointToOffset(parentNode, parentContent->IndexOf(childContent), &textData.start))) {
return NS_OK;
}
return FireTextChangeEvent(&textData);
@ -1094,7 +1102,7 @@ NS_IMETHODIMP nsHyperTextAccessible::WillDeleteNode(nsIDOMNode *aChild)
NS_IMETHODIMP nsHyperTextAccessible::DidDeleteNode(nsIDOMNode *aChild, nsresult aResult)
{
return NS_OK;
return InvalidateChildren();
}
NS_IMETHODIMP nsHyperTextAccessible::WillSplitNode(nsIDOMNode *aExistingRightNode, PRInt32 aOffset)
@ -1105,7 +1113,7 @@ NS_IMETHODIMP nsHyperTextAccessible::WillSplitNode(nsIDOMNode *aExistingRightNod
NS_IMETHODIMP nsHyperTextAccessible::DidSplitNode(nsIDOMNode *aExistingRightNode, PRInt32 aOffset,
nsIDOMNode *aNewLeftNode, nsresult aResult)
{
return NS_OK;
return InvalidateChildren();
}
NS_IMETHODIMP nsHyperTextAccessible::WillJoinNodes(nsIDOMNode *aLeftNode,
@ -1117,7 +1125,7 @@ NS_IMETHODIMP nsHyperTextAccessible::WillJoinNodes(nsIDOMNode *aLeftNode,
NS_IMETHODIMP nsHyperTextAccessible::DidJoinNodes(nsIDOMNode *aLeftNode, nsIDOMNode *aRightNode,
nsIDOMNode *aParent, nsresult aResult)
{
return NS_OK;
return InvalidateChildren();
}
NS_IMETHODIMP nsHyperTextAccessible::WillInsertText(nsIDOMCharacterData *aTextNode,

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

@ -65,6 +65,7 @@
#include "nsIDOMTextListener.h"
#include "nsIDOMCompositionListener.h"
#include "nsIDOMDragListener.h"
#include "nsIDOMHTMLBRElement.h"
#include "nsIDocument.h"
#include "nsITransactionManager.h"
#include "nsIAbsorbingTransaction.h"
@ -4593,29 +4594,110 @@ nsEditor::DeleteSelectionImpl(nsIEditor::EDirection aAction)
if (NS_FAILED(res)) return res;
nsAutoRules beginRulesSniffing(this, kOpDeleteSelection, aAction);
nsCOMPtr<nsIDOMCharacterData> deleteCharData;
nsCOMPtr<nsIDOMNode> deleteNode;
PRInt32 deleteCharOffset = -1;
PRBool isDeletingOneChar = PR_FALSE;
// Notification uses nsIEditActionListener::[Will|Did]Delete[Text|Node] instead of
// nsIEditActionListener::[Will|Did]DeleteSelection when collapsed action is
// used to delete one character forward or backwards.
// The following code block determines what to call by setting
// isDeletingOneChar, deleteNode and deleteCharData
if (aAction == ePrevious || aAction == eNext) {
#ifdef DEBUG
PRUint32 flags;
NS_ASSERTION(NS_SUCCEEDED(GetFlags(&flags) &&
(flags & nsIPlaintextEditor::eEditorPlaintextMask)),
"Should not have reached this point in rich text editor");
#endif
res = selection->GetIsCollapsed(&isDeletingOneChar);
if (isDeletingOneChar) {
// XXX After bug 240933 is fixed we will never be deleting a node
// a node, there will always be a char data
selection->GetFocusNode(getter_AddRefs(deleteNode));
deleteCharData = do_QueryInterface(deleteNode);
selection->GetFocusOffset(&deleteCharOffset);
if (!deleteCharData) {
nsCOMPtr<nsINode> parentNode(do_QueryInterface(deleteNode));
deleteNode = do_QueryInterface(parentNode->GetChildAt(deleteCharOffset));
deleteCharData = do_QueryInterface(deleteNode);
deleteCharOffset = 0;
}
if (aAction == ePrevious && --deleteCharOffset < 0) {
// Backspace pressed at beginning of node, so get the previous node
nsCOMPtr<nsIDOMNode> previousNode;
deleteNode->GetPreviousSibling(getter_AddRefs(previousNode));
deleteNode.swap(previousNode);
deleteCharData = do_QueryInterface(deleteNode);
}
PRUint32 deleteDataLength = 1; // Treat deleted node as length of 1
if (deleteCharData) {
deleteCharData->GetLength(&deleteDataLength);
}
// Check for valid position for a deletion
if (deleteCharOffset < 0) {
deleteCharOffset = deleteDataLength - 1;
}
else if (deleteCharOffset >= NS_STATIC_CAST(PRInt32, deleteDataLength)) {
nsCOMPtr<nsIDOMNode> nextNode;
deleteNode->GetNextSibling(getter_AddRefs(nextNode));
deleteNode.swap(nextNode);
deleteCharOffset = 0;
}
deleteCharData = do_QueryInterface(deleteNode);
#ifdef DEBUG
nsCOMPtr<nsIDOMHTMLBRElement> deleteBR(do_QueryInterface(deleteNode));
NS_ASSERTION(!deleteNode || deleteCharData || deleteBR,
"Deleting non-BR node in plaintext editor");
#endif
}
}
PRInt32 i;
nsIEditActionListener *listener;
if (NS_SUCCEEDED(res))
{
// Notify nsIEditActionListener::WillDelete[Selection|Text|Node]
if (mActionListeners)
{
for (i = 0; i < mActionListeners->Count(); i++)
{
listener = (nsIEditActionListener *)mActionListeners->ElementAt(i);
if (listener)
listener->WillDeleteSelection(selection);
if (listener) {
if (!isDeletingOneChar) {
listener->WillDeleteSelection(selection);
}
else if (deleteCharData) {
listener->WillDeleteText(deleteCharData, deleteCharOffset, 1);
}
else if (deleteNode) {
listener->WillDeleteNode(deleteNode);
}
}
}
}
// Delete the specified amount
res = DoTransaction(txn);
// Notify nsIEditActionListener::DidDelete[Selection|Text|Node]
if (mActionListeners)
{
for (i = 0; i < mActionListeners->Count(); i++)
{
listener = (nsIEditActionListener *)mActionListeners->ElementAt(i);
if (listener)
listener->DidDeleteSelection(selection);
if (listener) {
if (!isDeletingOneChar) {
listener->DidDeleteSelection(selection);
}
else if (deleteCharData) {
listener->DidDeleteText(deleteCharData, deleteCharOffset, 1, res);
}
else if (deleteNode) {
listener->DidDeleteNode(deleteNode, res);
}
}
}
}
}