зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1627175 - part 38: Move `EditorBase::GetNextContent()` and `EditorBase::GetPreviousContent()` to `HTMLEditUtils` r=m_kato
Differential Revision: https://phabricator.services.mozilla.com/D113242
This commit is contained in:
Родитель
7da0836039
Коммит
3aef835f6c
|
@ -128,6 +128,7 @@ using namespace widget;
|
|||
|
||||
using LeafNodeType = HTMLEditUtils::LeafNodeType;
|
||||
using LeafNodeTypes = HTMLEditUtils::LeafNodeTypes;
|
||||
using WalkTreeOption = HTMLEditUtils::WalkTreeOption;
|
||||
|
||||
/*****************************************************************************
|
||||
* mozilla::EditorBase
|
||||
|
@ -2802,231 +2803,6 @@ nsresult EditorBase::DeleteTextWithTransaction(Text& aTextNode,
|
|||
return rv;
|
||||
}
|
||||
|
||||
// static
|
||||
nsIContent* EditorBase::GetPreviousContent(
|
||||
const nsINode& aNode, const WalkTreeOptions& aOptions,
|
||||
const Element* aAncestorLimiter /* = nullptr */) {
|
||||
if (&aNode == aAncestorLimiter ||
|
||||
(aAncestorLimiter && !aNode.IsInclusiveDescendantOf(aAncestorLimiter))) {
|
||||
return nullptr;
|
||||
}
|
||||
return EditorBase::GetAdjacentContent(aNode, WalkTreeDirection::Backward,
|
||||
aOptions, aAncestorLimiter);
|
||||
}
|
||||
|
||||
// static
|
||||
nsIContent* EditorBase::GetPreviousContent(
|
||||
const EditorRawDOMPoint& aPoint, const WalkTreeOptions& aOptions,
|
||||
const Element* aAncestorLimiter /* = nullptr */) {
|
||||
MOZ_ASSERT(aPoint.IsSetAndValid());
|
||||
NS_WARNING_ASSERTION(
|
||||
!aPoint.IsInDataNode() || aPoint.IsInTextNode(),
|
||||
"GetPreviousContent() doesn't assume that the start point is a "
|
||||
"data node except text node");
|
||||
|
||||
// If we are at the beginning of the node, or it is a text node, then just
|
||||
// look before it.
|
||||
if (aPoint.IsStartOfContainer() || aPoint.IsInTextNode()) {
|
||||
if (aOptions.contains(WalkTreeOption::StopAtBlockBoundary) &&
|
||||
aPoint.IsInContentNode() &&
|
||||
HTMLEditUtils::IsBlockElement(*aPoint.ContainerAsContent())) {
|
||||
// If we aren't allowed to cross blocks, don't look before this block.
|
||||
return nullptr;
|
||||
}
|
||||
return EditorBase::GetPreviousContent(*aPoint.GetContainer(), aOptions,
|
||||
aAncestorLimiter);
|
||||
}
|
||||
|
||||
// else look before the child at 'aOffset'
|
||||
if (aPoint.GetChild()) {
|
||||
return EditorBase::GetPreviousContent(*aPoint.GetChild(), aOptions,
|
||||
aAncestorLimiter);
|
||||
}
|
||||
|
||||
// unless there isn't one, in which case we are at the end of the node
|
||||
// and want the deep-right child.
|
||||
nsIContent* lastLeafContent = HTMLEditUtils::GetLastLeafChild(
|
||||
*aPoint.GetContainer(),
|
||||
{aOptions.contains(WalkTreeOption::StopAtBlockBoundary)
|
||||
? LeafNodeType::LeafNodeOrChildBlock
|
||||
: LeafNodeType::OnlyLeafNode});
|
||||
if (!lastLeafContent) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if ((!aOptions.contains(WalkTreeOption::IgnoreNonEditableNode) ||
|
||||
EditorUtils::IsEditableContent(*lastLeafContent, EditorType::HTML)) &&
|
||||
(!aOptions.contains(WalkTreeOption::IgnoreDataNodeExceptText) ||
|
||||
EditorUtils::IsElementOrText(*lastLeafContent))) {
|
||||
return lastLeafContent;
|
||||
}
|
||||
|
||||
// restart the search from the non-editable node we just found
|
||||
return EditorBase::GetPreviousContent(*lastLeafContent, aOptions,
|
||||
aAncestorLimiter);
|
||||
}
|
||||
|
||||
// static
|
||||
nsIContent* EditorBase::GetNextContent(
|
||||
const nsINode& aNode, const WalkTreeOptions& aOptions,
|
||||
const Element* aAncestorLimiter /* = nullptr */) {
|
||||
if (&aNode == aAncestorLimiter ||
|
||||
(aAncestorLimiter && !aNode.IsInclusiveDescendantOf(aAncestorLimiter))) {
|
||||
return nullptr;
|
||||
}
|
||||
return EditorBase::GetAdjacentContent(aNode, WalkTreeDirection::Forward,
|
||||
aOptions, aAncestorLimiter);
|
||||
}
|
||||
|
||||
// static
|
||||
nsIContent* EditorBase::GetNextContent(
|
||||
const EditorRawDOMPoint& aPoint, const WalkTreeOptions& aOptions,
|
||||
const Element* aAncestorLimiter /* = nullptr */) {
|
||||
MOZ_ASSERT(aPoint.IsSetAndValid());
|
||||
NS_WARNING_ASSERTION(
|
||||
!aPoint.IsInDataNode() || aPoint.IsInTextNode(),
|
||||
"GetNextContent() doesn't assume that the start point is a "
|
||||
"data node except text node");
|
||||
|
||||
EditorRawDOMPoint point(aPoint);
|
||||
|
||||
// if the container is a text node, use its location instead
|
||||
if (point.IsInTextNode()) {
|
||||
point.SetAfter(point.GetContainer());
|
||||
if (NS_WARN_IF(!point.IsSet())) {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
if (point.GetChild()) {
|
||||
if (aOptions.contains(WalkTreeOption::StopAtBlockBoundary) &&
|
||||
HTMLEditUtils::IsBlockElement(*point.GetChild())) {
|
||||
return point.GetChild();
|
||||
}
|
||||
|
||||
nsIContent* firstLeafContent = HTMLEditUtils::GetFirstLeafChild(
|
||||
*point.GetChild(),
|
||||
{aOptions.contains(WalkTreeOption::StopAtBlockBoundary)
|
||||
? LeafNodeType::LeafNodeOrChildBlock
|
||||
: LeafNodeType::OnlyLeafNode});
|
||||
if (!firstLeafContent) {
|
||||
return point.GetChild();
|
||||
}
|
||||
|
||||
// XXX Why do we need to do this check? The leaf node must be a descendant
|
||||
// of `point.GetChild()`.
|
||||
if (aAncestorLimiter &&
|
||||
(firstLeafContent == aAncestorLimiter ||
|
||||
!firstLeafContent->IsInclusiveDescendantOf(aAncestorLimiter))) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if ((!aOptions.contains(WalkTreeOption::IgnoreNonEditableNode) ||
|
||||
EditorUtils::IsEditableContent(*firstLeafContent, EditorType::HTML)) &&
|
||||
(!aOptions.contains(WalkTreeOption::IgnoreDataNodeExceptText) ||
|
||||
EditorUtils::IsElementOrText(*firstLeafContent))) {
|
||||
return firstLeafContent;
|
||||
}
|
||||
|
||||
// restart the search from the non-editable node we just found
|
||||
return EditorBase::GetNextContent(*firstLeafContent, aOptions,
|
||||
aAncestorLimiter);
|
||||
}
|
||||
|
||||
// unless there isn't one, in which case we are at the end of the node
|
||||
// and want the next one.
|
||||
if (aOptions.contains(WalkTreeOption::StopAtBlockBoundary) &&
|
||||
point.IsInContentNode() &&
|
||||
HTMLEditUtils::IsBlockElement(*point.ContainerAsContent())) {
|
||||
// don't cross out of parent block
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return EditorBase::GetNextContent(*point.GetContainer(), aOptions,
|
||||
aAncestorLimiter);
|
||||
}
|
||||
|
||||
// static
|
||||
nsIContent* EditorBase::GetAdjacentLeafContent(
|
||||
const nsINode& aNode, WalkTreeDirection aWalkTreeDirection,
|
||||
const WalkTreeOptions& aOptions,
|
||||
const Element* aAncestorLimiter /* = nullptr */) {
|
||||
// called only by GetPriorNode so we don't need to check params.
|
||||
MOZ_ASSERT(&aNode != aAncestorLimiter);
|
||||
MOZ_ASSERT_IF(aAncestorLimiter,
|
||||
aAncestorLimiter->IsInclusiveDescendantOf(aAncestorLimiter));
|
||||
|
||||
const nsINode* node = &aNode;
|
||||
for (;;) {
|
||||
// if aNode has a sibling in the right direction, return
|
||||
// that sibling's closest child (or itself if it has no children)
|
||||
nsIContent* sibling = aWalkTreeDirection == WalkTreeDirection::Forward
|
||||
? node->GetNextSibling()
|
||||
: node->GetPreviousSibling();
|
||||
if (sibling) {
|
||||
if (aOptions.contains(WalkTreeOption::StopAtBlockBoundary) &&
|
||||
HTMLEditUtils::IsBlockElement(*sibling)) {
|
||||
// don't look inside prevsib, since it is a block
|
||||
return sibling;
|
||||
}
|
||||
const LeafNodeTypes leafNodeTypes = {
|
||||
aOptions.contains(WalkTreeOption::StopAtBlockBoundary)
|
||||
? LeafNodeType::LeafNodeOrChildBlock
|
||||
: LeafNodeType::OnlyLeafNode};
|
||||
nsIContent* leafContent =
|
||||
aWalkTreeDirection == WalkTreeDirection::Forward
|
||||
? HTMLEditUtils::GetFirstLeafChild(*sibling, leafNodeTypes)
|
||||
: HTMLEditUtils::GetLastLeafChild(*sibling, leafNodeTypes);
|
||||
return leafContent ? leafContent : sibling;
|
||||
}
|
||||
|
||||
nsIContent* parent = node->GetParent();
|
||||
if (!parent) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (parent == aAncestorLimiter ||
|
||||
(aOptions.contains(WalkTreeOption::StopAtBlockBoundary) &&
|
||||
HTMLEditUtils::IsBlockElement(*parent))) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
node = parent;
|
||||
}
|
||||
|
||||
MOZ_ASSERT_UNREACHABLE("What part of for(;;) do you not understand?");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// static
|
||||
nsIContent* EditorBase::GetAdjacentContent(
|
||||
const nsINode& aNode, WalkTreeDirection aWalkTreeDirection,
|
||||
const WalkTreeOptions& aOptions,
|
||||
const Element* aAncestorLimiter /* = nullptr */) {
|
||||
if (&aNode == aAncestorLimiter) {
|
||||
// Don't allow traversal above the root node! This helps
|
||||
// prevent us from accidentally editing browser content
|
||||
// when the editor is in a text widget.
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nsIContent* leafContent = EditorBase::GetAdjacentLeafContent(
|
||||
aNode, aWalkTreeDirection, aOptions, aAncestorLimiter);
|
||||
if (!leafContent) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if ((!aOptions.contains(WalkTreeOption::IgnoreNonEditableNode) ||
|
||||
EditorUtils::IsEditableContent(*leafContent, EditorType::HTML)) &&
|
||||
(!aOptions.contains(WalkTreeOption::IgnoreDataNodeExceptText) ||
|
||||
EditorUtils::IsElementOrText(*leafContent))) {
|
||||
return leafContent;
|
||||
}
|
||||
|
||||
return EditorBase::GetAdjacentContent(*leafContent, aWalkTreeDirection,
|
||||
aOptions, aAncestorLimiter);
|
||||
}
|
||||
|
||||
bool EditorBase::IsRoot(const nsINode* inNode) const {
|
||||
if (NS_WARN_IF(!inNode)) {
|
||||
return false;
|
||||
|
@ -3509,7 +3285,7 @@ EditorBase::CreateTransactionForCollapsedRange(
|
|||
MOZ_ASSERT(IsHTMLEditor());
|
||||
// We're backspacing from the beginning of a node. Delete the last thing
|
||||
// of previous editable content.
|
||||
nsIContent* previousEditableContent = EditorBase::GetPreviousContent(
|
||||
nsIContent* previousEditableContent = HTMLEditUtils::GetPreviousContent(
|
||||
*point.GetContainer(), {WalkTreeOption::IgnoreNonEditableNode},
|
||||
GetEditorRoot());
|
||||
if (!previousEditableContent) {
|
||||
|
@ -3553,7 +3329,7 @@ EditorBase::CreateTransactionForCollapsedRange(
|
|||
MOZ_ASSERT(IsHTMLEditor());
|
||||
// We're deleting from the end of a node. Delete the first thing of
|
||||
// next editable content.
|
||||
nsIContent* nextEditableContent = EditorBase::GetNextContent(
|
||||
nsIContent* nextEditableContent = HTMLEditUtils::GetNextContent(
|
||||
*point.GetContainer(), {WalkTreeOption::IgnoreNonEditableNode},
|
||||
GetEditorRoot());
|
||||
if (!nextEditableContent) {
|
||||
|
@ -3616,10 +3392,10 @@ EditorBase::CreateTransactionForCollapsedRange(
|
|||
if (IsHTMLEditor()) {
|
||||
editableContent =
|
||||
aHowToHandleCollapsedRange == HowToHandleCollapsedRange::ExtendBackward
|
||||
? EditorBase::GetPreviousContent(
|
||||
? HTMLEditUtils::GetPreviousContent(
|
||||
point, {WalkTreeOption::IgnoreNonEditableNode},
|
||||
GetEditorRoot())
|
||||
: EditorBase::GetNextContent(
|
||||
: HTMLEditUtils::GetNextContent(
|
||||
point, {WalkTreeOption::IgnoreNonEditableNode},
|
||||
GetEditorRoot());
|
||||
if (!editableContent) {
|
||||
|
@ -3632,10 +3408,10 @@ EditorBase::CreateTransactionForCollapsedRange(
|
|||
editableContent =
|
||||
aHowToHandleCollapsedRange ==
|
||||
HowToHandleCollapsedRange::ExtendBackward
|
||||
? EditorBase::GetPreviousContent(
|
||||
? HTMLEditUtils::GetPreviousContent(
|
||||
*editableContent, {WalkTreeOption::IgnoreNonEditableNode},
|
||||
GetEditorRoot())
|
||||
: EditorBase::GetNextContent(
|
||||
: HTMLEditUtils::GetNextContent(
|
||||
*editableContent, {WalkTreeOption::IgnoreNonEditableNode},
|
||||
GetEditorRoot());
|
||||
}
|
||||
|
|
|
@ -9,7 +9,6 @@
|
|||
#include "mozilla/Assertions.h" // for MOZ_ASSERT, etc.
|
||||
#include "mozilla/EditAction.h" // for EditAction and EditSubAction
|
||||
#include "mozilla/EditorDOMPoint.h" // for EditorDOMPoint
|
||||
#include "mozilla/EnumSet.h" // for EnumSet
|
||||
#include "mozilla/EventForwards.h" // for InputEventTargetRanges
|
||||
#include "mozilla/Maybe.h" // for Maybe
|
||||
#include "mozilla/OwningNonNull.h" // for OwningNonNull
|
||||
|
@ -1723,73 +1722,6 @@ class EditorBase : public nsIEditor,
|
|||
MOZ_CAN_RUN_SCRIPT nsresult
|
||||
DoTransactionInternal(nsITransaction* aTransaction);
|
||||
|
||||
/**
|
||||
* Get the next node.
|
||||
*
|
||||
*
|
||||
* On the other hand, the methods taking nsINode behavior must be what
|
||||
* you want. They start to search the result from next node of the given
|
||||
* node.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Get previous content node of aNode if there is.
|
||||
*
|
||||
* @param aNode The node from which we start to walk the DOM tree.
|
||||
*/
|
||||
enum class WalkTreeOption {
|
||||
IgnoreNonEditableNode, // Ignore non-editable nodes and their children.
|
||||
IgnoreDataNodeExceptText, // Ignore data nodes which are not text node.
|
||||
StopAtBlockBoundary, // Stop waking the tree at a block boundary.
|
||||
};
|
||||
using WalkTreeOptions = EnumSet<WalkTreeOption>;
|
||||
static nsIContent* GetPreviousContent(
|
||||
const nsINode& aNode, const WalkTreeOptions& aOptions,
|
||||
const Element* aAncestorLimiter = nullptr);
|
||||
|
||||
/**
|
||||
* And another version that takes a point in DOM tree rather than a node.
|
||||
*/
|
||||
static nsIContent* GetPreviousContent(
|
||||
const EditorRawDOMPoint& aPoint, const WalkTreeOptions& aOptions,
|
||||
const Element* aAncestorLimiter = nullptr);
|
||||
|
||||
/**
|
||||
* Get next content node of aNode if there is.
|
||||
*
|
||||
* @param aNode The node from which we start to walk the DOM tree.
|
||||
*/
|
||||
static nsIContent* GetNextContent(const nsINode& aNode,
|
||||
const WalkTreeOptions& aOptions,
|
||||
const Element* aAncestorLimiter = nullptr);
|
||||
|
||||
/**
|
||||
* And another version that takes a point in DOM tree rather than a node.
|
||||
*
|
||||
* Note that this may return the child at the offset. E.g., following code
|
||||
* causes infinite loop.
|
||||
*
|
||||
* EditorRawDOMPoint point(aEditableNode);
|
||||
* while (nsIContent* content =
|
||||
* GetNextContent(point, {WalkTreeOption::IgnoreNonEditableNode})) {
|
||||
* // Do something...
|
||||
* point.Set(content);
|
||||
* }
|
||||
*
|
||||
* Following code must be you expected:
|
||||
*
|
||||
* while (nsIContent* content =
|
||||
* GetNextContent(point, {WalkTreeOption::IgnoreNonEditableNode}) {
|
||||
* // Do something...
|
||||
* DebugOnly<bool> advanced = point.Advanced();
|
||||
* MOZ_ASSERT(advanced);
|
||||
* point.Set(point.GetChild());
|
||||
* }
|
||||
*/
|
||||
static nsIContent* GetNextContent(const EditorRawDOMPoint& aPoint,
|
||||
const WalkTreeOptions& aOptions,
|
||||
const Element* aAncestorLimiter = nullptr);
|
||||
|
||||
/**
|
||||
* Returns true if aNode is our root node.
|
||||
*/
|
||||
|
@ -2154,19 +2086,6 @@ class EditorBase : public nsIEditor,
|
|||
*/
|
||||
[[nodiscard]] MOZ_CAN_RUN_SCRIPT nsresult ScrollSelectionFocusIntoView();
|
||||
|
||||
/**
|
||||
* Helper for GetPreviousContent() and GetNextContent().
|
||||
*/
|
||||
enum class WalkTreeDirection { Forward, Backward };
|
||||
static nsIContent* GetAdjacentLeafContent(
|
||||
const nsINode& aNode, WalkTreeDirection aWalkTreeDirection,
|
||||
const WalkTreeOptions& aOptions,
|
||||
const Element* aAncestorLimiter = nullptr);
|
||||
static nsIContent* GetAdjacentContent(
|
||||
const nsINode& aNode, WalkTreeDirection aWalkTreeDirection,
|
||||
const WalkTreeOptions& aOptions,
|
||||
const Element* aAncestorLimiter = nullptr);
|
||||
|
||||
virtual nsresult InstallEventListeners();
|
||||
virtual void CreateEventListeners();
|
||||
virtual void RemoveEventListeners();
|
||||
|
|
|
@ -38,6 +38,31 @@ namespace mozilla {
|
|||
using namespace dom;
|
||||
using EditorType = EditorBase::EditorType;
|
||||
|
||||
template nsIContent* HTMLEditUtils::GetPreviousContent(
|
||||
const EditorDOMPoint& aPoint, const WalkTreeOptions& aOptions,
|
||||
const Element* aAncestorLimiter);
|
||||
template nsIContent* HTMLEditUtils::GetPreviousContent(
|
||||
const EditorRawDOMPoint& aPoint, const WalkTreeOptions& aOptions,
|
||||
const Element* aAncestorLimiter);
|
||||
template nsIContent* HTMLEditUtils::GetPreviousContent(
|
||||
const EditorDOMPointInText& aPoint, const WalkTreeOptions& aOptions,
|
||||
const Element* aAncestorLimiter);
|
||||
template nsIContent* HTMLEditUtils::GetPreviousContent(
|
||||
const EditorRawDOMPointInText& aPoint, const WalkTreeOptions& aOptions,
|
||||
const Element* aAncestorLimiter);
|
||||
template nsIContent* HTMLEditUtils::GetNextContent(
|
||||
const EditorDOMPoint& aPoint, const WalkTreeOptions& aOptions,
|
||||
const Element* aAncestorLimiter);
|
||||
template nsIContent* HTMLEditUtils::GetNextContent(
|
||||
const EditorRawDOMPoint& aPoint, const WalkTreeOptions& aOptions,
|
||||
const Element* aAncestorLimiter);
|
||||
template nsIContent* HTMLEditUtils::GetNextContent(
|
||||
const EditorDOMPointInText& aPoint, const WalkTreeOptions& aOptions,
|
||||
const Element* aAncestorLimiter);
|
||||
template nsIContent* HTMLEditUtils::GetNextContent(
|
||||
const EditorRawDOMPointInText& aPoint, const WalkTreeOptions& aOptions,
|
||||
const Element* aAncestorLimiter);
|
||||
|
||||
template EditorDOMPoint HTMLEditUtils::GetPreviousEditablePoint(
|
||||
nsIContent& aContent, const Element* aAncestorLimiter,
|
||||
InvisibleWhiteSpaces aInvisibleWhiteSpaces,
|
||||
|
@ -865,6 +890,209 @@ bool HTMLEditUtils::IsSingleLineContainer(nsINode& aNode) {
|
|||
aNode.IsAnyOfHTMLElements(nsGkAtoms::li, nsGkAtoms::dt, nsGkAtoms::dd);
|
||||
}
|
||||
|
||||
// static
|
||||
template <typename PT, typename CT>
|
||||
nsIContent* HTMLEditUtils::GetPreviousContent(
|
||||
const EditorDOMPointBase<PT, CT>& aPoint, const WalkTreeOptions& aOptions,
|
||||
const Element* aAncestorLimiter /* = nullptr */) {
|
||||
MOZ_ASSERT(aPoint.IsSetAndValid());
|
||||
NS_WARNING_ASSERTION(
|
||||
!aPoint.IsInDataNode() || aPoint.IsInTextNode(),
|
||||
"GetPreviousContent() doesn't assume that the start point is a "
|
||||
"data node except text node");
|
||||
|
||||
// If we are at the beginning of the node, or it is a text node, then just
|
||||
// look before it.
|
||||
if (aPoint.IsStartOfContainer() || aPoint.IsInTextNode()) {
|
||||
if (aOptions.contains(WalkTreeOption::StopAtBlockBoundary) &&
|
||||
aPoint.IsInContentNode() &&
|
||||
HTMLEditUtils::IsBlockElement(*aPoint.ContainerAsContent())) {
|
||||
// If we aren't allowed to cross blocks, don't look before this block.
|
||||
return nullptr;
|
||||
}
|
||||
return HTMLEditUtils::GetPreviousContent(*aPoint.GetContainer(), aOptions,
|
||||
aAncestorLimiter);
|
||||
}
|
||||
|
||||
// else look before the child at 'aOffset'
|
||||
if (aPoint.GetChild()) {
|
||||
return HTMLEditUtils::GetPreviousContent(*aPoint.GetChild(), aOptions,
|
||||
aAncestorLimiter);
|
||||
}
|
||||
|
||||
// unless there isn't one, in which case we are at the end of the node
|
||||
// and want the deep-right child.
|
||||
nsIContent* lastLeafContent = HTMLEditUtils::GetLastLeafChild(
|
||||
*aPoint.GetContainer(),
|
||||
{aOptions.contains(WalkTreeOption::StopAtBlockBoundary)
|
||||
? LeafNodeType::LeafNodeOrChildBlock
|
||||
: LeafNodeType::OnlyLeafNode});
|
||||
if (!lastLeafContent) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if ((!aOptions.contains(WalkTreeOption::IgnoreNonEditableNode) ||
|
||||
EditorUtils::IsEditableContent(*lastLeafContent, EditorType::HTML)) &&
|
||||
(!aOptions.contains(WalkTreeOption::IgnoreDataNodeExceptText) ||
|
||||
EditorUtils::IsElementOrText(*lastLeafContent))) {
|
||||
return lastLeafContent;
|
||||
}
|
||||
|
||||
// restart the search from the non-editable node we just found
|
||||
return HTMLEditUtils::GetPreviousContent(*lastLeafContent, aOptions,
|
||||
aAncestorLimiter);
|
||||
}
|
||||
|
||||
// static
|
||||
template <typename PT, typename CT>
|
||||
nsIContent* HTMLEditUtils::GetNextContent(
|
||||
const EditorDOMPointBase<PT, CT>& aPoint, const WalkTreeOptions& aOptions,
|
||||
const Element* aAncestorLimiter /* = nullptr */) {
|
||||
MOZ_ASSERT(aPoint.IsSetAndValid());
|
||||
NS_WARNING_ASSERTION(
|
||||
!aPoint.IsInDataNode() || aPoint.IsInTextNode(),
|
||||
"GetNextContent() doesn't assume that the start point is a "
|
||||
"data node except text node");
|
||||
|
||||
EditorRawDOMPoint point(aPoint);
|
||||
|
||||
// if the container is a text node, use its location instead
|
||||
if (point.IsInTextNode()) {
|
||||
point.SetAfter(point.GetContainer());
|
||||
if (NS_WARN_IF(!point.IsSet())) {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
if (point.GetChild()) {
|
||||
if (aOptions.contains(WalkTreeOption::StopAtBlockBoundary) &&
|
||||
HTMLEditUtils::IsBlockElement(*point.GetChild())) {
|
||||
return point.GetChild();
|
||||
}
|
||||
|
||||
nsIContent* firstLeafContent = HTMLEditUtils::GetFirstLeafChild(
|
||||
*point.GetChild(),
|
||||
{aOptions.contains(WalkTreeOption::StopAtBlockBoundary)
|
||||
? LeafNodeType::LeafNodeOrChildBlock
|
||||
: LeafNodeType::OnlyLeafNode});
|
||||
if (!firstLeafContent) {
|
||||
return point.GetChild();
|
||||
}
|
||||
|
||||
// XXX Why do we need to do this check? The leaf node must be a descendant
|
||||
// of `point.GetChild()`.
|
||||
if (aAncestorLimiter &&
|
||||
(firstLeafContent == aAncestorLimiter ||
|
||||
!firstLeafContent->IsInclusiveDescendantOf(aAncestorLimiter))) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if ((!aOptions.contains(WalkTreeOption::IgnoreNonEditableNode) ||
|
||||
EditorUtils::IsEditableContent(*firstLeafContent, EditorType::HTML)) &&
|
||||
(!aOptions.contains(WalkTreeOption::IgnoreDataNodeExceptText) ||
|
||||
EditorUtils::IsElementOrText(*firstLeafContent))) {
|
||||
return firstLeafContent;
|
||||
}
|
||||
|
||||
// restart the search from the non-editable node we just found
|
||||
return HTMLEditUtils::GetNextContent(*firstLeafContent, aOptions,
|
||||
aAncestorLimiter);
|
||||
}
|
||||
|
||||
// unless there isn't one, in which case we are at the end of the node
|
||||
// and want the next one.
|
||||
if (aOptions.contains(WalkTreeOption::StopAtBlockBoundary) &&
|
||||
point.IsInContentNode() &&
|
||||
HTMLEditUtils::IsBlockElement(*point.ContainerAsContent())) {
|
||||
// don't cross out of parent block
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return HTMLEditUtils::GetNextContent(*point.GetContainer(), aOptions,
|
||||
aAncestorLimiter);
|
||||
}
|
||||
|
||||
// static
|
||||
nsIContent* HTMLEditUtils::GetAdjacentLeafContent(
|
||||
const nsINode& aNode, WalkTreeDirection aWalkTreeDirection,
|
||||
const WalkTreeOptions& aOptions,
|
||||
const Element* aAncestorLimiter /* = nullptr */) {
|
||||
// called only by GetPriorNode so we don't need to check params.
|
||||
MOZ_ASSERT(&aNode != aAncestorLimiter);
|
||||
MOZ_ASSERT_IF(aAncestorLimiter,
|
||||
aAncestorLimiter->IsInclusiveDescendantOf(aAncestorLimiter));
|
||||
|
||||
const nsINode* node = &aNode;
|
||||
for (;;) {
|
||||
// if aNode has a sibling in the right direction, return
|
||||
// that sibling's closest child (or itself if it has no children)
|
||||
nsIContent* sibling = aWalkTreeDirection == WalkTreeDirection::Forward
|
||||
? node->GetNextSibling()
|
||||
: node->GetPreviousSibling();
|
||||
if (sibling) {
|
||||
if (aOptions.contains(WalkTreeOption::StopAtBlockBoundary) &&
|
||||
HTMLEditUtils::IsBlockElement(*sibling)) {
|
||||
// don't look inside prevsib, since it is a block
|
||||
return sibling;
|
||||
}
|
||||
const LeafNodeTypes leafNodeTypes = {
|
||||
aOptions.contains(WalkTreeOption::StopAtBlockBoundary)
|
||||
? LeafNodeType::LeafNodeOrChildBlock
|
||||
: LeafNodeType::OnlyLeafNode};
|
||||
nsIContent* leafContent =
|
||||
aWalkTreeDirection == WalkTreeDirection::Forward
|
||||
? HTMLEditUtils::GetFirstLeafChild(*sibling, leafNodeTypes)
|
||||
: HTMLEditUtils::GetLastLeafChild(*sibling, leafNodeTypes);
|
||||
return leafContent ? leafContent : sibling;
|
||||
}
|
||||
|
||||
nsIContent* parent = node->GetParent();
|
||||
if (!parent) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (parent == aAncestorLimiter ||
|
||||
(aOptions.contains(WalkTreeOption::StopAtBlockBoundary) &&
|
||||
HTMLEditUtils::IsBlockElement(*parent))) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
node = parent;
|
||||
}
|
||||
|
||||
MOZ_ASSERT_UNREACHABLE("What part of for(;;) do you not understand?");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// static
|
||||
nsIContent* HTMLEditUtils::GetAdjacentContent(
|
||||
const nsINode& aNode, WalkTreeDirection aWalkTreeDirection,
|
||||
const WalkTreeOptions& aOptions,
|
||||
const Element* aAncestorLimiter /* = nullptr */) {
|
||||
if (&aNode == aAncestorLimiter) {
|
||||
// Don't allow traversal above the root node! This helps
|
||||
// prevent us from accidentally editing browser content
|
||||
// when the editor is in a text widget.
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nsIContent* leafContent = HTMLEditUtils::GetAdjacentLeafContent(
|
||||
aNode, aWalkTreeDirection, aOptions, aAncestorLimiter);
|
||||
if (!leafContent) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if ((!aOptions.contains(WalkTreeOption::IgnoreNonEditableNode) ||
|
||||
EditorUtils::IsEditableContent(*leafContent, EditorType::HTML)) &&
|
||||
(!aOptions.contains(WalkTreeOption::IgnoreDataNodeExceptText) ||
|
||||
EditorUtils::IsElementOrText(*leafContent))) {
|
||||
return leafContent;
|
||||
}
|
||||
|
||||
return HTMLEditUtils::GetAdjacentContent(*leafContent, aWalkTreeDirection,
|
||||
aOptions, aAncestorLimiter);
|
||||
}
|
||||
|
||||
// static
|
||||
template <typename EditorDOMPointType>
|
||||
EditorDOMPointType HTMLEditUtils::GetPreviousEditablePoint(
|
||||
|
|
|
@ -370,6 +370,82 @@ class HTMLEditUtils final {
|
|||
aFoundLinkElement);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get adjacent content node of aNode if there is (even if one is in different
|
||||
* parent element).
|
||||
*
|
||||
* @param aNode The node from which we start to walk the DOM
|
||||
* tree.
|
||||
* @param aOptions See WalkTreeOption for the detail.
|
||||
* @param aAncestorLimiter Ancestor limiter element which these methods
|
||||
* never cross its boundary. This is typically
|
||||
* the editing host.
|
||||
*/
|
||||
enum class WalkTreeOption {
|
||||
IgnoreNonEditableNode, // Ignore non-editable nodes and their children.
|
||||
IgnoreDataNodeExceptText, // Ignore data nodes which are not text node.
|
||||
StopAtBlockBoundary, // Stop waking the tree at a block boundary.
|
||||
};
|
||||
using WalkTreeOptions = EnumSet<WalkTreeOption>;
|
||||
static nsIContent* GetPreviousContent(
|
||||
const nsINode& aNode, const WalkTreeOptions& aOptions,
|
||||
const Element* aAncestorLimiter = nullptr) {
|
||||
if (&aNode == aAncestorLimiter ||
|
||||
(aAncestorLimiter &&
|
||||
!aNode.IsInclusiveDescendantOf(aAncestorLimiter))) {
|
||||
return nullptr;
|
||||
}
|
||||
return HTMLEditUtils::GetAdjacentContent(aNode, WalkTreeDirection::Backward,
|
||||
aOptions, aAncestorLimiter);
|
||||
}
|
||||
static nsIContent* GetNextContent(const nsINode& aNode,
|
||||
const WalkTreeOptions& aOptions,
|
||||
const Element* aAncestorLimiter = nullptr) {
|
||||
if (&aNode == aAncestorLimiter ||
|
||||
(aAncestorLimiter &&
|
||||
!aNode.IsInclusiveDescendantOf(aAncestorLimiter))) {
|
||||
return nullptr;
|
||||
}
|
||||
return HTMLEditUtils::GetAdjacentContent(aNode, WalkTreeDirection::Forward,
|
||||
aOptions, aAncestorLimiter);
|
||||
}
|
||||
|
||||
/**
|
||||
* And another version that takes a point in DOM tree rather than a node.
|
||||
*/
|
||||
template <typename PT, typename CT>
|
||||
static nsIContent* GetPreviousContent(
|
||||
const EditorDOMPointBase<PT, CT>& aPoint, const WalkTreeOptions& aOptions,
|
||||
const Element* aAncestorLimiter = nullptr);
|
||||
|
||||
/**
|
||||
* And another version that takes a point in DOM tree rather than a node.
|
||||
*
|
||||
* Note that this may return the child at the offset. E.g., following code
|
||||
* causes infinite loop.
|
||||
*
|
||||
* EditorRawDOMPoint point(aEditableNode);
|
||||
* while (nsIContent* content =
|
||||
* GetNextContent(point, {WalkTreeOption::IgnoreNonEditableNode})) {
|
||||
* // Do something...
|
||||
* point.Set(content);
|
||||
* }
|
||||
*
|
||||
* Following code must be you expected:
|
||||
*
|
||||
* while (nsIContent* content =
|
||||
* GetNextContent(point, {WalkTreeOption::IgnoreNonEditableNode}) {
|
||||
* // Do something...
|
||||
* DebugOnly<bool> advanced = point.Advanced();
|
||||
* MOZ_ASSERT(advanced);
|
||||
* point.Set(point.GetChild());
|
||||
* }
|
||||
*/
|
||||
template <typename PT, typename CT>
|
||||
static nsIContent* GetNextContent(const EditorDOMPointBase<PT, CT>& aPoint,
|
||||
const WalkTreeOptions& aOptions,
|
||||
const Element* aAncestorLimiter = nullptr);
|
||||
|
||||
/**
|
||||
* GetLastLeafChild() returns rightmost leaf content in aNode. It depends on
|
||||
* aLeafNodeTypes whether this which types of nodes are treated as leaf nodes.
|
||||
|
@ -696,9 +772,8 @@ class HTMLEditUtils final {
|
|||
aRootElement, {LeafNodeType::OnlyLeafNode});
|
||||
if (leafContent && !EditorUtils::IsEditableContent(
|
||||
*leafContent, EditorBase::EditorType::HTML)) {
|
||||
leafContent = EditorBase::GetNextContent(
|
||||
*leafContent, {EditorBase::WalkTreeOption::IgnoreNonEditableNode},
|
||||
&aRootElement);
|
||||
leafContent = HTMLEditUtils::GetNextContent(
|
||||
*leafContent, {WalkTreeOption::IgnoreNonEditableNode}, &aRootElement);
|
||||
}
|
||||
MOZ_ASSERT(leafContent != &aRootElement);
|
||||
return leafContent;
|
||||
|
@ -1068,6 +1143,19 @@ class HTMLEditUtils final {
|
|||
aContent.IsHTMLElement(nsGkAtoms::table));
|
||||
return !cannotCrossBoundary;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper for GetPreviousContent() and GetNextContent().
|
||||
*/
|
||||
enum class WalkTreeDirection { Forward, Backward };
|
||||
static nsIContent* GetAdjacentLeafContent(
|
||||
const nsINode& aNode, WalkTreeDirection aWalkTreeDirection,
|
||||
const WalkTreeOptions& aOptions,
|
||||
const Element* aAncestorLimiter = nullptr);
|
||||
static nsIContent* GetAdjacentContent(
|
||||
const nsINode& aNode, WalkTreeDirection aWalkTreeDirection,
|
||||
const WalkTreeOptions& aOptions,
|
||||
const Element* aAncestorLimiter = nullptr);
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -72,6 +72,7 @@ using namespace widget;
|
|||
using EmptyCheckOption = HTMLEditUtils::EmptyCheckOption;
|
||||
using LeafNodeType = HTMLEditUtils::LeafNodeType;
|
||||
using LeafNodeTypes = HTMLEditUtils::LeafNodeTypes;
|
||||
using WalkTreeOption = HTMLEditUtils::WalkTreeOption;
|
||||
|
||||
const char16_t kNBSP = 160;
|
||||
|
||||
|
@ -5006,12 +5007,12 @@ nsIContent* HTMLEditor::GetPreviousHTMLElementOrTextInternal(
|
|||
return nullptr;
|
||||
}
|
||||
return aNoBlockCrossing
|
||||
? EditorBase::GetPreviousContent(
|
||||
? HTMLEditUtils::GetPreviousContent(
|
||||
aNode,
|
||||
{WalkTreeOption::IgnoreDataNodeExceptText,
|
||||
WalkTreeOption::StopAtBlockBoundary},
|
||||
editingHost)
|
||||
: EditorBase::GetPreviousContent(
|
||||
: HTMLEditUtils::GetPreviousContent(
|
||||
aNode, {WalkTreeOption::IgnoreDataNodeExceptText},
|
||||
editingHost);
|
||||
}
|
||||
|
@ -5024,12 +5025,12 @@ nsIContent* HTMLEditor::GetPreviousHTMLElementOrTextInternal(
|
|||
return nullptr;
|
||||
}
|
||||
return aNoBlockCrossing
|
||||
? EditorBase::GetPreviousContent(
|
||||
? HTMLEditUtils::GetPreviousContent(
|
||||
aPoint,
|
||||
{WalkTreeOption::IgnoreDataNodeExceptText,
|
||||
WalkTreeOption::StopAtBlockBoundary},
|
||||
editingHost)
|
||||
: EditorBase::GetPreviousContent(
|
||||
: HTMLEditUtils::GetPreviousContent(
|
||||
aPoint, {WalkTreeOption::IgnoreDataNodeExceptText},
|
||||
editingHost);
|
||||
}
|
||||
|
@ -5041,12 +5042,12 @@ nsIContent* HTMLEditor::GetPreviousEditableHTMLNodeInternal(
|
|||
return nullptr;
|
||||
}
|
||||
return aNoBlockCrossing
|
||||
? EditorBase::GetPreviousContent(
|
||||
? HTMLEditUtils::GetPreviousContent(
|
||||
aNode,
|
||||
{WalkTreeOption::IgnoreNonEditableNode,
|
||||
WalkTreeOption::StopAtBlockBoundary},
|
||||
editingHost)
|
||||
: EditorBase::GetPreviousContent(
|
||||
: HTMLEditUtils::GetPreviousContent(
|
||||
aNode, {WalkTreeOption::IgnoreNonEditableNode}, editingHost);
|
||||
}
|
||||
|
||||
|
@ -5057,12 +5058,12 @@ nsIContent* HTMLEditor::GetPreviousEditableHTMLNodeInternal(
|
|||
if (NS_WARN_IF(!editingHost)) {
|
||||
return nullptr;
|
||||
}
|
||||
return aNoBlockCrossing ? EditorBase::GetPreviousContent(
|
||||
return aNoBlockCrossing ? HTMLEditUtils::GetPreviousContent(
|
||||
aPoint,
|
||||
{WalkTreeOption::IgnoreNonEditableNode,
|
||||
WalkTreeOption::StopAtBlockBoundary},
|
||||
editingHost)
|
||||
: EditorBase::GetPreviousContent(
|
||||
: HTMLEditUtils::GetPreviousContent(
|
||||
aPoint, {WalkTreeOption::IgnoreNonEditableNode},
|
||||
editingHost);
|
||||
}
|
||||
|
@ -5074,12 +5075,12 @@ nsIContent* HTMLEditor::GetNextHTMLElementOrTextInternal(
|
|||
return nullptr;
|
||||
}
|
||||
return aNoBlockCrossing
|
||||
? EditorBase::GetNextContent(
|
||||
? HTMLEditUtils::GetNextContent(
|
||||
aNode,
|
||||
{WalkTreeOption::IgnoreDataNodeExceptText,
|
||||
WalkTreeOption::StopAtBlockBoundary},
|
||||
editingHost)
|
||||
: EditorBase::GetNextContent(
|
||||
: HTMLEditUtils::GetNextContent(
|
||||
aNode, {WalkTreeOption::IgnoreDataNodeExceptText},
|
||||
editingHost);
|
||||
}
|
||||
|
@ -5092,12 +5093,12 @@ nsIContent* HTMLEditor::GetNextHTMLElementOrTextInternal(
|
|||
return nullptr;
|
||||
}
|
||||
return aNoBlockCrossing
|
||||
? EditorBase::GetNextContent(
|
||||
? HTMLEditUtils::GetNextContent(
|
||||
aPoint,
|
||||
{WalkTreeOption::IgnoreDataNodeExceptText,
|
||||
WalkTreeOption::StopAtBlockBoundary},
|
||||
editingHost)
|
||||
: EditorBase::GetNextContent(
|
||||
: HTMLEditUtils::GetNextContent(
|
||||
aPoint, {WalkTreeOption::IgnoreDataNodeExceptText},
|
||||
editingHost);
|
||||
}
|
||||
|
@ -5109,12 +5110,12 @@ nsIContent* HTMLEditor::GetNextEditableHTMLNodeInternal(
|
|||
return nullptr;
|
||||
}
|
||||
return aNoBlockCrossing
|
||||
? EditorBase::GetNextContent(
|
||||
? HTMLEditUtils::GetNextContent(
|
||||
aNode,
|
||||
{WalkTreeOption::IgnoreNonEditableNode,
|
||||
WalkTreeOption::StopAtBlockBoundary},
|
||||
editingHost)
|
||||
: EditorBase::GetNextContent(
|
||||
: HTMLEditUtils::GetNextContent(
|
||||
aNode, {WalkTreeOption::IgnoreNonEditableNode}, editingHost);
|
||||
}
|
||||
|
||||
|
@ -5125,12 +5126,12 @@ nsIContent* HTMLEditor::GetNextEditableHTMLNodeInternal(
|
|||
if (NS_WARN_IF(!editingHost)) {
|
||||
return nullptr;
|
||||
}
|
||||
return aNoBlockCrossing ? EditorBase::GetNextContent(
|
||||
return aNoBlockCrossing ? HTMLEditUtils::GetNextContent(
|
||||
aPoint,
|
||||
{WalkTreeOption::IgnoreNonEditableNode,
|
||||
WalkTreeOption::StopAtBlockBoundary},
|
||||
editingHost)
|
||||
: EditorBase::GetNextContent(
|
||||
: HTMLEditUtils::GetNextContent(
|
||||
aPoint, {WalkTreeOption::IgnoreNonEditableNode},
|
||||
editingHost);
|
||||
}
|
||||
|
|
|
@ -978,8 +978,8 @@ class HTMLEditor final : public TextEditor,
|
|||
|
||||
/**
|
||||
* GetPreviousEditableHTMLNode*() methods are similar to
|
||||
* EditorBase::GetPreviousContent({WalkTreeOption::IgnoreNonEditableNode}) but
|
||||
* this won't return nodes outside active editing host.
|
||||
* HTMLEditUtils::GetPreviousContent({WalkTreeOption::IgnoreNonEditableNode})
|
||||
* but this won't return nodes outside active editing host.
|
||||
*/
|
||||
nsIContent* GetPreviousEditableHTMLNode(nsINode& aNode) const {
|
||||
return GetPreviousEditableHTMLNodeInternal(aNode, false);
|
||||
|
@ -1047,7 +1047,7 @@ class HTMLEditor final : public TextEditor,
|
|||
|
||||
/**
|
||||
* GetNextEditableHTMLNode*() methods are similar to
|
||||
* EditorBase::GetNextContent({WalkTreeOption::IgnoreNonEditableNode}) but
|
||||
* HTMLEditUtils::GetNextContent({WalkTreeOption::IgnoreNonEditableNode}) but
|
||||
* this won't return nodes outside active editing host.
|
||||
*
|
||||
* Note that same as EditorBase::GetTextEditableNode(), methods which take
|
||||
|
|
|
@ -50,6 +50,7 @@ using EmptyCheckOption = HTMLEditUtils::EmptyCheckOption;
|
|||
using InvisibleWhiteSpaces = HTMLEditUtils::InvisibleWhiteSpaces;
|
||||
using StyleDifference = HTMLEditUtils::StyleDifference;
|
||||
using TableBoundary = HTMLEditUtils::TableBoundary;
|
||||
using WalkTreeOption = HTMLEditUtils::WalkTreeOption;
|
||||
|
||||
template nsresult HTMLEditor::DeleteTextAndTextNodesWithTransaction(
|
||||
const EditorDOMPoint& aStartPoint, const EditorDOMPoint& aEndPoint,
|
||||
|
@ -3897,9 +3898,9 @@ HTMLEditor::AutoDeleteRangesHandler::ComputeRangesToDeleteRangesWithTransaction(
|
|||
if (howToHandleCollapsedRange ==
|
||||
EditorBase::HowToHandleCollapsedRange::ExtendBackward &&
|
||||
caretPoint.IsStartOfContainer()) {
|
||||
nsIContent* previousEditableContent = EditorBase::GetPreviousContent(
|
||||
*caretPoint.GetContainer(),
|
||||
{EditorBase::WalkTreeOption::IgnoreNonEditableNode}, editingHost);
|
||||
nsIContent* previousEditableContent = HTMLEditUtils::GetPreviousContent(
|
||||
*caretPoint.GetContainer(), {WalkTreeOption::IgnoreNonEditableNode},
|
||||
editingHost);
|
||||
if (!previousEditableContent) {
|
||||
continue;
|
||||
}
|
||||
|
@ -3920,9 +3921,9 @@ HTMLEditor::AutoDeleteRangesHandler::ComputeRangesToDeleteRangesWithTransaction(
|
|||
if (howToHandleCollapsedRange ==
|
||||
EditorBase::HowToHandleCollapsedRange::ExtendForward &&
|
||||
caretPoint.IsEndOfContainer()) {
|
||||
nsIContent* nextEditableContent = EditorBase::GetNextContent(
|
||||
*caretPoint.GetContainer(),
|
||||
{EditorBase::WalkTreeOption::IgnoreNonEditableNode}, editingHost);
|
||||
nsIContent* nextEditableContent = HTMLEditUtils::GetNextContent(
|
||||
*caretPoint.GetContainer(), {WalkTreeOption::IgnoreNonEditableNode},
|
||||
editingHost);
|
||||
if (!nextEditableContent) {
|
||||
continue;
|
||||
}
|
||||
|
@ -3957,13 +3958,11 @@ HTMLEditor::AutoDeleteRangesHandler::ComputeRangesToDeleteRangesWithTransaction(
|
|||
nsIContent* editableContent =
|
||||
howToHandleCollapsedRange ==
|
||||
EditorBase::HowToHandleCollapsedRange::ExtendBackward
|
||||
? EditorBase::GetPreviousContent(
|
||||
caretPoint,
|
||||
{EditorBase::WalkTreeOption::IgnoreNonEditableNode},
|
||||
? HTMLEditUtils::GetPreviousContent(
|
||||
caretPoint, {WalkTreeOption::IgnoreNonEditableNode},
|
||||
editingHost)
|
||||
: EditorBase::GetNextContent(
|
||||
caretPoint,
|
||||
{EditorBase::WalkTreeOption::IgnoreNonEditableNode},
|
||||
: HTMLEditUtils::GetNextContent(
|
||||
caretPoint, {WalkTreeOption::IgnoreNonEditableNode},
|
||||
editingHost);
|
||||
if (!editableContent) {
|
||||
continue;
|
||||
|
@ -3973,10 +3972,10 @@ HTMLEditor::AutoDeleteRangesHandler::ComputeRangesToDeleteRangesWithTransaction(
|
|||
editableContent =
|
||||
howToHandleCollapsedRange ==
|
||||
EditorBase::HowToHandleCollapsedRange::ExtendBackward
|
||||
? EditorBase::GetPreviousContent(
|
||||
? HTMLEditUtils::GetPreviousContent(
|
||||
*editableContent, {WalkTreeOption::IgnoreNonEditableNode},
|
||||
editingHost)
|
||||
: EditorBase::GetNextContent(
|
||||
: HTMLEditUtils::GetNextContent(
|
||||
*editableContent, {WalkTreeOption::IgnoreNonEditableNode},
|
||||
editingHost);
|
||||
}
|
||||
|
@ -4428,7 +4427,7 @@ nsresult HTMLEditor::AutoDeleteRangesHandler::AutoBlockElementsJoiner::
|
|||
atStart.IsEndOfContainer() && range.StartRef().GetChild() &&
|
||||
range.StartRef().GetChild()->IsHTMLElement(nsGkAtoms::br) &&
|
||||
!aHTMLEditor.IsVisibleBRElement(range.StartRef().GetChild())
|
||||
? EditorBase::GetNextContent(
|
||||
? HTMLEditUtils::GetNextContent(
|
||||
*atStart.ContainerAsContent(),
|
||||
{WalkTreeOption::IgnoreDataNodeExceptText,
|
||||
WalkTreeOption::StopAtBlockBoundary},
|
||||
|
@ -5177,7 +5176,7 @@ Result<EditorDOMPoint, nsresult> HTMLEditor::AutoDeleteRangesHandler::
|
|||
EditorDOMPoint afterEmptyBlock(
|
||||
EditorRawDOMPoint::After(mEmptyInclusiveAncestorBlockElement));
|
||||
MOZ_ASSERT(afterEmptyBlock.IsSet());
|
||||
if (nsIContent* nextContentOfEmptyBlock = EditorBase::GetNextContent(
|
||||
if (nsIContent* nextContentOfEmptyBlock = HTMLEditUtils::GetNextContent(
|
||||
afterEmptyBlock, {}, aHTMLEditor.GetActiveEditingHost())) {
|
||||
EditorDOMPoint pt = aHTMLEditor.GetGoodCaretPointFor(
|
||||
*nextContentOfEmptyBlock, aDirectionAndAmount);
|
||||
|
@ -5199,7 +5198,7 @@ Result<EditorDOMPoint, nsresult> HTMLEditor::AutoDeleteRangesHandler::
|
|||
// if there is. Otherwise, to after the empty block.
|
||||
EditorRawDOMPoint atEmptyBlock(mEmptyInclusiveAncestorBlockElement);
|
||||
if (nsIContent* previousContentOfEmptyBlock =
|
||||
EditorBase::GetPreviousContent(
|
||||
HTMLEditUtils::GetPreviousContent(
|
||||
atEmptyBlock, {WalkTreeOption::IgnoreNonEditableNode},
|
||||
aHTMLEditor.GetActiveEditingHost())) {
|
||||
EditorDOMPoint pt = aHTMLEditor.GetGoodCaretPointFor(
|
||||
|
|
|
@ -39,6 +39,7 @@
|
|||
namespace mozilla {
|
||||
|
||||
using EditorType = EditorUtils::EditorType;
|
||||
using WalkTreeOption = HTMLEditUtils::WalkTreeOption;
|
||||
|
||||
/*****************************************************************************
|
||||
* ListElementSelectionState
|
||||
|
@ -247,8 +248,8 @@ AlignStateAtSelection::AlignStateAtSelection(HTMLEditor& aHTMLEditor,
|
|||
else if (atStartOfSelection.IsContainerHTMLElement(nsGkAtoms::html) &&
|
||||
atBodyOrDocumentElement.IsSet() &&
|
||||
atStartOfSelection.Offset() == atBodyOrDocumentElement.Offset()) {
|
||||
editTargetContent = EditorBase::GetNextContent(
|
||||
atStartOfSelection, {EditorBase::WalkTreeOption::IgnoreNonEditableNode},
|
||||
editTargetContent = HTMLEditUtils::GetNextContent(
|
||||
atStartOfSelection, {WalkTreeOption::IgnoreNonEditableNode},
|
||||
aHTMLEditor.GetActiveEditingHost());
|
||||
if (NS_WARN_IF(!editTargetContent)) {
|
||||
aRv.Throw(NS_ERROR_FAILURE);
|
||||
|
|
Загрузка…
Ссылка в новой задаче