Bug 751323 - Cleanup nsHTMLEditRules::RemoveEmptyNodes(); r=ehsan

This commit is contained in:
Ms2ger 2012-05-05 11:00:06 +02:00
parent 6490825be5
commit 9f3641f0f6
5 changed files with 84 additions and 89 deletions

View File

@ -71,6 +71,7 @@ GK_ATOM(mozeditorbogusnode, "_moz_editor_bogus_node")
GK_ATOM(mozgeneratedcontentbefore, "_moz_generated_content_before")
GK_ATOM(mozgeneratedcontentafter, "_moz_generated_content_after")
GK_ATOM(mozgeneratedcontentimage, "_moz_generated_content_image")
GK_ATOM(mozquote, "_moz_quote")
GK_ATOM(_moz_original_size, "_moz_original_size")
GK_ATOM(_moz_target, "_moz_target")
GK_ATOM(_moz_type, "_moz-type")

View File

@ -7932,10 +7932,6 @@ nsHTMLEditRules::InDifferentTableElements(nsIDOMNode *aNode1, nsIDOMNode *aNode2
nsresult
nsHTMLEditRules::RemoveEmptyNodes()
{
nsCOMArray<nsIDOMNode> arrayOfEmptyNodes, arrayOfEmptyCites;
nsCOMPtr<nsISupports> isupports;
PRInt32 nodeCount,j;
// some general notes on the algorithm used here: the goal is to examine all the
// nodes in mDocChangeRange, and remove the empty ones. We do this by using a
// content iterator to traverse all the nodes in the range, and placing the empty
@ -7966,48 +7962,41 @@ nsHTMLEditRules::RemoveEmptyNodes()
nsresult res = iter->Init(mDocChangeRange);
NS_ENSURE_SUCCESS(res, res);
nsTArray<nsIDOMNode*> skipList;
nsCOMArray<nsINode> arrayOfEmptyNodes, arrayOfEmptyCites;
nsTArray<nsINode*> skipList;
// check for empty nodes
while (!iter->IsDone())
{
nsCOMPtr<nsIDOMNode> node, parent;
node = do_QueryInterface(iter->GetCurrentNode());
while (!iter->IsDone()) {
nsINode* node = iter->GetCurrentNode();
NS_ENSURE_TRUE(node, NS_ERROR_FAILURE);
node->GetParentNode(getter_AddRefs(parent));
nsINode* parent = node->GetNodeParent();
PRUint32 idx = skipList.IndexOf(node);
if (idx != skipList.NoIndex)
{
if (idx != skipList.NoIndex) {
// this node is on our skip list. Skip processing for this node,
// and replace its value in the skip list with the value of its parent
skipList[idx] = parent;
}
else
{
} else {
bool bIsCandidate = false;
bool bIsEmptyNode = false;
bool bIsMailCite = false;
// don't delete the body
if (!nsTextEditUtils::IsBody(node))
{
// only consider certain nodes to be empty for purposes of removal
if ( (bIsMailCite = nsHTMLEditUtils::IsMailCite(node)) ||
nsEditor::NodeIsType(node, nsEditProperty::a) ||
nsHTMLEditUtils::IsInlineStyle(node) ||
nsHTMLEditUtils::IsList(node) ||
nsHTMLEditUtils::IsDiv(node) )
{
if (node->IsElement()) {
dom::Element* element = node->AsElement();
if (element->IsHTML(nsGkAtoms::body)) {
// don't delete the body
} else if ((bIsMailCite = nsHTMLEditUtils::IsMailCite(element)) ||
element->IsHTML(nsGkAtoms::a) ||
nsHTMLEditUtils::IsInlineStyle(element) ||
nsHTMLEditUtils::IsList(element) ||
element->IsHTML(nsGkAtoms::div)) {
// only consider certain nodes to be empty for purposes of removal
bIsCandidate = true;
}
// these node types are candidates if selection is not in them
else if (nsHTMLEditUtils::IsFormatNode(node) ||
nsHTMLEditUtils::IsListItem(node) ||
nsHTMLEditUtils::IsBlockquote(node) )
{
} else if (nsHTMLEditUtils::IsFormatNode(element) ||
nsHTMLEditUtils::IsListItem(element) ||
element->IsHTML(nsGkAtoms::blockquote)) {
// these node types are candidates if selection is not in them
// if it is one of these, don't delete if selection inside.
// this is so we can create empty headings, etc, for the
// user to type into.
@ -8021,28 +8010,23 @@ nsHTMLEditRules::RemoveEmptyNodes()
}
}
if (bIsCandidate)
{
if (bIsMailCite) // we delete mailcites even if they have a solo br in them
res = mHTMLEditor->IsEmptyNode(node, &bIsEmptyNode, true, true);
else // other nodes we require to be empty
res = mHTMLEditor->IsEmptyNode(node, &bIsEmptyNode, false, true);
if (bIsCandidate) {
// we delete mailcites even if they have a solo br in them
// other nodes we require to be empty
res = mHTMLEditor->IsEmptyNode(node->AsDOMNode(), &bIsEmptyNode,
bIsMailCite, true);
NS_ENSURE_SUCCESS(res, res);
if (bIsEmptyNode)
{
if (bIsMailCite) // mailcites go on a separate list from other empty nodes
{
if (bIsEmptyNode) {
if (bIsMailCite) {
// mailcites go on a separate list from other empty nodes
arrayOfEmptyCites.AppendObject(node);
}
else
{
} else {
arrayOfEmptyNodes.AppendObject(node);
}
}
}
if (!bIsEmptyNode)
{
if (!bIsEmptyNode) {
// put parent on skip list
skipList.AppendElement(parent);
}
@ -8052,10 +8036,9 @@ nsHTMLEditRules::RemoveEmptyNodes()
}
// now delete the empty nodes
nodeCount = arrayOfEmptyNodes.Count();
for (j = 0; j < nodeCount; j++)
{
nsCOMPtr<nsIDOMNode> delNode = arrayOfEmptyNodes[0];
PRInt32 nodeCount = arrayOfEmptyNodes.Count();
for (PRInt32 j = 0; j < nodeCount; j++) {
nsCOMPtr<nsIDOMNode> delNode = arrayOfEmptyNodes[0]->AsDOMNode();
arrayOfEmptyNodes.RemoveObjectAt(0);
if (mHTMLEditor->IsModifiableNode(delNode)) {
res = mHTMLEditor->DeleteNode(delNode);
@ -8066,9 +8049,8 @@ nsHTMLEditRules::RemoveEmptyNodes()
// now delete the empty mailcites
// this is a separate step because we want to pull out any br's and preserve them.
nodeCount = arrayOfEmptyCites.Count();
for (j = 0; j < nodeCount; j++)
{
nsCOMPtr<nsIDOMNode> delNode = arrayOfEmptyCites[0];
for (PRInt32 j = 0; j < nodeCount; j++) {
nsCOMPtr<nsIDOMNode> delNode = arrayOfEmptyCites[0]->AsDOMNode();
arrayOfEmptyCites.RemoveObjectAt(0);
bool bIsEmptyNode;
res = mHTMLEditor->IsEmptyNode(delNode, &bIsEmptyNode, false, true);
@ -8092,9 +8074,11 @@ nsHTMLEditRules::RemoveEmptyNodes()
}
nsresult
nsHTMLEditRules::SelectionEndpointInNode(nsIDOMNode *aNode, bool *aResult)
nsHTMLEditRules::SelectionEndpointInNode(nsINode* aNode, bool* aResult)
{
NS_ENSURE_TRUE(aNode && aResult, NS_ERROR_NULL_POINTER);
nsIDOMNode* node = aNode->AsDOMNode();
*aResult = false;
@ -8120,13 +8104,11 @@ nsHTMLEditRules::SelectionEndpointInNode(nsIDOMNode *aNode, bool *aResult)
range->GetStartContainer(getter_AddRefs(startParent));
if (startParent)
{
if (aNode == startParent)
{
if (node == startParent) {
*aResult = true;
return NS_OK;
}
if (nsEditorUtils::IsDescendantOf(startParent, aNode))
{
if (nsEditorUtils::IsDescendantOf(startParent, node)) {
*aResult = true;
return NS_OK;
}
@ -8135,13 +8117,11 @@ nsHTMLEditRules::SelectionEndpointInNode(nsIDOMNode *aNode, bool *aResult)
if (startParent == endParent) continue;
if (endParent)
{
if (aNode == endParent)
{
if (node == endParent) {
*aResult = true;
return NS_OK;
}
if (nsEditorUtils::IsDescendantOf(endParent, aNode))
{
if (nsEditorUtils::IsDescendantOf(endParent, node)) {
*aResult = true;
return NS_OK;
}

View File

@ -290,7 +290,7 @@ protected:
nsCOMPtr<nsIDOMNode> *outSelectableNode);
nsresult InDifferentTableElements(nsIDOMNode *aNode1, nsIDOMNode *aNode2, bool *aResult);
nsresult RemoveEmptyNodes();
nsresult SelectionEndpointInNode(nsIDOMNode *aNode, bool *aResult);
nsresult SelectionEndpointInNode(nsINode *aNode, bool *aResult);
nsresult UpdateDocChangeRange(nsIDOMRange *aRange);
nsresult ConfirmSelectionInBody();
nsresult InsertMozBRIfNeeded(nsIDOMNode *aNode);

View File

@ -72,7 +72,15 @@ bool
nsHTMLEditUtils::IsInlineStyle(nsIDOMNode *node)
{
NS_PRECONDITION(node, "null parent passed to nsHTMLEditUtils::IsInlineStyle");
nsCOMPtr<nsIAtom> nodeAtom = nsEditor::GetTag(node);
nsCOMPtr<dom::Element> element = do_QueryInterface(node);
return element && IsInlineStyle(element);
}
bool
nsHTMLEditUtils::IsInlineStyle(dom::Element* aElement)
{
MOZ_ASSERT(aElement);
nsIAtom* nodeAtom = aElement->Tag();
return (nodeAtom == nsEditProperty::b)
|| (nodeAtom == nsEditProperty::i)
|| (nodeAtom == nsEditProperty::u)
@ -94,7 +102,15 @@ bool
nsHTMLEditUtils::IsFormatNode(nsIDOMNode *node)
{
NS_PRECONDITION(node, "null parent passed to nsHTMLEditUtils::IsFormatNode");
nsCOMPtr<nsIAtom> nodeAtom = nsEditor::GetTag(node);
nsCOMPtr<dom::Element> element = do_QueryInterface(node);
return element && IsFormatNode(element);
}
bool
nsHTMLEditUtils::IsFormatNode(dom::Element* aElement)
{
MOZ_ASSERT(aElement);
nsIAtom* nodeAtom = aElement->Tag();
return (nodeAtom == nsEditProperty::p)
|| (nodeAtom == nsEditProperty::pre)
|| (nodeAtom == nsEditProperty::h1)
@ -423,34 +439,29 @@ nsHTMLEditUtils::IsMozDiv(nsIDOMNode *node)
///////////////////////////////////////////////////////////////////////////
// IsMailCite: true if node an html blockquote with type=cite
//
bool
nsHTMLEditUtils::IsMailCite(nsIDOMNode *node)
bool
nsHTMLEditUtils::IsMailCite(nsIDOMNode* aNode)
{
NS_PRECONDITION(node, "null parent passed to nsHTMLEditUtils::IsMailCite");
nsCOMPtr<nsIDOMElement> elem = do_QueryInterface(node);
if (!elem) {
return false;
}
nsAutoString attrName (NS_LITERAL_STRING("type"));
NS_PRECONDITION(aNode, "null parent passed to nsHTMLEditUtils::IsMailCite");
nsCOMPtr<dom::Element> element = do_QueryInterface(aNode);
return element && IsMailCite(element);
}
bool
nsHTMLEditUtils::IsMailCite(dom::Element* aElement)
{
MOZ_ASSERT(aElement);
// don't ask me why, but our html mailcites are id'd by "type=cite"...
nsAutoString attrVal;
nsresult res = elem->GetAttribute(attrName, attrVal);
ToLowerCase(attrVal);
if (NS_SUCCEEDED(res))
{
if (attrVal.EqualsLiteral("cite"))
return true;
if (aElement->AttrValueIs(kNameSpaceID_None, nsGkAtoms::type,
NS_LITERAL_STRING("cite"), eIgnoreCase)) {
return true;
}
// ... but our plaintext mailcites by "_moz_quote=true". go figure.
attrName.AssignLiteral("_moz_quote");
res = elem->GetAttribute(attrName, attrVal);
if (NS_SUCCEEDED(res))
{
ToLowerCase(attrVal);
if (attrVal.EqualsLiteral("true"))
return true;
if (aElement->AttrValueIs(kNameSpaceID_None, nsGkAtoms::mozquote,
NS_LITERAL_STRING("true"), eIgnoreCase)) {
return true;
}
return false;

View File

@ -56,7 +56,9 @@ public:
static bool IsSmall(nsIDOMNode *aNode);
// from nsHTMLEditRules:
static bool IsInlineStyle(mozilla::dom::Element* aNode);
static bool IsInlineStyle(nsIDOMNode *aNode);
static bool IsFormatNode(mozilla::dom::Element* aNode);
static bool IsFormatNode(nsIDOMNode *aNode);
static bool IsNodeThatCanOutdent(nsIDOMNode *aNode);
static bool IsHeader(nsIDOMNode *aNode);
@ -85,6 +87,7 @@ public:
static bool IsNamedAnchor(nsIDOMNode *aNode);
static bool IsDiv(nsIDOMNode *aNode);
static bool IsMozDiv(nsIDOMNode *aNode);
static bool IsMailCite(mozilla::dom::Element* aNode);
static bool IsMailCite(nsIDOMNode *aNode);
static bool IsFormWidget(mozilla::dom::Element* aNode);
static bool IsFormWidget(nsIDOMNode *aNode);