зеркало из https://github.com/mozilla/gecko-dev.git
bug 76888: plaintext editor deletion can move/lose whitesapce. r=sfraser; sr=kin
This commit is contained in:
Родитель
39db36c9ab
Коммит
68326016b3
|
@ -3495,34 +3495,6 @@ nsEditor::IsEditable(nsIDOMNode *aNode)
|
|||
|
||||
if (IsMozEditorBogusNode(aNode)) return PR_FALSE;
|
||||
|
||||
/* THIS DOESN'T WORK!
|
||||
// it's not the bogus node, so see if it is an irrelevant text node
|
||||
if (PR_TRUE==IsTextNode(aNode))
|
||||
{
|
||||
nsCOMPtr<nsIDOMCharacterData> text = do_QueryInterface(aNode);
|
||||
// nsCOMPtr<nsIDOMComment> commentNode = do_QueryInterface(aNode);
|
||||
if (text)
|
||||
{
|
||||
nsAutoString data;
|
||||
text->GetData(data);
|
||||
PRUint32 length = data.Length();
|
||||
if (0==length) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
// if the node contains only newlines, it's not editable
|
||||
// you could use nsITextContent::IsOnlyWhitespace here
|
||||
PRUint32 i;
|
||||
for (i=0; i<length; i++)
|
||||
{
|
||||
PRUnichar character = data.CharAt(i);
|
||||
if ('\n'!=character) {
|
||||
return PR_TRUE;
|
||||
}
|
||||
}
|
||||
return PR_FALSE;
|
||||
}
|
||||
}
|
||||
*/
|
||||
// we got this far, so see if it has a frame. If so, we'll edit it.
|
||||
nsIFrame *resultFrame;
|
||||
nsCOMPtr<nsIContent>content;
|
||||
|
@ -3530,15 +3502,9 @@ nsEditor::IsEditable(nsIDOMNode *aNode)
|
|||
if (content)
|
||||
{
|
||||
nsresult result = shell->GetPrimaryFrameFor(content, &resultFrame);
|
||||
if (NS_FAILED(result) || !resultFrame) { // if it has no frame, it is not editable
|
||||
if (NS_FAILED(result) || !resultFrame) // if it has no frame, it is not editable
|
||||
return PR_FALSE;
|
||||
}
|
||||
else {
|
||||
// it has a frame, so it might editable
|
||||
// but not if it's a formatting whitespace node
|
||||
if (IsEmptyTextContent(content)) return PR_FALSE;
|
||||
return PR_TRUE;
|
||||
}
|
||||
return PR_TRUE;
|
||||
}
|
||||
return PR_FALSE; // it's not a content object (???) so it's not editable
|
||||
}
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
#include "nsCOMPtr.h"
|
||||
#include "nsIDOMNode.h"
|
||||
#include "nsIDOMElement.h"
|
||||
#include "nsIDOMText.h"
|
||||
#include "nsIDOMNodeList.h"
|
||||
#include "nsISelection.h"
|
||||
#include "nsISelectionPrivate.h"
|
||||
|
@ -771,11 +772,116 @@ nsTextEditRules::WillDeleteSelection(nsISelection *aSelection,
|
|||
*aCancel = PR_TRUE;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult res = NS_OK;
|
||||
|
||||
if (mFlags & nsIPlaintextEditor::eEditorPasswordMask)
|
||||
{
|
||||
// manage the password buffer
|
||||
PRInt32 start, end;
|
||||
mEditor->GetTextSelectionOffsets(aSelection, start, end);
|
||||
if (end==start)
|
||||
{ // collapsed selection
|
||||
if (nsIEditor::ePrevious==aCollapsedAction && 0<start) { // del back
|
||||
mPasswordText.Cut(start-1, 1);
|
||||
}
|
||||
else if (nsIEditor::eNext==aCollapsedAction) { // del forward
|
||||
mPasswordText.Cut(start, 1);
|
||||
}
|
||||
// otherwise nothing to do for this collapsed selection
|
||||
}
|
||||
else { // extended selection
|
||||
mPasswordText.Cut(start, end-start);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
PRBool bCollapsed;
|
||||
res = aSelection->GetIsCollapsed(&bCollapsed);
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
nsCOMPtr<nsIDOMNode> startNode, nextNode, selNode;
|
||||
PRInt32 startOffset;
|
||||
|
||||
res = mEditor->GetStartNodeAndOffset(aSelection, address_of(startNode), &startOffset);
|
||||
if (NS_FAILED(res)) return res;
|
||||
if (!startNode) return NS_ERROR_FAILURE;
|
||||
|
||||
if (bCollapsed)
|
||||
{
|
||||
nsCOMPtr<nsIDOMText> textNode;
|
||||
PRUint32 strLength;
|
||||
|
||||
// destroy any empty text nodes in our path
|
||||
if (mEditor->IsTextNode(startNode))
|
||||
{
|
||||
textNode = do_QueryInterface(startNode);
|
||||
res = textNode->GetLength(&strLength);
|
||||
if (NS_FAILED(res)) return res;
|
||||
// if it has a length and we aren't at the edge, we are done
|
||||
if (strLength && !( ((aCollapsedAction == nsIEditor::ePrevious) && startOffset) ||
|
||||
((aCollapsedAction == nsIEditor::eNext) && startOffset==strLength) ) )
|
||||
return NS_OK;
|
||||
|
||||
// remember where we are
|
||||
selNode = startNode;
|
||||
res = nsEditor::GetNodeLocation(selNode, address_of(startNode), &startOffset);
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
// delete this text node if empty
|
||||
if (!strLength)
|
||||
{
|
||||
// delete empty text node
|
||||
res = mEditor->DeleteNode(selNode);
|
||||
if (NS_FAILED(res)) return res;
|
||||
}
|
||||
else
|
||||
{
|
||||
// if text node isn't empty, but we are at end of it, remeber that we are after it
|
||||
if (aCollapsedAction == nsIEditor::eNext)
|
||||
startOffset++;
|
||||
}
|
||||
}
|
||||
|
||||
// find next node (we know we are in container here)
|
||||
nsCOMPtr<nsIContent> child, content(do_QueryInterface(startNode));
|
||||
if (!content) return NS_ERROR_NULL_POINTER;
|
||||
if (aCollapsedAction == nsIEditor::ePrevious)
|
||||
--startOffset;
|
||||
res = content->ChildAt(startOffset, *getter_AddRefs(child));
|
||||
if (NS_FAILED(res)) return res;
|
||||
nextNode = do_QueryInterface(child);
|
||||
|
||||
// scan for next node, deleting empty text nodes on way
|
||||
while (nextNode && mEditor->IsTextNode(nextNode))
|
||||
{
|
||||
textNode = do_QueryInterface(nextNode);
|
||||
if (!textNode) break;// found a br, stop there
|
||||
|
||||
res = textNode->GetLength(&strLength);
|
||||
if (NS_FAILED(res)) return res;
|
||||
if (strLength) break; // found a non-empty text node
|
||||
|
||||
// delete empty text node
|
||||
res = mEditor->DeleteNode(nextNode);
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
// find next node
|
||||
if (aCollapsedAction == nsIEditor::ePrevious)
|
||||
--startOffset;
|
||||
// don't need to increment startOffset for nsIEditor::eNext
|
||||
res = content->ChildAt(startOffset, *getter_AddRefs(child));
|
||||
if (NS_FAILED(res)) return res;
|
||||
nextNode = do_QueryInterface(child);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef IBMBIDI // Test for distance between caret and text that will be deleted
|
||||
nsCOMPtr<nsIDOMNode> node;
|
||||
PRInt32 offset;
|
||||
|
||||
nsresult res = mEditor->GetStartNodeAndOffset(aSelection, address_of(node), &offset);
|
||||
res = mEditor->GetStartNodeAndOffset(aSelection, address_of(node), &offset);
|
||||
if (NS_FAILED(res)) return res;
|
||||
if (!node) return NS_ERROR_FAILURE;
|
||||
nsCOMPtr<nsIPresShell> shell;
|
||||
|
@ -827,126 +933,34 @@ nsTextEditRules::WillDeleteSelection(nsISelection *aSelection,
|
|||
}
|
||||
#endif // IBMBIDI
|
||||
|
||||
if (mFlags & nsIPlaintextEditor::eEditorPasswordMask)
|
||||
{
|
||||
// manage the password buffer
|
||||
PRInt32 start, end;
|
||||
mEditor->GetTextSelectionOffsets(aSelection, start, end);
|
||||
if (end==start)
|
||||
{ // collapsed selection
|
||||
if (nsIEditor::ePrevious==aCollapsedAction && 0<start) { // del back
|
||||
mPasswordText.Cut(start-1, 1);
|
||||
}
|
||||
else if (nsIEditor::eNext==aCollapsedAction) { // del forward
|
||||
mPasswordText.Cut(start, 1);
|
||||
}
|
||||
// otherwise nothing to do for this collapsed selection
|
||||
}
|
||||
else { // extended selection
|
||||
mPasswordText.Cut(start, end-start);
|
||||
}
|
||||
|
||||
#ifdef DEBUG_buster
|
||||
char *password = mPasswordText.ToNewCString();
|
||||
printf("mPasswordText is %s\n", password);
|
||||
nsCRT::free(password);
|
||||
#endif
|
||||
}
|
||||
return NS_OK;
|
||||
return res;
|
||||
}
|
||||
|
||||
// if the document is empty, insert a bogus text node with a
|
||||
// if we ended up with consecutive text nodes, merge them
|
||||
nsresult
|
||||
nsTextEditRules::DidDeleteSelection(nsISelection *aSelection,
|
||||
nsIEditor::EDirection aCollapsedAction,
|
||||
nsresult aResult)
|
||||
{
|
||||
nsresult res = aResult; // if aResult is an error, we just return it
|
||||
if (!aSelection) { return NS_ERROR_NULL_POINTER; }
|
||||
PRBool isCollapsed;
|
||||
aSelection->GetIsCollapsed(&isCollapsed);
|
||||
NS_ASSERTION(PR_TRUE==isCollapsed, "selection not collapsed after delete selection.");
|
||||
if (NS_SUCCEEDED(res)) // only do this work if DeleteSelection completed successfully
|
||||
nsresult res = NS_OK;
|
||||
nsCOMPtr<nsIDOMNode> startNode;
|
||||
PRInt32 startOffset;
|
||||
|
||||
res = mEditor->GetStartNodeAndOffset(aSelection, address_of(startNode), &startOffset);
|
||||
if (NS_FAILED(res)) return res;
|
||||
if (!startNode) return NS_ERROR_FAILURE;
|
||||
|
||||
// delete empty text nodes at selection
|
||||
if (mEditor->IsTextNode(startNode))
|
||||
{
|
||||
// if we don't have an empty document, check the selection to see if any collapsing is necessary
|
||||
if (!mBogusNode)
|
||||
nsCOMPtr<nsIDOMText> textNode = do_QueryInterface(startNode);
|
||||
PRUint32 strLength;
|
||||
res = textNode->GetLength(&strLength);
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
// are we in an empty text node?
|
||||
if (!strLength)
|
||||
{
|
||||
// get the node that contains the selection point
|
||||
nsCOMPtr<nsIDOMNode>anchor;
|
||||
PRInt32 offset;
|
||||
res = aSelection->GetAnchorNode(getter_AddRefs(anchor));
|
||||
if (NS_FAILED(res)) return res;
|
||||
if (!anchor) return NS_ERROR_NULL_POINTER;
|
||||
res = aSelection->GetAnchorOffset(&offset);
|
||||
if (NS_FAILED(res)) return res;
|
||||
// selectedNode is either the anchor itself,
|
||||
// or if anchor has children, it's the referenced child node
|
||||
// XXX ----------------------------------------------- XXX
|
||||
// I believe this s wrong. Assuming anchor and focus
|
||||
// alwas correspond to selection endpoints, it is possible
|
||||
// for the first node after the selectin start point to not
|
||||
// be selected. As an example consider a selection that
|
||||
// starts right before a <ul>, and ends after the first character
|
||||
// in the text of the first list item. Really all that is
|
||||
// selected is one letter of text, not the <ul>
|
||||
nsCOMPtr<nsIDOMNode> selectedNode = do_QueryInterface(anchor);
|
||||
PRBool hasChildren=PR_FALSE;
|
||||
anchor->HasChildNodes(&hasChildren);
|
||||
if (PR_TRUE==hasChildren)
|
||||
{ // if anchor has children, set selectedNode to the child pointed at
|
||||
nsCOMPtr<nsIDOMNodeList> anchorChildren;
|
||||
res = anchor->GetChildNodes(getter_AddRefs(anchorChildren));
|
||||
if ((NS_SUCCEEDED(res)) && anchorChildren) {
|
||||
res = anchorChildren->Item(offset, getter_AddRefs(selectedNode));
|
||||
}
|
||||
}
|
||||
|
||||
if ((NS_SUCCEEDED(res)) && selectedNode && !DeleteEmptyTextNode(selectedNode))
|
||||
{
|
||||
nsCOMPtr<nsIDOMCharacterData>selectedNodeAsText;
|
||||
selectedNodeAsText = do_QueryInterface(selectedNode);
|
||||
if (selectedNodeAsText && mEditor->IsEditable(selectedNode))
|
||||
{
|
||||
nsCOMPtr<nsIDOMNode> siblingNode;
|
||||
selectedNode->GetPreviousSibling(getter_AddRefs(siblingNode));
|
||||
if (siblingNode && !DeleteEmptyTextNode(siblingNode))
|
||||
{
|
||||
nsCOMPtr<nsIDOMCharacterData>siblingNodeAsText;
|
||||
siblingNodeAsText = do_QueryInterface(siblingNode);
|
||||
if (siblingNodeAsText && mEditor->IsEditable(siblingNode))
|
||||
{
|
||||
PRUint32 siblingLength; // the length of siblingNode before the join
|
||||
siblingNodeAsText->GetLength(&siblingLength);
|
||||
nsCOMPtr<nsIDOMNode> parentNode;
|
||||
res = selectedNode->GetParentNode(getter_AddRefs(parentNode));
|
||||
if (NS_FAILED(res)) return res;
|
||||
if (!parentNode) return NS_ERROR_NULL_POINTER;
|
||||
res = mEditor->JoinNodes(siblingNode, selectedNode, parentNode);
|
||||
// selectedNode will remain after the join, siblingNode is removed
|
||||
}
|
||||
}
|
||||
selectedNode->GetNextSibling(getter_AddRefs(siblingNode));
|
||||
if (siblingNode && !DeleteEmptyTextNode(siblingNode))
|
||||
{
|
||||
nsCOMPtr<nsIDOMCharacterData>siblingNodeAsText;
|
||||
siblingNodeAsText = do_QueryInterface(siblingNode);
|
||||
if (siblingNodeAsText && mEditor->IsEditable(siblingNode))
|
||||
{
|
||||
PRUint32 selectedNodeLength; // the length of siblingNode before the join
|
||||
selectedNodeAsText->GetLength(&selectedNodeLength);
|
||||
nsCOMPtr<nsIDOMNode> parentNode;
|
||||
res = selectedNode->GetParentNode(getter_AddRefs(parentNode));
|
||||
if (NS_FAILED(res)) return res;
|
||||
if (!parentNode) return NS_ERROR_NULL_POINTER;
|
||||
|
||||
res = mEditor->JoinNodes(selectedNode, siblingNode, parentNode);
|
||||
if (NS_FAILED(res)) return res;
|
||||
// selectedNode will remain after the join, siblingNode is removed
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
res = mEditor->DeleteNode(startNode);
|
||||
}
|
||||
}
|
||||
return res;
|
||||
|
|
|
@ -3495,34 +3495,6 @@ nsEditor::IsEditable(nsIDOMNode *aNode)
|
|||
|
||||
if (IsMozEditorBogusNode(aNode)) return PR_FALSE;
|
||||
|
||||
/* THIS DOESN'T WORK!
|
||||
// it's not the bogus node, so see if it is an irrelevant text node
|
||||
if (PR_TRUE==IsTextNode(aNode))
|
||||
{
|
||||
nsCOMPtr<nsIDOMCharacterData> text = do_QueryInterface(aNode);
|
||||
// nsCOMPtr<nsIDOMComment> commentNode = do_QueryInterface(aNode);
|
||||
if (text)
|
||||
{
|
||||
nsAutoString data;
|
||||
text->GetData(data);
|
||||
PRUint32 length = data.Length();
|
||||
if (0==length) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
// if the node contains only newlines, it's not editable
|
||||
// you could use nsITextContent::IsOnlyWhitespace here
|
||||
PRUint32 i;
|
||||
for (i=0; i<length; i++)
|
||||
{
|
||||
PRUnichar character = data.CharAt(i);
|
||||
if ('\n'!=character) {
|
||||
return PR_TRUE;
|
||||
}
|
||||
}
|
||||
return PR_FALSE;
|
||||
}
|
||||
}
|
||||
*/
|
||||
// we got this far, so see if it has a frame. If so, we'll edit it.
|
||||
nsIFrame *resultFrame;
|
||||
nsCOMPtr<nsIContent>content;
|
||||
|
@ -3530,15 +3502,9 @@ nsEditor::IsEditable(nsIDOMNode *aNode)
|
|||
if (content)
|
||||
{
|
||||
nsresult result = shell->GetPrimaryFrameFor(content, &resultFrame);
|
||||
if (NS_FAILED(result) || !resultFrame) { // if it has no frame, it is not editable
|
||||
if (NS_FAILED(result) || !resultFrame) // if it has no frame, it is not editable
|
||||
return PR_FALSE;
|
||||
}
|
||||
else {
|
||||
// it has a frame, so it might editable
|
||||
// but not if it's a formatting whitespace node
|
||||
if (IsEmptyTextContent(content)) return PR_FALSE;
|
||||
return PR_TRUE;
|
||||
}
|
||||
return PR_TRUE;
|
||||
}
|
||||
return PR_FALSE; // it's not a content object (???) so it's not editable
|
||||
}
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
#include "nsCOMPtr.h"
|
||||
#include "nsIDOMNode.h"
|
||||
#include "nsIDOMElement.h"
|
||||
#include "nsIDOMText.h"
|
||||
#include "nsIDOMNodeList.h"
|
||||
#include "nsISelection.h"
|
||||
#include "nsISelectionPrivate.h"
|
||||
|
@ -771,11 +772,116 @@ nsTextEditRules::WillDeleteSelection(nsISelection *aSelection,
|
|||
*aCancel = PR_TRUE;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult res = NS_OK;
|
||||
|
||||
if (mFlags & nsIPlaintextEditor::eEditorPasswordMask)
|
||||
{
|
||||
// manage the password buffer
|
||||
PRInt32 start, end;
|
||||
mEditor->GetTextSelectionOffsets(aSelection, start, end);
|
||||
if (end==start)
|
||||
{ // collapsed selection
|
||||
if (nsIEditor::ePrevious==aCollapsedAction && 0<start) { // del back
|
||||
mPasswordText.Cut(start-1, 1);
|
||||
}
|
||||
else if (nsIEditor::eNext==aCollapsedAction) { // del forward
|
||||
mPasswordText.Cut(start, 1);
|
||||
}
|
||||
// otherwise nothing to do for this collapsed selection
|
||||
}
|
||||
else { // extended selection
|
||||
mPasswordText.Cut(start, end-start);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
PRBool bCollapsed;
|
||||
res = aSelection->GetIsCollapsed(&bCollapsed);
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
nsCOMPtr<nsIDOMNode> startNode, nextNode, selNode;
|
||||
PRInt32 startOffset;
|
||||
|
||||
res = mEditor->GetStartNodeAndOffset(aSelection, address_of(startNode), &startOffset);
|
||||
if (NS_FAILED(res)) return res;
|
||||
if (!startNode) return NS_ERROR_FAILURE;
|
||||
|
||||
if (bCollapsed)
|
||||
{
|
||||
nsCOMPtr<nsIDOMText> textNode;
|
||||
PRUint32 strLength;
|
||||
|
||||
// destroy any empty text nodes in our path
|
||||
if (mEditor->IsTextNode(startNode))
|
||||
{
|
||||
textNode = do_QueryInterface(startNode);
|
||||
res = textNode->GetLength(&strLength);
|
||||
if (NS_FAILED(res)) return res;
|
||||
// if it has a length and we aren't at the edge, we are done
|
||||
if (strLength && !( ((aCollapsedAction == nsIEditor::ePrevious) && startOffset) ||
|
||||
((aCollapsedAction == nsIEditor::eNext) && startOffset==strLength) ) )
|
||||
return NS_OK;
|
||||
|
||||
// remember where we are
|
||||
selNode = startNode;
|
||||
res = nsEditor::GetNodeLocation(selNode, address_of(startNode), &startOffset);
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
// delete this text node if empty
|
||||
if (!strLength)
|
||||
{
|
||||
// delete empty text node
|
||||
res = mEditor->DeleteNode(selNode);
|
||||
if (NS_FAILED(res)) return res;
|
||||
}
|
||||
else
|
||||
{
|
||||
// if text node isn't empty, but we are at end of it, remeber that we are after it
|
||||
if (aCollapsedAction == nsIEditor::eNext)
|
||||
startOffset++;
|
||||
}
|
||||
}
|
||||
|
||||
// find next node (we know we are in container here)
|
||||
nsCOMPtr<nsIContent> child, content(do_QueryInterface(startNode));
|
||||
if (!content) return NS_ERROR_NULL_POINTER;
|
||||
if (aCollapsedAction == nsIEditor::ePrevious)
|
||||
--startOffset;
|
||||
res = content->ChildAt(startOffset, *getter_AddRefs(child));
|
||||
if (NS_FAILED(res)) return res;
|
||||
nextNode = do_QueryInterface(child);
|
||||
|
||||
// scan for next node, deleting empty text nodes on way
|
||||
while (nextNode && mEditor->IsTextNode(nextNode))
|
||||
{
|
||||
textNode = do_QueryInterface(nextNode);
|
||||
if (!textNode) break;// found a br, stop there
|
||||
|
||||
res = textNode->GetLength(&strLength);
|
||||
if (NS_FAILED(res)) return res;
|
||||
if (strLength) break; // found a non-empty text node
|
||||
|
||||
// delete empty text node
|
||||
res = mEditor->DeleteNode(nextNode);
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
// find next node
|
||||
if (aCollapsedAction == nsIEditor::ePrevious)
|
||||
--startOffset;
|
||||
// don't need to increment startOffset for nsIEditor::eNext
|
||||
res = content->ChildAt(startOffset, *getter_AddRefs(child));
|
||||
if (NS_FAILED(res)) return res;
|
||||
nextNode = do_QueryInterface(child);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef IBMBIDI // Test for distance between caret and text that will be deleted
|
||||
nsCOMPtr<nsIDOMNode> node;
|
||||
PRInt32 offset;
|
||||
|
||||
nsresult res = mEditor->GetStartNodeAndOffset(aSelection, address_of(node), &offset);
|
||||
res = mEditor->GetStartNodeAndOffset(aSelection, address_of(node), &offset);
|
||||
if (NS_FAILED(res)) return res;
|
||||
if (!node) return NS_ERROR_FAILURE;
|
||||
nsCOMPtr<nsIPresShell> shell;
|
||||
|
@ -827,126 +933,34 @@ nsTextEditRules::WillDeleteSelection(nsISelection *aSelection,
|
|||
}
|
||||
#endif // IBMBIDI
|
||||
|
||||
if (mFlags & nsIPlaintextEditor::eEditorPasswordMask)
|
||||
{
|
||||
// manage the password buffer
|
||||
PRInt32 start, end;
|
||||
mEditor->GetTextSelectionOffsets(aSelection, start, end);
|
||||
if (end==start)
|
||||
{ // collapsed selection
|
||||
if (nsIEditor::ePrevious==aCollapsedAction && 0<start) { // del back
|
||||
mPasswordText.Cut(start-1, 1);
|
||||
}
|
||||
else if (nsIEditor::eNext==aCollapsedAction) { // del forward
|
||||
mPasswordText.Cut(start, 1);
|
||||
}
|
||||
// otherwise nothing to do for this collapsed selection
|
||||
}
|
||||
else { // extended selection
|
||||
mPasswordText.Cut(start, end-start);
|
||||
}
|
||||
|
||||
#ifdef DEBUG_buster
|
||||
char *password = mPasswordText.ToNewCString();
|
||||
printf("mPasswordText is %s\n", password);
|
||||
nsCRT::free(password);
|
||||
#endif
|
||||
}
|
||||
return NS_OK;
|
||||
return res;
|
||||
}
|
||||
|
||||
// if the document is empty, insert a bogus text node with a
|
||||
// if we ended up with consecutive text nodes, merge them
|
||||
nsresult
|
||||
nsTextEditRules::DidDeleteSelection(nsISelection *aSelection,
|
||||
nsIEditor::EDirection aCollapsedAction,
|
||||
nsresult aResult)
|
||||
{
|
||||
nsresult res = aResult; // if aResult is an error, we just return it
|
||||
if (!aSelection) { return NS_ERROR_NULL_POINTER; }
|
||||
PRBool isCollapsed;
|
||||
aSelection->GetIsCollapsed(&isCollapsed);
|
||||
NS_ASSERTION(PR_TRUE==isCollapsed, "selection not collapsed after delete selection.");
|
||||
if (NS_SUCCEEDED(res)) // only do this work if DeleteSelection completed successfully
|
||||
nsresult res = NS_OK;
|
||||
nsCOMPtr<nsIDOMNode> startNode;
|
||||
PRInt32 startOffset;
|
||||
|
||||
res = mEditor->GetStartNodeAndOffset(aSelection, address_of(startNode), &startOffset);
|
||||
if (NS_FAILED(res)) return res;
|
||||
if (!startNode) return NS_ERROR_FAILURE;
|
||||
|
||||
// delete empty text nodes at selection
|
||||
if (mEditor->IsTextNode(startNode))
|
||||
{
|
||||
// if we don't have an empty document, check the selection to see if any collapsing is necessary
|
||||
if (!mBogusNode)
|
||||
nsCOMPtr<nsIDOMText> textNode = do_QueryInterface(startNode);
|
||||
PRUint32 strLength;
|
||||
res = textNode->GetLength(&strLength);
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
// are we in an empty text node?
|
||||
if (!strLength)
|
||||
{
|
||||
// get the node that contains the selection point
|
||||
nsCOMPtr<nsIDOMNode>anchor;
|
||||
PRInt32 offset;
|
||||
res = aSelection->GetAnchorNode(getter_AddRefs(anchor));
|
||||
if (NS_FAILED(res)) return res;
|
||||
if (!anchor) return NS_ERROR_NULL_POINTER;
|
||||
res = aSelection->GetAnchorOffset(&offset);
|
||||
if (NS_FAILED(res)) return res;
|
||||
// selectedNode is either the anchor itself,
|
||||
// or if anchor has children, it's the referenced child node
|
||||
// XXX ----------------------------------------------- XXX
|
||||
// I believe this s wrong. Assuming anchor and focus
|
||||
// alwas correspond to selection endpoints, it is possible
|
||||
// for the first node after the selectin start point to not
|
||||
// be selected. As an example consider a selection that
|
||||
// starts right before a <ul>, and ends after the first character
|
||||
// in the text of the first list item. Really all that is
|
||||
// selected is one letter of text, not the <ul>
|
||||
nsCOMPtr<nsIDOMNode> selectedNode = do_QueryInterface(anchor);
|
||||
PRBool hasChildren=PR_FALSE;
|
||||
anchor->HasChildNodes(&hasChildren);
|
||||
if (PR_TRUE==hasChildren)
|
||||
{ // if anchor has children, set selectedNode to the child pointed at
|
||||
nsCOMPtr<nsIDOMNodeList> anchorChildren;
|
||||
res = anchor->GetChildNodes(getter_AddRefs(anchorChildren));
|
||||
if ((NS_SUCCEEDED(res)) && anchorChildren) {
|
||||
res = anchorChildren->Item(offset, getter_AddRefs(selectedNode));
|
||||
}
|
||||
}
|
||||
|
||||
if ((NS_SUCCEEDED(res)) && selectedNode && !DeleteEmptyTextNode(selectedNode))
|
||||
{
|
||||
nsCOMPtr<nsIDOMCharacterData>selectedNodeAsText;
|
||||
selectedNodeAsText = do_QueryInterface(selectedNode);
|
||||
if (selectedNodeAsText && mEditor->IsEditable(selectedNode))
|
||||
{
|
||||
nsCOMPtr<nsIDOMNode> siblingNode;
|
||||
selectedNode->GetPreviousSibling(getter_AddRefs(siblingNode));
|
||||
if (siblingNode && !DeleteEmptyTextNode(siblingNode))
|
||||
{
|
||||
nsCOMPtr<nsIDOMCharacterData>siblingNodeAsText;
|
||||
siblingNodeAsText = do_QueryInterface(siblingNode);
|
||||
if (siblingNodeAsText && mEditor->IsEditable(siblingNode))
|
||||
{
|
||||
PRUint32 siblingLength; // the length of siblingNode before the join
|
||||
siblingNodeAsText->GetLength(&siblingLength);
|
||||
nsCOMPtr<nsIDOMNode> parentNode;
|
||||
res = selectedNode->GetParentNode(getter_AddRefs(parentNode));
|
||||
if (NS_FAILED(res)) return res;
|
||||
if (!parentNode) return NS_ERROR_NULL_POINTER;
|
||||
res = mEditor->JoinNodes(siblingNode, selectedNode, parentNode);
|
||||
// selectedNode will remain after the join, siblingNode is removed
|
||||
}
|
||||
}
|
||||
selectedNode->GetNextSibling(getter_AddRefs(siblingNode));
|
||||
if (siblingNode && !DeleteEmptyTextNode(siblingNode))
|
||||
{
|
||||
nsCOMPtr<nsIDOMCharacterData>siblingNodeAsText;
|
||||
siblingNodeAsText = do_QueryInterface(siblingNode);
|
||||
if (siblingNodeAsText && mEditor->IsEditable(siblingNode))
|
||||
{
|
||||
PRUint32 selectedNodeLength; // the length of siblingNode before the join
|
||||
selectedNodeAsText->GetLength(&selectedNodeLength);
|
||||
nsCOMPtr<nsIDOMNode> parentNode;
|
||||
res = selectedNode->GetParentNode(getter_AddRefs(parentNode));
|
||||
if (NS_FAILED(res)) return res;
|
||||
if (!parentNode) return NS_ERROR_NULL_POINTER;
|
||||
|
||||
res = mEditor->JoinNodes(selectedNode, siblingNode, parentNode);
|
||||
if (NS_FAILED(res)) return res;
|
||||
// selectedNode will remain after the join, siblingNode is removed
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
res = mEditor->DeleteNode(startNode);
|
||||
}
|
||||
}
|
||||
return res;
|
||||
|
|
Загрузка…
Ссылка в новой задаче