Bug 718170 - Part a: Use nsINode in IsEmptyNodeImpl; r=ehsan

This commit is contained in:
Ms2ger 2012-01-25 08:50:05 +01:00
parent c35015ccf5
commit b930898e9f
5 changed files with 150 additions and 86 deletions

View File

@ -2942,10 +2942,10 @@ nsHTMLEditRules::DidDeleteSelection(nsISelection *aSelection,
res = GetTopEnclosingMailCite(startNode, address_of(citeNode),
IsPlaintextEditor());
NS_ENSURE_SUCCESS(res, res);
if (citeNode)
{
if (citeNode) {
nsCOMPtr<nsINode> cite = do_QueryInterface(citeNode);
bool isEmpty = true, seenBR = false;
mHTMLEditor->IsEmptyNodeImpl(citeNode, &isEmpty, true, true, false, &seenBR);
mHTMLEditor->IsEmptyNodeImpl(cite, &isEmpty, true, true, false, &seenBR);
if (isEmpty)
{
nsCOMPtr<nsIDOMNode> parent, brNode;

View File

@ -35,9 +35,12 @@
*
* ***** END LICENSE BLOCK ***** */
#include "mozilla/Util.h"
#include "nsHTMLEditUtils.h"
#include "mozilla/Assertions.h"
#include "mozilla/Util.h"
#include "mozilla/dom/Element.h"
#include "nsTextEditUtils.h"
#include "nsString.h"
@ -177,7 +180,15 @@ bool
nsHTMLEditUtils::IsListItem(nsIDOMNode *node)
{
NS_PRECONDITION(node, "null parent passed to nsHTMLEditUtils::IsListItem");
nsCOMPtr<nsIAtom> nodeAtom = nsEditor::GetTag(node);
nsCOMPtr<dom::Element> element = do_QueryInterface(node);
return element && IsListItem(element);
}
bool
nsHTMLEditUtils::IsListItem(dom::Element* node)
{
MOZ_ASSERT(node);
nsCOMPtr<nsIAtom> nodeAtom = node->Tag();
return (nodeAtom == nsEditProperty::li)
|| (nodeAtom == nsEditProperty::dd)
|| (nodeAtom == nsEditProperty::dt);
@ -245,7 +256,15 @@ bool
nsHTMLEditUtils::IsTableCell(nsIDOMNode *node)
{
NS_PRECONDITION(node, "null parent passed to nsHTMLEditUtils::IsTableCell");
nsCOMPtr<nsIAtom> nodeAtom = nsEditor::GetTag(node);
nsCOMPtr<dom::Element> element = do_QueryInterface(node);
return element && IsTableCell(element);
}
bool
nsHTMLEditUtils::IsTableCell(dom::Element* node)
{
MOZ_ASSERT(node);
nsCOMPtr<nsIAtom> nodeAtom = node->Tag();
return (nodeAtom == nsEditProperty::td)
|| (nodeAtom == nsEditProperty::th);
}
@ -268,11 +287,19 @@ nsHTMLEditUtils::IsTableCellOrCaption(nsIDOMNode *node)
///////////////////////////////////////////////////////////////////////////
// IsList: true if node an html list
//
bool
bool
nsHTMLEditUtils::IsList(nsIDOMNode *node)
{
NS_PRECONDITION(node, "null parent passed to nsHTMLEditUtils::IsList");
nsCOMPtr<nsIAtom> nodeAtom = nsEditor::GetTag(node);
nsCOMPtr<dom::Element> element = do_QueryInterface(node);
return element && IsList(element);
}
bool
nsHTMLEditUtils::IsList(dom::Element* node)
{
MOZ_ASSERT(node);
nsCOMPtr<nsIAtom> nodeAtom = node->Tag();
return (nodeAtom == nsEditProperty::ul)
|| (nodeAtom == nsEditProperty::ol)
|| (nodeAtom == nsEditProperty::dl);
@ -345,15 +372,21 @@ nsHTMLEditUtils::IsLink(nsIDOMNode *aNode)
bool
nsHTMLEditUtils::IsNamedAnchor(nsIDOMNode *aNode)
{
NS_ENSURE_TRUE(aNode, false);
nsCOMPtr<nsIDOMHTMLAnchorElement> anchor = do_QueryInterface(aNode);
if (anchor)
{
nsAutoString tmpText;
if (NS_SUCCEEDED(anchor->GetName(tmpText)) && !tmpText.IsEmpty())
return true;
nsCOMPtr<dom::Element> element = do_QueryInterface(aNode);
return element && IsNamedAnchor(element);
}
bool
nsHTMLEditUtils::IsNamedAnchor(dom::Element* aNode)
{
MOZ_ASSERT(aNode);
if (!aNode->IsHTML(nsGkAtoms::a)) {
return false;
}
return false;
nsAutoString text;
return aNode->GetAttr(kNameSpaceID_None, nsGkAtoms::name, text) &&
!text.IsEmpty();
}
@ -419,11 +452,19 @@ nsHTMLEditUtils::IsMailCite(nsIDOMNode *node)
///////////////////////////////////////////////////////////////////////////
// IsFormWidget: true if node is a form widget of some kind
//
bool
bool
nsHTMLEditUtils::IsFormWidget(nsIDOMNode *node)
{
NS_PRECONDITION(node, "null node passed to nsHTMLEditUtils::IsFormWidget");
nsCOMPtr<nsIAtom> nodeAtom = nsEditor::GetTag(node);
nsCOMPtr<dom::Element> element = do_QueryInterface(node);
return element && IsFormWidget(element);
}
bool
nsHTMLEditUtils::IsFormWidget(dom::Element* node)
{
MOZ_ASSERT(node);
nsCOMPtr<nsIAtom> nodeAtom = node->Tag();
return (nodeAtom == nsEditProperty::textarea)
|| (nodeAtom == nsEditProperty::select)
|| (nodeAtom == nsEditProperty::button)

View File

@ -40,6 +40,12 @@
#include "prtypes.h" // for PRInt32
namespace mozilla {
namespace dom {
class Element;
} // namespace dom
} // namespace mozilla
class nsIDOMNode;
class nsHTMLEditUtils
@ -56,13 +62,16 @@ public:
static bool IsHeader(nsIDOMNode *aNode);
static bool IsParagraph(nsIDOMNode *aNode);
static bool IsHR(nsIDOMNode *aNode);
static bool IsListItem(mozilla::dom::Element* aNode);
static bool IsListItem(nsIDOMNode *aNode);
static bool IsTable(nsIDOMNode *aNode);
static bool IsTableRow(nsIDOMNode *aNode);
static bool IsTableElement(nsIDOMNode *aNode);
static bool IsTableElementButNotTable(nsIDOMNode *aNode);
static bool IsTableCell(mozilla::dom::Element* node);
static bool IsTableCell(nsIDOMNode *aNode);
static bool IsTableCellOrCaption(nsIDOMNode *aNode);
static bool IsList(mozilla::dom::Element* aNode);
static bool IsList(nsIDOMNode *aNode);
static bool IsOrderedList(nsIDOMNode *aNode);
static bool IsUnorderedList(nsIDOMNode *aNode);
@ -71,10 +80,12 @@ public:
static bool IsAnchor(nsIDOMNode *aNode);
static bool IsImage(nsIDOMNode *aNode);
static bool IsLink(nsIDOMNode *aNode);
static bool IsNamedAnchor(mozilla::dom::Element* aNode);
static bool IsNamedAnchor(nsIDOMNode *aNode);
static bool IsDiv(nsIDOMNode *aNode);
static bool IsMozDiv(nsIDOMNode *aNode);
static bool IsMailCite(nsIDOMNode *aNode);
static bool IsFormWidget(mozilla::dom::Element* aNode);
static bool IsFormWidget(nsIDOMNode *aNode);
static bool SupportsAlignAttr(nsIDOMNode *aNode);
static bool CanContain(PRInt32 aParent, PRInt32 aChild);

View File

@ -3953,7 +3953,14 @@ nsHTMLEditor::TagCanContainTag(const nsAString& aParentTag, const nsAString& aCh
return nsHTMLEditUtils::CanContain(parentTagEnum, childTagEnum);
}
bool
bool
nsHTMLEditor::IsContainer(nsINode* aNode)
{
nsCOMPtr<nsIDOMNode> node = do_QueryInterface(aNode);
return IsContainer(node);
}
bool
nsHTMLEditor::IsContainer(nsIDOMNode *aNode)
{
if (!aNode) {
@ -4773,13 +4780,10 @@ bool
nsHTMLEditor::IsTextInDirtyFrameVisible(nsIContent *aNode)
{
bool isEmptyTextNode;
nsCOMPtr<nsIDOMNode> node = do_QueryInterface(aNode);
nsresult res = IsVisTextNode(node, &isEmptyTextNode, false);
if (NS_FAILED(res))
{
nsresult rv = IsVisTextNode(aNode, &isEmptyTextNode, false);
if (NS_FAILED(rv)) {
// We are following the historical decision:
// if we don't know, we say it's visible...
return true;
}
@ -4790,6 +4794,15 @@ nsHTMLEditor::IsTextInDirtyFrameVisible(nsIContent *aNode)
///////////////////////////////////////////////////////////////////////////
// IsVisTextNode: figure out if textnode aTextNode has any visible content.
//
nsresult
nsHTMLEditor::IsVisTextNode(nsIContent* aNode,
bool* outIsEmptyNode,
bool aSafeToAskFrames)
{
nsCOMPtr<nsIDOMNode> node = do_QueryInterface(aNode);
return IsVisTextNode(node);
}
nsresult
nsHTMLEditor::IsVisTextNode( nsIDOMNode* aNode,
bool *outIsEmptyNode,
@ -4861,10 +4874,11 @@ nsHTMLEditor::IsEmptyNode( nsIDOMNode *aNode,
bool aListOrCellNotEmpty,
bool aSafeToAskFrames)
{
NS_ENSURE_TRUE(aNode && outIsEmptyNode, NS_ERROR_NULL_POINTER);
nsCOMPtr<nsINode> node = do_QueryInterface(aNode);
NS_ENSURE_TRUE(node && outIsEmptyNode, NS_ERROR_NULL_POINTER);
*outIsEmptyNode = true;
bool seenBR = false;
return IsEmptyNodeImpl(aNode, outIsEmptyNode, aSingleBRDoesntCount,
return IsEmptyNodeImpl(node, outIsEmptyNode, aSingleBRDoesntCount,
aListOrCellNotEmpty, aSafeToAskFrames, &seenBR);
}
@ -4872,20 +4886,17 @@ nsHTMLEditor::IsEmptyNode( nsIDOMNode *aNode,
// IsEmptyNodeImpl: workhorse for IsEmptyNode.
//
nsresult
nsHTMLEditor::IsEmptyNodeImpl( nsIDOMNode *aNode,
bool *outIsEmptyNode,
bool aSingleBRDoesntCount,
bool aListOrCellNotEmpty,
bool aSafeToAskFrames,
bool *aSeenBR)
nsHTMLEditor::IsEmptyNodeImpl(nsINode* aNode,
bool *outIsEmptyNode,
bool aSingleBRDoesntCount,
bool aListOrCellNotEmpty,
bool aSafeToAskFrames,
bool *aSeenBR)
{
NS_ENSURE_TRUE(aNode && outIsEmptyNode && aSeenBR, NS_ERROR_NULL_POINTER);
nsresult res = NS_OK;
if (nsEditor::IsTextNode(aNode))
{
res = IsVisTextNode(aNode, outIsEmptyNode, aSafeToAskFrames);
return res;
if (aNode->NodeType() == nsIDOMNode::TEXT_NODE) {
return IsVisTextNode(static_cast<nsIContent*>(aNode), outIsEmptyNode, aSafeToAskFrames);
}
// if it's not a text node (handled above) and it's not a container,
@ -4894,74 +4905,72 @@ nsHTMLEditor::IsEmptyNodeImpl( nsIDOMNode *aNode,
// anchors are containers, named anchors are "empty" but we don't
// want to treat them as such. Also, don't call ListItems or table
// cells empty if caller desires. Form Widgets not empty.
if (!IsContainer(aNode) || nsHTMLEditUtils::IsNamedAnchor(aNode) ||
nsHTMLEditUtils::IsFormWidget(aNode) ||
(aListOrCellNotEmpty && nsHTMLEditUtils::IsListItem(aNode)) ||
(aListOrCellNotEmpty && nsHTMLEditUtils::IsTableCell(aNode)) )
{
if (!IsContainer(aNode) ||
(aNode->IsElement() &&
(nsHTMLEditUtils::IsNamedAnchor(aNode->AsElement()) ||
nsHTMLEditUtils::IsFormWidget(aNode->AsElement()) ||
(aListOrCellNotEmpty &&
(nsHTMLEditUtils::IsListItem(aNode->AsElement()) ||
nsHTMLEditUtils::IsTableCell(aNode->AsElement())))))) {
*outIsEmptyNode = false;
return NS_OK;
}
// need this for later
bool isListItemOrCell =
nsHTMLEditUtils::IsListItem(aNode) || nsHTMLEditUtils::IsTableCell(aNode);
bool isListItemOrCell = aNode->IsElement() &&
(nsHTMLEditUtils::IsListItem(aNode->AsElement()) ||
nsHTMLEditUtils::IsTableCell(aNode->AsElement()));
// loop over children of node. if no children, or all children are either
// empty text nodes or non-editable, then node qualifies as empty
nsCOMPtr<nsIDOMNode> child;
aNode->GetFirstChild(getter_AddRefs(child));
while (child)
{
nsCOMPtr<nsIDOMNode> node = child;
// is the node editable and non-empty? if so, return false
if (nsEditor::IsEditable(node))
{
if (nsEditor::IsTextNode(node))
{
res = IsVisTextNode(node, outIsEmptyNode, aSafeToAskFrames);
NS_ENSURE_SUCCESS(res, res);
for (nsCOMPtr<nsIContent> child = aNode->GetFirstChild();
child;
child = child->GetNextSibling()) {
// Is the child editable and non-empty? if so, return false
if (nsEditor::IsEditable(child)) {
if (child->NodeType() == nsIDOMNode::TEXT_NODE) {
nsresult rv = IsVisTextNode(child, outIsEmptyNode, aSafeToAskFrames);
NS_ENSURE_SUCCESS(rv, rv);
// break out if we find we aren't emtpy
if (!*outIsEmptyNode) {
return NS_OK;
}
}
else // an editable, non-text node. we need to check it's content.
{
// is it the node we are iterating over?
if (node == aNode) break;
else if (aSingleBRDoesntCount && !*aSeenBR && nsTextEditUtils::IsBreak(node))
{
} else {
// An editable, non-text node. We need to check its content.
// Is it the node we are iterating over?
if (child == aNode) {
break;
}
if (aSingleBRDoesntCount && !*aSeenBR && child->IsHTML(nsGkAtoms::br)) {
// the first br in a block doesn't count if the caller so indicated
*aSeenBR = true;
}
else
{
} else {
// is it an empty node of some sort?
// note: list items or table cells are not considered empty
// if they contain other lists or tables
if (isListItemOrCell)
{
if (nsHTMLEditUtils::IsList(node) || nsHTMLEditUtils::IsTable(node))
{ // break out if we find we aren't empty
if (child->IsElement()) {
if (isListItemOrCell) {
if (nsHTMLEditUtils::IsList(child->AsElement()) || child->IsHTML(nsGkAtoms::table)) {
// break out if we find we aren't empty
*outIsEmptyNode = false;
return NS_OK;
}
} else if (nsHTMLEditUtils::IsFormWidget(child->AsElement())) {
// is it a form widget?
// break out if we find we aren't empty
*outIsEmptyNode = false;
return NS_OK;
}
}
// is it a form widget?
else if (nsHTMLEditUtils::IsFormWidget(node))
{ // break out if we find we aren't empty
*outIsEmptyNode = false;
return NS_OK;
}
bool isEmptyNode = true;
res = IsEmptyNodeImpl(node, &isEmptyNode, aSingleBRDoesntCount,
aListOrCellNotEmpty, aSafeToAskFrames, aSeenBR);
NS_ENSURE_SUCCESS(res, res);
if (!isEmptyNode)
{
nsresult rv = IsEmptyNodeImpl(child, &isEmptyNode,
aSingleBRDoesntCount,
aListOrCellNotEmpty, aSafeToAskFrames,
aSeenBR);
NS_ENSURE_SUCCESS(rv, rv);
if (!isEmptyNode) {
// otherwise it ain't empty
*outIsEmptyNode = false;
return NS_OK;
@ -4969,7 +4978,6 @@ nsHTMLEditor::IsEmptyNodeImpl( nsIDOMNode *aNode,
}
}
}
node->GetNextSibling(getter_AddRefs(child));
}
return NS_OK;

View File

@ -324,6 +324,7 @@ public:
virtual bool TagCanContainTag(const nsAString& aParentTag, const nsAString& aChildTag);
/** returns true if aNode is a container */
virtual bool IsContainer(nsINode* aNode);
virtual bool IsContainer(nsIDOMNode *aNode);
/** make the given selection span the entire document */
@ -387,6 +388,9 @@ public:
virtual bool IsTextInDirtyFrameVisible(nsIContent *aNode);
nsresult IsVisTextNode(nsIContent* aNode,
bool* outIsEmptyNode,
bool aSafeToAskFrames);
nsresult IsVisTextNode( nsIDOMNode *aNode,
bool *outIsEmptyNode,
bool aSafeToAskFrames);
@ -394,7 +398,7 @@ public:
bool aMozBRDoesntCount = false,
bool aListOrCellNotEmpty = false,
bool aSafeToAskFrames = false);
nsresult IsEmptyNodeImpl(nsIDOMNode *aNode,
nsresult IsEmptyNodeImpl(nsINode* aNode,
bool *outIsEmptyBlock,
bool aMozBRDoesntCount,
bool aListOrCellNotEmpty,