зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1627175 - part 42: Get rid of `HTMLEditor::GetNextEditableHTMLNode()` and `HTMLEditor::GetPreviousEditableHTMLNode()` r=m_kato
This changes the logic of `HTMLEditor::GetFirstEditableLeaf()` and `HTMLEditor::GetLastEditableLeaf()`, but it shouldn't change actual behavior because the case is that the first/last child of `aNode` is not in editing host but editable. Differential Revision: https://phabricator.services.mozilla.com/D113282
This commit is contained in:
Родитель
95fc0ef210
Коммит
ebf2dd010f
|
@ -732,8 +732,16 @@ nsresult HTMLEditor::EnsureCaretNotAfterPaddingBRElement() {
|
|||
}
|
||||
MOZ_ASSERT(atSelectionStart.IsSetAndValid());
|
||||
|
||||
nsCOMPtr<nsIContent> previousEditableContent =
|
||||
GetPreviousEditableHTMLNode(atSelectionStart);
|
||||
Element* editingHost = GetActiveEditingHost();
|
||||
if (!editingHost) {
|
||||
NS_WARNING(
|
||||
"HTMLEditor::EnsureCaretNotAfterPaddingBRElement() did nothing because "
|
||||
"of no editing host");
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsIContent* previousEditableContent = HTMLEditUtils::GetPreviousContent(
|
||||
atSelectionStart, {WalkTreeOption::IgnoreNonEditableNode}, editingHost);
|
||||
if (!previousEditableContent ||
|
||||
!EditorUtils::IsPaddingBRElementForEmptyLastLine(
|
||||
*previousEditableContent)) {
|
||||
|
@ -3124,17 +3132,22 @@ nsresult HTMLEditor::FormatBlockContainerWithTransaction(nsAtom& blockType) {
|
|||
// If the first editable node after selection is a br, consume it.
|
||||
// Otherwise it gets pushed into a following block after the split,
|
||||
// which is visually bad.
|
||||
nsCOMPtr<nsIContent> brContent =
|
||||
GetNextEditableHTMLNode(pointToInsertBlock);
|
||||
if (brContent && brContent->IsHTMLElement(nsGkAtoms::br)) {
|
||||
AutoEditorDOMPointChildInvalidator lockOffset(pointToInsertBlock);
|
||||
rv = DeleteNodeWithTransaction(*brContent);
|
||||
if (NS_WARN_IF(Destroyed())) {
|
||||
return NS_ERROR_EDITOR_DESTROYED;
|
||||
}
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_WARNING("HTMLEditor::DeleteNodeWithTransaction() failed");
|
||||
return rv;
|
||||
// XXX Why do we keep handling it when there is no editing host?
|
||||
if (Element* editingHost = GetActiveEditingHost()) {
|
||||
if (nsCOMPtr<nsIContent> brContent = HTMLEditUtils::GetNextContent(
|
||||
pointToInsertBlock, {WalkTreeOption::IgnoreNonEditableNode},
|
||||
editingHost)) {
|
||||
if (brContent && brContent->IsHTMLElement(nsGkAtoms::br)) {
|
||||
AutoEditorDOMPointChildInvalidator lockOffset(pointToInsertBlock);
|
||||
rv = DeleteNodeWithTransaction(*brContent);
|
||||
if (NS_WARN_IF(Destroyed())) {
|
||||
return NS_ERROR_EDITOR_DESTROYED;
|
||||
}
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_WARNING("HTMLEditor::DeleteNodeWithTransaction() failed");
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Do the splits!
|
||||
|
@ -3150,18 +3163,19 @@ nsresult HTMLEditor::FormatBlockContainerWithTransaction(nsAtom& blockType) {
|
|||
}
|
||||
EditorDOMPoint pointToInsertBRNode(splitNodeResult.SplitPoint());
|
||||
// Put a <br> element at the split point
|
||||
brContent = InsertBRElementWithTransaction(pointToInsertBRNode);
|
||||
RefPtr<Element> brElement =
|
||||
InsertBRElementWithTransaction(pointToInsertBRNode);
|
||||
if (NS_WARN_IF(Destroyed())) {
|
||||
return NS_ERROR_EDITOR_DESTROYED;
|
||||
}
|
||||
if (!brContent) {
|
||||
if (!brElement) {
|
||||
NS_WARNING("HTMLEditor::InsertBRElementWithTransaction() failed");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
// Don't restore the selection
|
||||
restoreSelectionLater.Abort();
|
||||
// Put selection at the split point
|
||||
nsresult rv = CollapseSelectionTo(EditorRawDOMPoint(brContent));
|
||||
nsresult rv = CollapseSelectionTo(EditorRawDOMPoint(brElement));
|
||||
NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
|
||||
"HTMLEditor::CollapseSelectionTo() failed");
|
||||
return rv;
|
||||
|
@ -5401,10 +5415,13 @@ nsresult HTMLEditor::MaybeExtendSelectionToHardLineEdgesForBlockEditAction() {
|
|||
}
|
||||
// else block is empty - we can leave selection alone here, i think.
|
||||
} else if (wsScannerAtEnd.StartsFromCurrentBlockBoundary()) {
|
||||
// endpoint is just after start of this block
|
||||
nsINode* child = GetPreviousEditableHTMLNode(endPoint);
|
||||
if (child) {
|
||||
newEndPoint.SetAfter(child);
|
||||
if (wsScannerAtEnd.GetEditingHost()) {
|
||||
// endpoint is just after start of this block
|
||||
if (nsIContent* child = HTMLEditUtils::GetPreviousContent(
|
||||
endPoint, {WalkTreeOption::IgnoreNonEditableNode},
|
||||
wsScannerAtEnd.GetEditingHost())) {
|
||||
newEndPoint.SetAfter(child);
|
||||
}
|
||||
}
|
||||
// else block is empty - we can leave selection alone here, i think.
|
||||
} else if (wsScannerAtEnd.StartsFromBRElement()) {
|
||||
|
@ -5435,10 +5452,13 @@ nsresult HTMLEditor::MaybeExtendSelectionToHardLineEdgesForBlockEditAction() {
|
|||
}
|
||||
// else block is empty - we can leave selection alone here, i think.
|
||||
} else if (wsScannerAtStart.EndsByCurrentBlockBoundary()) {
|
||||
// startpoint is just before end of this block
|
||||
nsINode* child = GetNextEditableHTMLNode(startPoint);
|
||||
if (child) {
|
||||
newStartPoint.Set(child);
|
||||
if (wsScannerAtStart.GetEditingHost()) {
|
||||
// startpoint is just before end of this block
|
||||
if (nsIContent* child = HTMLEditUtils::GetNextContent(
|
||||
startPoint, {WalkTreeOption::IgnoreNonEditableNode},
|
||||
wsScannerAtStart.GetEditingHost())) {
|
||||
newStartPoint.Set(child);
|
||||
}
|
||||
}
|
||||
// else block is empty - we can leave selection alone here, i think.
|
||||
} else if (wsScannerAtStart.EndsByBRElement()) {
|
||||
|
@ -6713,12 +6733,20 @@ EditActionResult HTMLEditor::HandleInsertParagraphInParagraph(
|
|||
} else {
|
||||
// not in a text node.
|
||||
// is there a BR prior to it?
|
||||
nsCOMPtr<nsIContent> nearContent =
|
||||
GetPreviousEditableHTMLNode(atStartOfSelection);
|
||||
Element* editingHost = GetActiveEditingHost();
|
||||
nsIContent* nearContent =
|
||||
editingHost ? HTMLEditUtils::GetPreviousContent(
|
||||
atStartOfSelection,
|
||||
{WalkTreeOption::IgnoreNonEditableNode}, editingHost)
|
||||
: nullptr;
|
||||
if (!nearContent || !IsVisibleBRElement(nearContent) ||
|
||||
EditorUtils::IsPaddingBRElementForEmptyLastLine(*nearContent)) {
|
||||
// is there a BR after it?
|
||||
nearContent = GetNextEditableHTMLNode(atStartOfSelection);
|
||||
nearContent = editingHost ? HTMLEditUtils::GetNextContent(
|
||||
atStartOfSelection,
|
||||
{WalkTreeOption::IgnoreNonEditableNode},
|
||||
editingHost)
|
||||
: nullptr;
|
||||
if (!nearContent || !IsVisibleBRElement(nearContent) ||
|
||||
EditorUtils::IsPaddingBRElementForEmptyLastLine(*nearContent)) {
|
||||
pointToInsertBR = atStartOfSelection;
|
||||
|
@ -8151,57 +8179,58 @@ nsresult HTMLEditor::AdjustCaretPositionAndEnsurePaddingBRElement(
|
|||
// 1) prior node is in same block where selection is AND
|
||||
// 2) prior node is a br AND
|
||||
// 3) that br is not visible
|
||||
RefPtr<Element> editingHost = GetActiveEditingHost();
|
||||
if (nsCOMPtr<nsIContent> previousEditableContent =
|
||||
GetPreviousEditableHTMLNode(point)) {
|
||||
RefPtr<Element> blockElementAtCaret =
|
||||
HTMLEditUtils::GetInclusiveAncestorBlockElement(
|
||||
*point.ContainerAsContent());
|
||||
RefPtr<Element> blockElementParentAtPreviousEditableContent =
|
||||
HTMLEditUtils::GetAncestorBlockElement(*previousEditableContent);
|
||||
// If previous editable content of caret is in same block and a `<br>`
|
||||
// element, we need to adjust interline position.
|
||||
if (blockElementAtCaret &&
|
||||
blockElementAtCaret == blockElementParentAtPreviousEditableContent &&
|
||||
previousEditableContent &&
|
||||
previousEditableContent->IsHTMLElement(nsGkAtoms::br)) {
|
||||
// If it's an invisible `<br>` element, we need to insert a padding
|
||||
// `<br>` element for making empty line have one-line height.
|
||||
if (!IsVisibleBRElement(previousEditableContent)) {
|
||||
CreateElementResult createPaddingBRResult =
|
||||
InsertPaddingBRElementForEmptyLastLineWithTransaction(point);
|
||||
if (createPaddingBRResult.Failed()) {
|
||||
NS_WARNING(
|
||||
"HTMLEditor::"
|
||||
"InsertPaddingBRElementForEmptyLastLineWithTransaction() failed");
|
||||
return createPaddingBRResult.Rv();
|
||||
if (RefPtr<Element> editingHost = GetActiveEditingHost()) {
|
||||
if (nsCOMPtr<nsIContent> previousEditableContent =
|
||||
HTMLEditUtils::GetPreviousContent(
|
||||
point, {WalkTreeOption::IgnoreNonEditableNode}, editingHost)) {
|
||||
RefPtr<Element> blockElementAtCaret =
|
||||
HTMLEditUtils::GetInclusiveAncestorBlockElement(
|
||||
*point.ContainerAsContent());
|
||||
RefPtr<Element> blockElementParentAtPreviousEditableContent =
|
||||
HTMLEditUtils::GetAncestorBlockElement(*previousEditableContent);
|
||||
// If previous editable content of caret is in same block and a `<br>`
|
||||
// element, we need to adjust interline position.
|
||||
if (blockElementAtCaret &&
|
||||
blockElementAtCaret == blockElementParentAtPreviousEditableContent &&
|
||||
previousEditableContent &&
|
||||
previousEditableContent->IsHTMLElement(nsGkAtoms::br)) {
|
||||
// If it's an invisible `<br>` element, we need to insert a padding
|
||||
// `<br>` element for making empty line have one-line height.
|
||||
if (!IsVisibleBRElement(previousEditableContent)) {
|
||||
CreateElementResult createPaddingBRResult =
|
||||
InsertPaddingBRElementForEmptyLastLineWithTransaction(point);
|
||||
if (createPaddingBRResult.Failed()) {
|
||||
NS_WARNING(
|
||||
"HTMLEditor::"
|
||||
"InsertPaddingBRElementForEmptyLastLineWithTransaction() "
|
||||
"failed");
|
||||
return createPaddingBRResult.Rv();
|
||||
}
|
||||
point.Set(createPaddingBRResult.GetNewNode());
|
||||
// Selection stays *before* padding `<br>` element for empty last
|
||||
// line, sticking to it.
|
||||
IgnoredErrorResult ignoredError;
|
||||
SelectionRef().SetInterlinePosition(true, ignoredError);
|
||||
if (NS_WARN_IF(Destroyed())) {
|
||||
return NS_ERROR_EDITOR_DESTROYED;
|
||||
}
|
||||
NS_WARNING_ASSERTION(
|
||||
!ignoredError.Failed(),
|
||||
"Selection::SetInterlinePosition(true) failed, but ignored");
|
||||
nsresult rv = CollapseSelectionTo(point);
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_WARNING("HTMLEditor::CollapseSelectionTo() failed");
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
point.Set(createPaddingBRResult.GetNewNode());
|
||||
// Selection stays *before* padding `<br>` element for empty last
|
||||
// line, sticking to it.
|
||||
IgnoredErrorResult ignoredError;
|
||||
SelectionRef().SetInterlinePosition(true, ignoredError);
|
||||
if (NS_WARN_IF(Destroyed())) {
|
||||
return NS_ERROR_EDITOR_DESTROYED;
|
||||
}
|
||||
NS_WARNING_ASSERTION(
|
||||
!ignoredError.Failed(),
|
||||
"Selection::SetInterlinePosition(true) failed, but ignored");
|
||||
nsresult rv = CollapseSelectionTo(point);
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_WARNING("HTMLEditor::CollapseSelectionTo() failed");
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
// If it's a visible `<br>` element and next editable content is a
|
||||
// padding `<br>` element, we need to set interline position.
|
||||
else if (editingHost) {
|
||||
if (nsIContent* nextEditableContentInBlock =
|
||||
HTMLEditUtils::GetNextContent(
|
||||
*previousEditableContent,
|
||||
{WalkTreeOption::IgnoreNonEditableNode,
|
||||
WalkTreeOption::StopAtBlockBoundary},
|
||||
editingHost)) {
|
||||
// If it's a visible `<br>` element and next editable content is a
|
||||
// padding `<br>` element, we need to set interline position.
|
||||
else if (nsIContent* nextEditableContentInBlock =
|
||||
HTMLEditUtils::GetNextContent(
|
||||
*previousEditableContent,
|
||||
{WalkTreeOption::IgnoreNonEditableNode,
|
||||
WalkTreeOption::StopAtBlockBoundary},
|
||||
editingHost)) {
|
||||
if (EditorUtils::IsPaddingBRElementForEmptyLastLine(
|
||||
*nextEditableContentInBlock)) {
|
||||
// Make it stick to the padding `<br>` element so that it will be
|
||||
|
@ -8215,9 +8244,7 @@ nsresult HTMLEditor::AdjustCaretPositionAndEnsurePaddingBRElement(
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (editingHost) {
|
||||
// If previous editable content in same block is `<br>`, text node, `<img>`
|
||||
// or `<hr>`, current caret position is fine.
|
||||
if (nsIContent* previousEditableContentInBlock =
|
||||
|
@ -8277,14 +8304,21 @@ nsIContent* HTMLEditor::FindNearEditableContent(
|
|||
MOZ_ASSERT(IsEditActionDataAvailable());
|
||||
MOZ_ASSERT(aPoint.IsSetAndValid());
|
||||
|
||||
Element* editingHost = GetActiveEditingHost();
|
||||
if (NS_WARN_IF(!editingHost)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nsIContent* editableContent = nullptr;
|
||||
if (aDirection == nsIEditor::ePrevious) {
|
||||
editableContent = GetPreviousEditableHTMLNode(aPoint);
|
||||
editableContent = HTMLEditUtils::GetPreviousContent(
|
||||
aPoint, {WalkTreeOption::IgnoreNonEditableNode}, editingHost);
|
||||
if (!editableContent) {
|
||||
return nullptr; // Not illegal.
|
||||
}
|
||||
} else {
|
||||
editableContent = GetNextEditableHTMLNode(aPoint);
|
||||
editableContent = HTMLEditUtils::GetNextContent(
|
||||
aPoint, {WalkTreeOption::IgnoreNonEditableNode}, editingHost);
|
||||
if (NS_WARN_IF(!editableContent)) {
|
||||
// Perhaps, illegal because the node pointed by aPoint isn't editable
|
||||
// and nobody of previous nodes is editable.
|
||||
|
@ -8300,12 +8334,16 @@ nsIContent* HTMLEditor::FindNearEditableContent(
|
|||
!editableContent->IsHTMLElement(nsGkAtoms::br) &&
|
||||
!HTMLEditUtils::IsImage(editableContent)) {
|
||||
if (aDirection == nsIEditor::ePrevious) {
|
||||
editableContent = GetPreviousEditableHTMLNode(*editableContent);
|
||||
editableContent = HTMLEditUtils::GetPreviousContent(
|
||||
*editableContent, {WalkTreeOption::IgnoreNonEditableNode},
|
||||
editingHost);
|
||||
if (NS_WARN_IF(!editableContent)) {
|
||||
return nullptr;
|
||||
}
|
||||
} else {
|
||||
editableContent = GetNextEditableHTMLNode(*editableContent);
|
||||
editableContent = HTMLEditUtils::GetNextContent(
|
||||
*editableContent, {WalkTreeOption::IgnoreNonEditableNode},
|
||||
editingHost);
|
||||
if (NS_WARN_IF(!editableContent)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
|
|
@ -5012,47 +5012,6 @@ nsIContent* HTMLEditor::GetNextHTMLSibling(nsINode* aNode,
|
|||
return content;
|
||||
}
|
||||
|
||||
nsIContent* HTMLEditor::GetPreviousEditableHTMLNodeInternal(
|
||||
nsINode& aNode) const {
|
||||
Element* editingHost = GetActiveEditingHost();
|
||||
if (NS_WARN_IF(!editingHost)) {
|
||||
return nullptr;
|
||||
}
|
||||
return HTMLEditUtils::GetPreviousContent(
|
||||
aNode, {WalkTreeOption::IgnoreNonEditableNode}, editingHost);
|
||||
}
|
||||
|
||||
template <typename PT, typename CT>
|
||||
nsIContent* HTMLEditor::GetPreviousEditableHTMLNodeInternal(
|
||||
const EditorDOMPointBase<PT, CT>& aPoint) const {
|
||||
Element* editingHost = GetActiveEditingHost();
|
||||
if (NS_WARN_IF(!editingHost)) {
|
||||
return nullptr;
|
||||
}
|
||||
return HTMLEditUtils::GetPreviousContent(
|
||||
aPoint, {WalkTreeOption::IgnoreNonEditableNode}, editingHost);
|
||||
}
|
||||
|
||||
nsIContent* HTMLEditor::GetNextEditableHTMLNodeInternal(nsINode& aNode) const {
|
||||
Element* editingHost = GetActiveEditingHost();
|
||||
if (NS_WARN_IF(!editingHost)) {
|
||||
return nullptr;
|
||||
}
|
||||
return HTMLEditUtils::GetNextContent(
|
||||
aNode, {WalkTreeOption::IgnoreNonEditableNode}, editingHost);
|
||||
}
|
||||
|
||||
template <typename PT, typename CT>
|
||||
nsIContent* HTMLEditor::GetNextEditableHTMLNodeInternal(
|
||||
const EditorDOMPointBase<PT, CT>& aPoint) const {
|
||||
Element* editingHost = GetActiveEditingHost();
|
||||
if (NS_WARN_IF(!editingHost)) {
|
||||
return nullptr;
|
||||
}
|
||||
return HTMLEditUtils::GetNextContent(
|
||||
aPoint, {WalkTreeOption::IgnoreNonEditableNode}, editingHost);
|
||||
}
|
||||
|
||||
bool HTMLEditor::IsFirstEditableChild(nsINode* aNode) const {
|
||||
MOZ_ASSERT(aNode);
|
||||
// find first editable child and compare it to aNode
|
||||
|
@ -5090,32 +5049,36 @@ nsIContent* HTMLEditor::GetLastEditableChild(nsINode& aNode) const {
|
|||
}
|
||||
|
||||
nsIContent* HTMLEditor::GetFirstEditableLeaf(nsINode& aNode) const {
|
||||
Element* editingHost = GetActiveEditingHost();
|
||||
if (NS_WARN_IF(!editingHost) ||
|
||||
editingHost->IsInclusiveDescendantOf(&aNode)) {
|
||||
return nullptr;
|
||||
}
|
||||
nsIContent* child =
|
||||
HTMLEditUtils::GetFirstLeafChild(aNode, {LeafNodeType::OnlyLeafNode});
|
||||
while (child && (!EditorUtils::IsEditableContent(*child, EditorType::HTML) ||
|
||||
child->HasChildren())) {
|
||||
child = GetNextEditableHTMLNode(*child);
|
||||
|
||||
// Only accept nodes that are descendants of aNode
|
||||
if (!aNode.Contains(child)) {
|
||||
return nullptr;
|
||||
}
|
||||
child = HTMLEditUtils::GetNextContent(
|
||||
*child, {WalkTreeOption::IgnoreNonEditableNode},
|
||||
aNode.IsElement() ? aNode.AsElement() : editingHost);
|
||||
}
|
||||
|
||||
return child;
|
||||
}
|
||||
|
||||
nsIContent* HTMLEditor::GetLastEditableLeaf(nsINode& aNode) const {
|
||||
Element* editingHost = GetActiveEditingHost();
|
||||
if (NS_WARN_IF(!editingHost) ||
|
||||
editingHost->IsInclusiveDescendantOf(&aNode)) {
|
||||
return nullptr;
|
||||
}
|
||||
nsIContent* child =
|
||||
HTMLEditUtils::GetLastLeafChild(aNode, {LeafNodeType::OnlyLeafNode});
|
||||
while (child && (!EditorUtils::IsEditableContent(*child, EditorType::HTML) ||
|
||||
child->HasChildren())) {
|
||||
child = GetPreviousEditableHTMLNode(*child);
|
||||
|
||||
// Only accept nodes that are descendants of aNode
|
||||
if (!aNode.Contains(child)) {
|
||||
return nullptr;
|
||||
}
|
||||
child = HTMLEditUtils::GetPreviousContent(
|
||||
*child, {WalkTreeOption::IgnoreNonEditableNode},
|
||||
aNode.IsElement() ? aNode.AsElement() : editingHost);
|
||||
}
|
||||
|
||||
return child;
|
||||
|
@ -5664,6 +5627,11 @@ nsresult HTMLEditor::CopyLastEditableChildStylesWithTransaction(
|
|||
}
|
||||
}
|
||||
|
||||
RefPtr<Element> editingHost = GetActiveEditingHost();
|
||||
if (!editingHost) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// XXX aNewBlock may be moved or removed. Even in such case, we should
|
||||
// keep cloning the styles?
|
||||
|
||||
|
@ -5676,8 +5644,9 @@ nsresult HTMLEditor::CopyLastEditableChildStylesWithTransaction(
|
|||
}
|
||||
while (deepestEditableContent &&
|
||||
deepestEditableContent->IsHTMLElement(nsGkAtoms::br)) {
|
||||
deepestEditableContent =
|
||||
GetPreviousEditableHTMLNode(*deepestEditableContent);
|
||||
deepestEditableContent = HTMLEditUtils::GetPreviousContent(
|
||||
*deepestEditableContent, {WalkTreeOption::IgnoreNonEditableNode},
|
||||
editingHost);
|
||||
}
|
||||
if (!deepestEditableContent) {
|
||||
return NS_OK;
|
||||
|
|
|
@ -944,57 +944,6 @@ class HTMLEditor final : public TextEditor,
|
|||
aNode->AsText()->TextIsOnlyWhitespace();
|
||||
}
|
||||
|
||||
/**
|
||||
* GetPreviousEditableHTMLNode*() methods are similar to
|
||||
* HTMLEditUtils::GetPreviousContent({WalkTreeOption::IgnoreNonEditableNode})
|
||||
* but this won't return nodes outside active editing host.
|
||||
*/
|
||||
nsIContent* GetPreviousEditableHTMLNode(nsINode& aNode) const {
|
||||
return GetPreviousEditableHTMLNodeInternal(aNode);
|
||||
}
|
||||
template <typename PT, typename CT>
|
||||
nsIContent* GetPreviousEditableHTMLNode(
|
||||
const EditorDOMPointBase<PT, CT>& aPoint) const {
|
||||
return GetPreviousEditableHTMLNodeInternal(aPoint);
|
||||
}
|
||||
|
||||
/**
|
||||
* GetPreviousEditableHTMLNodeInternal() methods are common implementation
|
||||
* of above methods. Please don't use this method directly.
|
||||
*/
|
||||
nsIContent* GetPreviousEditableHTMLNodeInternal(nsINode& aNode) const;
|
||||
template <typename PT, typename CT>
|
||||
nsIContent* GetPreviousEditableHTMLNodeInternal(
|
||||
const EditorDOMPointBase<PT, CT>& aPoint) const;
|
||||
|
||||
/**
|
||||
* GetNextEditableHTMLNode*() methods are similar to
|
||||
* HTMLEditUtils::GetNextContent({WalkTreeOption::IgnoreNonEditableNode}) but
|
||||
* this won't return nodes outside active editing host.
|
||||
*
|
||||
* Note that same as EditorBase::GetTextEditableNode(), methods which take
|
||||
* |const EditorRawDOMPoint&| start to search from the node pointed by it.
|
||||
* On the other hand, methods which take |nsINode&| start to search from
|
||||
* next node of aNode.
|
||||
*/
|
||||
nsIContent* GetNextEditableHTMLNode(nsINode& aNode) const {
|
||||
return GetNextEditableHTMLNodeInternal(aNode);
|
||||
}
|
||||
template <typename PT, typename CT>
|
||||
nsIContent* GetNextEditableHTMLNode(
|
||||
const EditorDOMPointBase<PT, CT>& aPoint) const {
|
||||
return GetNextEditableHTMLNodeInternal(aPoint);
|
||||
}
|
||||
|
||||
/**
|
||||
* GetNextEditableHTMLNodeInternal() methods are common implementation
|
||||
* of above methods. Please don't use this method directly.
|
||||
*/
|
||||
nsIContent* GetNextEditableHTMLNodeInternal(nsINode& aNode) const;
|
||||
template <typename PT, typename CT>
|
||||
nsIContent* GetNextEditableHTMLNodeInternal(
|
||||
const EditorDOMPointBase<PT, CT>& aPoint) const;
|
||||
|
||||
bool IsFirstEditableChild(nsINode* aNode) const;
|
||||
bool IsLastEditableChild(nsINode* aNode) const;
|
||||
nsIContent* GetFirstEditableChild(nsINode& aNode) const;
|
||||
|
|
|
@ -2764,12 +2764,20 @@ bool HTMLEditor::AutoDeleteRangesHandler::AutoBlockElementsJoiner::
|
|||
return false;
|
||||
}
|
||||
|
||||
Element* editingHost = aHTMLEditor.GetActiveEditingHost();
|
||||
if (NS_WARN_IF(!editingHost)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (aDirectionAndAmount == nsIEditor::ePrevious) {
|
||||
mLeftContent =
|
||||
aHTMLEditor.GetPreviousEditableHTMLNode(aCurrentBlockElement);
|
||||
mLeftContent = HTMLEditUtils::GetPreviousContent(
|
||||
aCurrentBlockElement, {WalkTreeOption::IgnoreNonEditableNode},
|
||||
editingHost);
|
||||
mRightContent = aCaretPoint.GetContainerAsContent();
|
||||
} else {
|
||||
mRightContent = aHTMLEditor.GetNextEditableHTMLNode(aCurrentBlockElement);
|
||||
mRightContent = HTMLEditUtils::GetNextContent(
|
||||
aCurrentBlockElement, {WalkTreeOption::IgnoreNonEditableNode},
|
||||
editingHost);
|
||||
mLeftContent = aCaretPoint.GetContainerAsContent();
|
||||
}
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче