Bug 1883562 - part 2: Make EditorBase::DeleteRangesWithTransaction and the fallback path of AutoDeleteRangesHandler work with single range r=m_kato

Although from the maintenance cost point of view, we should not duplicate
`EditorBase::DeleteRangesWithTransaction`, but let's add a wrapper for it
for making the callers simpler.

Differential Revision: https://phabricator.services.mozilla.com/D203854
This commit is contained in:
Masayuki Nakano 2024-03-11 08:01:51 +00:00
parent 4099ab71e0
commit 900d40dd31
3 changed files with 242 additions and 153 deletions

View file

@ -4869,6 +4869,29 @@ nsresult EditorBase::DeleteSelectionWithTransaction(
return NS_OK;
}
Result<CaretPoint, nsresult> EditorBase::DeleteRangeWithTransaction(
nsIEditor::EDirection aDirectionAndAmount,
nsIEditor::EStripWrappers aStripWrappers, nsRange& aRangeToDelete) {
MOZ_ASSERT(IsEditActionDataAvailable());
MOZ_ASSERT(!Destroyed());
MOZ_ASSERT(aStripWrappers == eStrip || aStripWrappers == eNoStrip);
HowToHandleCollapsedRange howToHandleCollapsedRange =
EditorBase::HowToHandleCollapsedRangeFor(aDirectionAndAmount);
if (MOZ_UNLIKELY(aRangeToDelete.Collapsed() &&
howToHandleCollapsedRange ==
HowToHandleCollapsedRange::Ignore)) {
return CaretPoint(EditorDOMPoint(aRangeToDelete.StartRef()));
}
AutoRangeArray rangesToDelete(aRangeToDelete);
Result<CaretPoint, nsresult> result = DeleteRangesWithTransaction(
aDirectionAndAmount, aStripWrappers, rangesToDelete);
NS_WARNING_ASSERTION(result.isOk(),
"EditorBase::DeleteRangesWithTransaction() failed");
return result;
}
Result<CaretPoint, nsresult> EditorBase::DeleteRangesWithTransaction(
nsIEditor::EDirection aDirectionAndAmount,
nsIEditor::EStripWrappers aStripWrappers,

View file

@ -2518,6 +2518,25 @@ class EditorBase : public nsIEditor,
DeleteSelectionWithTransaction(nsIEditor::EDirection aDirectionAndAmount,
nsIEditor::EStripWrappers aStripWrappers);
/**
* DeleteRangeWithTransaction() removes content in aRangeToDelete or content
* around collapsed aRangeToDelete with transactions and remove empty
* inclusive ancestor inline elements of the collapsed range after removing
* the contents.
*
* @param aDirectionAndAmount How much range should be removed.
* @param aStripWrappers Whether the parent blocks should be removed
* when they become empty.
* Note that this must be `nsIEditor::eNoStrip`
* if this is a TextEditor because anyway it'll
* be ignored.
* @param aRangeToDelete The range to delete content.
*/
[[nodiscard]] MOZ_CAN_RUN_SCRIPT Result<CaretPoint, nsresult>
DeleteRangeWithTransaction(nsIEditor::EDirection aDirectionAndAmount,
nsIEditor::EStripWrappers aStripWrappers,
nsRange& aRangeToDelete);
/**
* DeleteRangesWithTransaction() removes content in aRangesToDelete or content
* around collapsed ranges in aRangesToDelete with transactions and remove

View file

@ -415,6 +415,20 @@ class MOZ_STACK_CLASS HTMLEditor::AutoDeleteRangesHandler final {
DeleteParentBlocksWithTransactionIfEmpty(HTMLEditor& aHTMLEditor,
const EditorDOMPoint& aPoint);
[[nodiscard]] MOZ_CAN_RUN_SCRIPT Result<CaretPoint, nsresult>
FallbackToDeleteRangeWithTransaction(HTMLEditor& aHTMLEditor,
nsRange& aRangeToDelete) const {
MOZ_ASSERT(aHTMLEditor.IsEditActionDataAvailable());
MOZ_ASSERT(CanFallbackToDeleteRangeWithTransaction(aRangeToDelete));
Result<CaretPoint, nsresult> caretPointOrError =
aHTMLEditor.DeleteRangeWithTransaction(mOriginalDirectionAndAmount,
mOriginalStripWrappers,
aRangeToDelete);
NS_WARNING_ASSERTION(caretPointOrError.isOk(),
"EditorBase::DeleteRangeWithTransaction() failed");
return caretPointOrError;
}
[[nodiscard]] MOZ_CAN_RUN_SCRIPT Result<CaretPoint, nsresult>
FallbackToDeleteRangesWithTransaction(HTMLEditor& aHTMLEditor,
AutoRangeArray& aRangesToDelete) const {
@ -425,26 +439,68 @@ class MOZ_STACK_CLASS HTMLEditor::AutoDeleteRangesHandler final {
mOriginalStripWrappers,
aRangesToDelete);
NS_WARNING_ASSERTION(caretPointOrError.isOk(),
"HTMLEditor::DeleteRangesWithTransaction() failed");
"EditorBase::DeleteRangesWithTransaction() failed");
return caretPointOrError;
}
/**
* ComputeRangesToDeleteRangesWithTransaction() computes target ranges
* which will be called by `EditorBase::DeleteRangesWithTransaction()`.
* Compute target range(s) which will be called by
* `EditorBase::DeleteRangeWithTransaction()` or
* `EditorBase::DeleteRangesWithTransaction()`.
* TODO: We should not use it for consistency with each deletion handler
* in this and nested classes.
*/
nsresult ComputeRangeToDeleteRangeWithTransaction(
const HTMLEditor& aHTMLEditor, nsIEditor::EDirection aDirectionAndAmount,
nsRange& aRange, const Element& aEditingHost) const;
nsresult ComputeRangesToDeleteRangesWithTransaction(
const HTMLEditor& aHTMLEditor, nsIEditor::EDirection aDirectionAndAmount,
AutoRangeArray& aRangesToDelete) const;
AutoRangeArray& aRangesToDelete, const Element& aEditingHost) const {
MOZ_ASSERT(!aRangesToDelete.Ranges().IsEmpty());
const EditorBase::HowToHandleCollapsedRange howToHandleCollapsedRange =
EditorBase::HowToHandleCollapsedRangeFor(aDirectionAndAmount);
if (NS_WARN_IF(aRangesToDelete.IsCollapsed() &&
howToHandleCollapsedRange ==
EditorBase::HowToHandleCollapsedRange::Ignore)) {
return NS_ERROR_FAILURE;
}
for (const OwningNonNull<nsRange>& range : aRangesToDelete.Ranges()) {
if (range->Collapsed()) {
continue;
}
nsresult rv = ComputeRangeToDeleteRangeWithTransaction(
aHTMLEditor, aDirectionAndAmount, range, aEditingHost);
if (NS_FAILED(rv)) {
NS_WARNING(
"AutoDeleteRangesHandler::ComputeRangeToDeleteRangeWithTransaction("
") failed");
return rv;
}
}
return NS_OK;
}
nsresult FallbackToComputeRangeToDeleteRangeWithTransaction(
const HTMLEditor& aHTMLEditor, nsRange& aRangeToDelete,
const Element& aEditingHost) const {
MOZ_ASSERT(aHTMLEditor.IsEditActionDataAvailable());
MOZ_ASSERT(CanFallbackToDeleteRangeWithTransaction(aRangeToDelete));
nsresult rv = ComputeRangeToDeleteRangeWithTransaction(
aHTMLEditor, mOriginalDirectionAndAmount, aRangeToDelete, aEditingHost);
NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
"AutoDeleteRangesHandler::"
"ComputeRangeToDeleteRangeWithTransaction() failed");
return rv;
}
nsresult FallbackToComputeRangesToDeleteRangesWithTransaction(
const HTMLEditor& aHTMLEditor, AutoRangeArray& aRangesToDelete) const {
const HTMLEditor& aHTMLEditor, AutoRangeArray& aRangesToDelete,
const Element& aEditingHost) const {
MOZ_ASSERT(aHTMLEditor.IsEditActionDataAvailable());
MOZ_ASSERT(CanFallbackToDeleteRangesWithTransaction(aRangesToDelete));
nsresult rv = ComputeRangesToDeleteRangesWithTransaction(
aHTMLEditor, mOriginalDirectionAndAmount, aRangesToDelete);
aHTMLEditor, mOriginalDirectionAndAmount, aRangesToDelete,
aEditingHost);
NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
"AutoDeleteRangesHandler::"
"ComputeRangesToDeleteRangesWithTransaction() failed");
@ -694,7 +750,7 @@ class MOZ_STACK_CLASS HTMLEditor::AutoDeleteRangesHandler final {
return NS_ERROR_UNEXPECTED;
case Mode::JoinBlocksInSameParent: {
nsresult rv = ComputeRangeToJoinBlockElementsInSameParent(
aHTMLEditor, aDirectionAndAmount, aRangeToDelete);
aHTMLEditor, aDirectionAndAmount, aRangeToDelete, aEditingHost);
NS_WARNING_ASSERTION(
NS_SUCCEEDED(rv),
"AutoBlockElementsJoiner::"
@ -703,7 +759,7 @@ class MOZ_STACK_CLASS HTMLEditor::AutoDeleteRangesHandler final {
}
case Mode::DeleteContentInRange: {
nsresult rv = ComputeRangeToDeleteContentInRange(
aHTMLEditor, aDirectionAndAmount, aRangeToDelete);
aHTMLEditor, aDirectionAndAmount, aRangeToDelete, aEditingHost);
NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
"AutoBlockElementsJoiner::"
"ComputeRangesToDeleteContentInRanges() failed");
@ -766,8 +822,8 @@ class MOZ_STACK_CLASS HTMLEditor::AutoDeleteRangesHandler final {
const Element& aEditingHost);
nsresult ComputeRangeToJoinBlockElementsInSameParent(
const HTMLEditor& aHTMLEditor,
nsIEditor::EDirection aDirectionAndAmount,
nsRange& aRangeToDelete) const;
nsIEditor::EDirection aDirectionAndAmount, nsRange& aRangeToDelete,
const Element& aEditingHost) const;
[[nodiscard]] MOZ_CAN_RUN_SCRIPT Result<EditActionResult, nsresult>
DeleteBRElement(HTMLEditor& aHTMLEditor,
nsIEditor::EDirection aDirectionAndAmount,
@ -780,7 +836,8 @@ class MOZ_STACK_CLASS HTMLEditor::AutoDeleteRangesHandler final {
nsRange& aRangeToDelete);
nsresult ComputeRangeToDeleteContentInRange(
const HTMLEditor& aHTMLEditor,
nsIEditor::EDirection aDirectionAndAmount, nsRange& aRange) const;
nsIEditor::EDirection aDirectionAndAmount, nsRange& aRange,
const Element& aEditingHost) const;
[[nodiscard]] MOZ_CAN_RUN_SCRIPT Result<EditActionResult, nsresult>
HandleDeleteNonCollapsedRange(
HTMLEditor& aHTMLEditor, nsIEditor::EDirection aDirectionAndAmount,
@ -1293,7 +1350,7 @@ nsresult HTMLEditor::AutoDeleteRangesHandler::ComputeRangesToDelete(
return NS_SUCCESS_DOM_NO_OPERATION;
}
nsresult rv = FallbackToComputeRangesToDeleteRangesWithTransaction(
aHTMLEditor, aRangesToDelete);
aHTMLEditor, aRangesToDelete, *editingHost);
NS_WARNING_ASSERTION(
NS_SUCCEEDED(rv),
"AutoDeleteRangesHandler::"
@ -2605,14 +2662,13 @@ nsresult HTMLEditor::AutoDeleteRangesHandler::AutoBlockElementsJoiner::
NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "nsRange::CollapseTo() failed");
return rv;
}
AutoRangeArray rangesToDelete(aRangeToDelete);
nsresult rv = mDeleteRangesHandlerConst
.FallbackToComputeRangesToDeleteRangesWithTransaction(
aHTMLEditor, rangesToDelete);
.FallbackToComputeRangeToDeleteRangeWithTransaction(
aHTMLEditor, aRangeToDelete, aEditingHost);
NS_WARNING_ASSERTION(
NS_SUCCEEDED(rv),
"AutoDeleteRangesHandler::"
"FallbackToComputeRangesToDeleteRangesWithTransaction() failed");
"FallbackToComputeRangeToDeleteRangeWithTransaction() failed");
return rv;
}
@ -2723,10 +2779,9 @@ Result<EditActionResult, nsresult> HTMLEditor::AutoDeleteRangesHandler::
aRangeToDelete)) {
return EditActionResult::IgnoredResult();
}
AutoRangeArray rangesToDelete(aRangeToDelete);
Result<CaretPoint, nsresult> caretPointOrError =
mDeleteRangesHandler->FallbackToDeleteRangesWithTransaction(
aHTMLEditor, rangesToDelete);
mDeleteRangesHandler->FallbackToDeleteRangeWithTransaction(
aHTMLEditor, aRangeToDelete);
if (MOZ_UNLIKELY(caretPointOrError.isErr())) {
NS_WARNING(
"AutoDeleteRangesHandler::FallbackToDeleteRangesWithTransaction() "
@ -3199,7 +3254,7 @@ HTMLEditor::AutoDeleteRangesHandler::ComputeRangesToDeleteNonCollapsedRanges(
aRangesToDelete.FirstRangeRef()->GetEndContainer()) {
if (!aRangesToDelete.FirstRangeRef()->Collapsed()) {
nsresult rv = ComputeRangesToDeleteRangesWithTransaction(
aHTMLEditor, aDirectionAndAmount, aRangesToDelete);
aHTMLEditor, aDirectionAndAmount, aRangesToDelete, aEditingHost);
NS_WARNING_ASSERTION(
NS_SUCCEEDED(rv),
"AutoDeleteRangesHandler::ComputeRangesToDeleteRangesWithTransaction("
@ -3480,8 +3535,8 @@ bool HTMLEditor::AutoDeleteRangesHandler::AutoBlockElementsJoiner::
nsresult HTMLEditor::AutoDeleteRangesHandler::AutoBlockElementsJoiner::
ComputeRangeToDeleteContentInRange(
const HTMLEditor& aHTMLEditor,
nsIEditor::EDirection aDirectionAndAmount,
nsRange& aRangeToDelete) const {
nsIEditor::EDirection aDirectionAndAmount, nsRange& aRangeToDelete,
const Element& aEditingHost) const {
MOZ_ASSERT(aHTMLEditor.IsEditActionDataAvailable());
MOZ_ASSERT(!aRangeToDelete.Collapsed());
MOZ_ASSERT(mMode == Mode::DeleteContentInRange);
@ -3504,13 +3559,12 @@ nsresult HTMLEditor::AutoDeleteRangesHandler::AutoBlockElementsJoiner::
*aRangeToDelete.GetStartContainer()->AsContent()->GetEditingHost(),
BlockInlineCheck::UseComputedDisplayOutsideStyle));
AutoRangeArray rangesToDelete(aRangeToDelete);
nsresult rv =
mDeleteRangesHandlerConst.ComputeRangesToDeleteRangesWithTransaction(
aHTMLEditor, aDirectionAndAmount, rangesToDelete);
mDeleteRangesHandlerConst.ComputeRangeToDeleteRangeWithTransaction(
aHTMLEditor, aDirectionAndAmount, aRangeToDelete, aEditingHost);
NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
"AutoDeleteRangesHandler::"
"ComputeRangesToDeleteRangesWithTransaction() failed");
"ComputeRangeToDeleteRangeWithTransaction() failed");
return rv;
}
@ -3590,8 +3644,8 @@ Result<EditActionResult, nsresult> HTMLEditor::AutoDeleteRangesHandler::
nsresult HTMLEditor::AutoDeleteRangesHandler::AutoBlockElementsJoiner::
ComputeRangeToJoinBlockElementsInSameParent(
const HTMLEditor& aHTMLEditor,
nsIEditor::EDirection aDirectionAndAmount,
nsRange& aRangeToDelete) const {
nsIEditor::EDirection aDirectionAndAmount, nsRange& aRangeToDelete,
const Element& aEditingHost) const {
MOZ_ASSERT(aHTMLEditor.IsEditActionDataAvailable());
MOZ_ASSERT(!aRangeToDelete.Collapsed());
MOZ_ASSERT(mMode == Mode::JoinBlocksInSameParent);
@ -3605,13 +3659,12 @@ nsresult HTMLEditor::AutoDeleteRangesHandler::AutoBlockElementsJoiner::
aRangeToDelete.GetEndContainer()->IsInclusiveDescendantOf(mRightContent));
MOZ_ASSERT(mLeftContent->GetParentNode() == mRightContent->GetParentNode());
AutoRangeArray rangesToDelete(aRangeToDelete);
nsresult rv =
mDeleteRangesHandlerConst.ComputeRangesToDeleteRangesWithTransaction(
aHTMLEditor, aDirectionAndAmount, rangesToDelete);
mDeleteRangesHandlerConst.ComputeRangeToDeleteRangeWithTransaction(
aHTMLEditor, aDirectionAndAmount, aRangeToDelete, aEditingHost);
NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
"AutoDeleteRangesHandler::"
"ComputeRangesToDeleteRangesWithTransaction() failed");
"ComputeRangeToDeleteRangeWithTransaction() failed");
return rv;
}
@ -4349,21 +4402,26 @@ HTMLEditor::AutoDeleteRangesHandler::DeleteParentBlocksWithTransactionIfEmpty(
}
nsresult
HTMLEditor::AutoDeleteRangesHandler::ComputeRangesToDeleteRangesWithTransaction(
HTMLEditor::AutoDeleteRangesHandler::ComputeRangeToDeleteRangeWithTransaction(
const HTMLEditor& aHTMLEditor, nsIEditor::EDirection aDirectionAndAmount,
AutoRangeArray& aRangesToDelete) const {
nsRange& aRangeToDelete, const Element& aEditingHost) const {
MOZ_ASSERT(aHTMLEditor.IsEditActionDataAvailable());
MOZ_ASSERT(!aRangesToDelete.Ranges().IsEmpty());
EditorBase::HowToHandleCollapsedRange howToHandleCollapsedRange =
const EditorBase::HowToHandleCollapsedRange howToHandleCollapsedRange =
EditorBase::HowToHandleCollapsedRangeFor(aDirectionAndAmount);
if (NS_WARN_IF(aRangesToDelete.IsCollapsed() &&
howToHandleCollapsedRange ==
EditorBase::HowToHandleCollapsedRange::Ignore)) {
return NS_ERROR_FAILURE;
if (MOZ_UNLIKELY(aRangeToDelete.Collapsed() &&
howToHandleCollapsedRange ==
EditorBase::HowToHandleCollapsedRange::Ignore)) {
return NS_SUCCESS_DOM_NO_OPERATION;
}
auto extendRangeToSelectCharacterForward =
// If it's not collapsed, `DeleteRangeTransaction::Create()` will be called
// with it and `DeleteRangeTransaction` won't modify the range.
if (!aRangeToDelete.Collapsed()) {
return NS_OK;
}
const auto ExtendRangeToSelectCharacterForward =
[](nsRange& aRange, const EditorRawDOMPointInText& aCaretPoint) -> void {
const nsTextFragment& textFragment =
aCaretPoint.ContainerAs<Text>()->TextFragment();
@ -4385,7 +4443,7 @@ HTMLEditor::AutoDeleteRangesHandler::ComputeRangesToDeleteRangesWithTransaction(
NS_WARNING_ASSERTION(NS_SUCCEEDED(rvIgnored),
"nsRange::SetStartAndEnd() failed");
};
auto extendRangeToSelectCharacterBackward =
const auto ExtendRangeToSelectCharacterBackward =
[](nsRange& aRange, const EditorRawDOMPointInText& aCaretPoint) -> void {
if (aCaretPoint.IsStartOfContainer()) {
return;
@ -4411,127 +4469,116 @@ HTMLEditor::AutoDeleteRangesHandler::ComputeRangesToDeleteRangesWithTransaction(
"nsRange::SetStartAndEnd() failed");
};
RefPtr<Element> editingHost = aHTMLEditor.ComputeEditingHost();
for (OwningNonNull<nsRange>& range : aRangesToDelete.Ranges()) {
// If it's not collapsed, `DeleteRangeTransaction::Create()` will be called
// with it and `DeleteRangeTransaction` won't modify the range.
if (!range->Collapsed()) {
continue;
// In the other cases, `EditorBase::CreateTransactionForCollapsedRange()`
// will handle the collapsed range.
EditorRawDOMPoint caretPoint(aRangeToDelete.StartRef());
if (howToHandleCollapsedRange ==
EditorBase::HowToHandleCollapsedRange::ExtendBackward &&
caretPoint.IsStartOfContainer()) {
nsIContent* previousEditableContent = HTMLEditUtils::GetPreviousContent(
*caretPoint.GetContainer(), {WalkTreeOption::IgnoreNonEditableNode},
BlockInlineCheck::Unused, &aEditingHost);
if (!previousEditableContent) {
return NS_OK;
}
if (!previousEditableContent->IsText()) {
IgnoredErrorResult ignoredError;
aRangeToDelete.SelectNode(*previousEditableContent, ignoredError);
NS_WARNING_ASSERTION(!ignoredError.Failed(),
"nsRange::SelectNode() failed");
return NS_OK;
}
ExtendRangeToSelectCharacterBackward(
aRangeToDelete,
EditorRawDOMPointInText::AtEndOf(*previousEditableContent->AsText()));
return NS_OK;
}
if (howToHandleCollapsedRange ==
EditorBase::HowToHandleCollapsedRange::ExtendForward &&
caretPoint.IsEndOfContainer()) {
nsIContent* nextEditableContent = HTMLEditUtils::GetNextContent(
*caretPoint.GetContainer(), {WalkTreeOption::IgnoreNonEditableNode},
BlockInlineCheck::Unused, &aEditingHost);
if (!nextEditableContent) {
return NS_OK;
}
if (!nextEditableContent->IsText()) {
IgnoredErrorResult ignoredError;
aRangeToDelete.SelectNode(*nextEditableContent, ignoredError);
NS_WARNING_ASSERTION(!ignoredError.Failed(),
"nsRange::SelectNode() failed");
return NS_OK;
}
ExtendRangeToSelectCharacterForward(
aRangeToDelete,
EditorRawDOMPointInText(nextEditableContent->AsText(), 0));
return NS_OK;
}
if (caretPoint.IsInTextNode()) {
if (howToHandleCollapsedRange ==
EditorBase::HowToHandleCollapsedRange::Ignore) {
continue;
EditorBase::HowToHandleCollapsedRange::ExtendBackward) {
ExtendRangeToSelectCharacterBackward(
aRangeToDelete,
EditorRawDOMPointInText(caretPoint.ContainerAs<Text>(),
caretPoint.Offset()));
return NS_OK;
}
ExtendRangeToSelectCharacterForward(
aRangeToDelete, EditorRawDOMPointInText(caretPoint.ContainerAs<Text>(),
caretPoint.Offset()));
return NS_OK;
}
// In the other cases, `EditorBase::CreateTransactionForCollapsedRange()`
// will handle the collapsed range.
EditorRawDOMPoint caretPoint(range->StartRef());
if (howToHandleCollapsedRange ==
EditorBase::HowToHandleCollapsedRange::ExtendBackward &&
caretPoint.IsStartOfContainer()) {
nsIContent* previousEditableContent = HTMLEditUtils::GetPreviousContent(
*caretPoint.GetContainer(), {WalkTreeOption::IgnoreNonEditableNode},
BlockInlineCheck::Unused, editingHost);
if (!previousEditableContent) {
continue;
}
if (!previousEditableContent->IsText()) {
IgnoredErrorResult ignoredError;
range->SelectNode(*previousEditableContent, ignoredError);
NS_WARNING_ASSERTION(!ignoredError.Failed(),
"nsRange::SelectNode() failed");
continue;
}
extendRangeToSelectCharacterBackward(
range,
EditorRawDOMPointInText::AtEndOf(*previousEditableContent->AsText()));
continue;
}
if (howToHandleCollapsedRange ==
EditorBase::HowToHandleCollapsedRange::ExtendForward &&
caretPoint.IsEndOfContainer()) {
nsIContent* nextEditableContent = HTMLEditUtils::GetNextContent(
*caretPoint.GetContainer(), {WalkTreeOption::IgnoreNonEditableNode},
BlockInlineCheck::Unused, editingHost);
if (!nextEditableContent) {
continue;
}
if (!nextEditableContent->IsText()) {
IgnoredErrorResult ignoredError;
range->SelectNode(*nextEditableContent, ignoredError);
NS_WARNING_ASSERTION(!ignoredError.Failed(),
"nsRange::SelectNode() failed");
continue;
}
extendRangeToSelectCharacterForward(
range, EditorRawDOMPointInText(nextEditableContent->AsText(), 0));
continue;
}
if (caretPoint.IsInTextNode()) {
if (howToHandleCollapsedRange ==
EditorBase::HowToHandleCollapsedRange::ExtendBackward) {
extendRangeToSelectCharacterBackward(
range, EditorRawDOMPointInText(caretPoint.ContainerAs<Text>(),
caretPoint.Offset()));
continue;
}
extendRangeToSelectCharacterForward(
range, EditorRawDOMPointInText(caretPoint.ContainerAs<Text>(),
caretPoint.Offset()));
continue;
}
nsIContent* editableContent =
nsIContent* editableContent =
howToHandleCollapsedRange ==
EditorBase::HowToHandleCollapsedRange::ExtendBackward
? HTMLEditUtils::GetPreviousContent(
caretPoint, {WalkTreeOption::IgnoreNonEditableNode},
BlockInlineCheck::Unused, &aEditingHost)
: HTMLEditUtils::GetNextContent(
caretPoint, {WalkTreeOption::IgnoreNonEditableNode},
BlockInlineCheck::Unused, &aEditingHost);
if (!editableContent) {
return NS_OK;
}
while (editableContent && editableContent->IsCharacterData() &&
!editableContent->Length()) {
editableContent =
howToHandleCollapsedRange ==
EditorBase::HowToHandleCollapsedRange::ExtendBackward
? HTMLEditUtils::GetPreviousContent(
caretPoint, {WalkTreeOption::IgnoreNonEditableNode},
BlockInlineCheck::Unused, editingHost)
*editableContent, {WalkTreeOption::IgnoreNonEditableNode},
BlockInlineCheck::Unused, &aEditingHost)
: HTMLEditUtils::GetNextContent(
caretPoint, {WalkTreeOption::IgnoreNonEditableNode},
BlockInlineCheck::Unused, editingHost);
if (!editableContent) {
continue;
}
while (editableContent && editableContent->IsCharacterData() &&
!editableContent->Length()) {
editableContent =
howToHandleCollapsedRange ==
EditorBase::HowToHandleCollapsedRange::ExtendBackward
? HTMLEditUtils::GetPreviousContent(
*editableContent, {WalkTreeOption::IgnoreNonEditableNode},
BlockInlineCheck::Unused, editingHost)
: HTMLEditUtils::GetNextContent(
*editableContent, {WalkTreeOption::IgnoreNonEditableNode},
BlockInlineCheck::Unused, editingHost);
}
if (!editableContent) {
continue;
}
if (!editableContent->IsText()) {
IgnoredErrorResult ignoredError;
range->SelectNode(*editableContent, ignoredError);
NS_WARNING_ASSERTION(!ignoredError.Failed(),
"nsRange::SelectNode() failed");
continue;
}
if (howToHandleCollapsedRange ==
EditorBase::HowToHandleCollapsedRange::ExtendBackward) {
extendRangeToSelectCharacterBackward(
range, EditorRawDOMPointInText::AtEndOf(*editableContent->AsText()));
continue;
}
extendRangeToSelectCharacterForward(
range, EditorRawDOMPointInText(editableContent->AsText(), 0));
*editableContent, {WalkTreeOption::IgnoreNonEditableNode},
BlockInlineCheck::Unused, &aEditingHost);
}
if (!editableContent) {
return NS_OK;
}
if (!editableContent->IsText()) {
IgnoredErrorResult ignoredError;
aRangeToDelete.SelectNode(*editableContent, ignoredError);
NS_WARNING_ASSERTION(!ignoredError.Failed(),
"nsRange::SelectNode() failed, but ignored");
return NS_OK;
}
if (howToHandleCollapsedRange ==
EditorBase::HowToHandleCollapsedRange::ExtendBackward) {
ExtendRangeToSelectCharacterBackward(
aRangeToDelete,
EditorRawDOMPointInText::AtEndOf(*editableContent->AsText()));
return NS_OK;
}
ExtendRangeToSelectCharacterForward(
aRangeToDelete, EditorRawDOMPointInText(editableContent->AsText(), 0));
return NS_OK;
}