--- a/editor/libeditor/HTMLEditRules.cpp
+++ b/editor/libeditor/HTMLEditRules.cpp
@@ -5435,104 +5435,98 @@ HTMLEditRules::NormalizeSelection(Select
inSelection->Extend(newEndNode, newEndOffset);
return NS_OK;
}
/**
* GetPromotedPoint() figures out where a start or end point for a block
* operation really is.
*/
-void
+EditorDOMPoint
HTMLEditRules::GetPromotedPoint(RulesEndpoint aWhere,
- nsIDOMNode* aNode,
+ nsINode& aNode,
int32_t aOffset,
- EditAction actionID,
- nsCOMPtr<nsIDOMNode>* outNode,
- int32_t* outOffset)
-{
- nsCOMPtr<nsINode> node = do_QueryInterface(aNode);
- MOZ_ASSERT(node && outNode && outOffset);
-
- // default values
- *outNode = node->AsDOMNode();
- *outOffset = aOffset;
+ EditAction actionID)
+{
+ if (NS_WARN_IF(!mHTMLEditor)) {
+ return EditorDOMPoint(&aNode, aOffset);
+ }
+ RefPtr<HTMLEditor> htmlEditor = mHTMLEditor;
// we do one thing for text actions, something else entirely for other
// actions
if (actionID == EditAction::insertText ||
actionID == EditAction::insertIMEText ||
actionID == EditAction::insertBreak ||
actionID == EditAction::deleteText) {
bool isSpace, isNBSP;
- nsCOMPtr<nsIContent> content = do_QueryInterface(node), temp;
+ nsCOMPtr<nsIContent> content =
+ aNode.IsContent() ? aNode.AsContent() : nullptr;
+ nsCOMPtr<nsIContent> temp;
+ int32_t newOffset = aOffset;
// for text actions, we want to look backwards (or forwards, as
// appropriate) for additional whitespace or nbsp's. We may have to act on
// these later even though they are outside of the initial selection. Even
// if they are in another node!
while (content) {
int32_t offset;
if (aWhere == kStart) {
- NS_ENSURE_TRUE_VOID(mHTMLEditor);
- mHTMLEditor->IsPrevCharInNodeWhitespace(content, *outOffset,
- &isSpace, &isNBSP,
- getter_AddRefs(temp), &offset);
+ htmlEditor->IsPrevCharInNodeWhitespace(content, newOffset,
+ &isSpace, &isNBSP,
+ getter_AddRefs(temp), &offset);
} else {
- NS_ENSURE_TRUE_VOID(mHTMLEditor);
- mHTMLEditor->IsNextCharInNodeWhitespace(content, *outOffset,
- &isSpace, &isNBSP,
- getter_AddRefs(temp), &offset);
+ htmlEditor->IsNextCharInNodeWhitespace(content, newOffset,
+ &isSpace, &isNBSP,
+ getter_AddRefs(temp), &offset);
}
if (isSpace || isNBSP) {
content = temp;
- *outOffset = offset;
+ newOffset = offset;
} else {
break;
}
}
- *outNode = content->AsDOMNode();
- return;
- }
-
+ return EditorDOMPoint(content, newOffset);
+ }
+
+ nsCOMPtr<nsINode> node = &aNode;
int32_t offset = 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()) {
// Okay, can't promote any further
- return;
+ return EditorDOMPoint(node, offset);
}
offset = node->GetParentNode()->IndexOf(node);
node = node->GetParentNode();
}
// look back through any further inline nodes that aren't across a <br>
// from us, and that are enclosed in the same block.
- NS_ENSURE_TRUE_VOID(mHTMLEditor);
nsCOMPtr<nsINode> priorNode =
- mHTMLEditor->GetPriorHTMLNode(node, offset, true);
+ htmlEditor->GetPriorHTMLNode(node, offset, true);
while (priorNode && priorNode->GetParentNode() &&
- mHTMLEditor && !mHTMLEditor->IsVisBreak(priorNode) &&
+ !htmlEditor->IsVisBreak(priorNode) &&
!IsBlockNode(*priorNode)) {
offset = priorNode->GetParentNode()->IndexOf(priorNode);
node = priorNode->GetParentNode();
- NS_ENSURE_TRUE_VOID(mHTMLEditor);
- priorNode = mHTMLEditor->GetPriorHTMLNode(node, offset, true);
+ priorNode = htmlEditor->GetPriorHTMLNode(node, offset, true);
}
// 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.
- NS_ENSURE_TRUE_VOID(mHTMLEditor);
nsCOMPtr<nsIContent> nearNode =
- mHTMLEditor->GetPriorHTMLNode(node, offset, true);
+ htmlEditor->GetPriorHTMLNode(node, offset, true);
while (!nearNode && !node->IsHTMLElement(nsGkAtoms::body) &&
node->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)) {
@@ -5545,111 +5539,97 @@ HTMLEditRules::GetPromotedPoint(RulesEnd
// 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 we're not performing a block-level action.
bool blockLevelAction = actionID == EditAction::indent ||
actionID == EditAction::outdent ||
actionID == EditAction::align ||
actionID == EditAction::makeBasicBlock;
- NS_ENSURE_TRUE_VOID(mHTMLEditor);
- if (!mHTMLEditor->IsDescendantOfEditorRoot(parent) &&
- (blockLevelAction || !mHTMLEditor ||
- !mHTMLEditor->IsDescendantOfEditorRoot(node))) {
- NS_ENSURE_TRUE_VOID(mHTMLEditor);
+ if (!htmlEditor->IsDescendantOfEditorRoot(parent) &&
+ (blockLevelAction ||
+ !htmlEditor->IsDescendantOfEditorRoot(node))) {
break;
}
node = parent;
offset = parentOffset;
- NS_ENSURE_TRUE_VOID(mHTMLEditor);
- nearNode = mHTMLEditor->GetPriorHTMLNode(node, offset, true);
- }
- *outNode = node->AsDOMNode();
- *outOffset = offset;
- return;
+ nearNode = htmlEditor->GetPriorHTMLNode(node, offset, true);
+ }
+ return EditorDOMPoint(node, offset);
}
// aWhere == kEnd
// some special casing for text nodes
if (node->IsNodeOfType(nsINode::eTEXT)) {
if (!node->GetParentNode()) {
// Okay, can't promote any further
- return;
+ return EditorDOMPoint(node, offset);
}
// want to be after the text node
offset = 1 + node->GetParentNode()->IndexOf(node);
node = node->GetParentNode();
}
// look ahead through any further inline nodes that aren't across a <br> from
// us, and that are enclosed in the same block.
- NS_ENSURE_TRUE(mHTMLEditor, /* void */);
nsCOMPtr<nsIContent> nextNode =
- mHTMLEditor->GetNextHTMLNode(node, offset, true);
+ htmlEditor->GetNextHTMLNode(node, offset, true);
while (nextNode && !IsBlockNode(*nextNode) && nextNode->GetParentNode()) {
offset = 1 + nextNode->GetParentNode()->IndexOf(nextNode);
node = nextNode->GetParentNode();
- NS_ENSURE_TRUE_VOID(mHTMLEditor);
- if (mHTMLEditor->IsVisBreak(nextNode)) {
+ if (htmlEditor->IsVisBreak(nextNode)) {
break;
}
// Check for newlines in pre-formatted text nodes.
bool isPRE;
- mHTMLEditor->IsPreformatted(nextNode->AsDOMNode(), &isPRE);
+ htmlEditor->IsPreformatted(nextNode->AsDOMNode(), &isPRE);
if (isPRE) {
if (EditorBase::IsTextNode(nextNode)) {
nsAutoString tempString;
nextNode->GetAsText()->GetData(tempString);
int32_t newlinePos = tempString.FindChar(nsCRT::LF);
if (newlinePos >= 0) {
if (static_cast<uint32_t>(newlinePos) + 1 == tempString.Length()) {
// No need for special processing if the newline is at the end.
break;
}
- *outNode = nextNode->AsDOMNode();
- *outOffset = newlinePos + 1;
- return;
+ return EditorDOMPoint(nextNode, newlinePos + 1);
}
}
}
- NS_ENSURE_TRUE_VOID(mHTMLEditor);
- nextNode = mHTMLEditor->GetNextHTMLNode(node, offset, true);
+ nextNode = htmlEditor->GetNextHTMLNode(node, offset, 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.
- NS_ENSURE_TRUE_VOID(mHTMLEditor);
nsCOMPtr<nsIContent> nearNode =
- mHTMLEditor->GetNextHTMLNode(node, offset, true);
+ htmlEditor->GetNextHTMLNode(node, offset, true);
while (!nearNode && !node->IsHTMLElement(nsGkAtoms::body) &&
node->GetParentNode()) {
int32_t parentOffset = node->GetParentNode()->IndexOf(node);
nsCOMPtr<nsINode> 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 it's OK.
- if ((!mHTMLEditor || !mHTMLEditor->IsDescendantOfEditorRoot(node)) &&
- (!mHTMLEditor || !mHTMLEditor->IsDescendantOfEditorRoot(parent))) {
- NS_ENSURE_TRUE_VOID(mHTMLEditor);
+ if (!htmlEditor->IsDescendantOfEditorRoot(node) &&
+ !htmlEditor->IsDescendantOfEditorRoot(parent)) {
break;
}
node = parent;
// we want to be AFTER nearNode
offset = parentOffset + 1;
- NS_ENSURE_TRUE_VOID(mHTMLEditor);
- nearNode = mHTMLEditor->GetNextHTMLNode(node, offset, true);
- }
- *outNode = node->AsDOMNode();
- *outOffset = offset;
+ nearNode = htmlEditor->GetNextHTMLNode(node, offset, true);
+ }
+ return EditorDOMPoint(node, offset);
}
/**
* GetPromotedRanges() runs all the selection range endpoint through
* GetPromotedPoint().
*/
void
HTMLEditRules::GetPromotedRanges(Selection& aSelection,
@@ -5681,16 +5661,20 @@ HTMLEditRules::GetPromotedRanges(Selecti
*/
void
HTMLEditRules::PromoteRange(nsRange& aRange,
EditAction aOperationType)
{
NS_ENSURE_TRUE(mHTMLEditor, );
RefPtr<HTMLEditor> htmlEditor(mHTMLEditor);
+ if (!aRange.IsPositioned()) {
+ return;
+ }
+
nsCOMPtr<nsINode> startNode = aRange.GetStartParent();
nsCOMPtr<nsINode> endNode = aRange.GetEndParent();
int32_t startOffset = aRange.StartOffset();
int32_t endOffset = aRange.EndOffset();
// MOOSE major hack:
// GetPromotedPoint doesn't really do the right thing for collapsed ranges
// inside block elements that contain nothing but a solo <br>. It's easier
@@ -5713,37 +5697,32 @@ HTMLEditRules::PromoteRange(nsRange& aRa
}
}
}
// Make a new adjusted range to represent the appropriate block content.
// This is tricky. The basic idea is to push out the range endpoints to
// truly enclose the blocks that we will affect.
- nsCOMPtr<nsIDOMNode> opDOMStartNode;
- nsCOMPtr<nsIDOMNode> opDOMEndNode;
- int32_t opStartOffset, opEndOffset;
-
- GetPromotedPoint(kStart, GetAsDOMNode(startNode), startOffset,
- aOperationType, address_of(opDOMStartNode), &opStartOffset);
- GetPromotedPoint(kEnd, GetAsDOMNode(endNode), endOffset, aOperationType,
- address_of(opDOMEndNode), &opEndOffset);
+ EditorDOMPoint opStart =
+ GetPromotedPoint(kStart, *startNode, startOffset, aOperationType);
+ EditorDOMPoint opEnd =
+ GetPromotedPoint(kEnd, *endNode, endOffset, aOperationType);
// Make sure that the new range ends up to be in the editable section.
if (!htmlEditor->IsDescendantOfEditorRoot(
- EditorBase::GetNodeAtRangeOffsetPoint(opDOMStartNode, opStartOffset)) ||
+ EditorBase::GetNodeAtRangeOffsetPoint(opStart.node, opStart.offset)) ||
!htmlEditor->IsDescendantOfEditorRoot(
- EditorBase::GetNodeAtRangeOffsetPoint(opDOMEndNode, opEndOffset - 1))) {
+ EditorBase::GetNodeAtRangeOffsetPoint(opEnd.node, opEnd.offset - 1))) {
return;
}
- nsCOMPtr<nsINode> opStartNode = do_QueryInterface(opDOMStartNode);
- nsCOMPtr<nsINode> opEndNode = do_QueryInterface(opDOMEndNode);
DebugOnly<nsresult> rv =
- aRange.SetStartAndEnd(opStartNode, opStartOffset, opEndNode, opEndOffset);
+ aRange.SetStartAndEnd(opStart.node, opStart.offset,
+ opEnd.node, opEnd.offset);
MOZ_ASSERT(NS_SUCCEEDED(rv));
}
class UniqueFunctor final : public BoolDomIterFunctor
{
public:
explicit UniqueFunctor(nsTArray<OwningNonNull<nsINode>>& aArray)
: mArray(aArray)
--- a/editor/libeditor/HTMLEditRules.h
+++ b/editor/libeditor/HTMLEditRules.h
@@ -316,19 +316,18 @@ protected:
nsIEditor::EDirection aAction, bool* aHandled);
enum class BRLocation { beforeBlock, blockEnd };
Element* CheckForInvisibleBR(Element& aBlock, BRLocation aWhere,
int32_t aOffset = 0);
nsresult ExpandSelectionForDeletion(Selection& aSelection);
bool IsFirstNode(nsIDOMNode* aNode);
bool IsLastNode(nsIDOMNode* aNode);
nsresult NormalizeSelection(Selection* aSelection);
- void GetPromotedPoint(RulesEndpoint aWhere, nsIDOMNode* aNode,
- int32_t aOffset, EditAction actionID,
- nsCOMPtr<nsIDOMNode>* outNode, int32_t* outOffset);
+ EditorDOMPoint GetPromotedPoint(RulesEndpoint aWhere, nsINode& aNode,
+ int32_t aOffset, EditAction actionID);
void GetPromotedRanges(Selection& aSelection,
nsTArray<RefPtr<nsRange>>& outArrayOfRanges,
EditAction inOperationType);
void PromoteRange(nsRange& aRange, EditAction inOperationType);
enum class TouchContent { no, yes };
nsresult GetNodesForOperation(
nsTArray<RefPtr<nsRange>>& aArrayOfRanges,
nsTArray<OwningNonNull<nsINode>>& aOutArrayOfNodes,