Bug 1637856 - part 1: Move WSRunObject::DeleteRange() to HTMLEditor r=m_kato

`WSRunObject::DeleteRange()` removes only text nodes which are stored when
`WSRunObject` is created.  Although it removes text nodes if it's removed,
this patch does not take care about it in the new method.  The reason is
the following patch will remove `mNodeArray` and anyway DOM tree modifiers
can check whether they are in proper position before access if it's needed.

Differential Revision: https://phabricator.services.mozilla.com/D75470
This commit is contained in:
Masayuki Nakano 2020-05-18 05:12:16 +00:00
parent 465e7d393b
commit 714518769f
4 changed files with 215 additions and 161 deletions

View File

@ -196,6 +196,11 @@ template nsIContent* HTMLEditor::FindNearEditableContent(
const EditorDOMPoint& aPoint, nsIEditor::EDirection aDirection);
template nsIContent* HTMLEditor::FindNearEditableContent(
const EditorRawDOMPoint& aPoint, nsIEditor::EDirection aDirection);
template nsresult HTMLEditor::DeleteTextAndTextNodesWithTransaction(
const EditorDOMPoint& aStartPoint, const EditorDOMPoint& aEndPoint);
template nsresult HTMLEditor::DeleteTextAndTextNodesWithTransaction(
const EditorDOMPointInText& aStartPoint,
const EditorDOMPointInText& aEndPoint);
nsresult HTMLEditor::InitEditorContentAndSelection() {
MOZ_ASSERT(IsEditActionDataAvailable());
@ -3566,6 +3571,100 @@ nsresult HTMLEditor::DeleteNodeIfInvisibleAndEditableTextNode(
return rv;
}
template <typename EditorDOMPointType>
nsresult HTMLEditor::DeleteTextAndTextNodesWithTransaction(
const EditorDOMPointType& aStartPoint,
const EditorDOMPointType& aEndPoint) {
if (NS_WARN_IF(!aStartPoint.IsSet()) || NS_WARN_IF(!aEndPoint.IsSet())) {
return NS_ERROR_INVALID_ARG;
}
// MOOSE: this routine needs to be modified to preserve the integrity of the
// wsFragment info.
if (aStartPoint == aEndPoint) {
// Nothing to delete
return NS_OK;
}
if (aStartPoint.GetContainer() == aEndPoint.GetContainer() &&
aStartPoint.IsInTextNode()) {
RefPtr<Text> textNode = aStartPoint.ContainerAsText();
nsresult rv =
DeleteTextWithTransaction(*textNode, aStartPoint.Offset(),
aEndPoint.Offset() - aStartPoint.Offset());
NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
"HTMLEditor::DeleteTextWithTransaction() failed");
return rv;
}
RefPtr<nsRange> range =
nsRange::Create(aStartPoint.ToRawRangeBoundary(),
aEndPoint.ToRawRangeBoundary(), IgnoreErrors());
if (!range) {
NS_WARNING("nsRange::Create() failed");
return NS_ERROR_FAILURE;
}
// Collect editable text nodes in the given range.
AutoTArray<OwningNonNull<Text>, 16> arrayOfTextNodes;
DOMIterator iter;
if (NS_FAILED(iter.Init(*range))) {
return NS_OK; // Nothing to delete in the range.
}
iter.AppendNodesToArray(
+[](nsINode& aNode, void*) {
MOZ_ASSERT(aNode.IsText());
return HTMLEditUtils::IsSimplyEditableNode(aNode);
},
arrayOfTextNodes);
for (OwningNonNull<Text>& textNode : arrayOfTextNodes) {
if (textNode == aStartPoint.GetContainer()) {
if (aStartPoint.IsEndOfContainer()) {
continue;
}
nsresult rv = DeleteTextWithTransaction(
MOZ_KnownLive(textNode), aStartPoint.Offset(),
textNode->Length() - aStartPoint.Offset());
if (NS_WARN_IF(Destroyed())) {
return NS_ERROR_EDITOR_DESTROYED;
}
if (NS_FAILED(rv)) {
NS_WARNING("HTMLEditor::DeleteTextWithTransaction() failed");
return rv;
}
continue;
}
if (textNode == aEndPoint.GetContainer()) {
if (aEndPoint.IsStartOfContainer()) {
break;
}
nsresult rv = DeleteTextWithTransaction(MOZ_KnownLive(textNode), 0,
aEndPoint.Offset());
if (NS_WARN_IF(Destroyed())) {
return NS_ERROR_EDITOR_DESTROYED;
}
if (NS_FAILED(rv)) {
NS_WARNING("HTMLEditor::DeleteTextWithTransaction() failed");
return rv;
}
return NS_OK;
}
nsresult rv = DeleteNodeWithTransaction(MOZ_KnownLive(textNode));
if (NS_WARN_IF(Destroyed())) {
return NS_ERROR_EDITOR_DESTROYED;
}
if (NS_FAILED(rv)) {
NS_WARNING("HTMLEditor::DeleteNodeWithTransaction() failed");
return rv;
}
}
return NS_OK;
}
nsresult HTMLEditor::InsertBRElementIfHardLineIsEmptyAndEndsWithBlockBoundary(
const EditorDOMPoint& aPointToInsert) {
MOZ_ASSERT(IsEditActionDataAvailable());

View File

@ -2012,6 +2012,16 @@ class HTMLEditor final : public TextEditor,
[[nodiscard]] MOZ_CAN_RUN_SCRIPT nsresult
DeleteNodeIfInvisibleAndEditableTextNode(nsIContent& aContent);
/**
* DeleteTextAndTextNodesWithTransaction() removes text nodes which are in
* the given range and delete some characters in start and/or end of
* the range.
*/
template <typename EditorDOMPointType>
[[nodiscard]] MOZ_CAN_RUN_SCRIPT nsresult
DeleteTextAndTextNodesWithTransaction(const EditorDOMPointType& aStartPoint,
const EditorDOMPointType& aEndPoint);
/**
* If aPoint follows invisible `<br>` element, returns the invisible `<br>`
* element. Otherwise, nullptr.

View File

@ -214,9 +214,12 @@ already_AddRefed<Element> WSRunObject::InsertBreak(
// Delete the leading ws that is after insertion point. We don't
// have to (it would still not be significant after br), but it's
// just more aesthetically pleasing to.
nsresult rv = DeleteRange(pointToInsert, afterRun->EndPoint());
nsresult rv = MOZ_KnownLive(mHTMLEditor)
.DeleteTextAndTextNodesWithTransaction(
pointToInsert, afterRun->EndPoint());
if (NS_FAILED(rv)) {
NS_WARNING("WSRunObject::DeleteRange() failed");
NS_WARNING(
"HTMLEditor::DeleteTextAndTextNodesWithTransaction() failed");
return nullptr;
}
} else if (afterRun->IsVisibleAndMiddleOfHardLine()) {
@ -251,9 +254,12 @@ already_AddRefed<Element> WSRunObject::InsertBreak(
} else if (beforeRun->IsEndOfHardLine()) {
// Need to delete the trailing ws that is before insertion point, because
// it would become significant after break inserted.
nsresult rv = DeleteRange(beforeRun->StartPoint(), pointToInsert);
nsresult rv = MOZ_KnownLive(mHTMLEditor)
.DeleteTextAndTextNodesWithTransaction(
beforeRun->StartPoint(), pointToInsert);
if (NS_FAILED(rv)) {
NS_WARNING("WSRunObject::DeleteRange() failed");
NS_WARNING(
"WSRunObject::DeleteTextAndTextNodesWithTransaction() failed");
return nullptr;
}
} else if (beforeRun->IsVisibleAndMiddleOfHardLine()) {
@ -313,9 +319,12 @@ nsresult WSRunObject::InsertText(Document& aDocument,
} else if (afterRun->IsStartOfHardLine()) {
// Delete the leading ws that is after insertion point, because it
// would become significant after text inserted.
nsresult rv = DeleteRange(pointToInsert, afterRun->EndPoint());
nsresult rv = MOZ_KnownLive(mHTMLEditor)
.DeleteTextAndTextNodesWithTransaction(
pointToInsert, afterRun->EndPoint());
if (NS_FAILED(rv)) {
NS_WARNING("WSRunObject::DeleteRange() failed");
NS_WARNING(
"HTMLEditor::DeleteTextAndTextNodesWithTransaction() failed");
return rv;
}
} else if (afterRun->IsVisibleAndMiddleOfHardLine()) {
@ -336,9 +345,12 @@ nsresult WSRunObject::InsertText(Document& aDocument,
} else if (beforeRun->IsEndOfHardLine()) {
// Need to delete the trailing ws that is before insertion point, because
// it would become significant after text inserted.
nsresult rv = DeleteRange(beforeRun->StartPoint(), pointToInsert);
nsresult rv = MOZ_KnownLive(mHTMLEditor)
.DeleteTextAndTextNodesWithTransaction(
beforeRun->StartPoint(), pointToInsert);
if (NS_FAILED(rv)) {
NS_WARNING("WSRunObject::DeleteRange() failed");
NS_WARNING(
"HTMLEditor::DeleteTextAndTextNodesWithTransaction() failed");
return rv;
}
} else if (beforeRun->IsVisibleAndMiddleOfHardLine()) {
@ -456,8 +468,12 @@ nsresult WSRunObject::DeleteWSBackward() {
return NS_OK;
}
nsresult rv =
DeleteRange(atPreviousCharOfStart, atPreviousCharOfStart.NextPoint());
NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "WSRunObject::DeleteRange() failed");
MOZ_KnownLive(mHTMLEditor)
.DeleteTextAndTextNodesWithTransaction(
atPreviousCharOfStart, atPreviousCharOfStart.NextPoint());
NS_WARNING_ASSERTION(
NS_SUCCEEDED(rv),
"HTMLEditor::DeleteTextAndTextNodesWithTransaction() failed");
return rv;
}
@ -484,8 +500,11 @@ nsresult WSRunObject::DeleteWSBackward() {
}
// finally, delete that ws
rv = DeleteRange(startToDelete, endToDelete);
NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "WSRunObject::DeleteRange() failed");
rv = MOZ_KnownLive(mHTMLEditor)
.DeleteTextAndTextNodesWithTransaction(startToDelete, endToDelete);
NS_WARNING_ASSERTION(
NS_SUCCEEDED(rv),
"HTMLEditor::DeleteTextAndTextNodesWithTransaction() failed");
return rv;
}
@ -500,8 +519,11 @@ nsresult WSRunObject::DeleteWSBackward() {
}
// finally, delete that ws
rv = DeleteRange(startToDelete, endToDelete);
NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "WSRunObject::DeleteRange() failed");
rv = MOZ_KnownLive(mHTMLEditor)
.DeleteTextAndTextNodesWithTransaction(startToDelete, endToDelete);
NS_WARNING_ASSERTION(
NS_SUCCEEDED(rv),
"HTMLEditor::DeleteTextAndTextNodesWithTransaction() failed");
return rv;
}
@ -520,8 +542,12 @@ nsresult WSRunObject::DeleteWSForward() {
!atNextCharOfStart.IsCharNBSP()) {
return NS_OK;
}
nsresult rv = DeleteRange(atNextCharOfStart, atNextCharOfStart.NextPoint());
NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "WSRunObject::DeleteRange() failed");
nsresult rv = MOZ_KnownLive(mHTMLEditor)
.DeleteTextAndTextNodesWithTransaction(
atNextCharOfStart, atNextCharOfStart.NextPoint());
NS_WARNING_ASSERTION(
NS_SUCCEEDED(rv),
"HTMLEditor::DeleteTextAndTextNodesWithTransaction() failed");
return rv;
}
@ -547,8 +573,11 @@ nsresult WSRunObject::DeleteWSForward() {
}
// Finally, delete that ws
rv = DeleteRange(startToDelete, endToDelete);
NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "WSRunObject::DeleteRange() failed");
rv = MOZ_KnownLive(mHTMLEditor)
.DeleteTextAndTextNodesWithTransaction(startToDelete, endToDelete);
NS_WARNING_ASSERTION(
NS_SUCCEEDED(rv),
"HTMLEditor::DeleteTextAndTextNodesWithTransaction() failed");
return rv;
}
@ -563,8 +592,11 @@ nsresult WSRunObject::DeleteWSForward() {
}
// Finally, delete that ws
rv = DeleteRange(startToDelete, endToDelete);
NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "WSRunObject::DeleteRange() failed");
rv = MOZ_KnownLive(mHTMLEditor)
.DeleteTextAndTextNodesWithTransaction(startToDelete, endToDelete);
NS_WARNING_ASSERTION(
NS_SUCCEEDED(rv),
"HTMLEditor::DeleteTextAndTextNodesWithTransaction() failed");
return rv;
}
@ -1121,10 +1153,12 @@ nsresult WSRunObject::PrepareToDeleteRangePriv(WSRunObject* aEndObject) {
// mScanStartPoint will be referred bellow so that we need to keep
// it a valid point.
AutoEditorDOMPointChildInvalidator forgetChild(mScanStartPoint);
nsresult rv = aEndObject->DeleteRange(aEndObject->mScanStartPoint,
afterRun->EndPoint());
nsresult rv = MOZ_KnownLive(mHTMLEditor)
.DeleteTextAndTextNodesWithTransaction(
aEndObject->mScanStartPoint, afterRun->EndPoint());
if (NS_FAILED(rv)) {
NS_WARNING("WSRunObject::DeleteRange() failed");
NS_WARNING(
"HTMLEditor::DeleteTextAndTextNodesWithTransaction() failed");
return rv;
}
}
@ -1162,12 +1196,13 @@ nsresult WSRunObject::PrepareToDeleteRangePriv(WSRunObject* aEndObject) {
// trim before run of any trailing ws
if (beforeRun->IsEndOfHardLine()) {
nsresult rv = DeleteRange(beforeRun->StartPoint(), mScanStartPoint);
if (NS_FAILED(rv)) {
NS_WARNING("WSRunObject::DeleteRange() failed");
return rv;
}
return NS_OK;
nsresult rv = MOZ_KnownLive(mHTMLEditor)
.DeleteTextAndTextNodesWithTransaction(
beforeRun->StartPoint(), mScanStartPoint);
NS_WARNING_ASSERTION(
NS_SUCCEEDED(rv),
"HTMLEditor::DeleteTextAndTextNodesWithTransaction() failed");
return rv;
}
if (beforeRun->IsVisibleAndMiddleOfHardLine() && !mPRE) {
@ -1260,107 +1295,6 @@ nsresult WSRunObject::PrepareToSplitAcrossBlocksPriv() {
return NS_OK;
}
nsresult WSRunObject::DeleteRange(const EditorDOMPoint& aStartPoint,
const EditorDOMPoint& aEndPoint) {
if (NS_WARN_IF(!aStartPoint.IsSet()) || NS_WARN_IF(!aEndPoint.IsSet())) {
return NS_ERROR_INVALID_ARG;
}
MOZ_ASSERT(aStartPoint.IsSetAndValid());
MOZ_ASSERT(aEndPoint.IsSetAndValid());
// MOOSE: this routine needs to be modified to preserve the integrity of the
// wsFragment info.
if (aStartPoint == aEndPoint) {
// Nothing to delete
return NS_OK;
}
if (aStartPoint.GetContainer() == aEndPoint.GetContainer() &&
aStartPoint.IsInTextNode()) {
RefPtr<Text> textNode = aStartPoint.ContainerAsText();
nsresult rv = MOZ_KnownLive(mHTMLEditor)
.DeleteTextWithTransaction(
*textNode, aStartPoint.Offset(),
aEndPoint.Offset() - aStartPoint.Offset());
NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
"HTMLEditor::DeleteTextWithTransaction() failed");
return rv;
}
RefPtr<nsRange> range;
int32_t count = mNodeArray.Length();
int32_t idx = mNodeArray.IndexOf(aStartPoint.GetContainer());
if (idx == -1) {
// If our starting point wasn't one of our ws text nodes, then just go
// through them from the beginning.
idx = 0;
}
for (; idx < count; idx++) {
RefPtr<Text> node = mNodeArray[idx];
if (!node) {
// We ran out of ws nodes; must have been deleting to end
return NS_OK;
}
if (node == aStartPoint.GetContainer()) {
if (!aStartPoint.IsEndOfContainer()) {
nsresult rv = MOZ_KnownLive(mHTMLEditor)
.DeleteTextWithTransaction(
*node, aStartPoint.Offset(),
aStartPoint.GetContainer()->Length() -
aStartPoint.Offset());
if (NS_FAILED(rv)) {
NS_WARNING("HTMLEditor::DeleteTextWithTransaction() failed");
return rv;
}
}
} else if (node == aEndPoint.GetContainer()) {
if (!aEndPoint.IsStartOfContainer()) {
nsresult rv =
MOZ_KnownLive(mHTMLEditor)
.DeleteTextWithTransaction(*node, 0, aEndPoint.Offset());
if (NS_FAILED(rv)) {
NS_WARNING("HTMLEditor::DeleteTextWithTransaction() failed");
return rv;
}
}
break;
} else {
if (!range) {
ErrorResult error;
range = nsRange::Create(aStartPoint.ToRawRangeBoundary(),
aEndPoint.ToRawRangeBoundary(), error);
if (!range) {
NS_WARNING("nsRange::Create() failed");
return error.StealNSResult();
}
}
bool nodeBefore, nodeAfter;
nsresult rv =
RangeUtils::CompareNodeToRange(node, range, &nodeBefore, &nodeAfter);
if (NS_FAILED(rv)) {
NS_WARNING("RangeUtils::CompareNodeToRange() failed");
return rv;
}
if (nodeAfter) {
break;
}
if (!nodeBefore) {
nsresult rv =
MOZ_KnownLive(mHTMLEditor).DeleteNodeWithTransaction(*node);
if (NS_FAILED(rv)) {
NS_WARNING("HTMLEditor::DeleteNodeWithTransaction() failed");
return rv;
}
mNodeArray.RemoveElement(node);
--count;
--idx;
}
}
}
return NS_OK;
}
template <typename PT, typename CT>
EditorDOMPointInText WSRunScanner::GetNextCharPoint(
const EditorDOMPointBase<PT, CT>& aPoint) const {
@ -1481,8 +1415,11 @@ nsresult WSRunObject::InsertNBSPAndRemoveFollowingASCIIWhitespaces(
"end point, but ignored");
// Finally, delete that replaced ws, if any
rv = DeleteRange(start, end);
NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "WSRunObject::DeleteRange() failed");
rv = MOZ_KnownLive(mHTMLEditor)
.DeleteTextAndTextNodesWithTransaction(start, end);
NS_WARNING_ASSERTION(
NS_SUCCEEDED(rv),
"HTMLEditor::DeleteTextAndTextNodesWithTransaction() failed");
return rv;
}
@ -1808,11 +1745,13 @@ nsresult WSRunObject::CheckTrailingNBSPOfRun(WSFragment* aRun) {
"expected position");
EditorDOMPointInText atNextCharOfPreviousCharOfEndOfRun =
atPreviousCharOfEndOfRun.NextPoint();
nsresult rv =
DeleteRange(atNextCharOfPreviousCharOfEndOfRun,
atNextCharOfPreviousCharOfEndOfRun.NextPoint());
nsresult rv = MOZ_KnownLive(mHTMLEditor)
.DeleteTextAndTextNodesWithTransaction(
atNextCharOfPreviousCharOfEndOfRun,
atNextCharOfPreviousCharOfEndOfRun.NextPoint());
if (NS_FAILED(rv)) {
NS_WARNING("WSRunObject::DeleteRange() failed");
NS_WARNING(
"HTMLEditor::DeleteTextAndTextNodesWithTransaction() failed");
return rv;
}
}
@ -1842,10 +1781,13 @@ nsresult WSRunObject::CheckTrailingNBSPOfRun(WSFragment* aRun) {
NS_ASSERTION(atPreviousCharOfEndOfRun.IsCharNBSP(),
"Trying to remove an NBSP, but it's gone from the "
"expected position");
nsresult rv = DeleteRange(atPreviousCharOfEndOfRun,
atPreviousCharOfEndOfRun.NextPoint());
nsresult rv = MOZ_KnownLive(mHTMLEditor)
.DeleteTextAndTextNodesWithTransaction(
atPreviousCharOfEndOfRun,
atPreviousCharOfEndOfRun.NextPoint());
if (NS_FAILED(rv)) {
NS_WARNING("WSRunObject::DeleteRange() failed");
NS_WARNING(
"HTMLEditor::DeleteTextAndTextNodesWithTransaction() failed");
return rv;
}
}
@ -1927,9 +1869,13 @@ nsresult WSRunObject::ReplacePreviousNBSPIfUnnecessary(
atPreviousChar.IsNextCharNBSP(),
"Trying to remove an NBSP, but it's gone from the expected position");
EditorDOMPointInText atNextCharOfPreviousChar = atPreviousChar.NextPoint();
nsresult rv = DeleteRange(atNextCharOfPreviousChar,
atNextCharOfPreviousChar.NextPoint());
NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "WSRunObject::DeleteRange() failed");
nsresult rv =
MOZ_KnownLive(mHTMLEditor)
.DeleteTextAndTextNodesWithTransaction(
atNextCharOfPreviousChar, atNextCharOfPreviousChar.NextPoint());
NS_WARNING_ASSERTION(
NS_SUCCEEDED(rv),
"HTMLEditor::DeleteTextAndTextNodesWithTransaction() failed");
return rv;
}
@ -1982,9 +1928,12 @@ nsresult WSRunObject::CheckLeadingNBSP(WSFragment* aRun, nsINode* aNode,
atNextChar.IsNextCharNBSP(),
"Trying to remove an NBSP, but it's gone from the expected position");
EditorDOMPointInText atNextCharOfNextChar = atNextChar.NextPoint();
rv = DeleteRange(atNextCharOfNextChar, atNextCharOfNextChar.NextPoint());
NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
"WSRunObject::DeleteRange() failed");
rv = MOZ_KnownLive(mHTMLEditor)
.DeleteTextAndTextNodesWithTransaction(
atNextCharOfNextChar, atNextCharOfNextChar.NextPoint());
NS_WARNING_ASSERTION(
NS_SUCCEEDED(rv),
"HTMLEditor::DeleteTextAndTextNodesWithTransaction() failed");
return rv;
}
}
@ -1996,9 +1945,11 @@ nsresult WSRunObject::Scrub() {
if (run->IsMiddleOfHardLine()) {
continue;
}
nsresult rv = DeleteRange(run->StartPoint(), run->EndPoint());
nsresult rv = MOZ_KnownLive(mHTMLEditor)
.DeleteTextAndTextNodesWithTransaction(run->StartPoint(),
run->EndPoint());
if (NS_FAILED(rv)) {
NS_WARNING("WSRunObject::DeleteRange() failed");
NS_WARNING("HTMLEditor::DeleteTextAndTextNodesWithTransaction() failed");
return rv;
}
}

View File

@ -436,10 +436,16 @@ class MOZ_STACK_CLASS WSRunScanner {
mIsStartOfHardLine(StartOfHardLine::No),
mIsEndOfHardLine(EndOfHardLine::No) {}
EditorRawDOMPoint StartPoint() const {
EditorDOMPoint StartPoint() const {
return EditorDOMPoint(mStartNode, mStartOffset);
}
EditorDOMPoint EndPoint() const {
return EditorDOMPoint(mEndNode, mEndOffset);
}
EditorRawDOMPoint RawStartPoint() const {
return EditorRawDOMPoint(mStartNode, mStartOffset);
}
EditorRawDOMPoint EndPoint() const {
EditorRawDOMPoint RawEndPoint() const {
return EditorRawDOMPoint(mEndNode, mEndOffset);
}
@ -798,18 +804,6 @@ class MOZ_STACK_CLASS WSRunObject final : public WSRunScanner {
MOZ_CAN_RUN_SCRIPT nsresult PrepareToDeleteRangePriv(WSRunObject* aEndObject);
MOZ_CAN_RUN_SCRIPT nsresult PrepareToSplitAcrossBlocksPriv();
/**
* DeleteRange() removes the range between aStartPoint and aEndPoint.
* When aStartPoint and aEndPoint are same point, does nothing.
* When aStartPoint and aEndPoint are in same text node, removes characters
* between them.
* When aStartPoint is in a text node, removes the text data after the point.
* When aEndPoint is in a text node, removes the text data before the point.
* Removes any nodes between them.
*/
MOZ_CAN_RUN_SCRIPT nsresult DeleteRange(const EditorDOMPoint& aStartPoint,
const EditorDOMPoint& aEndPoint);
/**
* InsertNBSPAndRemoveFollowingASCIIWhitespaces() inserts an NBSP first.
* Then, if following characters are ASCII whitespaces, will remove them.