зеркало из https://github.com/mozilla/pjs.git
partial fix for bug 30763
This commit is contained in:
Родитель
ad7c9a339c
Коммит
b70e6e443b
|
@ -1871,106 +1871,6 @@ nsHTMLEditRules::IsEmptyBlock(nsIDOMNode *aNode,
|
|||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// IsEmptyNode: figure out if aNode is an empty node.
|
||||
// A block can have children and still be considered empty,
|
||||
// if the children are empty or non-editable.
|
||||
//
|
||||
nsresult
|
||||
nsHTMLEditRules::IsEmptyNode( nsIDOMNode *aNode,
|
||||
PRBool *outIsEmptyNode,
|
||||
PRBool aMozBRDoesntCount,
|
||||
PRBool aListItemsNotEmpty)
|
||||
{
|
||||
if (!aNode || !outIsEmptyNode) return NS_ERROR_NULL_POINTER;
|
||||
*outIsEmptyNode = PR_TRUE;
|
||||
|
||||
// effeciency hack - special case if it's a text node
|
||||
if (nsEditor::IsTextNode(aNode))
|
||||
{
|
||||
PRUint32 length = 0;
|
||||
nsCOMPtr<nsIDOMCharacterData>nodeAsText;
|
||||
nodeAsText = do_QueryInterface(aNode);
|
||||
nodeAsText->GetLength(&length);
|
||||
if (length) *outIsEmptyNode = PR_FALSE;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// if it's not a text node (handled above) and it's not a container,
|
||||
// then we dont call it empty (it's an <hr>, or <br>, etc).
|
||||
// Also, if it's an anchor then dont treat it as empty - even though
|
||||
// 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.
|
||||
if (!mEditor->IsContainer(aNode) || nsHTMLEditUtils::IsAnchor(aNode) ||
|
||||
(aListItemsNotEmpty && nsHTMLEditUtils::IsListItem(aNode)) ||
|
||||
(aListItemsNotEmpty && nsHTMLEditUtils::IsTableCell(aNode)) )
|
||||
{
|
||||
*outIsEmptyNode = PR_FALSE;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// iterate over node. if no children, or all children are either
|
||||
// empty text nodes or non-editable, then node qualifies as empty
|
||||
nsCOMPtr<nsIContentIterator> iter;
|
||||
nsCOMPtr<nsIContent> nodeAsContent = do_QueryInterface(aNode);
|
||||
if (!nodeAsContent) return NS_ERROR_FAILURE;
|
||||
nsresult res = nsComponentManager::CreateInstance(kContentIteratorCID,
|
||||
nsnull,
|
||||
NS_GET_IID(nsIContentIterator),
|
||||
getter_AddRefs(iter));
|
||||
if (NS_FAILED(res)) return res;
|
||||
res = iter->Init(nodeAsContent);
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
while (NS_ENUMERATOR_FALSE == iter->IsDone())
|
||||
{
|
||||
nsCOMPtr<nsIDOMNode> node;
|
||||
nsCOMPtr<nsIContent> content;
|
||||
res = iter->CurrentNode(getter_AddRefs(content));
|
||||
if (NS_FAILED(res)) return res;
|
||||
node = do_QueryInterface(content);
|
||||
if (!node) return NS_ERROR_FAILURE;
|
||||
|
||||
// is the node editable and non-empty? if so, return false
|
||||
if (mEditor->IsEditable(node))
|
||||
{
|
||||
if (nsEditor::IsTextNode(node))
|
||||
{
|
||||
PRUint32 length = 0;
|
||||
nsCOMPtr<nsIDOMCharacterData>nodeAsText;
|
||||
nodeAsText = do_QueryInterface(node);
|
||||
nodeAsText->GetLength(&length);
|
||||
if (length) *outIsEmptyNode = PR_FALSE;
|
||||
}
|
||||
else // an editable, non-text node. we aren't an empty block
|
||||
{
|
||||
// is it the node we are iterating over?
|
||||
if (node.get() == aNode) break;
|
||||
// is it a moz-BR and did the caller ask us not to consider those relevant?
|
||||
if (!(aMozBRDoesntCount && nsHTMLEditUtils::IsMozBR(node)))
|
||||
{
|
||||
// is it an empty node of some sort?
|
||||
PRBool isEmptyNode;
|
||||
res = IsEmptyNode(node, &isEmptyNode, aMozBRDoesntCount, aListItemsNotEmpty);
|
||||
if (NS_FAILED(res)) return res;
|
||||
if (!isEmptyNode)
|
||||
{
|
||||
// otherwise it ain't empty
|
||||
*outIsEmptyNode = PR_FALSE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
res = iter->Next();
|
||||
if (NS_FAILED(res)) return res;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
nsresult
|
||||
nsHTMLEditRules::WillAlign(nsIDOMSelection *aSelection,
|
||||
const nsString *alignType,
|
||||
|
|
|
@ -117,10 +117,12 @@ protected:
|
|||
PRBool *outIsEmptyBlock,
|
||||
PRBool aMozBRDoesntCount = PR_FALSE,
|
||||
PRBool aListItemsNotEmpty = PR_FALSE);
|
||||
#if 0
|
||||
nsresult IsEmptyNode(nsIDOMNode *aNode,
|
||||
PRBool *outIsEmptyBlock,
|
||||
PRBool aMozBRDoesntCount = PR_FALSE,
|
||||
PRBool aListItemsNotEmpty = PR_FALSE);
|
||||
#endif
|
||||
PRBool IsFirstNode(nsIDOMNode *aNode);
|
||||
PRBool IsLastNode(nsIDOMNode *aNode);
|
||||
PRBool AtStartOfBlock(nsIDOMNode *aNode, PRInt32 aOffset, nsIDOMNode *aBlock);
|
||||
|
|
|
@ -4676,8 +4676,11 @@ nsHTMLEditor::InsertAsPlaintextQuotation(const nsString& aQuotedText,
|
|||
// Do this after the insertion, so that
|
||||
nsCOMPtr<nsIDOMElement> preElement (do_QueryInterface(preNode));
|
||||
if (preElement)
|
||||
{
|
||||
preElement->SetAttribute(NS_ConvertASCIItoUCS2("_moz_quote"), NS_ConvertASCIItoUCS2("true"));
|
||||
|
||||
// set style to not have unwanted vertical margins
|
||||
preElement->SetAttribute(NS_ConvertASCIItoUCS2("style"), NS_ConvertASCIItoUCS2("margin: 0 0 0 0px;"));
|
||||
}
|
||||
// and set the selection inside it:
|
||||
selection->Collapse(preNode, 0);
|
||||
}
|
||||
|
|
|
@ -456,13 +456,37 @@ nsTextEditRules::WillInsertBreak(nsIDOMSelection *aSelection, PRBool *aCancel, P
|
|||
&& isMozQuote)
|
||||
{
|
||||
printf("It's a moz quote -- splitting\n");
|
||||
res = mEditor->SplitNodeDeep(preNode, selNode, selOffset, &newOffset);
|
||||
nsCOMPtr<nsIDOMNode> outLeftNode;
|
||||
nsCOMPtr<nsIDOMNode> outRightNode;
|
||||
res = mEditor->SplitNodeDeep(preNode, selNode, selOffset, &newOffset, &outLeftNode, &outRightNode);
|
||||
if (NS_FAILED(res)) return res;
|
||||
PRBool bIsEmptyNode;
|
||||
if (outLeftNode)
|
||||
{
|
||||
res = IsEmptyNode(outLeftNode, &bIsEmptyNode, PR_TRUE, PR_FALSE);
|
||||
if (NS_FAILED(res)) return res;
|
||||
if (bIsEmptyNode) mEditor->DeleteNode(outLeftNode);
|
||||
}
|
||||
if (outRightNode)
|
||||
{
|
||||
// HACK alert: consume a br if there s one at front of node
|
||||
nsCOMPtr<nsIDOMNode> firstNode;
|
||||
res = mEditor->GetFirstEditableNode(outRightNode, &firstNode);
|
||||
if (firstNode && nsHTMLEditUtils::IsBreak(firstNode))
|
||||
{
|
||||
mEditor->DeleteNode(firstNode);
|
||||
}
|
||||
|
||||
res = IsEmptyNode(outRightNode, &bIsEmptyNode, PR_TRUE, PR_FALSE);
|
||||
if (NS_FAILED(res)) return res;
|
||||
if (bIsEmptyNode) mEditor->DeleteNode(outRightNode);
|
||||
}
|
||||
res = preNode->GetParentNode(getter_AddRefs(selNode));
|
||||
if (NS_FAILED(res)) return res;
|
||||
nsCOMPtr<nsIDOMNode> brNode;
|
||||
// last ePrevious param causes selection to be set before the break
|
||||
res = mEditor->CreateBR(selNode, newOffset, &brNode, nsIEditor::ePrevious);
|
||||
*aHandled = PR_TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1300,5 +1324,103 @@ nsTextEditRules::CreateMozBR(nsIDOMNode *inParent, PRInt32 inOffset, nsCOMPtr<ns
|
|||
return res;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// IsEmptyNode: figure out if aNode is an empty node.
|
||||
// A block can have children and still be considered empty,
|
||||
// if the children are empty or non-editable.
|
||||
//
|
||||
nsresult
|
||||
nsTextEditRules::IsEmptyNode( nsIDOMNode *aNode,
|
||||
PRBool *outIsEmptyNode,
|
||||
PRBool aMozBRDoesntCount,
|
||||
PRBool aListItemsNotEmpty)
|
||||
{
|
||||
if (!aNode || !outIsEmptyNode) return NS_ERROR_NULL_POINTER;
|
||||
*outIsEmptyNode = PR_TRUE;
|
||||
|
||||
// effeciency hack - special case if it's a text node
|
||||
if (nsEditor::IsTextNode(aNode))
|
||||
{
|
||||
PRUint32 length = 0;
|
||||
nsCOMPtr<nsIDOMCharacterData>nodeAsText;
|
||||
nodeAsText = do_QueryInterface(aNode);
|
||||
nodeAsText->GetLength(&length);
|
||||
if (length) *outIsEmptyNode = PR_FALSE;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// if it's not a text node (handled above) and it's not a container,
|
||||
// then we dont call it empty (it's an <hr>, or <br>, etc).
|
||||
// Also, if it's an anchor then dont treat it as empty - even though
|
||||
// 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.
|
||||
if (!mEditor->IsContainer(aNode) || nsHTMLEditUtils::IsAnchor(aNode) ||
|
||||
(aListItemsNotEmpty && nsHTMLEditUtils::IsListItem(aNode)) ||
|
||||
(aListItemsNotEmpty && nsHTMLEditUtils::IsTableCell(aNode)) )
|
||||
{
|
||||
*outIsEmptyNode = PR_FALSE;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// iterate over node. if no children, or all children are either
|
||||
// empty text nodes or non-editable, then node qualifies as empty
|
||||
nsCOMPtr<nsIContentIterator> iter;
|
||||
nsCOMPtr<nsIContent> nodeAsContent = do_QueryInterface(aNode);
|
||||
if (!nodeAsContent) return NS_ERROR_FAILURE;
|
||||
nsresult res = nsComponentManager::CreateInstance(kContentIteratorCID,
|
||||
nsnull,
|
||||
NS_GET_IID(nsIContentIterator),
|
||||
getter_AddRefs(iter));
|
||||
if (NS_FAILED(res)) return res;
|
||||
res = iter->Init(nodeAsContent);
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
while (NS_ENUMERATOR_FALSE == iter->IsDone())
|
||||
{
|
||||
nsCOMPtr<nsIDOMNode> node;
|
||||
nsCOMPtr<nsIContent> content;
|
||||
res = iter->CurrentNode(getter_AddRefs(content));
|
||||
if (NS_FAILED(res)) return res;
|
||||
node = do_QueryInterface(content);
|
||||
if (!node) return NS_ERROR_FAILURE;
|
||||
|
||||
// is the node editable and non-empty? if so, return false
|
||||
if (mEditor->IsEditable(node))
|
||||
{
|
||||
if (nsEditor::IsTextNode(node))
|
||||
{
|
||||
PRUint32 length = 0;
|
||||
nsCOMPtr<nsIDOMCharacterData>nodeAsText;
|
||||
nodeAsText = do_QueryInterface(node);
|
||||
nodeAsText->GetLength(&length);
|
||||
if (length) *outIsEmptyNode = PR_FALSE;
|
||||
}
|
||||
else // an editable, non-text node. we aren't an empty block
|
||||
{
|
||||
// is it the node we are iterating over?
|
||||
if (node.get() == aNode) break;
|
||||
// is it a moz-BR and did the caller ask us not to consider those relevant?
|
||||
if (!(aMozBRDoesntCount && nsHTMLEditUtils::IsMozBR(node)))
|
||||
{
|
||||
// is it an empty node of some sort?
|
||||
PRBool isEmptyNode;
|
||||
res = IsEmptyNode(node, &isEmptyNode, aMozBRDoesntCount, aListItemsNotEmpty);
|
||||
if (NS_FAILED(res)) return res;
|
||||
if (!isEmptyNode)
|
||||
{
|
||||
// otherwise it ain't empty
|
||||
*outIsEmptyNode = PR_FALSE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
res = iter->Next();
|
||||
if (NS_FAILED(res)) return res;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -160,6 +160,10 @@ protected:
|
|||
|
||||
nsresult CreateMozBR(nsIDOMNode *inParent, PRInt32 inOffset, nsCOMPtr<nsIDOMNode> *outBRNode);
|
||||
|
||||
nsresult IsEmptyNode(nsIDOMNode *aNode,
|
||||
PRBool *outIsEmptyBlock,
|
||||
PRBool aMozBRDoesntCount = PR_FALSE,
|
||||
PRBool aListItemsNotEmpty = PR_FALSE);
|
||||
|
||||
// data members
|
||||
nsHTMLEditor *mEditor; // note that we do not refcount the editor
|
||||
|
|
|
@ -1871,106 +1871,6 @@ nsHTMLEditRules::IsEmptyBlock(nsIDOMNode *aNode,
|
|||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// IsEmptyNode: figure out if aNode is an empty node.
|
||||
// A block can have children and still be considered empty,
|
||||
// if the children are empty or non-editable.
|
||||
//
|
||||
nsresult
|
||||
nsHTMLEditRules::IsEmptyNode( nsIDOMNode *aNode,
|
||||
PRBool *outIsEmptyNode,
|
||||
PRBool aMozBRDoesntCount,
|
||||
PRBool aListItemsNotEmpty)
|
||||
{
|
||||
if (!aNode || !outIsEmptyNode) return NS_ERROR_NULL_POINTER;
|
||||
*outIsEmptyNode = PR_TRUE;
|
||||
|
||||
// effeciency hack - special case if it's a text node
|
||||
if (nsEditor::IsTextNode(aNode))
|
||||
{
|
||||
PRUint32 length = 0;
|
||||
nsCOMPtr<nsIDOMCharacterData>nodeAsText;
|
||||
nodeAsText = do_QueryInterface(aNode);
|
||||
nodeAsText->GetLength(&length);
|
||||
if (length) *outIsEmptyNode = PR_FALSE;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// if it's not a text node (handled above) and it's not a container,
|
||||
// then we dont call it empty (it's an <hr>, or <br>, etc).
|
||||
// Also, if it's an anchor then dont treat it as empty - even though
|
||||
// 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.
|
||||
if (!mEditor->IsContainer(aNode) || nsHTMLEditUtils::IsAnchor(aNode) ||
|
||||
(aListItemsNotEmpty && nsHTMLEditUtils::IsListItem(aNode)) ||
|
||||
(aListItemsNotEmpty && nsHTMLEditUtils::IsTableCell(aNode)) )
|
||||
{
|
||||
*outIsEmptyNode = PR_FALSE;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// iterate over node. if no children, or all children are either
|
||||
// empty text nodes or non-editable, then node qualifies as empty
|
||||
nsCOMPtr<nsIContentIterator> iter;
|
||||
nsCOMPtr<nsIContent> nodeAsContent = do_QueryInterface(aNode);
|
||||
if (!nodeAsContent) return NS_ERROR_FAILURE;
|
||||
nsresult res = nsComponentManager::CreateInstance(kContentIteratorCID,
|
||||
nsnull,
|
||||
NS_GET_IID(nsIContentIterator),
|
||||
getter_AddRefs(iter));
|
||||
if (NS_FAILED(res)) return res;
|
||||
res = iter->Init(nodeAsContent);
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
while (NS_ENUMERATOR_FALSE == iter->IsDone())
|
||||
{
|
||||
nsCOMPtr<nsIDOMNode> node;
|
||||
nsCOMPtr<nsIContent> content;
|
||||
res = iter->CurrentNode(getter_AddRefs(content));
|
||||
if (NS_FAILED(res)) return res;
|
||||
node = do_QueryInterface(content);
|
||||
if (!node) return NS_ERROR_FAILURE;
|
||||
|
||||
// is the node editable and non-empty? if so, return false
|
||||
if (mEditor->IsEditable(node))
|
||||
{
|
||||
if (nsEditor::IsTextNode(node))
|
||||
{
|
||||
PRUint32 length = 0;
|
||||
nsCOMPtr<nsIDOMCharacterData>nodeAsText;
|
||||
nodeAsText = do_QueryInterface(node);
|
||||
nodeAsText->GetLength(&length);
|
||||
if (length) *outIsEmptyNode = PR_FALSE;
|
||||
}
|
||||
else // an editable, non-text node. we aren't an empty block
|
||||
{
|
||||
// is it the node we are iterating over?
|
||||
if (node.get() == aNode) break;
|
||||
// is it a moz-BR and did the caller ask us not to consider those relevant?
|
||||
if (!(aMozBRDoesntCount && nsHTMLEditUtils::IsMozBR(node)))
|
||||
{
|
||||
// is it an empty node of some sort?
|
||||
PRBool isEmptyNode;
|
||||
res = IsEmptyNode(node, &isEmptyNode, aMozBRDoesntCount, aListItemsNotEmpty);
|
||||
if (NS_FAILED(res)) return res;
|
||||
if (!isEmptyNode)
|
||||
{
|
||||
// otherwise it ain't empty
|
||||
*outIsEmptyNode = PR_FALSE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
res = iter->Next();
|
||||
if (NS_FAILED(res)) return res;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
nsresult
|
||||
nsHTMLEditRules::WillAlign(nsIDOMSelection *aSelection,
|
||||
const nsString *alignType,
|
||||
|
|
|
@ -117,10 +117,12 @@ protected:
|
|||
PRBool *outIsEmptyBlock,
|
||||
PRBool aMozBRDoesntCount = PR_FALSE,
|
||||
PRBool aListItemsNotEmpty = PR_FALSE);
|
||||
#if 0
|
||||
nsresult IsEmptyNode(nsIDOMNode *aNode,
|
||||
PRBool *outIsEmptyBlock,
|
||||
PRBool aMozBRDoesntCount = PR_FALSE,
|
||||
PRBool aListItemsNotEmpty = PR_FALSE);
|
||||
#endif
|
||||
PRBool IsFirstNode(nsIDOMNode *aNode);
|
||||
PRBool IsLastNode(nsIDOMNode *aNode);
|
||||
PRBool AtStartOfBlock(nsIDOMNode *aNode, PRInt32 aOffset, nsIDOMNode *aBlock);
|
||||
|
|
|
@ -4676,8 +4676,11 @@ nsHTMLEditor::InsertAsPlaintextQuotation(const nsString& aQuotedText,
|
|||
// Do this after the insertion, so that
|
||||
nsCOMPtr<nsIDOMElement> preElement (do_QueryInterface(preNode));
|
||||
if (preElement)
|
||||
{
|
||||
preElement->SetAttribute(NS_ConvertASCIItoUCS2("_moz_quote"), NS_ConvertASCIItoUCS2("true"));
|
||||
|
||||
// set style to not have unwanted vertical margins
|
||||
preElement->SetAttribute(NS_ConvertASCIItoUCS2("style"), NS_ConvertASCIItoUCS2("margin: 0 0 0 0px;"));
|
||||
}
|
||||
// and set the selection inside it:
|
||||
selection->Collapse(preNode, 0);
|
||||
}
|
||||
|
|
|
@ -456,13 +456,37 @@ nsTextEditRules::WillInsertBreak(nsIDOMSelection *aSelection, PRBool *aCancel, P
|
|||
&& isMozQuote)
|
||||
{
|
||||
printf("It's a moz quote -- splitting\n");
|
||||
res = mEditor->SplitNodeDeep(preNode, selNode, selOffset, &newOffset);
|
||||
nsCOMPtr<nsIDOMNode> outLeftNode;
|
||||
nsCOMPtr<nsIDOMNode> outRightNode;
|
||||
res = mEditor->SplitNodeDeep(preNode, selNode, selOffset, &newOffset, &outLeftNode, &outRightNode);
|
||||
if (NS_FAILED(res)) return res;
|
||||
PRBool bIsEmptyNode;
|
||||
if (outLeftNode)
|
||||
{
|
||||
res = IsEmptyNode(outLeftNode, &bIsEmptyNode, PR_TRUE, PR_FALSE);
|
||||
if (NS_FAILED(res)) return res;
|
||||
if (bIsEmptyNode) mEditor->DeleteNode(outLeftNode);
|
||||
}
|
||||
if (outRightNode)
|
||||
{
|
||||
// HACK alert: consume a br if there s one at front of node
|
||||
nsCOMPtr<nsIDOMNode> firstNode;
|
||||
res = mEditor->GetFirstEditableNode(outRightNode, &firstNode);
|
||||
if (firstNode && nsHTMLEditUtils::IsBreak(firstNode))
|
||||
{
|
||||
mEditor->DeleteNode(firstNode);
|
||||
}
|
||||
|
||||
res = IsEmptyNode(outRightNode, &bIsEmptyNode, PR_TRUE, PR_FALSE);
|
||||
if (NS_FAILED(res)) return res;
|
||||
if (bIsEmptyNode) mEditor->DeleteNode(outRightNode);
|
||||
}
|
||||
res = preNode->GetParentNode(getter_AddRefs(selNode));
|
||||
if (NS_FAILED(res)) return res;
|
||||
nsCOMPtr<nsIDOMNode> brNode;
|
||||
// last ePrevious param causes selection to be set before the break
|
||||
res = mEditor->CreateBR(selNode, newOffset, &brNode, nsIEditor::ePrevious);
|
||||
*aHandled = PR_TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1300,5 +1324,103 @@ nsTextEditRules::CreateMozBR(nsIDOMNode *inParent, PRInt32 inOffset, nsCOMPtr<ns
|
|||
return res;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// IsEmptyNode: figure out if aNode is an empty node.
|
||||
// A block can have children and still be considered empty,
|
||||
// if the children are empty or non-editable.
|
||||
//
|
||||
nsresult
|
||||
nsTextEditRules::IsEmptyNode( nsIDOMNode *aNode,
|
||||
PRBool *outIsEmptyNode,
|
||||
PRBool aMozBRDoesntCount,
|
||||
PRBool aListItemsNotEmpty)
|
||||
{
|
||||
if (!aNode || !outIsEmptyNode) return NS_ERROR_NULL_POINTER;
|
||||
*outIsEmptyNode = PR_TRUE;
|
||||
|
||||
// effeciency hack - special case if it's a text node
|
||||
if (nsEditor::IsTextNode(aNode))
|
||||
{
|
||||
PRUint32 length = 0;
|
||||
nsCOMPtr<nsIDOMCharacterData>nodeAsText;
|
||||
nodeAsText = do_QueryInterface(aNode);
|
||||
nodeAsText->GetLength(&length);
|
||||
if (length) *outIsEmptyNode = PR_FALSE;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// if it's not a text node (handled above) and it's not a container,
|
||||
// then we dont call it empty (it's an <hr>, or <br>, etc).
|
||||
// Also, if it's an anchor then dont treat it as empty - even though
|
||||
// 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.
|
||||
if (!mEditor->IsContainer(aNode) || nsHTMLEditUtils::IsAnchor(aNode) ||
|
||||
(aListItemsNotEmpty && nsHTMLEditUtils::IsListItem(aNode)) ||
|
||||
(aListItemsNotEmpty && nsHTMLEditUtils::IsTableCell(aNode)) )
|
||||
{
|
||||
*outIsEmptyNode = PR_FALSE;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// iterate over node. if no children, or all children are either
|
||||
// empty text nodes or non-editable, then node qualifies as empty
|
||||
nsCOMPtr<nsIContentIterator> iter;
|
||||
nsCOMPtr<nsIContent> nodeAsContent = do_QueryInterface(aNode);
|
||||
if (!nodeAsContent) return NS_ERROR_FAILURE;
|
||||
nsresult res = nsComponentManager::CreateInstance(kContentIteratorCID,
|
||||
nsnull,
|
||||
NS_GET_IID(nsIContentIterator),
|
||||
getter_AddRefs(iter));
|
||||
if (NS_FAILED(res)) return res;
|
||||
res = iter->Init(nodeAsContent);
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
while (NS_ENUMERATOR_FALSE == iter->IsDone())
|
||||
{
|
||||
nsCOMPtr<nsIDOMNode> node;
|
||||
nsCOMPtr<nsIContent> content;
|
||||
res = iter->CurrentNode(getter_AddRefs(content));
|
||||
if (NS_FAILED(res)) return res;
|
||||
node = do_QueryInterface(content);
|
||||
if (!node) return NS_ERROR_FAILURE;
|
||||
|
||||
// is the node editable and non-empty? if so, return false
|
||||
if (mEditor->IsEditable(node))
|
||||
{
|
||||
if (nsEditor::IsTextNode(node))
|
||||
{
|
||||
PRUint32 length = 0;
|
||||
nsCOMPtr<nsIDOMCharacterData>nodeAsText;
|
||||
nodeAsText = do_QueryInterface(node);
|
||||
nodeAsText->GetLength(&length);
|
||||
if (length) *outIsEmptyNode = PR_FALSE;
|
||||
}
|
||||
else // an editable, non-text node. we aren't an empty block
|
||||
{
|
||||
// is it the node we are iterating over?
|
||||
if (node.get() == aNode) break;
|
||||
// is it a moz-BR and did the caller ask us not to consider those relevant?
|
||||
if (!(aMozBRDoesntCount && nsHTMLEditUtils::IsMozBR(node)))
|
||||
{
|
||||
// is it an empty node of some sort?
|
||||
PRBool isEmptyNode;
|
||||
res = IsEmptyNode(node, &isEmptyNode, aMozBRDoesntCount, aListItemsNotEmpty);
|
||||
if (NS_FAILED(res)) return res;
|
||||
if (!isEmptyNode)
|
||||
{
|
||||
// otherwise it ain't empty
|
||||
*outIsEmptyNode = PR_FALSE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
res = iter->Next();
|
||||
if (NS_FAILED(res)) return res;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -160,6 +160,10 @@ protected:
|
|||
|
||||
nsresult CreateMozBR(nsIDOMNode *inParent, PRInt32 inOffset, nsCOMPtr<nsIDOMNode> *outBRNode);
|
||||
|
||||
nsresult IsEmptyNode(nsIDOMNode *aNode,
|
||||
PRBool *outIsEmptyBlock,
|
||||
PRBool aMozBRDoesntCount = PR_FALSE,
|
||||
PRBool aListItemsNotEmpty = PR_FALSE);
|
||||
|
||||
// data members
|
||||
nsHTMLEditor *mEditor; // note that we do not refcount the editor
|
||||
|
|
Загрузка…
Ссылка в новой задаче