Skip to content

Commit

Permalink
Bug 1053779 part 2 - Clean up nsEditor::ReplaceContainer; r=ehsan
Browse files Browse the repository at this point in the history
  • Loading branch information
ayg committed Aug 13, 2014
1 parent c5a22b8 commit c9b178f
Show file tree
Hide file tree
Showing 5 changed files with 79 additions and 106 deletions.
56 changes: 32 additions & 24 deletions editor/libeditor/html/nsHTMLEditRules.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3256,6 +3256,7 @@ nsHTMLEditRules::WillMakeList(Selection* aSelection,
// here's where we actually figure out what to do
nsCOMPtr<nsIDOMNode> newBlock;
nsCOMPtr<nsIDOMNode> curNode = arrayOfNodes[i];
nsCOMPtr<Element> curNodeAsElement = do_QueryInterface(curNode);
int32_t offset;
curParent = nsEditor::GetNodeLocation(curNode, &offset);
Expand Down Expand Up @@ -3332,9 +3333,10 @@ nsHTMLEditRules::WillMakeList(Selection* aSelection,
NS_ENSURE_STATE(mHTMLEditor);
if (!mHTMLEditor->NodeIsType(curNode, itemType)) {
NS_ENSURE_STATE(mHTMLEditor);
res = mHTMLEditor->ReplaceContainer(curNode, address_of(newBlock),
nsDependentAtomString(itemType));
NS_ENSURE_SUCCESS(res, res);
NS_ENSURE_STATE(curNodeAsElement);
newBlock = dont_AddRef(GetAsDOMNode(
mHTMLEditor->ReplaceContainer(curNodeAsElement, itemType).take()));
NS_ENSURE_STATE(newBlock);
}
} else {
// item is in right type of list. But we might still have to move it.
Expand All @@ -3350,9 +3352,10 @@ nsHTMLEditRules::WillMakeList(Selection* aSelection,
NS_ENSURE_STATE(mHTMLEditor);
if (!mHTMLEditor->NodeIsType(curNode, itemType)) {
NS_ENSURE_STATE(mHTMLEditor);
res = mHTMLEditor->ReplaceContainer(curNode, address_of(newBlock),
nsDependentAtomString(itemType));
NS_ENSURE_SUCCESS(res, res);
NS_ENSURE_STATE(curNodeAsElement);
newBlock = dont_AddRef(GetAsDOMNode(
mHTMLEditor->ReplaceContainer(curNodeAsElement, itemType).take()));
NS_ENSURE_STATE(newBlock);
}
}
nsCOMPtr<nsIDOMElement> curElement = do_QueryInterface(curNode);
Expand Down Expand Up @@ -3409,14 +3412,16 @@ nsHTMLEditRules::WillMakeList(Selection* aSelection,
// don't wrap li around a paragraph. instead replace paragraph with li
if (nsHTMLEditUtils::IsParagraph(curNode)) {
NS_ENSURE_STATE(mHTMLEditor);
res = mHTMLEditor->ReplaceContainer(curNode, address_of(listItem),
nsDependentAtomString(itemType));
NS_ENSURE_STATE(curNodeAsElement);
listItem = dont_AddRef(GetAsDOMNode(
mHTMLEditor->ReplaceContainer(curNodeAsElement, itemType).take()));
NS_ENSURE_STATE(listItem);
} else {
NS_ENSURE_STATE(mHTMLEditor);
res = mHTMLEditor->InsertContainerAbove(curNode, address_of(listItem),
nsDependentAtomString(itemType));
NS_ENSURE_SUCCESS(res, res);
}
NS_ENSURE_SUCCESS(res, res);
if (IsInlineNode(curNode)) {
prevListItem = listItem;
} else {
Expand Down Expand Up @@ -4567,7 +4572,7 @@ nsHTMLEditRules::ConvertListType(nsIDOMNode* aList,
MOZ_ASSERT(aItemType);
NS_ENSURE_TRUE(aList && outList, NS_ERROR_NULL_POINTER);
nsCOMPtr<nsINode> list = do_QueryInterface(aList);
nsCOMPtr<Element> list = do_QueryInterface(aList);
NS_ENSURE_STATE(list);
nsCOMPtr<dom::Element> outNode;
Expand All @@ -4577,7 +4582,7 @@ nsHTMLEditRules::ConvertListType(nsIDOMNode* aList,
}
nsresult
nsHTMLEditRules::ConvertListType(nsINode* aList,
nsHTMLEditRules::ConvertListType(Element* aList,
dom::Element** aOutList,
nsIAtom* aListType,
nsIAtom* aItemType)
Expand All @@ -4593,17 +4598,13 @@ nsHTMLEditRules::ConvertListType(nsINode* aList,
if (child->IsElement()) {
dom::Element* element = child->AsElement();
if (nsHTMLEditUtils::IsListItem(element) && !element->IsHTML(aItemType)) {
nsCOMPtr<dom::Element> temp;
nsresult rv =
mHTMLEditor->ReplaceContainer(child, getter_AddRefs(temp),
nsDependentAtomString(aItemType));
NS_ENSURE_SUCCESS(rv, rv);
child = temp.forget();
child = mHTMLEditor->ReplaceContainer(element, aItemType);
NS_ENSURE_STATE(child);
} else if (nsHTMLEditUtils::IsList(element) &&
!element->IsHTML(aListType)) {
nsCOMPtr<dom::Element> temp;
nsresult rv =
ConvertListType(child, getter_AddRefs(temp), aListType, aItemType);
nsresult rv = ConvertListType(child->AsElement(), getter_AddRefs(temp),
aListType, aItemType);
NS_ENSURE_SUCCESS(rv, rv);
child = temp.forget();
}
Expand All @@ -4617,8 +4618,10 @@ nsHTMLEditRules::ConvertListType(nsINode* aList,
return NS_OK;
}
return mHTMLEditor->ReplaceContainer(aList, aOutList,
nsDependentAtomString(aListType));
*aOutList = mHTMLEditor->ReplaceContainer(aList, aListType).take();
NS_ENSURE_STATE(aOutList);
return NS_OK;
}
Expand Down Expand Up @@ -7328,9 +7331,14 @@ nsHTMLEditRules::ApplyBlockStyle(nsCOMArray<nsIDOMNode>& arrayOfNodes, const nsA
{
curBlock = 0; // forget any previous block used for previous inline nodes
NS_ENSURE_STATE(mHTMLEditor);
res = mHTMLEditor->ReplaceContainer(curNode, address_of(newBlock), *aBlockTag,
nullptr, nullptr, true);
NS_ENSURE_SUCCESS(res, res);
nsCOMPtr<Element> element = do_QueryInterface(curNode);
NS_ENSURE_STATE(element);
newBlock = dont_AddRef(GetAsDOMNode(
mHTMLEditor->ReplaceContainer(element,
nsCOMPtr<nsIAtom>(do_GetAtom(*aBlockTag)),
nullptr, nullptr,
nsEditor::eCloneAttributes).take()));
NS_ENSURE_STATE(newBlock);
}
else if (nsHTMLEditUtils::IsTable(curNode) ||
(curNodeTag.EqualsLiteral("tbody")) ||
Expand Down
2 changes: 1 addition & 1 deletion editor/libeditor/html/nsHTMLEditRules.h
Original file line number Diff line number Diff line change
Expand Up @@ -231,7 +231,7 @@ class nsHTMLEditRules : public nsTextEditRules, public nsIEditActionListener
nsCOMPtr<nsIDOMNode>* outList,
nsIAtom* aListType,
nsIAtom* aItemType);
nsresult ConvertListType(nsINode* aList,
nsresult ConvertListType(mozilla::dom::Element* aList,
mozilla::dom::Element** aOutList,
nsIAtom* aListType,
nsIAtom* aItemType);
Expand Down
13 changes: 6 additions & 7 deletions editor/libeditor/html/nsTableEditor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1942,14 +1942,13 @@ nsHTMLEditor::SplitCellIntoRows(nsIDOMElement *aTable, int32_t aRowIndex, int32_
NS_IMETHODIMP
nsHTMLEditor::SwitchTableCellHeaderType(nsIDOMElement *aSourceCell, nsIDOMElement **aNewCell)
{
NS_ENSURE_TRUE(aSourceCell, NS_ERROR_NULL_POINTER);
nsCOMPtr<Element> sourceCell = do_QueryInterface(aSourceCell);
NS_ENSURE_TRUE(sourceCell, NS_ERROR_NULL_POINTER);

nsAutoEditBatch beginBatching(this);
// Prevent auto insertion of BR in new cell created by ReplaceContainer
nsAutoRules beginRulesSniffing(this, EditAction::insertNode, nsIEditor::eNext);

nsCOMPtr<nsIDOMNode> newNode;

// Save current selection to restore when done
// This is needed so ReplaceContainer can monitor selection
// when replacing nodes
Expand All @@ -1959,13 +1958,13 @@ nsHTMLEditor::SwitchTableCellHeaderType(nsIDOMElement *aSourceCell, nsIDOMElemen

// Set to the opposite of current type
nsCOMPtr<nsIAtom> atom = nsEditor::GetTag(aSourceCell);
nsString newCellType( (atom == nsEditProperty::td) ? NS_LITERAL_STRING("th") : NS_LITERAL_STRING("td"));
nsIAtom* newCellType = atom == nsEditProperty::td
? nsGkAtoms::th : nsGkAtoms::td;

// This creates new node, moves children, copies attributes (true)
// and manages the selection!
nsresult res = ReplaceContainer(aSourceCell, address_of(newNode),
newCellType, nullptr, nullptr, true);
NS_ENSURE_SUCCESS(res, res);
nsCOMPtr<Element> newNode = ReplaceContainer(sourceCell, newCellType,
nullptr, nullptr, nsEditor::eCloneAttributes);
NS_ENSURE_TRUE(newNode, NS_ERROR_FAILURE);

// Return the new cell
Expand Down
97 changes: 34 additions & 63 deletions editor/libeditor/nsEditor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -512,15 +512,12 @@ nsEditor::GetIsSelectionEditable(bool *aIsSelectionEditable)
NS_ENSURE_ARG_POINTER(aIsSelectionEditable);

// get current selection
nsCOMPtr<nsISelection> selection;
nsresult res = GetSelection(getter_AddRefs(selection));
NS_ENSURE_SUCCESS(res, res);
nsRefPtr<Selection> selection = GetSelection();
NS_ENSURE_TRUE(selection, NS_ERROR_NULL_POINTER);

// XXX we just check that the anchor node is editable at the moment
// we should check that all nodes in the selection are editable
nsCOMPtr<nsIDOMNode> anchorNode;
selection->GetAnchorNode(getter_AddRefs(anchorNode));
nsCOMPtr<nsINode> anchorNode = selection->GetAnchorNode();
*aIsSelectionEditable = anchorNode && IsEditable(anchorNode);

return NS_OK;
Expand All @@ -530,7 +527,7 @@ NS_IMETHODIMP
nsEditor::GetIsDocumentEditable(bool *aIsDocumentEditable)
{
NS_ENSURE_ARG_POINTER(aIsDocumentEditable);
nsCOMPtr<nsIDOMDocument> doc = GetDOMDocument();
nsCOMPtr<nsIDocument> doc = GetDocument();
*aIsDocumentEditable = !!doc;

return NS_OK;
Expand All @@ -555,8 +552,7 @@ nsEditor::GetDOMDocument()
NS_IMETHODIMP
nsEditor::GetDocument(nsIDOMDocument **aDoc)
{
nsCOMPtr<nsIDOMDocument> doc = GetDOMDocument();
doc.forget(aDoc);
*aDoc = GetDOMDocument().take();
return *aDoc ? NS_OK : NS_ERROR_NOT_INITIALIZED;
}

Expand Down Expand Up @@ -1527,87 +1523,62 @@ nsEditor::DeleteNode(nsINode* aNode)
// to be of type aNodeType. Put inNodes children into outNode.
// Callers responsibility to make sure inNode's children can
// go in outNode.
nsresult
nsEditor::ReplaceContainer(nsIDOMNode *inNode,
nsCOMPtr<nsIDOMNode> *outNode,
const nsAString &aNodeType,
const nsAString *aAttribute,
const nsAString *aValue,
bool aCloneAttributes)
{
NS_ENSURE_TRUE(inNode && outNode, NS_ERROR_NULL_POINTER);

nsCOMPtr<nsINode> node = do_QueryInterface(inNode);
NS_ENSURE_STATE(node);

nsCOMPtr<dom::Element> element;
nsresult rv = ReplaceContainer(node, getter_AddRefs(element), aNodeType,
aAttribute, aValue, aCloneAttributes);
*outNode = element ? element->AsDOMNode() : nullptr;
return rv;
}

nsresult
nsEditor::ReplaceContainer(nsINode* aNode,
dom::Element** outNode,
const nsAString& aNodeType,
const nsAString* aAttribute,
already_AddRefed<Element>
nsEditor::ReplaceContainer(Element* aOldContainer,
nsIAtom* aNodeType,
nsIAtom* aAttribute,
const nsAString* aValue,
bool aCloneAttributes)
ECloneAttributes aCloneAttributes)
{
MOZ_ASSERT(aNode);
MOZ_ASSERT(outNode);
MOZ_ASSERT(aOldContainer && aNodeType);

*outNode = nullptr;
nsCOMPtr<nsIContent> parent = aOldContainer->GetParent();
NS_ENSURE_TRUE(parent, nullptr);

nsCOMPtr<nsIContent> parent = aNode->GetParent();
NS_ENSURE_STATE(parent);

int32_t offset = parent->IndexOf(aNode);
int32_t offset = parent->IndexOf(aOldContainer);

// create new container
*outNode =
CreateHTMLContent(nsCOMPtr<nsIAtom>(do_GetAtom(aNodeType))).take();
NS_ENSURE_STATE(*outNode);

nsCOMPtr<nsIDOMElement> elem = do_QueryInterface(*outNode);

nsIDOMNode* inNode = aNode->AsDOMNode();
nsCOMPtr<Element> ret = CreateHTMLContent(aNodeType);
NS_ENSURE_TRUE(ret, nullptr);

// set attribute if needed
nsresult res;
if (aAttribute && aValue && !aAttribute->IsEmpty()) {
res = elem->SetAttribute(*aAttribute, *aValue);
NS_ENSURE_SUCCESS(res, res);
if (aAttribute && aValue && aAttribute != nsGkAtoms::_empty) {
res = ret->SetAttr(kNameSpaceID_None, aAttribute, *aValue, true);
NS_ENSURE_SUCCESS(res, nullptr);
}
if (aCloneAttributes) {
res = CloneAttributes(elem, inNode);
NS_ENSURE_SUCCESS(res, res);
if (aCloneAttributes == eCloneAttributes) {
res = CloneAttributes(ret->AsDOMNode(), aOldContainer->AsDOMNode());
NS_ENSURE_SUCCESS(res, nullptr);
}

// notify our internal selection state listener
// (Note: A nsAutoSelectionReset object must be created
// before calling this to initialize mRangeUpdater)
nsAutoReplaceContainerSelNotify selStateNotify(mRangeUpdater, inNode, elem);
nsAutoReplaceContainerSelNotify selStateNotify(mRangeUpdater,
aOldContainer->AsDOMNode(), ret->AsDOMNode());
{
nsAutoTxnsConserveSelection conserveSelection(this);
while (aNode->HasChildren()) {
nsCOMPtr<nsIDOMNode> child = aNode->GetFirstChild()->AsDOMNode();
while (aOldContainer->HasChildren()) {
nsCOMPtr<nsIContent> child = aOldContainer->GetFirstChild();

res = DeleteNode(child);
NS_ENSURE_SUCCESS(res, res);
NS_ENSURE_SUCCESS(res, nullptr);

res = InsertNode(child, elem, -1);
NS_ENSURE_SUCCESS(res, res);
res = InsertNode(child, ret, -1);
NS_ENSURE_SUCCESS(res, nullptr);
}
}

// insert new container into tree
res = InsertNode(elem, parent->AsDOMNode(), offset);
NS_ENSURE_SUCCESS(res, res);
res = InsertNode(ret, parent, offset);
NS_ENSURE_SUCCESS(res, nullptr);

// delete old container
return DeleteNode(inNode);
res = DeleteNode(aOldContainer);
NS_ENSURE_SUCCESS(res, nullptr);

return ret.forget();
}

///////////////////////////////////////////////////////////////////////////
Expand Down
17 changes: 6 additions & 11 deletions editor/libeditor/nsEditor.h
Original file line number Diff line number Diff line change
Expand Up @@ -224,18 +224,13 @@ class nsEditor : public nsIEditor,
nsresult DeleteNode(nsINode* aNode);
nsresult InsertNode(nsIContent* aContent, nsINode* aParent,
int32_t aPosition);
nsresult ReplaceContainer(nsINode* inNode,
mozilla::dom::Element** outNode,
const nsAString& aNodeType,
const nsAString* aAttribute = nullptr,
enum ECloneAttributes { eDontCloneAttributes, eCloneAttributes };
already_AddRefed<mozilla::dom::Element> ReplaceContainer(
mozilla::dom::Element* aOldContainer,
nsIAtom* aNodeType,
nsIAtom* aAttribute = nullptr,
const nsAString* aValue = nullptr,
bool aCloneAttributes = false);
nsresult ReplaceContainer(nsIDOMNode *inNode,
nsCOMPtr<nsIDOMNode> *outNode,
const nsAString &aNodeType,
const nsAString *aAttribute = nullptr,
const nsAString *aValue = nullptr,
bool aCloneAttributes = false);
ECloneAttributes aCloneAttributes = eDontCloneAttributes);

nsresult RemoveContainer(nsINode* aNode);
nsresult RemoveContainer(nsIDOMNode *inNode);
Expand Down

0 comments on commit c9b178f

Please sign in to comment.