зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1149163 part 5 - Clean up nsHTMLEditRules::GetNodesForOperation; r=froydnj
This commit is contained in:
Родитель
179b7441b8
Коммит
12ccfaab76
|
@ -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<nsIDOMNode> arrayOfNodes;
|
||||
nsTArray<nsCOMPtr<nsINode>> 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<nsIDOMNode> arrayOfNodes;
|
||||
res = GetNodesForOperation(arrayOfRanges, arrayOfNodes, EditAction::indent);
|
||||
nsTArray<nsCOMPtr<nsINode>> array;
|
||||
res = GetNodesForOperation(arrayOfRanges, array, EditAction::indent);
|
||||
NS_ENSURE_SUCCESS(res, res);
|
||||
|
||||
nsCOMArray<nsIDOMNode> 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<nsINode*>(node));
|
||||
}
|
||||
};
|
||||
|
||||
class nsUniqueFunctor : public nsBoolDomIterFunctor
|
||||
{
|
||||
public:
|
||||
explicit nsUniqueFunctor(nsCOMArray<nsIDOMNode> &aArray) : mArray(aArray)
|
||||
explicit nsUniqueFunctor(nsTArray<nsCOMPtr<nsINode>> &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<nsIDOMNode> &mArray;
|
||||
nsTArray<nsCOMPtr<nsINode>>& mArray;
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// GetNodesForOperation: run through the ranges in the array and construct
|
||||
// a new array of nodes to be acted on.
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// GetNodesForOperation: Run through the ranges in the array and construct a
|
||||
// new array of nodes to be acted on.
|
||||
//
|
||||
nsresult
|
||||
nsHTMLEditRules::GetNodesForOperation(nsTArray<nsRefPtr<nsRange>>& inArrayOfRanges,
|
||||
nsCOMArray<nsIDOMNode>& outArrayOfNodes,
|
||||
EditAction inOperationType,
|
||||
bool aDontTouchContent)
|
||||
nsHTMLEditRules::GetNodesForOperation(nsTArray<nsRefPtr<nsRange>>& aArrayOfRanges,
|
||||
nsTArray<nsCOMPtr<nsINode>>& aOutArrayOfNodes,
|
||||
EditAction aOperationType,
|
||||
TouchContent aTouchContent)
|
||||
{
|
||||
int32_t rangeCount = inArrayOfRanges.Length();
|
||||
NS_ENSURE_STATE(mHTMLEditor);
|
||||
nsCOMPtr<nsIEditor> kungFuDeathGrip(mHTMLEditor);
|
||||
|
||||
int32_t i;
|
||||
nsRefPtr<nsRange> opRange;
|
||||
int32_t rangeCount = aArrayOfRanges.Length();
|
||||
nsresult res;
|
||||
|
||||
nsresult res = NS_OK;
|
||||
// Bust up any inlines that cross our range endpoints, but only if we are
|
||||
// allowed to touch content.
|
||||
|
||||
// bust up any inlines that cross our range endpoints,
|
||||
// but only if we are allowed to touch content.
|
||||
|
||||
if (!aDontTouchContent)
|
||||
{
|
||||
if (aTouchContent == TouchContent::yes) {
|
||||
nsTArray<nsRefPtr<nsRangeStore>> rangeItemArray;
|
||||
rangeItemArray.AppendElements(rangeCount);
|
||||
|
||||
NS_ASSERTION(static_cast<uint32_t>(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);
|
||||
aArrayOfRanges.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]);
|
||||
// Now bust up inlines.
|
||||
for (auto& item : Reversed(rangeItemArray)) {
|
||||
res = BustUpInlinesAtRangeEndpoints(*item);
|
||||
if (NS_FAILED(res)) {
|
||||
break;
|
||||
}
|
||||
// then unregister the ranges
|
||||
for (i = 0; i < rangeCount; i++)
|
||||
{
|
||||
nsRangeStore* item = rangeItemArray[i];
|
||||
NS_ENSURE_STATE(mHTMLEditor);
|
||||
}
|
||||
// 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<nsIDOMNode> nodes;
|
||||
nsUniqueFunctor functor(outArrayOfNodes);
|
||||
iter.AppendList(functor, nodes);
|
||||
if (!outArrayOfNodes.AppendObjects(nodes))
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
// aOutArrayOfNodes.
|
||||
nsTArray<nsCOMPtr<nsINode>> 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<nsIDOMNode> node = outArrayOfNodes[i];
|
||||
if (nsHTMLEditUtils::IsListItem(node))
|
||||
{
|
||||
// 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<nsINode> node = aOutArrayOfNodes[i];
|
||||
if (nsHTMLEditUtils::IsListItem(node)) {
|
||||
int32_t j = i;
|
||||
outArrayOfNodes.RemoveObjectAt(i);
|
||||
res = GetInnerContent(node, outArrayOfNodes, &j);
|
||||
NS_ENSURE_SUCCESS(res, res);
|
||||
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<nsIDOMNode> node = outArrayOfNodes[i];
|
||||
if (nsHTMLEditUtils::IsTableElementButNotTable(node))
|
||||
{
|
||||
// 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<nsINode> node = aOutArrayOfNodes[i];
|
||||
if (nsHTMLEditUtils::IsTableElementButNotTable(node)) {
|
||||
int32_t j = i;
|
||||
outArrayOfNodes.RemoveObjectAt(i);
|
||||
res = GetInnerContent(node, outArrayOfNodes, &j);
|
||||
NS_ENSURE_SUCCESS(res, res);
|
||||
aOutArrayOfNodes.RemoveElementAt(i);
|
||||
GetInnerContent(*node, aOutArrayOfNodes, &j);
|
||||
}
|
||||
}
|
||||
}
|
||||
// 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<nsIDOMNode> node = outArrayOfNodes[i];
|
||||
if (nsHTMLEditUtils::IsDiv(node))
|
||||
{
|
||||
// Outdent should look inside of divs.
|
||||
if (aOperationType == EditAction::outdent &&
|
||||
!mHTMLEditor->IsCSSEnabled()) {
|
||||
for (int32_t i = aOutArrayOfNodes.Length() - 1; i >= 0; i--) {
|
||||
nsCOMPtr<nsINode> node = aOutArrayOfNodes[i];
|
||||
if (node->IsHTMLElement(nsGkAtoms::div)) {
|
||||
int32_t j = i;
|
||||
outArrayOfNodes.RemoveObjectAt(i);
|
||||
res = GetInnerContent(node, outArrayOfNodes, &j, false, false);
|
||||
NS_ENSURE_SUCCESS(res, res);
|
||||
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<nsINode> 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<nsINode> node = aOutArrayOfNodes[i];
|
||||
if (aTouchContent == TouchContent::yes &&
|
||||
IsInlineNode(GetAsDOMNode(node)) && mHTMLEditor->IsContainer(node) &&
|
||||
!mHTMLEditor->IsTextNode(node)) {
|
||||
nsTArray<nsCOMPtr<nsINode>> arrayOfInlines;
|
||||
res = BustUpInlinesAtBRs(*node, arrayOfInlines);
|
||||
NS_ENSURE_SUCCESS(res, res);
|
||||
nsCOMArray<nsIDOMNode> 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<nsCOMPtr<nsINode>> 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<nsCOMPtr<nsINode>> 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<nsIDOMNode> arrayOfNodes;
|
||||
res = GetNodesForOperation(arrayOfRanges, arrayOfNodes,
|
||||
nsTArray<nsCOMPtr<nsINode>> array;
|
||||
res = GetNodesForOperation(arrayOfRanges, array,
|
||||
EditAction::setAbsolutePosition);
|
||||
NS_ENSURE_SUCCESS(res, res);
|
||||
|
||||
nsCOMArray<nsIDOMNode> arrayOfNodes;
|
||||
for (auto& node : array) {
|
||||
arrayOfNodes.AppendObject(GetAsDOMNode(node));
|
||||
}
|
||||
// if nothing visible in list, make an empty block
|
||||
if (ListIsEmptyLine(arrayOfNodes))
|
||||
{
|
||||
|
|
|
@ -276,10 +276,11 @@ protected:
|
|||
nsTArray<nsRefPtr<nsRange>>& outArrayOfRanges,
|
||||
EditAction inOperationType);
|
||||
nsresult PromoteRange(nsRange* inRange, EditAction inOperationType);
|
||||
nsresult GetNodesForOperation(nsTArray<nsRefPtr<nsRange>>& inArrayOfRanges,
|
||||
nsCOMArray<nsIDOMNode>& outArrayOfNodes,
|
||||
EditAction inOperationType,
|
||||
bool aDontTouchContent=false);
|
||||
enum class TouchContent { no, yes };
|
||||
nsresult GetNodesForOperation(nsTArray<nsRefPtr<nsRange>>& aArrayOfRanges,
|
||||
nsTArray<nsCOMPtr<nsINode>>& aOutArrayOfNodes,
|
||||
EditAction aOperationType,
|
||||
TouchContent aTouchContent = TouchContent::yes);
|
||||
nsresult GetChildNodesForOperation(nsIDOMNode *inNode,
|
||||
nsCOMArray<nsIDOMNode>& outArrayOfNodes);
|
||||
nsresult GetNodesFromPoint(::DOMPoint point,
|
||||
|
|
Загрузка…
Ссылка в новой задаче