зеркало из https://github.com/mozilla/pjs.git
Bug 718170 - Part a: Use nsINode in IsEmptyNodeImpl; r=ehsan
This commit is contained in:
Родитель
3154e5df5b
Коммит
9acebd55d1
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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,
|
||||
|
|
Загрузка…
Ссылка в новой задаче