diff --git a/editor/libeditor/nsHTMLEditRules.cpp b/editor/libeditor/nsHTMLEditRules.cpp
index 9fd0e90743b3..f05e522f5822 100644
--- a/editor/libeditor/nsHTMLEditRules.cpp
+++ b/editor/libeditor/nsHTMLEditRules.cpp
@@ -841,11 +841,11 @@ nsHTMLEditRules::GetAlignment(bool *aMixed, nsIHTMLEditor::EAlignment *aAlign)
NS_ENSURE_SUCCESS(res, res);
// use these ranges to construct a list of nodes to act on.
- nsCOMArray arrayOfNodes;
+ nsTArray> arrayOfNodes;
res = GetNodesForOperation(arrayOfRanges, arrayOfNodes,
- EditAction::align, true);
+ EditAction::align, TouchContent::no);
NS_ENSURE_SUCCESS(res, res);
- nodeToExamine = arrayOfNodes.SafeObjectAt(0);
+ nodeToExamine = GetAsDOMNode(arrayOfNodes.SafeElementAt(0));
}
NS_ENSURE_TRUE(nodeToExamine, NS_ERROR_NULL_POINTER);
@@ -3870,10 +3870,15 @@ nsHTMLEditRules::WillHTMLIndent(Selection* aSelection,
NS_ENSURE_SUCCESS(res, res);
// use these ranges to contruct a list of nodes to act on.
- nsCOMArray arrayOfNodes;
- res = GetNodesForOperation(arrayOfRanges, arrayOfNodes, EditAction::indent);
+ nsTArray> array;
+ res = GetNodesForOperation(arrayOfRanges, array, EditAction::indent);
NS_ENSURE_SUCCESS(res, res);
+ nsCOMArray arrayOfNodes;
+ for (auto& node : array) {
+ arrayOfNodes.AppendObject(GetAsDOMNode(node));
+ }
+
// if nothing visible in list, make an empty block
if (ListIsEmptyLine(arrayOfNodes))
{
@@ -5859,184 +5864,153 @@ nsHTMLEditRules::PromoteRange(nsRange* inRange, EditAction inOperationType)
return res;
}
+class NodeComparator
+{
+ public:
+ bool Equals(const nsINode* node, const nsIDOMNode* domNode) const
+ {
+ return domNode == GetAsDOMNode(const_cast(node));
+ }
+};
+
class nsUniqueFunctor : public nsBoolDomIterFunctor
{
public:
- explicit nsUniqueFunctor(nsCOMArray &aArray) : mArray(aArray)
+ explicit nsUniqueFunctor(nsTArray> &aArray) : mArray(aArray)
{
}
// used to build list of all nodes iterator covers
virtual bool operator()(nsIDOMNode* aNode) const
{
- return mArray.IndexOf(aNode) < 0;
+ return !mArray.Contains(aNode, NodeComparator());
}
private:
- nsCOMArray &mArray;
+ nsTArray>& mArray;
};
-///////////////////////////////////////////////////////////////////////////
-// GetNodesForOperation: run through the ranges in the array and construct
-// a new array of nodes to be acted on.
-//
-nsresult
-nsHTMLEditRules::GetNodesForOperation(nsTArray>& inArrayOfRanges,
- nsCOMArray& outArrayOfNodes,
- EditAction inOperationType,
- bool aDontTouchContent)
+///////////////////////////////////////////////////////////////////////////////
+// GetNodesForOperation: Run through the ranges in the array and construct a
+// new array of nodes to be acted on.
+//
+nsresult
+nsHTMLEditRules::GetNodesForOperation(nsTArray>& aArrayOfRanges,
+ nsTArray>& aOutArrayOfNodes,
+ EditAction aOperationType,
+ TouchContent aTouchContent)
{
- int32_t rangeCount = inArrayOfRanges.Length();
-
- int32_t i;
- nsRefPtr opRange;
+ NS_ENSURE_STATE(mHTMLEditor);
+ nsCOMPtr kungFuDeathGrip(mHTMLEditor);
- nsresult res = NS_OK;
-
- // bust up any inlines that cross our range endpoints,
- // but only if we are allowed to touch content.
-
- if (!aDontTouchContent)
- {
+ int32_t rangeCount = aArrayOfRanges.Length();
+ nsresult res;
+
+ // Bust up any inlines that cross our range endpoints, but only if we are
+ // allowed to touch content.
+
+ if (aTouchContent == TouchContent::yes) {
nsTArray> rangeItemArray;
rangeItemArray.AppendElements(rangeCount);
- NS_ASSERTION(static_cast(rangeCount) == rangeItemArray.Length(),
- "How did that happen?");
-
- // first register ranges for special editor gravity
- for (i = 0; i < rangeCount; i++)
- {
- opRange = inArrayOfRanges[0];
+ // First register ranges for special editor gravity
+ for (int32_t i = 0; i < rangeCount; i++) {
rangeItemArray[i] = new nsRangeStore();
- rangeItemArray[i]->StoreRange(opRange);
- NS_ENSURE_STATE(mHTMLEditor);
+ rangeItemArray[i]->StoreRange(aArrayOfRanges[0]);
mHTMLEditor->mRangeUpdater.RegisterRangeItem(rangeItemArray[i]);
- inArrayOfRanges.RemoveElementAt(0);
- }
- // now bust up inlines. Safe to start at rangeCount-1, since we
- // asserted we have enough items above.
- for (i = rangeCount-1; i >= 0 && NS_SUCCEEDED(res); i--)
- {
- res = BustUpInlinesAtRangeEndpoints(*rangeItemArray[i]);
- }
- // then unregister the ranges
- for (i = 0; i < rangeCount; i++)
- {
- nsRangeStore* item = rangeItemArray[i];
- NS_ENSURE_STATE(mHTMLEditor);
+ aArrayOfRanges.RemoveElementAt(0);
+ }
+ // Now bust up inlines.
+ for (auto& item : Reversed(rangeItemArray)) {
+ res = BustUpInlinesAtRangeEndpoints(*item);
+ if (NS_FAILED(res)) {
+ break;
+ }
+ }
+ // Then unregister the ranges
+ for (auto& item : rangeItemArray) {
mHTMLEditor->mRangeUpdater.DropRangeItem(item);
- opRange = item->GetRange();
- inArrayOfRanges.AppendElement(opRange);
+ aArrayOfRanges.AppendElement(item->GetRange());
}
NS_ENSURE_SUCCESS(res, res);
}
- // gather up a list of all the nodes
- for (i = 0; i < rangeCount; i++)
- {
- opRange = inArrayOfRanges[i];
-
- nsDOMSubtreeIterator iter(*opRange);
- if (outArrayOfNodes.Count() == 0) {
- nsTrivialFunctor functor;
- iter.AppendList(functor, outArrayOfNodes);
- }
- else {
- // We don't want duplicates in outArrayOfNodes, so we use an
+ // Gather up a list of all the nodes
+ for (auto& range : aArrayOfRanges) {
+ nsDOMSubtreeIterator iter(*range);
+ if (aOutArrayOfNodes.Length() == 0) {
+ iter.AppendList(nsTrivialFunctor(), aOutArrayOfNodes);
+ } else {
+ // We don't want duplicates in aOutArrayOfNodes, so we use an
// iterator/functor that only return nodes that are not already in
- // outArrayOfNodes.
- nsCOMArray nodes;
- nsUniqueFunctor functor(outArrayOfNodes);
- iter.AppendList(functor, nodes);
- if (!outArrayOfNodes.AppendObjects(nodes))
- return NS_ERROR_OUT_OF_MEMORY;
+ // aOutArrayOfNodes.
+ nsTArray> nodes;
+ iter.AppendList(nsUniqueFunctor(aOutArrayOfNodes), nodes);
+ aOutArrayOfNodes.AppendElements(nodes);
}
- }
+ }
- // certain operations should not act on li's and td's, but rather inside
- // them. alter the list as needed
- if (inOperationType == EditAction::makeBasicBlock) {
- int32_t listCount = outArrayOfNodes.Count();
- for (i=listCount-1; i>=0; i--)
- {
- nsCOMPtr node = outArrayOfNodes[i];
- if (nsHTMLEditUtils::IsListItem(node))
- {
- int32_t j=i;
- outArrayOfNodes.RemoveObjectAt(i);
- res = GetInnerContent(node, outArrayOfNodes, &j);
- NS_ENSURE_SUCCESS(res, res);
+ // Certain operations should not act on li's and td's, but rather inside
+ // them. Alter the list as needed.
+ if (aOperationType == EditAction::makeBasicBlock) {
+ for (int32_t i = aOutArrayOfNodes.Length() - 1; i >= 0; i--) {
+ nsCOMPtr node = aOutArrayOfNodes[i];
+ if (nsHTMLEditUtils::IsListItem(node)) {
+ int32_t j = i;
+ aOutArrayOfNodes.RemoveElementAt(i);
+ GetInnerContent(*node, aOutArrayOfNodes, &j);
+ }
+ }
+ // Indent/outdent already do something special for list items, but we still
+ // need to make sure we don't act on table elements
+ } else if (aOperationType == EditAction::outdent ||
+ aOperationType == EditAction::indent ||
+ aOperationType == EditAction::setAbsolutePosition) {
+ for (int32_t i = aOutArrayOfNodes.Length() - 1; i >= 0; i--) {
+ nsCOMPtr node = aOutArrayOfNodes[i];
+ if (nsHTMLEditUtils::IsTableElementButNotTable(node)) {
+ int32_t j = i;
+ aOutArrayOfNodes.RemoveElementAt(i);
+ GetInnerContent(*node, aOutArrayOfNodes, &j);
}
}
}
- // indent/outdent already do something special for list items, but
- // we still need to make sure we don't act on table elements
- else if (inOperationType == EditAction::outdent ||
- inOperationType == EditAction::indent ||
- inOperationType == EditAction::setAbsolutePosition) {
- int32_t listCount = outArrayOfNodes.Count();
- for (i=listCount-1; i>=0; i--)
- {
- nsCOMPtr node = outArrayOfNodes[i];
- if (nsHTMLEditUtils::IsTableElementButNotTable(node))
- {
- int32_t j=i;
- outArrayOfNodes.RemoveObjectAt(i);
- res = GetInnerContent(node, outArrayOfNodes, &j);
- NS_ENSURE_SUCCESS(res, res);
- }
- }
- }
- // outdent should look inside of divs.
- if (inOperationType == EditAction::outdent &&
- (!mHTMLEditor || !mHTMLEditor->IsCSSEnabled())) {
- NS_ENSURE_STATE(mHTMLEditor);
- int32_t listCount = outArrayOfNodes.Count();
- for (i=listCount-1; i>=0; i--)
- {
- nsCOMPtr node = outArrayOfNodes[i];
- if (nsHTMLEditUtils::IsDiv(node))
- {
- int32_t j=i;
- outArrayOfNodes.RemoveObjectAt(i);
- res = GetInnerContent(node, outArrayOfNodes, &j, false, false);
- NS_ENSURE_SUCCESS(res, res);
+ // Outdent should look inside of divs.
+ if (aOperationType == EditAction::outdent &&
+ !mHTMLEditor->IsCSSEnabled()) {
+ for (int32_t i = aOutArrayOfNodes.Length() - 1; i >= 0; i--) {
+ nsCOMPtr node = aOutArrayOfNodes[i];
+ if (node->IsHTMLElement(nsGkAtoms::div)) {
+ int32_t j = i;
+ aOutArrayOfNodes.RemoveElementAt(i);
+ GetInnerContent(*node, aOutArrayOfNodes, &j, Lists::no, Tables::no);
}
}
}
- // post process the list to break up inline containers that contain br's.
- // but only for operations that might care, like making lists or para's...
- if (inOperationType == EditAction::makeBasicBlock ||
- inOperationType == EditAction::makeList ||
- inOperationType == EditAction::align ||
- inOperationType == EditAction::setAbsolutePosition ||
- inOperationType == EditAction::indent ||
- inOperationType == EditAction::outdent) {
- int32_t listCount = outArrayOfNodes.Count();
- for (i=listCount-1; i>=0; i--)
- {
- nsCOMPtr node = do_QueryInterface(outArrayOfNodes[i]);
- NS_ENSURE_STATE(node);
- if (!aDontTouchContent && IsInlineNode(GetAsDOMNode(node)) &&
- (!mHTMLEditor || mHTMLEditor->IsContainer(node)) &&
- (!mHTMLEditor || !mHTMLEditor->IsTextNode(node)))
- {
- NS_ENSURE_STATE(mHTMLEditor);
+ // Post-process the list to break up inline containers that contain br's, but
+ // only for operations that might care, like making lists or paragraphs
+ if (aOperationType == EditAction::makeBasicBlock ||
+ aOperationType == EditAction::makeList ||
+ aOperationType == EditAction::align ||
+ aOperationType == EditAction::setAbsolutePosition ||
+ aOperationType == EditAction::indent ||
+ aOperationType == EditAction::outdent) {
+ for (int32_t i = aOutArrayOfNodes.Length() - 1; i >= 0; i--) {
+ nsCOMPtr node = aOutArrayOfNodes[i];
+ if (aTouchContent == TouchContent::yes &&
+ IsInlineNode(GetAsDOMNode(node)) && mHTMLEditor->IsContainer(node) &&
+ !mHTMLEditor->IsTextNode(node)) {
nsTArray> arrayOfInlines;
res = BustUpInlinesAtBRs(*node, arrayOfInlines);
NS_ENSURE_SUCCESS(res, res);
- nsCOMArray arrayOfInlinesDOM;
- for (auto& inlineNode : arrayOfInlines) {
- arrayOfInlinesDOM.AppendObject(GetAsDOMNode(inlineNode));
- }
- // put these nodes in outArrayOfNodes, replacing the current node
- outArrayOfNodes.RemoveObjectAt(i);
- outArrayOfNodes.InsertObjectsAt(arrayOfInlinesDOM, i);
+
+ // Put these nodes in aOutArrayOfNodes, replacing the current node
+ aOutArrayOfNodes.RemoveElementAt(i);
+ aOutArrayOfNodes.InsertElementsAt(i, arrayOfInlines);
}
}
}
- return res;
+ return NS_OK;
}
@@ -6433,7 +6407,12 @@ nsHTMLEditRules::GetNodesFromPoint(::DOMPoint point,
arrayOfRanges.AppendElement(range);
// use these ranges to contruct a list of nodes to act on.
- res = GetNodesForOperation(arrayOfRanges, arrayOfNodes, operation, dontTouchContent);
+ nsTArray> array;
+ res = GetNodesForOperation(arrayOfRanges, array, operation, dontTouchContent
+ ? TouchContent::no : TouchContent::yes);
+ for (auto& node : array) {
+ arrayOfNodes.AppendObject(GetAsDOMNode(node));
+ }
return res;
}
@@ -6457,7 +6436,12 @@ nsHTMLEditRules::GetNodesFromSelection(Selection* selection,
NS_ENSURE_SUCCESS(res, res);
// use these ranges to contruct a list of nodes to act on.
- res = GetNodesForOperation(arrayOfRanges, arrayOfNodes, operation, dontTouchContent);
+ nsTArray> array;
+ res = GetNodesForOperation(arrayOfRanges, array, operation, dontTouchContent
+ ? TouchContent::no : TouchContent::yes);
+ for (auto& node : array) {
+ arrayOfNodes.AppendObject(GetAsDOMNode(node));
+ }
return res;
}
@@ -9079,11 +9063,15 @@ nsHTMLEditRules::WillAbsolutePosition(Selection* aSelection,
NS_ENSURE_SUCCESS(res, res);
// use these ranges to contruct a list of nodes to act on.
- nsCOMArray arrayOfNodes;
- res = GetNodesForOperation(arrayOfRanges, arrayOfNodes,
+ nsTArray> array;
+ res = GetNodesForOperation(arrayOfRanges, array,
EditAction::setAbsolutePosition);
NS_ENSURE_SUCCESS(res, res);
+ nsCOMArray arrayOfNodes;
+ for (auto& node : array) {
+ arrayOfNodes.AppendObject(GetAsDOMNode(node));
+ }
// if nothing visible in list, make an empty block
if (ListIsEmptyLine(arrayOfNodes))
{
diff --git a/editor/libeditor/nsHTMLEditRules.h b/editor/libeditor/nsHTMLEditRules.h
index e4d030a64845..b589c3d28d7d 100644
--- a/editor/libeditor/nsHTMLEditRules.h
+++ b/editor/libeditor/nsHTMLEditRules.h
@@ -276,10 +276,11 @@ protected:
nsTArray>& outArrayOfRanges,
EditAction inOperationType);
nsresult PromoteRange(nsRange* inRange, EditAction inOperationType);
- nsresult GetNodesForOperation(nsTArray>& inArrayOfRanges,
- nsCOMArray& outArrayOfNodes,
- EditAction inOperationType,
- bool aDontTouchContent=false);
+ enum class TouchContent { no, yes };
+ nsresult GetNodesForOperation(nsTArray>& aArrayOfRanges,
+ nsTArray>& aOutArrayOfNodes,
+ EditAction aOperationType,
+ TouchContent aTouchContent = TouchContent::yes);
nsresult GetChildNodesForOperation(nsIDOMNode *inNode,
nsCOMArray& outArrayOfNodes);
nsresult GetNodesFromPoint(::DOMPoint point,