From 36d22d82aa202bb199967e9512281e9a53db42c9 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 7 Apr 2024 21:33:14 +0200 Subject: Adding upstream version 115.7.0esr. Signed-off-by: Daniel Baumann --- editor/libeditor/AutoRangeArray.h | 469 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 469 insertions(+) create mode 100644 editor/libeditor/AutoRangeArray.h (limited to 'editor/libeditor/AutoRangeArray.h') diff --git a/editor/libeditor/AutoRangeArray.h b/editor/libeditor/AutoRangeArray.h new file mode 100644 index 0000000000..ff0f223663 --- /dev/null +++ b/editor/libeditor/AutoRangeArray.h @@ -0,0 +1,469 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef AutoRangeArray_h +#define AutoRangeArray_h + +#include "EditAction.h" // for EditSubAction +#include "EditorBase.h" // for EditorBase +#include "EditorDOMPoint.h" // for EditorDOMPoint, EditorDOMRange, etc +#include "EditorForwards.h" +#include "SelectionState.h" // for SelectionState + +#include "mozilla/ErrorResult.h" // for ErrorResult +#include "mozilla/IntegerRange.h" // for IntegerRange +#include "mozilla/Maybe.h" // for Maybe +#include "mozilla/RangeBoundary.h" // for RangeBoundary +#include "mozilla/Result.h" // for Result<> +#include "mozilla/dom/Element.h" // for dom::Element +#include "mozilla/dom/HTMLBRElement.h" // for dom::HTMLBRElement +#include "mozilla/dom/Selection.h" // for dom::Selection +#include "mozilla/dom/Text.h" // for dom::Text + +#include "nsDebug.h" // for NS_WARNING, etc +#include "nsDirection.h" // for nsDirection +#include "nsError.h" // for NS_SUCCESS_* and NS_ERROR_* +#include "nsRange.h" // for nsRange + +namespace mozilla { + +/****************************************************************************** + * AutoRangeArray stores ranges which do no belong any `Selection`. + * So, different from `AutoSelectionRangeArray`, this can be used for + * ranges which may need to be modified before touching the DOM tree, + * but does not want to modify `Selection` for the performance. + *****************************************************************************/ +class MOZ_STACK_CLASS AutoRangeArray final { + public: + explicit AutoRangeArray(const dom::Selection& aSelection); + template + explicit AutoRangeArray(const EditorDOMRangeBase& aRange); + template + explicit AutoRangeArray(const EditorDOMPointBase& aPoint); + // The copy constructor copies everything except saved ranges. + explicit AutoRangeArray(const AutoRangeArray& aOther); + + ~AutoRangeArray(); + + void Initialize(const dom::Selection& aSelection) { + ClearSavedRanges(); + mDirection = aSelection.GetDirection(); + mRanges.Clear(); + for (const uint32_t i : IntegerRange(aSelection.RangeCount())) { + MOZ_ASSERT(aSelection.GetRangeAt(i)); + mRanges.AppendElement(aSelection.GetRangeAt(i)->CloneRange()); + if (aSelection.GetRangeAt(i) == aSelection.GetAnchorFocusRange()) { + mAnchorFocusRange = mRanges.LastElement(); + } + } + } + + /** + * Check whether all ranges in content nodes or not. If the ranges is empty, + * this returns false. + */ + [[nodiscard]] bool IsInContent() const { + if (mRanges.IsEmpty()) { + return false; + } + for (const OwningNonNull& range : mRanges) { + if (MOZ_UNLIKELY(!range->IsPositioned() || !range->GetStartContainer() || + !range->GetStartContainer()->IsContent() || + !range->GetEndContainer() || + !range->GetEndContainer()->IsContent())) { + return false; + } + } + return true; + } + + /** + * EnsureOnlyEditableRanges() removes ranges which cannot modify. + * Note that this is designed only for `HTMLEditor` because this must not + * be required by `TextEditor`. + */ + void EnsureOnlyEditableRanges(const dom::Element& aEditingHost); + + /** + * EnsureRangesInTextNode() is designed for TextEditor to guarantee that + * all ranges are in its text node which is first child of the anonymous
+ * element and is first child. + */ + void EnsureRangesInTextNode(const dom::Text& aTextNode); + + /** + * Extend ranges to wrap lines to handle block level edit actions such as + * updating the block parent or indent/outdent around the selection. + */ + void ExtendRangesToWrapLinesToHandleBlockLevelEditAction( + EditSubAction aEditSubAction, const dom::Element& aEditingHost); + + /** + * Check whether the range is in aEditingHost and both containers of start and + * end boundaries of the range are editable. + */ + [[nodiscard]] static bool IsEditableRange(const dom::AbstractRange& aRange, + const dom::Element& aEditingHost); + + /** + * Check whether the first range is in aEditingHost and both containers of + * start and end boundaries of the first range are editable. + */ + [[nodiscard]] bool IsFirstRangeEditable( + const dom::Element& aEditingHost) const { + return IsEditableRange(FirstRangeRef(), aEditingHost); + } + + /** + * IsAtLeastOneContainerOfRangeBoundariesInclusiveDescendantOf() returns true + * if at least one of the containers of the range boundaries is an inclusive + * descendant of aContent. + */ + [[nodiscard]] bool + IsAtLeastOneContainerOfRangeBoundariesInclusiveDescendantOf( + const nsIContent& aContent) const { + for (const OwningNonNull& range : mRanges) { + nsINode* startContainer = range->GetStartContainer(); + if (startContainer && + startContainer->IsInclusiveDescendantOf(&aContent)) { + return true; + } + nsINode* endContainer = range->GetEndContainer(); + if (startContainer == endContainer) { + continue; + } + if (endContainer && endContainer->IsInclusiveDescendantOf(&aContent)) { + return true; + } + } + return false; + } + + [[nodiscard]] auto& Ranges() { return mRanges; } + [[nodiscard]] const auto& Ranges() const { return mRanges; } + [[nodiscard]] OwningNonNull& FirstRangeRef() { return mRanges[0]; } + [[nodiscard]] const OwningNonNull& FirstRangeRef() const { + return mRanges[0]; + } + + template