From 44f51bc1277d2d9cee5d1629245e2d46535c1c8f Mon Sep 17 00:00:00 2001 From: Masayuki Nakano Date: Thu, 9 Nov 2017 23:31:59 +0900 Subject: [PATCH] Bug 1415800 - part 3: Redesign HTMLEditor::GetPriorHTMLNode() as similar to EditorBase::GetPrevious*() r=m_kato HTMLEditor::GetPriorHTMLNode() methods are similar to EditorBase::GetPriorNode() which was redesigned with the previous patch. So, it should be redesigned as HTMLEditor::GetPreviousEditableHTMLNode(nsINode&), HTMLEditor::GetPreviousEditableHTMLNode(const EditorRawDOMPoint&), HTMLEditor::GetPreviousEditableHTMLNodeInBlock(nsINode&) and HTMLEditor::GetPreviousEditableHTMLNodeInBlock(const EditorRawDOMPoint&). Note that HTMLEditor::GetPriorHTMLNode() are always return editable node. So, we don't need to create non-editable node methods for them. Although, I don't like the word "HTMLNode" because this can return SVG element or something too. The additional feature of those methods is just checking given node is in active editing host. So, they are for HTML editor, but not returning only HTML nodes. However, I have no better idea with shorter name. MozReview-Commit-ID: 3J4IaBOFjzj --HG-- extra : rebase_source : 712bc8676fcdc37f38fd46083df177c0fe6bd408 --- editor/libeditor/HTMLEditRules.cpp | 254 +++++++++++++++-------------- editor/libeditor/HTMLEditor.cpp | 42 ++--- editor/libeditor/HTMLEditor.h | 36 +++- 3 files changed, 175 insertions(+), 157 deletions(-) diff --git a/editor/libeditor/HTMLEditRules.cpp b/editor/libeditor/HTMLEditRules.cpp index 2327db4030de..4501e7c61551 100644 --- a/editor/libeditor/HTMLEditRules.cpp +++ b/editor/libeditor/HTMLEditRules.cpp @@ -1250,20 +1250,24 @@ HTMLEditRules::WillInsert(Selection& aSelection, // If we are after a mozBR in the same block, then move selection to be // before it - NS_ENSURE_TRUE_VOID(aSelection.GetRangeAt(0) && - aSelection.GetRangeAt(0)->GetStartContainer()); - OwningNonNull selNode = - *aSelection.GetRangeAt(0)->GetStartContainer(); - nsIContent* selChild = aSelection.GetRangeAt(0)->GetChildAtStartOffset(); - int32_t selOffset = aSelection.GetRangeAt(0)->StartOffset(); + nsRange* firstRange = aSelection.GetRangeAt(0); + if (NS_WARN_IF(!firstRange)) { + return; + } + + EditorRawDOMPoint atStartOfSelection(firstRange->StartRef()); + if (NS_WARN_IF(!atStartOfSelection.IsSet())) { + return; + } + MOZ_ASSERT(atStartOfSelection.IsSetAndValid()); // Get prior node - nsCOMPtr priorNode = htmlEditor->GetPriorHTMLNode(selNode, - selOffset, - selChild); + nsCOMPtr priorNode = + htmlEditor->GetPreviousEditableHTMLNode(atStartOfSelection); if (priorNode && TextEditUtils::IsMozBR(priorNode)) { - nsCOMPtr block1 = htmlEditor->GetBlock(selNode); - nsCOMPtr block2 = htmlEditor->GetBlockNodeParent(priorNode); + RefPtr block1 = + htmlEditor->GetBlock(*atStartOfSelection.Container()); + RefPtr block2 = htmlEditor->GetBlockNodeParent(priorNode); if (block1 && block1 == block2) { // If we are here then the selection is right after a mozBR that is in @@ -2481,7 +2485,7 @@ HTMLEditRules::WillDeleteSelection(Selection* aSelection, nsCOMPtr leftNode, rightNode; if (aAction == nsIEditor::ePrevious) { NS_ENSURE_STATE(mHTMLEditor); - leftNode = mHTMLEditor->GetPriorHTMLNode(visNode); + leftNode = mHTMLEditor->GetPreviousEditableHTMLNode(*visNode); rightNode = startNode; } else { NS_ENSURE_STATE(mHTMLEditor); @@ -5587,9 +5591,8 @@ HTMLEditRules::NormalizeSelection(Selection* inSelection) // else block is empty - we can leave selection alone here, i think. } else if (wsEndObj.mStartReason == WSType::thisBlock) { // endpoint is just after start of this block - nsINode* child = - htmlEditor->GetPriorHTMLNode(endNode, static_cast(endOffset), - endChild); + EditorRawDOMPoint atEnd(endNode, endChild, endOffset); + nsINode* child = htmlEditor->GetPreviousEditableHTMLNode(atEnd); if (child) { int32_t offset = -1; newEndNode = EditorBase::GetNodeLocation(child, &offset); @@ -5727,57 +5730,49 @@ HTMLEditRules::GetPromotedPoint(RulesEndpoint aWhere, return EditorDOMPoint(content, newOffset); } - nsCOMPtr node = &aNode; - nsINode* child = node->GetChildAt(aOffset); - int32_t offset = aOffset; + EditorDOMPoint point(&aNode, aOffset); // else not a text section. In this case we want to see if we should grab // any adjacent inline nodes and/or parents and other ancestors if (aWhere == kStart) { // some special casing for text nodes - if (node->IsNodeOfType(nsINode::eTEXT)) { - if (!node->GetParentNode()) { + if (point.Container()->IsNodeOfType(nsINode::eTEXT)) { + if (!point.Container()->GetParentNode()) { // Okay, can't promote any further - return EditorDOMPoint(node, offset); + return point; } - offset = node->GetParentNode()->IndexOf(node); - child = node; - node = node->GetParentNode(); + point.Set(point.Container()); } // look back through any further inline nodes that aren't across a
// from us, and that are enclosed in the same block. nsCOMPtr priorNode = - htmlEditor->GetPriorHTMLNode(node, offset, child, true); + htmlEditor->GetPreviousEditableHTMLNodeInBlock(point.AsRaw()); while (priorNode && priorNode->GetParentNode() && !htmlEditor->IsVisibleBRElement(priorNode) && !IsBlockNode(*priorNode)) { - offset = priorNode->GetParentNode()->IndexOf(priorNode); - child = priorNode; - node = priorNode->GetParentNode(); - priorNode = htmlEditor->GetPriorHTMLNode(node, offset, child, true); + point.Set(priorNode); + priorNode = htmlEditor->GetPreviousEditableHTMLNodeInBlock(point.AsRaw()); } // finding the real start for this point. look up the tree for as long as // we are the first node in the container, and as long as we haven't hit // the body node. nsCOMPtr nearNode = - htmlEditor->GetPriorHTMLNode(node, offset, child, true); - while (!nearNode && !node->IsHTMLElement(nsGkAtoms::body) && - node->GetParentNode()) { + htmlEditor->GetPreviousEditableHTMLNodeInBlock(point.AsRaw()); + while (!nearNode && + !point.Container()->IsHTMLElement(nsGkAtoms::body) && + point.Container()->GetParentNode()) { // some cutoffs are here: we don't need to also include them in the // aWhere == kEnd case. as long as they are in one or the other it will // work. special case for outdent: don't keep looking up if we have // found a blockquote element to act on if (actionID == EditAction::outdent && - node->IsHTMLElement(nsGkAtoms::blockquote)) { + point.Container()->IsHTMLElement(nsGkAtoms::blockquote)) { break; } - int32_t parentOffset = node->GetParentNode()->IndexOf(node); - nsCOMPtr parent = node->GetParentNode(); - // Don't walk past the editable section. Note that we need to check // before walking up to a parent because we need to return the parent // object, so the parent itself might not be in the editable area, but @@ -5786,42 +5781,44 @@ HTMLEditRules::GetPromotedPoint(RulesEndpoint aWhere, actionID == EditAction::outdent || actionID == EditAction::align || actionID == EditAction::makeBasicBlock; - if (!htmlEditor->IsDescendantOfEditorRoot(parent) && + if (!htmlEditor->IsDescendantOfEditorRoot( + point.Container()->GetParentNode()) && (blockLevelAction || - !htmlEditor->IsDescendantOfEditorRoot(node))) { + !htmlEditor->IsDescendantOfEditorRoot(point.Container()))) { break; } - child = node; - node = parent; - offset = parentOffset; - nearNode = htmlEditor->GetPriorHTMLNode(node, offset, child, true); + point.Set(point.Container()); + nearNode = htmlEditor->GetPreviousEditableHTMLNodeInBlock(point.AsRaw()); } - return EditorDOMPoint(node, offset); + return point; } // aWhere == kEnd // some special casing for text nodes - if (node->IsNodeOfType(nsINode::eTEXT)) { - if (!node->GetParentNode()) { + if (point.Container()->IsNodeOfType(nsINode::eTEXT)) { + if (!point.Container()->GetParentNode()) { // Okay, can't promote any further - return EditorDOMPoint(node, offset); + return point; } // want to be after the text node - offset = 1 + node->GetParentNode()->IndexOf(node); - child = node->GetNextSibling(); - node = node->GetParentNode(); + point.Set(point.Container()); + DebugOnly advanced = point.AdvanceOffset(); + NS_WARNING_ASSERTION(advanced, + "Failed to advance offset to after the text node"); } // look ahead through any further inline nodes that aren't across a
from // us, and that are enclosed in the same block. nsCOMPtr nextNode = - htmlEditor->GetNextHTMLNode(node, offset, child, true); + htmlEditor->GetNextHTMLNode(point.Container(), point.Offset(), + point.GetChildAtOffset(), true); while (nextNode && !IsBlockNode(*nextNode) && nextNode->GetParentNode()) { - offset = 1 + nextNode->GetParentNode()->IndexOf(nextNode); - child = nextNode->GetNextSibling(); - node = nextNode->GetParentNode(); + point.Set(nextNode); + if (NS_WARN_IF(!point.AdvanceOffset())) { + break; + } if (htmlEditor->IsVisibleBRElement(nextNode)) { break; } @@ -5843,34 +5840,36 @@ HTMLEditRules::GetPromotedPoint(RulesEndpoint aWhere, } } } - nextNode = htmlEditor->GetNextHTMLNode(node, offset, child, true); + nextNode = htmlEditor->GetNextHTMLNode(point.Container(), point.Offset(), + point.GetChildAtOffset(), true); } // finding the real end for this point. look up the tree for as long as we // are the last node in the container, and as long as we haven't hit the body // node. nsCOMPtr nearNode = - htmlEditor->GetNextHTMLNode(node, offset, child, true); - while (!nearNode && !node->IsHTMLElement(nsGkAtoms::body) && - node->GetParentNode()) { - int32_t parentOffset = node->GetParentNode()->IndexOf(node); - nsCOMPtr parent = node->GetParentNode(); - + htmlEditor->GetNextHTMLNode(point.Container(), point.Offset(), + point.GetChildAtOffset(), true); + while (!nearNode && + !point.Container()->IsHTMLElement(nsGkAtoms::body) && + point.Container()->GetParentNode()) { // Don't walk past the editable section. Note that we need to check before // walking up to a parent because we need to return the parent object, so // the parent itself might not be in the editable area, but it's OK. - if (!htmlEditor->IsDescendantOfEditorRoot(node) && - !htmlEditor->IsDescendantOfEditorRoot(parent)) { + if (!htmlEditor->IsDescendantOfEditorRoot(point.Container()) && + !htmlEditor->IsDescendantOfEditorRoot( + point.Container()->GetParentNode())) { break; } - child = node->GetNextSibling(); - node = parent; - // we want to be AFTER nearNode - offset = parentOffset + 1; - nearNode = htmlEditor->GetNextHTMLNode(node, offset, child, true); + point.Set(point.Container()); + if (NS_WARN_IF(!point.AdvanceOffset())) { + break; + } + nearNode = htmlEditor->GetNextHTMLNode(point.Container(), point.Offset(), + point.GetChildAtOffset(), true); } - return EditorDOMPoint(node, offset); + return point; } /** @@ -6797,7 +6796,9 @@ HTMLEditRules::ReturnInParagraph(Selection* aSelection, // is there a BR prior to it? nsCOMPtr nearNode; NS_ENSURE_STATE(mHTMLEditor); - nearNode = mHTMLEditor->GetPriorHTMLNode(node, aOffset, aChildAtOffset); + nearNode = + mHTMLEditor->GetPreviousEditableHTMLNode( + EditorRawDOMPoint(node, aChildAtOffset, aOffset)); NS_ENSURE_STATE(mHTMLEditor); if (!nearNode || !mHTMLEditor->IsVisibleBRElement(nearNode) || TextEditUtils::HasMozAttr(GetAsDOMNode(nearNode))) { @@ -7812,26 +7813,31 @@ HTMLEditRules::CheckInterlinePosition(Selection& aSelection) RefPtr htmlEditor(mHTMLEditor); // Get the (collapsed) selection location - NS_ENSURE_TRUE_VOID(aSelection.GetRangeAt(0) && - aSelection.GetRangeAt(0)->GetStartContainer()); - OwningNonNull selNode = - *aSelection.GetRangeAt(0)->GetStartContainer(); - int32_t selOffset = aSelection.GetRangeAt(0)->StartOffset(); - nsIContent* child = aSelection.GetRangeAt(0)->GetChildAtStartOffset(); + nsRange* firstRange = aSelection.GetRangeAt(0); + if (NS_WARN_IF(!firstRange)) { + return; + } + + EditorDOMPoint atStartOfSelection(firstRange->StartRef()); + if (NS_WARN_IF(!atStartOfSelection.IsSet())) { + return; + } + MOZ_ASSERT(atStartOfSelection.IsSetAndValid()); // First, let's check to see if we are after a
. We take care of this // special-case first so that we don't accidentally fall through into one of // the other conditionals. nsCOMPtr node = - htmlEditor->GetPriorHTMLNode(selNode, selOffset, child, true); + htmlEditor->GetPreviousEditableHTMLNodeInBlock(atStartOfSelection.AsRaw()); if (node && node->IsHTMLElement(nsGkAtoms::br)) { aSelection.SetInterlinePosition(true); return; } // Are we after a block? If so try set caret to following content - if (child) { - node = htmlEditor->GetPriorHTMLSibling(child); + if (atStartOfSelection.GetChildAtOffset()) { + node = + htmlEditor->GetPriorHTMLSibling(atStartOfSelection.GetChildAtOffset()); } else { node = nullptr; } @@ -7841,8 +7847,9 @@ HTMLEditRules::CheckInterlinePosition(Selection& aSelection) } // Are we before a block? If so try set caret to prior content - if (child) { - node = htmlEditor->GetNextHTMLSibling(child); + if (atStartOfSelection.GetChildAtOffset()) { + node = + htmlEditor->GetNextHTMLSibling(atStartOfSelection.GetChildAtOffset()); } else { node = nullptr; } @@ -7865,43 +7872,40 @@ HTMLEditRules::AdjustSelection(Selection* aSelection, } // get the (collapsed) selection location - nsCOMPtr selNode, temp; - int32_t selOffset; - nsresult rv = - EditorBase::GetStartNodeAndOffset(aSelection, - getter_AddRefs(selNode), &selOffset); - NS_ENSURE_SUCCESS(rv, rv); - nsINode* child = aSelection->GetRangeAt(0)->GetChildAtStartOffset(); - temp = selNode; + EditorDOMPoint point(EditorBase::GetStartPoint(aSelection)); + if (NS_WARN_IF(!point.IsSet())) { + return NS_ERROR_FAILURE; + } // are we in an editable node? NS_ENSURE_STATE(mHTMLEditor); - while (!mHTMLEditor->IsEditable(selNode)) { + while (!mHTMLEditor->IsEditable(point.Container())) { // scan up the tree until we find an editable place to be - child = temp; - selNode = EditorBase::GetNodeLocation(temp, &selOffset); - NS_ENSURE_TRUE(selNode, NS_ERROR_FAILURE); - temp = selNode; - NS_ENSURE_STATE(mHTMLEditor); + point.Set(point.Container()); + if (NS_WARN_IF(!point.IsSet())) { + return NS_ERROR_FAILURE; + } } // make sure we aren't in an empty block - user will see no cursor. If this // is happening, put a
in the block if allowed. NS_ENSURE_STATE(mHTMLEditor); - nsCOMPtr theblock = mHTMLEditor->GetBlock(*selNode); + nsCOMPtr theblock = mHTMLEditor->GetBlock(*point.Container()); if (theblock && mHTMLEditor->IsEditable(theblock)) { bool bIsEmptyNode; NS_ENSURE_STATE(mHTMLEditor); - rv = mHTMLEditor->IsEmptyNode(theblock, &bIsEmptyNode, false, false); + nsresult rv = + mHTMLEditor->IsEmptyNode(theblock, &bIsEmptyNode, false, false); NS_ENSURE_SUCCESS(rv, rv); // check if br can go into the destination node NS_ENSURE_STATE(mHTMLEditor); - if (bIsEmptyNode && mHTMLEditor->CanContainTag(*selNode, *nsGkAtoms::br)) { + if (bIsEmptyNode && + mHTMLEditor->CanContainTag(*point.Container(), *nsGkAtoms::br)) { NS_ENSURE_STATE(mHTMLEditor); nsCOMPtr rootNode = mHTMLEditor->GetRoot(); NS_ENSURE_TRUE(rootNode, NS_ERROR_FAILURE); - if (selNode == rootNode) { + if (point.Container() == rootNode) { // Our root node is completely empty. Don't add a
here. // AfterEditInner() will add one for us when it calls // CreateBogusNodeIfNeeded()! @@ -7909,12 +7913,12 @@ HTMLEditRules::AdjustSelection(Selection* aSelection, } // we know we can skip the rest of this routine given the cirumstance - return CreateMozBR(GetAsDOMNode(selNode), selOffset); + return CreateMozBR(GetAsDOMNode(point.Container()), point.Offset()); } } // are we in a text node? - if (EditorBase::IsTextNode(selNode)) { + if (EditorBase::IsTextNode(point.Container())) { return NS_OK; // we LIKE it when we are in a text node. that RULZ } @@ -7925,11 +7929,11 @@ HTMLEditRules::AdjustSelection(Selection* aSelection, NS_ENSURE_STATE(mHTMLEditor); nsCOMPtr nearNode = - mHTMLEditor->GetPriorHTMLNode(selNode, selOffset, child); + mHTMLEditor->GetPreviousEditableHTMLNode(point.AsRaw()); if (nearNode) { // is nearNode also a descendant of same block? NS_ENSURE_STATE(mHTMLEditor); - nsCOMPtr block = mHTMLEditor->GetBlock(*selNode); + nsCOMPtr block = mHTMLEditor->GetBlock(*point.Container()); nsCOMPtr nearBlock = mHTMLEditor->GetBlockNodeParent(nearNode); if (block && block == nearBlock) { if (nearNode && TextEditUtils::IsBreak(nearNode)) { @@ -7939,17 +7943,19 @@ HTMLEditRules::AdjustSelection(Selection* aSelection, // the user will see no new line for the break. Also, things // like table cells won't grow in height. nsCOMPtr brNode; - rv = CreateMozBR(GetAsDOMNode(selNode), selOffset, - getter_AddRefs(brNode)); + nsresult rv = + CreateMozBR(GetAsDOMNode(point.Container()), point.Offset(), + getter_AddRefs(brNode)); NS_ENSURE_SUCCESS(rv, rv); - nsCOMPtr brParent = - EditorBase::GetNodeLocation(brNode, &selOffset); nsCOMPtr br = do_QueryInterface(brNode); - child = br; + point.Set(br); // selection stays *before* moz-br, sticking to it aSelection->SetInterlinePosition(true); - rv = aSelection->Collapse(brParent, selOffset); - NS_ENSURE_SUCCESS(rv, rv); + ErrorResult error; + aSelection->Collapse(point.AsRaw(), error); + if (NS_WARN_IF(error.Failed())) { + return error.StealNSResult(); + } } else { NS_ENSURE_STATE(mHTMLEditor); nsCOMPtr nextNode = @@ -7966,7 +7972,7 @@ HTMLEditRules::AdjustSelection(Selection* aSelection, // we aren't in a textnode: are we adjacent to text or a break or an image? NS_ENSURE_STATE(mHTMLEditor); - nearNode = mHTMLEditor->GetPriorHTMLNode(selNode, selOffset, child, true); + nearNode = mHTMLEditor->GetPreviousEditableHTMLNodeInBlock(point.AsRaw()); if (nearNode && (TextEditUtils::IsBreak(nearNode) || EditorBase::IsTextNode(nearNode) || HTMLEditUtils::IsImage(nearNode) || @@ -7975,7 +7981,8 @@ HTMLEditRules::AdjustSelection(Selection* aSelection, return NS_OK; } NS_ENSURE_STATE(mHTMLEditor); - nearNode = mHTMLEditor->GetNextHTMLNode(selNode, selOffset, child, true); + nearNode = mHTMLEditor->GetNextHTMLNode(point.Container(), point.Offset(), + point.GetChildAtOffset(), true); if (nearNode && (TextEditUtils::IsBreak(nearNode) || EditorBase::IsTextNode(nearNode) || nearNode->IsAnyOfHTMLElements(nsGkAtoms::img, @@ -7985,8 +7992,9 @@ HTMLEditRules::AdjustSelection(Selection* aSelection, // look for a nearby text node. // prefer the correct direction. - rv = FindNearSelectableNode(selNode, selOffset, child, aAction, - address_of(nearNode)); + nsresult rv = FindNearSelectableNode(point.Container(), point.Offset(), + point.GetChildAtOffset(), aAction, + address_of(nearNode)); NS_ENSURE_SUCCESS(rv, rv); if (!nearNode) { @@ -8011,18 +8019,22 @@ HTMLEditRules::FindNearSelectableNode(nsINode* aSelNode, NS_ENSURE_TRUE(aSelNode && outSelectableNode, NS_ERROR_NULL_POINTER); *outSelectableNode = nullptr; + EditorRawDOMPoint point(aSelNode, + aChildAtOffset && aChildAtOffset->IsContent() ? + aChildAtOffset->AsContent() : nullptr, + aSelOffset); + nsCOMPtr nearNode, curNode; if (aDirection == nsIEditor::ePrevious) { NS_ENSURE_STATE(mHTMLEditor); - nearNode = mHTMLEditor->GetPriorHTMLNode(aSelNode, aSelOffset, - aChildAtOffset); + nearNode = mHTMLEditor->GetPreviousEditableHTMLNode(point); if (NS_WARN_IF(!nearNode)) { return NS_ERROR_FAILURE; } } else { NS_ENSURE_STATE(mHTMLEditor); - nearNode = mHTMLEditor->GetNextHTMLNode(aSelNode, aSelOffset, - aChildAtOffset); + nearNode = mHTMLEditor->GetNextHTMLNode(point.Container(), point.Offset(), + point.GetChildAtOffset()); if (NS_WARN_IF(!nearNode)) { return NS_ERROR_FAILURE; } @@ -8038,15 +8050,13 @@ HTMLEditRules::FindNearSelectableNode(nsINode* aSelNode, if (aDirection == nsIEditor::ePrevious) { NS_ENSURE_STATE(mHTMLEditor); - nearNode = mHTMLEditor->GetPriorHTMLNode(aSelNode, aSelOffset, - aChildAtOffset); + nearNode = mHTMLEditor->GetPreviousEditableHTMLNode(point); if (NS_WARN_IF(!nearNode)) { return NS_ERROR_FAILURE; } } else { NS_ENSURE_STATE(mHTMLEditor); - nearNode = mHTMLEditor->GetPriorHTMLNode(aSelNode, aSelOffset, - aChildAtOffset); + nearNode = mHTMLEditor->GetPreviousEditableHTMLNode(point); if (NS_WARN_IF(!nearNode)) { return NS_ERROR_FAILURE; } @@ -8061,7 +8071,7 @@ HTMLEditRules::FindNearSelectableNode(nsINode* aSelNode, curNode = nearNode; if (aDirection == nsIEditor::ePrevious) { NS_ENSURE_STATE(mHTMLEditor); - nearNode = mHTMLEditor->GetPriorHTMLNode(curNode); + nearNode = mHTMLEditor->GetPreviousEditableHTMLNode(*curNode); if (NS_WARN_IF(!nearNode)) { return NS_ERROR_FAILURE; } diff --git a/editor/libeditor/HTMLEditor.cpp b/editor/libeditor/HTMLEditor.cpp index 2fd8e35434cd..4dae5eacb1e8 100644 --- a/editor/libeditor/HTMLEditor.cpp +++ b/editor/libeditor/HTMLEditor.cpp @@ -895,7 +895,7 @@ HTMLEditor::IsVisibleBRElement(nsINode* aNode) // If there's an inline node after this one that's not a break, and also a // prior break, this break must be visible. - nsCOMPtr priorNode = GetPriorHTMLNode(aNode, true); + nsCOMPtr priorNode = GetPreviousEditableHTMLNodeInBlock(*aNode); if (priorNode && TextEditUtils::IsBreak(priorNode)) { return true; } @@ -3867,46 +3867,26 @@ HTMLEditor::GetNextHTMLSibling(nsINode* aNode) return node; } -/** - * GetPriorHTMLNode() returns the previous editable leaf node, if there is - * one within the . - */ nsIContent* -HTMLEditor::GetPriorHTMLNode(nsINode* aNode, - bool aNoBlockCrossing) +HTMLEditor::GetPreviousEditableHTMLNodeInternal(nsINode& aNode, + bool aNoBlockCrossing) { - MOZ_ASSERT(aNode); - if (!GetActiveEditingHost()) { return nullptr; } - - return aNoBlockCrossing ? GetPreviousEditableNodeInBlock(*aNode) : - GetPreviousEditableNode(*aNode); + return aNoBlockCrossing ? GetPreviousEditableNodeInBlock(aNode) : + GetPreviousEditableNode(aNode); } -/** - * GetPriorHTMLNode() is same as above but takes {parent,offset} instead of - * node. - */ nsIContent* -HTMLEditor::GetPriorHTMLNode(nsINode* aParent, - int32_t aOffset, - nsINode* aChildAtOffset, - bool aNoBlockCrossing) +HTMLEditor::GetPreviousEditableHTMLNodeInternal(const EditorRawDOMPoint& aPoint, + bool aNoBlockCrossing) { - MOZ_ASSERT(aParent); - if (!GetActiveEditingHost()) { return nullptr; } - - EditorRawDOMPoint point(aParent, - aChildAtOffset && aChildAtOffset->IsContent() ? - aChildAtOffset->AsContent() : nullptr, - aOffset); - return aNoBlockCrossing ? GetPreviousEditableNodeInBlock(point) : - GetPreviousEditableNode(point); + return aNoBlockCrossing ? GetPreviousEditableNodeInBlock(aPoint) : + GetPreviousEditableNode(aPoint); } /** @@ -4019,7 +3999,7 @@ HTMLEditor::GetLastEditableLeaf(nsINode& aNode) { nsCOMPtr child = GetRightmostChild(&aNode, false); while (child && (!IsEditable(child) || child->HasChildren())) { - child = GetPriorHTMLNode(child); + child = GetPreviousEditableHTMLNode(*child); // Only accept nodes that are descendants of aNode if (!aNode.Contains(child)) { @@ -4534,7 +4514,7 @@ HTMLEditor::CopyLastEditableChildStyles(nsINode* aPreviousBlock, tmp = GetLastEditableChild(*child); } while (child && TextEditUtils::IsBreak(child)) { - child = GetPriorHTMLNode(child); + child = GetPreviousEditableHTMLNode(*child); } nsCOMPtr newStyles, deepestStyle; nsCOMPtr childNode = child; diff --git a/editor/libeditor/HTMLEditor.h b/editor/libeditor/HTMLEditor.h index fe788dfee84b..1bdd61a0f19e 100644 --- a/editor/libeditor/HTMLEditor.h +++ b/editor/libeditor/HTMLEditor.h @@ -777,10 +777,38 @@ protected: nsIContent* GetNextHTMLSibling(nsINode* aNode); - nsIContent* GetPriorHTMLNode(nsINode* aNode, bool aNoBlockCrossing = false); - nsIContent* GetPriorHTMLNode(nsINode* aParent, int32_t aOffset, - nsINode* aChildAtOffset, - bool aNoBlockCrossing = false); + /** + * GetPreviousEditableHTMLNode*() methods are similar to + * EditorBase::GetPreviousEditableNode() but this won't return nodes outside + * active editing host. + */ + nsIContent* GetPreviousEditableHTMLNode(nsINode& aNode) + { + return GetPreviousEditableHTMLNodeInternal(aNode, false); + } + nsIContent* GetPreviousEditableHTMLNodeInBlock(nsINode& aNode) + { + return GetPreviousEditableHTMLNodeInternal(aNode, true); + } + nsIContent* GetPreviousEditableHTMLNode(const EditorRawDOMPoint& aPoint) + { + return GetPreviousEditableHTMLNodeInternal(aPoint, false); + } + nsIContent* GetPreviousEditableHTMLNodeInBlock( + const EditorRawDOMPoint& aPoint) + { + return GetPreviousEditableHTMLNodeInternal(aPoint, true); + } + + /** + * GetPreviousEditableHTMLNodeInternal() methods are common implementation + * of above methods. Please don't use this method directly. + */ + nsIContent* GetPreviousEditableHTMLNodeInternal(nsINode& aNode, + bool aNoBlockCrossing); + nsIContent* GetPreviousEditableHTMLNodeInternal( + const EditorRawDOMPoint& aPoint, + bool aNoBlockCrossing); nsIContent* GetNextHTMLNode(nsINode* aNode, bool aNoBlockCrossing = false); nsIContent* GetNextHTMLNode(nsINode* aParent, int32_t aOffset,