--- a/editor/libeditor/HTMLEditRules.cpp
+++ b/editor/libeditor/HTMLEditRules.cpp
@@ -2483,17 +2483,17 @@ HTMLEditRules::WillDeleteSelection(Selec
// First find the relevant nodes
nsCOMPtr<nsINode> leftNode, rightNode;
if (aAction == nsIEditor::ePrevious) {
NS_ENSURE_STATE(mHTMLEditor);
leftNode = mHTMLEditor->GetPreviousEditableHTMLNode(*visNode);
rightNode = startNode;
} else {
NS_ENSURE_STATE(mHTMLEditor);
- rightNode = mHTMLEditor->GetNextHTMLNode(visNode);
+ rightNode = mHTMLEditor->GetNextEditableHTMLNode(*visNode);
leftNode = startNode;
}
// Nothing to join
if (!leftNode || !rightNode) {
*aCancel = true;
return NS_OK;
}
@@ -3796,17 +3796,18 @@ HTMLEditRules::MakeBasicBlock(Selection&
// We are removing blocks (going to "body text")
NS_ENSURE_TRUE(htmlEditor->GetBlock(container), NS_ERROR_NULL_POINTER);
OwningNonNull<Element> curBlock = *htmlEditor->GetBlock(container);
if (HTMLEditUtils::IsFormatNode(curBlock)) {
// 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> brNode =
- htmlEditor->GetNextHTMLNode(container, offset, child);
+ htmlEditor->GetNextEditableHTMLNode(
+ EditorRawDOMPoint(container, child, offset));
if (brNode && brNode->IsHTMLElement(nsGkAtoms::br)) {
rv = htmlEditor->DeleteNode(brNode);
NS_ENSURE_SUCCESS(rv, rv);
}
// Do the splits!
offset = htmlEditor->SplitNodeDeep(curBlock, *container->AsContent(),
offset,
HTMLEditor::EmptyContainers::no);
@@ -3819,17 +3820,18 @@ HTMLEditRules::MakeBasicBlock(Selection&
// Don't restore the selection
selectionRestorer.Abort();
NS_ENSURE_SUCCESS(rv, rv);
}
// Else nothing to do!
} else {
// We are making a block. Consume a br, if needed.
nsCOMPtr<nsIContent> brNode =
- htmlEditor->GetNextHTMLNode(container, offset, child, true);
+ htmlEditor->GetNextEditableHTMLNodeInBlock(
+ EditorRawDOMPoint(container, child, offset));
if (brNode && brNode->IsHTMLElement(nsGkAtoms::br)) {
rv = htmlEditor->DeleteNode(brNode);
NS_ENSURE_SUCCESS(rv, rv);
// We don't need to act on this node any more
arrayOfNodes.RemoveElement(brNode);
// XXX We need to recompute child here because SplitAsNeeded() and
// EditorBase::SplitNodeDeep() don't compute child in some cases.
child = container->GetChildAt(offset);
@@ -4960,32 +4962,32 @@ HTMLEditRules::WillAlign(Selection& aSel
nsCOMPtr<nsIContent> child =
aSelection.GetRangeAt(0)->GetChildAtStartOffset();
rv = SplitAsNeeded(*nsGkAtoms::div, parent, offset,
address_of(child));
NS_ENSURE_SUCCESS(rv, rv);
// Consume a trailing br, if any. This is to keep an alignment from
// creating extra lines, if possible.
+ EditorRawDOMPoint atChild(parent, child, offset);
nsCOMPtr<nsIContent> brContent =
- htmlEditor->GetNextHTMLNode(parent, offset, child);
+ htmlEditor->GetNextEditableHTMLNodeInBlock(atChild);
if (brContent && TextEditUtils::IsBreak(brContent)) {
// Making use of html structure... if next node after where we are
// putting our div is not a block, then the br we found is in same block
// we are, so it's safe to consume it.
nsCOMPtr<nsIContent> sibling;
if (child) {
sibling = htmlEditor->GetNextHTMLSibling(child);
}
if (sibling && !IsBlockNode(*sibling)) {
rv = htmlEditor->DeleteNode(brContent);
NS_ENSURE_SUCCESS(rv, rv);
}
}
- EditorRawDOMPoint atChild(parent, child, offset);
RefPtr<Element> div = htmlEditor->CreateNode(nsGkAtoms::div, atChild);
NS_ENSURE_STATE(div);
// Remember our new block for postprocessing
mNewBlock = div;
// Set up the alignment on the div, using HTML or CSS
rv = AlignBlock(*div, aAlignType, ContentsOnly::yes);
NS_ENSURE_SUCCESS(rv, rv);
*aHandled = true;
@@ -5627,19 +5629,18 @@ HTMLEditRules::NormalizeSelection(Select
int32_t offset = -1;
newStartNode = EditorBase::GetNodeLocation(child, &offset);
newStartOffset = static_cast<uint32_t>(offset);
}
// else block is empty - we can leave selection alone here, i think.
} else if (wsStartObj.mEndReason == WSType::thisBlock) {
// startpoint is just before end of this block
nsINode* child =
- htmlEditor->GetNextHTMLNode(startNode,
- static_cast<int32_t>(startOffset),
- startChild);
+ htmlEditor->GetNextEditableHTMLNode(
+ EditorRawDOMPoint(startNode, startChild, startOffset));
if (child) {
int32_t offset = -1;
newStartNode = EditorBase::GetNodeLocation(child, &offset);
newStartOffset = static_cast<uint32_t>(offset);
}
// else block is empty - we can leave selection alone here, i think.
} else if (wsStartObj.mEndReason == WSType::br) {
// startpoint is just before a break. lets adjust it to after it.
@@ -5805,18 +5806,17 @@ HTMLEditRules::GetPromotedPoint(RulesEnd
DebugOnly<bool> 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 <br> from
// us, and that are enclosed in the same block.
nsCOMPtr<nsIContent> nextNode =
- htmlEditor->GetNextHTMLNode(point.Container(), point.Offset(),
- point.GetChildAtOffset(), true);
+ htmlEditor->GetNextEditableHTMLNodeInBlock(point.AsRaw());
while (nextNode && !IsBlockNode(*nextNode) && nextNode->GetParentNode()) {
point.Set(nextNode);
if (NS_WARN_IF(!point.AdvanceOffset())) {
break;
}
if (htmlEditor->IsVisibleBRElement(nextNode)) {
break;
@@ -5834,44 +5834,41 @@ HTMLEditRules::GetPromotedPoint(RulesEnd
if (static_cast<uint32_t>(newlinePos) + 1 == tempString.Length()) {
// No need for special processing if the newline is at the end.
break;
}
return EditorDOMPoint(nextNode, newlinePos + 1);
}
}
}
- nextNode = htmlEditor->GetNextHTMLNode(point.Container(), point.Offset(),
- point.GetChildAtOffset(), true);
+ nextNode = htmlEditor->GetNextEditableHTMLNodeInBlock(point.AsRaw());
}
// 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<nsIContent> nearNode =
- htmlEditor->GetNextHTMLNode(point.Container(), point.Offset(),
- point.GetChildAtOffset(), true);
+ htmlEditor->GetNextEditableHTMLNodeInBlock(point.AsRaw());
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(point.Container()) &&
!htmlEditor->IsDescendantOfEditorRoot(
point.Container()->GetParentNode())) {
break;
}
point.Set(point.Container());
if (NS_WARN_IF(!point.AdvanceOffset())) {
break;
}
- nearNode = htmlEditor->GetNextHTMLNode(point.Container(), point.Offset(),
- point.GetChildAtOffset(), true);
+ nearNode = htmlEditor->GetNextEditableHTMLNodeInBlock(point.AsRaw());
}
return point;
}
/**
* GetPromotedRanges() runs all the selection range endpoint through
* GetPromotedPoint().
*/
@@ -6798,17 +6795,19 @@ HTMLEditRules::ReturnInParagraph(Selecti
nearNode =
mHTMLEditor->GetPreviousEditableHTMLNode(
EditorRawDOMPoint(node, aChildAtOffset, aOffset));
NS_ENSURE_STATE(mHTMLEditor);
if (!nearNode || !mHTMLEditor->IsVisibleBRElement(nearNode) ||
TextEditUtils::HasMozAttr(GetAsDOMNode(nearNode))) {
// is there a BR after it?
NS_ENSURE_STATE(mHTMLEditor);
- nearNode = mHTMLEditor->GetNextHTMLNode(node, aOffset, aChildAtOffset);
+ nearNode =
+ mHTMLEditor->GetNextEditableHTMLNode(
+ EditorRawDOMPoint(node, aChildAtOffset, aOffset));
NS_ENSURE_STATE(mHTMLEditor);
if (!nearNode || !mHTMLEditor->IsVisibleBRElement(nearNode) ||
TextEditUtils::HasMozAttr(GetAsDOMNode(nearNode))) {
newBRneeded = true;
parent = node;
offset = aOffset;
newSelNode = true;
}
@@ -7953,17 +7952,17 @@ HTMLEditRules::AdjustSelection(Selection
ErrorResult error;
aSelection->Collapse(point.AsRaw(), error);
if (NS_WARN_IF(error.Failed())) {
return error.StealNSResult();
}
} else {
NS_ENSURE_STATE(mHTMLEditor);
nsCOMPtr<nsIContent> nextNode =
- mHTMLEditor->GetNextHTMLNode(nearNode, true);
+ mHTMLEditor->GetNextEditableHTMLNodeInBlock(*nearNode);
if (nextNode && TextEditUtils::IsMozBR(nextNode)) {
// selection between br and mozbr. make it stick to mozbr
// so that it will be on blank line.
aSelection->SetInterlinePosition(true);
}
}
}
}
@@ -7975,18 +7974,17 @@ HTMLEditRules::AdjustSelection(Selection
if (nearNode && (TextEditUtils::IsBreak(nearNode) ||
EditorBase::IsTextNode(nearNode) ||
HTMLEditUtils::IsImage(nearNode) ||
nearNode->IsHTMLElement(nsGkAtoms::hr))) {
// this is a good place for the caret to be
return NS_OK;
}
NS_ENSURE_STATE(mHTMLEditor);
- nearNode = mHTMLEditor->GetNextHTMLNode(point.Container(), point.Offset(),
- point.GetChildAtOffset(), true);
+ nearNode = mHTMLEditor->GetNextEditableHTMLNodeInBlock(point.AsRaw());
if (nearNode && (TextEditUtils::IsBreak(nearNode) ||
EditorBase::IsTextNode(nearNode) ||
nearNode->IsAnyOfHTMLElements(nsGkAtoms::img,
nsGkAtoms::hr))) {
return NS_OK; // this is a good place for the caret to be
}
// look for a nearby text node.
@@ -8027,18 +8025,17 @@ HTMLEditRules::FindNearSelectableNode(ns
if (aDirection == nsIEditor::ePrevious) {
NS_ENSURE_STATE(mHTMLEditor);
nearNode = mHTMLEditor->GetPreviousEditableHTMLNode(point);
if (NS_WARN_IF(!nearNode)) {
return NS_ERROR_FAILURE;
}
} else {
NS_ENSURE_STATE(mHTMLEditor);
- nearNode = mHTMLEditor->GetNextHTMLNode(point.Container(), point.Offset(),
- point.GetChildAtOffset());
+ nearNode = mHTMLEditor->GetNextEditableHTMLNode(point);
if (NS_WARN_IF(!nearNode)) {
return NS_ERROR_FAILURE;
}
}
// Try the other direction then.
if (!nearNode) {
if (aDirection == nsIEditor::ePrevious) {
@@ -8071,17 +8068,17 @@ HTMLEditRules::FindNearSelectableNode(ns
if (aDirection == nsIEditor::ePrevious) {
NS_ENSURE_STATE(mHTMLEditor);
nearNode = mHTMLEditor->GetPreviousEditableHTMLNode(*curNode);
if (NS_WARN_IF(!nearNode)) {
return NS_ERROR_FAILURE;
}
} else {
NS_ENSURE_STATE(mHTMLEditor);
- nearNode = mHTMLEditor->GetNextHTMLNode(curNode);
+ nearNode = mHTMLEditor->GetNextEditableHTMLNode(*curNode);
if (NS_WARN_IF(!nearNode)) {
return NS_ERROR_FAILURE;
}
}
NS_ENSURE_STATE(mHTMLEditor);
}
if (nearNode) {
--- a/editor/libeditor/HTMLEditor.cpp
+++ b/editor/libeditor/HTMLEditor.cpp
@@ -871,17 +871,17 @@ HTMLEditor::IsPrevCharInNodeWhitespace(n
bool
HTMLEditor::IsVisibleBRElement(nsINode* aNode)
{
MOZ_ASSERT(aNode);
if (!TextEditUtils::IsBreak(aNode)) {
return false;
}
// Check if there is a later node in block after br
- nsCOMPtr<nsINode> nextNode = GetNextHTMLNode(aNode, true);
+ nsCOMPtr<nsINode> nextNode = GetNextEditableHTMLNodeInBlock(*aNode);
if (nextNode && TextEditUtils::IsBreak(nextNode)) {
return true;
}
// A single line break before a block boundary is not displayed, so e.g.
// foo<p>bar<br></p> and foo<br><p>bar</p> display the same as foo<p>bar</p>.
// But if there are multiple <br>s in a row, all but the last are visible.
if (!nextNode) {
@@ -3884,55 +3884,36 @@ HTMLEditor::GetPreviousEditableHTMLNodeI
{
if (!GetActiveEditingHost()) {
return nullptr;
}
return aNoBlockCrossing ? GetPreviousEditableNodeInBlock(aPoint) :
GetPreviousEditableNode(aPoint);
}
-/**
- * GetNextHTMLNode() returns the next editable leaf node, if there is
- * one within the <body>.
- */
nsIContent*
-HTMLEditor::GetNextHTMLNode(nsINode* aNode,
- bool aNoBlockCrossing)
+HTMLEditor::GetNextEditableHTMLNodeInternal(nsINode& aNode,
+ bool aNoBlockCrossing)
{
- MOZ_ASSERT(aNode);
-
- nsIContent* result =
- aNoBlockCrossing ? GetNextEditableNodeInBlock(*aNode) :
- GetNextEditableNode(*aNode);
- if (result && !IsDescendantOfEditorRoot(result)) {
+ if (!GetActiveEditingHost()) {
return nullptr;
}
- return result;
+ return aNoBlockCrossing ? GetNextEditableNodeInBlock(aNode) :
+ GetNextEditableNode(aNode);
}
-/**
- * GetNextHTMLNode() is same as above but takes {parent,offset} instead of node.
- */
nsIContent*
-HTMLEditor::GetNextHTMLNode(nsINode* aParent,
- int32_t aOffset,
- nsINode* aChildAtOffset,
- bool aNoBlockCrossing)
+HTMLEditor::GetNextEditableHTMLNodeInternal(const EditorRawDOMPoint& aPoint,
+ bool aNoBlockCrossing)
{
- EditorRawDOMPoint point(aParent,
- aChildAtOffset && aChildAtOffset->IsContent() ?
- aChildAtOffset->AsContent() : nullptr,
- aOffset);
- nsIContent* content =
- aNoBlockCrossing ? GetNextEditableNodeInBlock(point) :
- GetNextEditableNode(point);
- if (content && !IsDescendantOfEditorRoot(content)) {
+ if (!GetActiveEditingHost()) {
return nullptr;
}
- return content;
+ return aNoBlockCrossing ? GetNextEditableNodeInBlock(aPoint) :
+ GetNextEditableNode(aPoint);
}
bool
HTMLEditor::IsFirstEditableChild(nsINode* aNode)
{
MOZ_ASSERT(aNode);
// find first editable child and compare it to aNode
nsCOMPtr<nsINode> parent = aNode->GetParentNode();
@@ -3978,17 +3959,17 @@ HTMLEditor::GetLastEditableChild(nsINode
return child;
}
nsIContent*
HTMLEditor::GetFirstEditableLeaf(nsINode& aNode)
{
nsCOMPtr<nsIContent> child = GetLeftmostChild(&aNode);
while (child && (!IsEditable(child) || child->HasChildren())) {
- child = GetNextHTMLNode(child);
+ child = GetNextEditableHTMLNode(*child);
// Only accept nodes that are descendants of aNode
if (!aNode.Contains(child)) {
return nullptr;
}
}
return child;
--- a/editor/libeditor/HTMLEditor.h
+++ b/editor/libeditor/HTMLEditor.h
@@ -805,20 +805,53 @@ protected:
* 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,
- nsINode* aChildAtOffset,
- bool aNoBlockCrossing = false);
+ /**
+ * GetNextEditableHTMLNode*() methods are similar to
+ * EditorBase::GetNextEditableNode() but this won't return nodes outside
+ * active editing host.
+ *
+ * Note that same as EditorBaseGetTextEditableNode(), 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)
+ {
+ return GetNextEditableHTMLNodeInternal(aNode, false);
+ }
+ nsIContent* GetNextEditableHTMLNodeInBlock(nsINode& aNode)
+ {
+ return GetNextEditableHTMLNodeInternal(aNode, true);
+ }
+ nsIContent* GetNextEditableHTMLNode(const EditorRawDOMPoint& aPoint)
+ {
+ return GetNextEditableHTMLNodeInternal(aPoint, false);
+ }
+ nsIContent* GetNextEditableHTMLNodeInBlock(
+ const EditorRawDOMPoint& aPoint)
+ {
+ return GetNextEditableHTMLNodeInternal(aPoint, true);
+ }
+
+ /**
+ * GetNextEditableHTMLNodeInternal() methods are common implementation
+ * of above methods. Please don't use this method directly.
+ */
+ nsIContent* GetNextEditableHTMLNodeInternal(nsINode& aNode,
+ bool aNoBlockCrossing);
+ nsIContent* GetNextEditableHTMLNodeInternal(
+ const EditorRawDOMPoint& aPoint,
+ bool aNoBlockCrossing);
bool IsFirstEditableChild(nsINode* aNode);
bool IsLastEditableChild(nsINode* aNode);
nsIContent* GetFirstEditableChild(nsINode& aNode);
nsIContent* GetLastEditableChild(nsINode& aNode);
nsIContent* GetFirstEditableLeaf(nsINode& aNode);
nsIContent* GetLastEditableLeaf(nsINode& aNode);