forked from mirrors/gecko-dev
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:
parent
4099ab71e0
commit
900d40dd31
3 changed files with 242 additions and 153 deletions
|
|
@ -4869,6 +4869,29 @@ nsresult EditorBase::DeleteSelectionWithTransaction(
|
||||||
return NS_OK;
|
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(
|
Result<CaretPoint, nsresult> EditorBase::DeleteRangesWithTransaction(
|
||||||
nsIEditor::EDirection aDirectionAndAmount,
|
nsIEditor::EDirection aDirectionAndAmount,
|
||||||
nsIEditor::EStripWrappers aStripWrappers,
|
nsIEditor::EStripWrappers aStripWrappers,
|
||||||
|
|
|
||||||
|
|
@ -2518,6 +2518,25 @@ class EditorBase : public nsIEditor,
|
||||||
DeleteSelectionWithTransaction(nsIEditor::EDirection aDirectionAndAmount,
|
DeleteSelectionWithTransaction(nsIEditor::EDirection aDirectionAndAmount,
|
||||||
nsIEditor::EStripWrappers aStripWrappers);
|
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
|
* DeleteRangesWithTransaction() removes content in aRangesToDelete or content
|
||||||
* around collapsed ranges in aRangesToDelete with transactions and remove
|
* around collapsed ranges in aRangesToDelete with transactions and remove
|
||||||
|
|
|
||||||
|
|
@ -415,6 +415,20 @@ class MOZ_STACK_CLASS HTMLEditor::AutoDeleteRangesHandler final {
|
||||||
DeleteParentBlocksWithTransactionIfEmpty(HTMLEditor& aHTMLEditor,
|
DeleteParentBlocksWithTransactionIfEmpty(HTMLEditor& aHTMLEditor,
|
||||||
const EditorDOMPoint& aPoint);
|
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>
|
[[nodiscard]] MOZ_CAN_RUN_SCRIPT Result<CaretPoint, nsresult>
|
||||||
FallbackToDeleteRangesWithTransaction(HTMLEditor& aHTMLEditor,
|
FallbackToDeleteRangesWithTransaction(HTMLEditor& aHTMLEditor,
|
||||||
AutoRangeArray& aRangesToDelete) const {
|
AutoRangeArray& aRangesToDelete) const {
|
||||||
|
|
@ -425,26 +439,68 @@ class MOZ_STACK_CLASS HTMLEditor::AutoDeleteRangesHandler final {
|
||||||
mOriginalStripWrappers,
|
mOriginalStripWrappers,
|
||||||
aRangesToDelete);
|
aRangesToDelete);
|
||||||
NS_WARNING_ASSERTION(caretPointOrError.isOk(),
|
NS_WARNING_ASSERTION(caretPointOrError.isOk(),
|
||||||
"HTMLEditor::DeleteRangesWithTransaction() failed");
|
"EditorBase::DeleteRangesWithTransaction() failed");
|
||||||
return caretPointOrError;
|
return caretPointOrError;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ComputeRangesToDeleteRangesWithTransaction() computes target ranges
|
* Compute target range(s) which will be called by
|
||||||
* which will be called by `EditorBase::DeleteRangesWithTransaction()`.
|
* `EditorBase::DeleteRangeWithTransaction()` or
|
||||||
|
* `EditorBase::DeleteRangesWithTransaction()`.
|
||||||
* TODO: We should not use it for consistency with each deletion handler
|
* TODO: We should not use it for consistency with each deletion handler
|
||||||
* in this and nested classes.
|
* in this and nested classes.
|
||||||
*/
|
*/
|
||||||
|
nsresult ComputeRangeToDeleteRangeWithTransaction(
|
||||||
|
const HTMLEditor& aHTMLEditor, nsIEditor::EDirection aDirectionAndAmount,
|
||||||
|
nsRange& aRange, const Element& aEditingHost) const;
|
||||||
nsresult ComputeRangesToDeleteRangesWithTransaction(
|
nsresult ComputeRangesToDeleteRangesWithTransaction(
|
||||||
const HTMLEditor& aHTMLEditor, nsIEditor::EDirection aDirectionAndAmount,
|
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(
|
nsresult FallbackToComputeRangesToDeleteRangesWithTransaction(
|
||||||
const HTMLEditor& aHTMLEditor, AutoRangeArray& aRangesToDelete) const {
|
const HTMLEditor& aHTMLEditor, AutoRangeArray& aRangesToDelete,
|
||||||
|
const Element& aEditingHost) const {
|
||||||
MOZ_ASSERT(aHTMLEditor.IsEditActionDataAvailable());
|
MOZ_ASSERT(aHTMLEditor.IsEditActionDataAvailable());
|
||||||
MOZ_ASSERT(CanFallbackToDeleteRangesWithTransaction(aRangesToDelete));
|
MOZ_ASSERT(CanFallbackToDeleteRangesWithTransaction(aRangesToDelete));
|
||||||
nsresult rv = ComputeRangesToDeleteRangesWithTransaction(
|
nsresult rv = ComputeRangesToDeleteRangesWithTransaction(
|
||||||
aHTMLEditor, mOriginalDirectionAndAmount, aRangesToDelete);
|
aHTMLEditor, mOriginalDirectionAndAmount, aRangesToDelete,
|
||||||
|
aEditingHost);
|
||||||
NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
|
NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
|
||||||
"AutoDeleteRangesHandler::"
|
"AutoDeleteRangesHandler::"
|
||||||
"ComputeRangesToDeleteRangesWithTransaction() failed");
|
"ComputeRangesToDeleteRangesWithTransaction() failed");
|
||||||
|
|
@ -694,7 +750,7 @@ class MOZ_STACK_CLASS HTMLEditor::AutoDeleteRangesHandler final {
|
||||||
return NS_ERROR_UNEXPECTED;
|
return NS_ERROR_UNEXPECTED;
|
||||||
case Mode::JoinBlocksInSameParent: {
|
case Mode::JoinBlocksInSameParent: {
|
||||||
nsresult rv = ComputeRangeToJoinBlockElementsInSameParent(
|
nsresult rv = ComputeRangeToJoinBlockElementsInSameParent(
|
||||||
aHTMLEditor, aDirectionAndAmount, aRangeToDelete);
|
aHTMLEditor, aDirectionAndAmount, aRangeToDelete, aEditingHost);
|
||||||
NS_WARNING_ASSERTION(
|
NS_WARNING_ASSERTION(
|
||||||
NS_SUCCEEDED(rv),
|
NS_SUCCEEDED(rv),
|
||||||
"AutoBlockElementsJoiner::"
|
"AutoBlockElementsJoiner::"
|
||||||
|
|
@ -703,7 +759,7 @@ class MOZ_STACK_CLASS HTMLEditor::AutoDeleteRangesHandler final {
|
||||||
}
|
}
|
||||||
case Mode::DeleteContentInRange: {
|
case Mode::DeleteContentInRange: {
|
||||||
nsresult rv = ComputeRangeToDeleteContentInRange(
|
nsresult rv = ComputeRangeToDeleteContentInRange(
|
||||||
aHTMLEditor, aDirectionAndAmount, aRangeToDelete);
|
aHTMLEditor, aDirectionAndAmount, aRangeToDelete, aEditingHost);
|
||||||
NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
|
NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
|
||||||
"AutoBlockElementsJoiner::"
|
"AutoBlockElementsJoiner::"
|
||||||
"ComputeRangesToDeleteContentInRanges() failed");
|
"ComputeRangesToDeleteContentInRanges() failed");
|
||||||
|
|
@ -766,8 +822,8 @@ class MOZ_STACK_CLASS HTMLEditor::AutoDeleteRangesHandler final {
|
||||||
const Element& aEditingHost);
|
const Element& aEditingHost);
|
||||||
nsresult ComputeRangeToJoinBlockElementsInSameParent(
|
nsresult ComputeRangeToJoinBlockElementsInSameParent(
|
||||||
const HTMLEditor& aHTMLEditor,
|
const HTMLEditor& aHTMLEditor,
|
||||||
nsIEditor::EDirection aDirectionAndAmount,
|
nsIEditor::EDirection aDirectionAndAmount, nsRange& aRangeToDelete,
|
||||||
nsRange& aRangeToDelete) const;
|
const Element& aEditingHost) const;
|
||||||
[[nodiscard]] MOZ_CAN_RUN_SCRIPT Result<EditActionResult, nsresult>
|
[[nodiscard]] MOZ_CAN_RUN_SCRIPT Result<EditActionResult, nsresult>
|
||||||
DeleteBRElement(HTMLEditor& aHTMLEditor,
|
DeleteBRElement(HTMLEditor& aHTMLEditor,
|
||||||
nsIEditor::EDirection aDirectionAndAmount,
|
nsIEditor::EDirection aDirectionAndAmount,
|
||||||
|
|
@ -780,7 +836,8 @@ class MOZ_STACK_CLASS HTMLEditor::AutoDeleteRangesHandler final {
|
||||||
nsRange& aRangeToDelete);
|
nsRange& aRangeToDelete);
|
||||||
nsresult ComputeRangeToDeleteContentInRange(
|
nsresult ComputeRangeToDeleteContentInRange(
|
||||||
const HTMLEditor& aHTMLEditor,
|
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>
|
[[nodiscard]] MOZ_CAN_RUN_SCRIPT Result<EditActionResult, nsresult>
|
||||||
HandleDeleteNonCollapsedRange(
|
HandleDeleteNonCollapsedRange(
|
||||||
HTMLEditor& aHTMLEditor, nsIEditor::EDirection aDirectionAndAmount,
|
HTMLEditor& aHTMLEditor, nsIEditor::EDirection aDirectionAndAmount,
|
||||||
|
|
@ -1293,7 +1350,7 @@ nsresult HTMLEditor::AutoDeleteRangesHandler::ComputeRangesToDelete(
|
||||||
return NS_SUCCESS_DOM_NO_OPERATION;
|
return NS_SUCCESS_DOM_NO_OPERATION;
|
||||||
}
|
}
|
||||||
nsresult rv = FallbackToComputeRangesToDeleteRangesWithTransaction(
|
nsresult rv = FallbackToComputeRangesToDeleteRangesWithTransaction(
|
||||||
aHTMLEditor, aRangesToDelete);
|
aHTMLEditor, aRangesToDelete, *editingHost);
|
||||||
NS_WARNING_ASSERTION(
|
NS_WARNING_ASSERTION(
|
||||||
NS_SUCCEEDED(rv),
|
NS_SUCCEEDED(rv),
|
||||||
"AutoDeleteRangesHandler::"
|
"AutoDeleteRangesHandler::"
|
||||||
|
|
@ -2605,14 +2662,13 @@ nsresult HTMLEditor::AutoDeleteRangesHandler::AutoBlockElementsJoiner::
|
||||||
NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "nsRange::CollapseTo() failed");
|
NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "nsRange::CollapseTo() failed");
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
AutoRangeArray rangesToDelete(aRangeToDelete);
|
|
||||||
nsresult rv = mDeleteRangesHandlerConst
|
nsresult rv = mDeleteRangesHandlerConst
|
||||||
.FallbackToComputeRangesToDeleteRangesWithTransaction(
|
.FallbackToComputeRangeToDeleteRangeWithTransaction(
|
||||||
aHTMLEditor, rangesToDelete);
|
aHTMLEditor, aRangeToDelete, aEditingHost);
|
||||||
NS_WARNING_ASSERTION(
|
NS_WARNING_ASSERTION(
|
||||||
NS_SUCCEEDED(rv),
|
NS_SUCCEEDED(rv),
|
||||||
"AutoDeleteRangesHandler::"
|
"AutoDeleteRangesHandler::"
|
||||||
"FallbackToComputeRangesToDeleteRangesWithTransaction() failed");
|
"FallbackToComputeRangeToDeleteRangeWithTransaction() failed");
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2723,10 +2779,9 @@ Result<EditActionResult, nsresult> HTMLEditor::AutoDeleteRangesHandler::
|
||||||
aRangeToDelete)) {
|
aRangeToDelete)) {
|
||||||
return EditActionResult::IgnoredResult();
|
return EditActionResult::IgnoredResult();
|
||||||
}
|
}
|
||||||
AutoRangeArray rangesToDelete(aRangeToDelete);
|
|
||||||
Result<CaretPoint, nsresult> caretPointOrError =
|
Result<CaretPoint, nsresult> caretPointOrError =
|
||||||
mDeleteRangesHandler->FallbackToDeleteRangesWithTransaction(
|
mDeleteRangesHandler->FallbackToDeleteRangeWithTransaction(
|
||||||
aHTMLEditor, rangesToDelete);
|
aHTMLEditor, aRangeToDelete);
|
||||||
if (MOZ_UNLIKELY(caretPointOrError.isErr())) {
|
if (MOZ_UNLIKELY(caretPointOrError.isErr())) {
|
||||||
NS_WARNING(
|
NS_WARNING(
|
||||||
"AutoDeleteRangesHandler::FallbackToDeleteRangesWithTransaction() "
|
"AutoDeleteRangesHandler::FallbackToDeleteRangesWithTransaction() "
|
||||||
|
|
@ -3199,7 +3254,7 @@ HTMLEditor::AutoDeleteRangesHandler::ComputeRangesToDeleteNonCollapsedRanges(
|
||||||
aRangesToDelete.FirstRangeRef()->GetEndContainer()) {
|
aRangesToDelete.FirstRangeRef()->GetEndContainer()) {
|
||||||
if (!aRangesToDelete.FirstRangeRef()->Collapsed()) {
|
if (!aRangesToDelete.FirstRangeRef()->Collapsed()) {
|
||||||
nsresult rv = ComputeRangesToDeleteRangesWithTransaction(
|
nsresult rv = ComputeRangesToDeleteRangesWithTransaction(
|
||||||
aHTMLEditor, aDirectionAndAmount, aRangesToDelete);
|
aHTMLEditor, aDirectionAndAmount, aRangesToDelete, aEditingHost);
|
||||||
NS_WARNING_ASSERTION(
|
NS_WARNING_ASSERTION(
|
||||||
NS_SUCCEEDED(rv),
|
NS_SUCCEEDED(rv),
|
||||||
"AutoDeleteRangesHandler::ComputeRangesToDeleteRangesWithTransaction("
|
"AutoDeleteRangesHandler::ComputeRangesToDeleteRangesWithTransaction("
|
||||||
|
|
@ -3480,8 +3535,8 @@ bool HTMLEditor::AutoDeleteRangesHandler::AutoBlockElementsJoiner::
|
||||||
nsresult HTMLEditor::AutoDeleteRangesHandler::AutoBlockElementsJoiner::
|
nsresult HTMLEditor::AutoDeleteRangesHandler::AutoBlockElementsJoiner::
|
||||||
ComputeRangeToDeleteContentInRange(
|
ComputeRangeToDeleteContentInRange(
|
||||||
const HTMLEditor& aHTMLEditor,
|
const HTMLEditor& aHTMLEditor,
|
||||||
nsIEditor::EDirection aDirectionAndAmount,
|
nsIEditor::EDirection aDirectionAndAmount, nsRange& aRangeToDelete,
|
||||||
nsRange& aRangeToDelete) const {
|
const Element& aEditingHost) const {
|
||||||
MOZ_ASSERT(aHTMLEditor.IsEditActionDataAvailable());
|
MOZ_ASSERT(aHTMLEditor.IsEditActionDataAvailable());
|
||||||
MOZ_ASSERT(!aRangeToDelete.Collapsed());
|
MOZ_ASSERT(!aRangeToDelete.Collapsed());
|
||||||
MOZ_ASSERT(mMode == Mode::DeleteContentInRange);
|
MOZ_ASSERT(mMode == Mode::DeleteContentInRange);
|
||||||
|
|
@ -3504,13 +3559,12 @@ nsresult HTMLEditor::AutoDeleteRangesHandler::AutoBlockElementsJoiner::
|
||||||
*aRangeToDelete.GetStartContainer()->AsContent()->GetEditingHost(),
|
*aRangeToDelete.GetStartContainer()->AsContent()->GetEditingHost(),
|
||||||
BlockInlineCheck::UseComputedDisplayOutsideStyle));
|
BlockInlineCheck::UseComputedDisplayOutsideStyle));
|
||||||
|
|
||||||
AutoRangeArray rangesToDelete(aRangeToDelete);
|
|
||||||
nsresult rv =
|
nsresult rv =
|
||||||
mDeleteRangesHandlerConst.ComputeRangesToDeleteRangesWithTransaction(
|
mDeleteRangesHandlerConst.ComputeRangeToDeleteRangeWithTransaction(
|
||||||
aHTMLEditor, aDirectionAndAmount, rangesToDelete);
|
aHTMLEditor, aDirectionAndAmount, aRangeToDelete, aEditingHost);
|
||||||
NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
|
NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
|
||||||
"AutoDeleteRangesHandler::"
|
"AutoDeleteRangesHandler::"
|
||||||
"ComputeRangesToDeleteRangesWithTransaction() failed");
|
"ComputeRangeToDeleteRangeWithTransaction() failed");
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -3590,8 +3644,8 @@ Result<EditActionResult, nsresult> HTMLEditor::AutoDeleteRangesHandler::
|
||||||
nsresult HTMLEditor::AutoDeleteRangesHandler::AutoBlockElementsJoiner::
|
nsresult HTMLEditor::AutoDeleteRangesHandler::AutoBlockElementsJoiner::
|
||||||
ComputeRangeToJoinBlockElementsInSameParent(
|
ComputeRangeToJoinBlockElementsInSameParent(
|
||||||
const HTMLEditor& aHTMLEditor,
|
const HTMLEditor& aHTMLEditor,
|
||||||
nsIEditor::EDirection aDirectionAndAmount,
|
nsIEditor::EDirection aDirectionAndAmount, nsRange& aRangeToDelete,
|
||||||
nsRange& aRangeToDelete) const {
|
const Element& aEditingHost) const {
|
||||||
MOZ_ASSERT(aHTMLEditor.IsEditActionDataAvailable());
|
MOZ_ASSERT(aHTMLEditor.IsEditActionDataAvailable());
|
||||||
MOZ_ASSERT(!aRangeToDelete.Collapsed());
|
MOZ_ASSERT(!aRangeToDelete.Collapsed());
|
||||||
MOZ_ASSERT(mMode == Mode::JoinBlocksInSameParent);
|
MOZ_ASSERT(mMode == Mode::JoinBlocksInSameParent);
|
||||||
|
|
@ -3605,13 +3659,12 @@ nsresult HTMLEditor::AutoDeleteRangesHandler::AutoBlockElementsJoiner::
|
||||||
aRangeToDelete.GetEndContainer()->IsInclusiveDescendantOf(mRightContent));
|
aRangeToDelete.GetEndContainer()->IsInclusiveDescendantOf(mRightContent));
|
||||||
MOZ_ASSERT(mLeftContent->GetParentNode() == mRightContent->GetParentNode());
|
MOZ_ASSERT(mLeftContent->GetParentNode() == mRightContent->GetParentNode());
|
||||||
|
|
||||||
AutoRangeArray rangesToDelete(aRangeToDelete);
|
|
||||||
nsresult rv =
|
nsresult rv =
|
||||||
mDeleteRangesHandlerConst.ComputeRangesToDeleteRangesWithTransaction(
|
mDeleteRangesHandlerConst.ComputeRangeToDeleteRangeWithTransaction(
|
||||||
aHTMLEditor, aDirectionAndAmount, rangesToDelete);
|
aHTMLEditor, aDirectionAndAmount, aRangeToDelete, aEditingHost);
|
||||||
NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
|
NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
|
||||||
"AutoDeleteRangesHandler::"
|
"AutoDeleteRangesHandler::"
|
||||||
"ComputeRangesToDeleteRangesWithTransaction() failed");
|
"ComputeRangeToDeleteRangeWithTransaction() failed");
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -4349,21 +4402,26 @@ HTMLEditor::AutoDeleteRangesHandler::DeleteParentBlocksWithTransactionIfEmpty(
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
HTMLEditor::AutoDeleteRangesHandler::ComputeRangesToDeleteRangesWithTransaction(
|
HTMLEditor::AutoDeleteRangesHandler::ComputeRangeToDeleteRangeWithTransaction(
|
||||||
const HTMLEditor& aHTMLEditor, nsIEditor::EDirection aDirectionAndAmount,
|
const HTMLEditor& aHTMLEditor, nsIEditor::EDirection aDirectionAndAmount,
|
||||||
AutoRangeArray& aRangesToDelete) const {
|
nsRange& aRangeToDelete, const Element& aEditingHost) const {
|
||||||
MOZ_ASSERT(aHTMLEditor.IsEditActionDataAvailable());
|
MOZ_ASSERT(aHTMLEditor.IsEditActionDataAvailable());
|
||||||
MOZ_ASSERT(!aRangesToDelete.Ranges().IsEmpty());
|
|
||||||
|
|
||||||
EditorBase::HowToHandleCollapsedRange howToHandleCollapsedRange =
|
const EditorBase::HowToHandleCollapsedRange howToHandleCollapsedRange =
|
||||||
EditorBase::HowToHandleCollapsedRangeFor(aDirectionAndAmount);
|
EditorBase::HowToHandleCollapsedRangeFor(aDirectionAndAmount);
|
||||||
if (NS_WARN_IF(aRangesToDelete.IsCollapsed() &&
|
if (MOZ_UNLIKELY(aRangeToDelete.Collapsed() &&
|
||||||
howToHandleCollapsedRange ==
|
howToHandleCollapsedRange ==
|
||||||
EditorBase::HowToHandleCollapsedRange::Ignore)) {
|
EditorBase::HowToHandleCollapsedRange::Ignore)) {
|
||||||
return NS_ERROR_FAILURE;
|
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 {
|
[](nsRange& aRange, const EditorRawDOMPointInText& aCaretPoint) -> void {
|
||||||
const nsTextFragment& textFragment =
|
const nsTextFragment& textFragment =
|
||||||
aCaretPoint.ContainerAs<Text>()->TextFragment();
|
aCaretPoint.ContainerAs<Text>()->TextFragment();
|
||||||
|
|
@ -4385,7 +4443,7 @@ HTMLEditor::AutoDeleteRangesHandler::ComputeRangesToDeleteRangesWithTransaction(
|
||||||
NS_WARNING_ASSERTION(NS_SUCCEEDED(rvIgnored),
|
NS_WARNING_ASSERTION(NS_SUCCEEDED(rvIgnored),
|
||||||
"nsRange::SetStartAndEnd() failed");
|
"nsRange::SetStartAndEnd() failed");
|
||||||
};
|
};
|
||||||
auto extendRangeToSelectCharacterBackward =
|
const auto ExtendRangeToSelectCharacterBackward =
|
||||||
[](nsRange& aRange, const EditorRawDOMPointInText& aCaretPoint) -> void {
|
[](nsRange& aRange, const EditorRawDOMPointInText& aCaretPoint) -> void {
|
||||||
if (aCaretPoint.IsStartOfContainer()) {
|
if (aCaretPoint.IsStartOfContainer()) {
|
||||||
return;
|
return;
|
||||||
|
|
@ -4411,43 +4469,30 @@ HTMLEditor::AutoDeleteRangesHandler::ComputeRangesToDeleteRangesWithTransaction(
|
||||||
"nsRange::SetStartAndEnd() failed");
|
"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;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (howToHandleCollapsedRange ==
|
|
||||||
EditorBase::HowToHandleCollapsedRange::Ignore) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// In the other cases, `EditorBase::CreateTransactionForCollapsedRange()`
|
// In the other cases, `EditorBase::CreateTransactionForCollapsedRange()`
|
||||||
// will handle the collapsed range.
|
// will handle the collapsed range.
|
||||||
EditorRawDOMPoint caretPoint(range->StartRef());
|
EditorRawDOMPoint caretPoint(aRangeToDelete.StartRef());
|
||||||
if (howToHandleCollapsedRange ==
|
if (howToHandleCollapsedRange ==
|
||||||
EditorBase::HowToHandleCollapsedRange::ExtendBackward &&
|
EditorBase::HowToHandleCollapsedRange::ExtendBackward &&
|
||||||
caretPoint.IsStartOfContainer()) {
|
caretPoint.IsStartOfContainer()) {
|
||||||
nsIContent* previousEditableContent = HTMLEditUtils::GetPreviousContent(
|
nsIContent* previousEditableContent = HTMLEditUtils::GetPreviousContent(
|
||||||
*caretPoint.GetContainer(), {WalkTreeOption::IgnoreNonEditableNode},
|
*caretPoint.GetContainer(), {WalkTreeOption::IgnoreNonEditableNode},
|
||||||
BlockInlineCheck::Unused, editingHost);
|
BlockInlineCheck::Unused, &aEditingHost);
|
||||||
if (!previousEditableContent) {
|
if (!previousEditableContent) {
|
||||||
continue;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
if (!previousEditableContent->IsText()) {
|
if (!previousEditableContent->IsText()) {
|
||||||
IgnoredErrorResult ignoredError;
|
IgnoredErrorResult ignoredError;
|
||||||
range->SelectNode(*previousEditableContent, ignoredError);
|
aRangeToDelete.SelectNode(*previousEditableContent, ignoredError);
|
||||||
NS_WARNING_ASSERTION(!ignoredError.Failed(),
|
NS_WARNING_ASSERTION(!ignoredError.Failed(),
|
||||||
"nsRange::SelectNode() failed");
|
"nsRange::SelectNode() failed");
|
||||||
continue;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
extendRangeToSelectCharacterBackward(
|
ExtendRangeToSelectCharacterBackward(
|
||||||
range,
|
aRangeToDelete,
|
||||||
EditorRawDOMPointInText::AtEndOf(*previousEditableContent->AsText()));
|
EditorRawDOMPointInText::AtEndOf(*previousEditableContent->AsText()));
|
||||||
continue;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (howToHandleCollapsedRange ==
|
if (howToHandleCollapsedRange ==
|
||||||
|
|
@ -4455,36 +4500,38 @@ HTMLEditor::AutoDeleteRangesHandler::ComputeRangesToDeleteRangesWithTransaction(
|
||||||
caretPoint.IsEndOfContainer()) {
|
caretPoint.IsEndOfContainer()) {
|
||||||
nsIContent* nextEditableContent = HTMLEditUtils::GetNextContent(
|
nsIContent* nextEditableContent = HTMLEditUtils::GetNextContent(
|
||||||
*caretPoint.GetContainer(), {WalkTreeOption::IgnoreNonEditableNode},
|
*caretPoint.GetContainer(), {WalkTreeOption::IgnoreNonEditableNode},
|
||||||
BlockInlineCheck::Unused, editingHost);
|
BlockInlineCheck::Unused, &aEditingHost);
|
||||||
if (!nextEditableContent) {
|
if (!nextEditableContent) {
|
||||||
continue;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!nextEditableContent->IsText()) {
|
if (!nextEditableContent->IsText()) {
|
||||||
IgnoredErrorResult ignoredError;
|
IgnoredErrorResult ignoredError;
|
||||||
range->SelectNode(*nextEditableContent, ignoredError);
|
aRangeToDelete.SelectNode(*nextEditableContent, ignoredError);
|
||||||
NS_WARNING_ASSERTION(!ignoredError.Failed(),
|
NS_WARNING_ASSERTION(!ignoredError.Failed(),
|
||||||
"nsRange::SelectNode() failed");
|
"nsRange::SelectNode() failed");
|
||||||
continue;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
extendRangeToSelectCharacterForward(
|
ExtendRangeToSelectCharacterForward(
|
||||||
range, EditorRawDOMPointInText(nextEditableContent->AsText(), 0));
|
aRangeToDelete,
|
||||||
continue;
|
EditorRawDOMPointInText(nextEditableContent->AsText(), 0));
|
||||||
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (caretPoint.IsInTextNode()) {
|
if (caretPoint.IsInTextNode()) {
|
||||||
if (howToHandleCollapsedRange ==
|
if (howToHandleCollapsedRange ==
|
||||||
EditorBase::HowToHandleCollapsedRange::ExtendBackward) {
|
EditorBase::HowToHandleCollapsedRange::ExtendBackward) {
|
||||||
extendRangeToSelectCharacterBackward(
|
ExtendRangeToSelectCharacterBackward(
|
||||||
range, EditorRawDOMPointInText(caretPoint.ContainerAs<Text>(),
|
aRangeToDelete,
|
||||||
|
EditorRawDOMPointInText(caretPoint.ContainerAs<Text>(),
|
||||||
caretPoint.Offset()));
|
caretPoint.Offset()));
|
||||||
continue;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
extendRangeToSelectCharacterForward(
|
ExtendRangeToSelectCharacterForward(
|
||||||
range, EditorRawDOMPointInText(caretPoint.ContainerAs<Text>(),
|
aRangeToDelete, EditorRawDOMPointInText(caretPoint.ContainerAs<Text>(),
|
||||||
caretPoint.Offset()));
|
caretPoint.Offset()));
|
||||||
continue;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
nsIContent* editableContent =
|
nsIContent* editableContent =
|
||||||
|
|
@ -4492,12 +4539,12 @@ HTMLEditor::AutoDeleteRangesHandler::ComputeRangesToDeleteRangesWithTransaction(
|
||||||
EditorBase::HowToHandleCollapsedRange::ExtendBackward
|
EditorBase::HowToHandleCollapsedRange::ExtendBackward
|
||||||
? HTMLEditUtils::GetPreviousContent(
|
? HTMLEditUtils::GetPreviousContent(
|
||||||
caretPoint, {WalkTreeOption::IgnoreNonEditableNode},
|
caretPoint, {WalkTreeOption::IgnoreNonEditableNode},
|
||||||
BlockInlineCheck::Unused, editingHost)
|
BlockInlineCheck::Unused, &aEditingHost)
|
||||||
: HTMLEditUtils::GetNextContent(
|
: HTMLEditUtils::GetNextContent(
|
||||||
caretPoint, {WalkTreeOption::IgnoreNonEditableNode},
|
caretPoint, {WalkTreeOption::IgnoreNonEditableNode},
|
||||||
BlockInlineCheck::Unused, editingHost);
|
BlockInlineCheck::Unused, &aEditingHost);
|
||||||
if (!editableContent) {
|
if (!editableContent) {
|
||||||
continue;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
while (editableContent && editableContent->IsCharacterData() &&
|
while (editableContent && editableContent->IsCharacterData() &&
|
||||||
!editableContent->Length()) {
|
!editableContent->Length()) {
|
||||||
|
|
@ -4506,32 +4553,32 @@ HTMLEditor::AutoDeleteRangesHandler::ComputeRangesToDeleteRangesWithTransaction(
|
||||||
EditorBase::HowToHandleCollapsedRange::ExtendBackward
|
EditorBase::HowToHandleCollapsedRange::ExtendBackward
|
||||||
? HTMLEditUtils::GetPreviousContent(
|
? HTMLEditUtils::GetPreviousContent(
|
||||||
*editableContent, {WalkTreeOption::IgnoreNonEditableNode},
|
*editableContent, {WalkTreeOption::IgnoreNonEditableNode},
|
||||||
BlockInlineCheck::Unused, editingHost)
|
BlockInlineCheck::Unused, &aEditingHost)
|
||||||
: HTMLEditUtils::GetNextContent(
|
: HTMLEditUtils::GetNextContent(
|
||||||
*editableContent, {WalkTreeOption::IgnoreNonEditableNode},
|
*editableContent, {WalkTreeOption::IgnoreNonEditableNode},
|
||||||
BlockInlineCheck::Unused, editingHost);
|
BlockInlineCheck::Unused, &aEditingHost);
|
||||||
}
|
}
|
||||||
if (!editableContent) {
|
if (!editableContent) {
|
||||||
continue;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!editableContent->IsText()) {
|
if (!editableContent->IsText()) {
|
||||||
IgnoredErrorResult ignoredError;
|
IgnoredErrorResult ignoredError;
|
||||||
range->SelectNode(*editableContent, ignoredError);
|
aRangeToDelete.SelectNode(*editableContent, ignoredError);
|
||||||
NS_WARNING_ASSERTION(!ignoredError.Failed(),
|
NS_WARNING_ASSERTION(!ignoredError.Failed(),
|
||||||
"nsRange::SelectNode() failed");
|
"nsRange::SelectNode() failed, but ignored");
|
||||||
continue;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (howToHandleCollapsedRange ==
|
if (howToHandleCollapsedRange ==
|
||||||
EditorBase::HowToHandleCollapsedRange::ExtendBackward) {
|
EditorBase::HowToHandleCollapsedRange::ExtendBackward) {
|
||||||
extendRangeToSelectCharacterBackward(
|
ExtendRangeToSelectCharacterBackward(
|
||||||
range, EditorRawDOMPointInText::AtEndOf(*editableContent->AsText()));
|
aRangeToDelete,
|
||||||
continue;
|
EditorRawDOMPointInText::AtEndOf(*editableContent->AsText()));
|
||||||
}
|
return NS_OK;
|
||||||
extendRangeToSelectCharacterForward(
|
|
||||||
range, EditorRawDOMPointInText(editableContent->AsText(), 0));
|
|
||||||
}
|
}
|
||||||
|
ExtendRangeToSelectCharacterForward(
|
||||||
|
aRangeToDelete, EditorRawDOMPointInText(editableContent->AsText(), 0));
|
||||||
|
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue