зеркало из 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
|
nsresult
|
||||||
nsHTMLEditRules::WillAlign(nsIDOMSelection *aSelection,
|
nsHTMLEditRules::WillAlign(nsIDOMSelection *aSelection,
|
||||||
const nsString *alignType,
|
const nsString *alignType,
|
||||||
|
|
|
@ -117,10 +117,12 @@ protected:
|
||||||
PRBool *outIsEmptyBlock,
|
PRBool *outIsEmptyBlock,
|
||||||
PRBool aMozBRDoesntCount = PR_FALSE,
|
PRBool aMozBRDoesntCount = PR_FALSE,
|
||||||
PRBool aListItemsNotEmpty = PR_FALSE);
|
PRBool aListItemsNotEmpty = PR_FALSE);
|
||||||
|
#if 0
|
||||||
nsresult IsEmptyNode(nsIDOMNode *aNode,
|
nsresult IsEmptyNode(nsIDOMNode *aNode,
|
||||||
PRBool *outIsEmptyBlock,
|
PRBool *outIsEmptyBlock,
|
||||||
PRBool aMozBRDoesntCount = PR_FALSE,
|
PRBool aMozBRDoesntCount = PR_FALSE,
|
||||||
PRBool aListItemsNotEmpty = PR_FALSE);
|
PRBool aListItemsNotEmpty = PR_FALSE);
|
||||||
|
#endif
|
||||||
PRBool IsFirstNode(nsIDOMNode *aNode);
|
PRBool IsFirstNode(nsIDOMNode *aNode);
|
||||||
PRBool IsLastNode(nsIDOMNode *aNode);
|
PRBool IsLastNode(nsIDOMNode *aNode);
|
||||||
PRBool AtStartOfBlock(nsIDOMNode *aNode, PRInt32 aOffset, nsIDOMNode *aBlock);
|
PRBool AtStartOfBlock(nsIDOMNode *aNode, PRInt32 aOffset, nsIDOMNode *aBlock);
|
||||||
|
|
|
@ -4676,8 +4676,11 @@ nsHTMLEditor::InsertAsPlaintextQuotation(const nsString& aQuotedText,
|
||||||
// Do this after the insertion, so that
|
// Do this after the insertion, so that
|
||||||
nsCOMPtr<nsIDOMElement> preElement (do_QueryInterface(preNode));
|
nsCOMPtr<nsIDOMElement> preElement (do_QueryInterface(preNode));
|
||||||
if (preElement)
|
if (preElement)
|
||||||
|
{
|
||||||
preElement->SetAttribute(NS_ConvertASCIItoUCS2("_moz_quote"), NS_ConvertASCIItoUCS2("true"));
|
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:
|
// and set the selection inside it:
|
||||||
selection->Collapse(preNode, 0);
|
selection->Collapse(preNode, 0);
|
||||||
}
|
}
|
||||||
|
|
|
@ -456,13 +456,37 @@ nsTextEditRules::WillInsertBreak(nsIDOMSelection *aSelection, PRBool *aCancel, P
|
||||||
&& isMozQuote)
|
&& isMozQuote)
|
||||||
{
|
{
|
||||||
printf("It's a moz quote -- splitting\n");
|
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;
|
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));
|
res = preNode->GetParentNode(getter_AddRefs(selNode));
|
||||||
if (NS_FAILED(res)) return res;
|
if (NS_FAILED(res)) return res;
|
||||||
nsCOMPtr<nsIDOMNode> brNode;
|
nsCOMPtr<nsIDOMNode> brNode;
|
||||||
// last ePrevious param causes selection to be set before the break
|
// last ePrevious param causes selection to be set before the break
|
||||||
res = mEditor->CreateBR(selNode, newOffset, &brNode, nsIEditor::ePrevious);
|
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;
|
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 CreateMozBR(nsIDOMNode *inParent, PRInt32 inOffset, nsCOMPtr<nsIDOMNode> *outBRNode);
|
||||||
|
|
||||||
|
nsresult IsEmptyNode(nsIDOMNode *aNode,
|
||||||
|
PRBool *outIsEmptyBlock,
|
||||||
|
PRBool aMozBRDoesntCount = PR_FALSE,
|
||||||
|
PRBool aListItemsNotEmpty = PR_FALSE);
|
||||||
|
|
||||||
// data members
|
// data members
|
||||||
nsHTMLEditor *mEditor; // note that we do not refcount the editor
|
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
|
nsresult
|
||||||
nsHTMLEditRules::WillAlign(nsIDOMSelection *aSelection,
|
nsHTMLEditRules::WillAlign(nsIDOMSelection *aSelection,
|
||||||
const nsString *alignType,
|
const nsString *alignType,
|
||||||
|
|
|
@ -117,10 +117,12 @@ protected:
|
||||||
PRBool *outIsEmptyBlock,
|
PRBool *outIsEmptyBlock,
|
||||||
PRBool aMozBRDoesntCount = PR_FALSE,
|
PRBool aMozBRDoesntCount = PR_FALSE,
|
||||||
PRBool aListItemsNotEmpty = PR_FALSE);
|
PRBool aListItemsNotEmpty = PR_FALSE);
|
||||||
|
#if 0
|
||||||
nsresult IsEmptyNode(nsIDOMNode *aNode,
|
nsresult IsEmptyNode(nsIDOMNode *aNode,
|
||||||
PRBool *outIsEmptyBlock,
|
PRBool *outIsEmptyBlock,
|
||||||
PRBool aMozBRDoesntCount = PR_FALSE,
|
PRBool aMozBRDoesntCount = PR_FALSE,
|
||||||
PRBool aListItemsNotEmpty = PR_FALSE);
|
PRBool aListItemsNotEmpty = PR_FALSE);
|
||||||
|
#endif
|
||||||
PRBool IsFirstNode(nsIDOMNode *aNode);
|
PRBool IsFirstNode(nsIDOMNode *aNode);
|
||||||
PRBool IsLastNode(nsIDOMNode *aNode);
|
PRBool IsLastNode(nsIDOMNode *aNode);
|
||||||
PRBool AtStartOfBlock(nsIDOMNode *aNode, PRInt32 aOffset, nsIDOMNode *aBlock);
|
PRBool AtStartOfBlock(nsIDOMNode *aNode, PRInt32 aOffset, nsIDOMNode *aBlock);
|
||||||
|
|
|
@ -4676,8 +4676,11 @@ nsHTMLEditor::InsertAsPlaintextQuotation(const nsString& aQuotedText,
|
||||||
// Do this after the insertion, so that
|
// Do this after the insertion, so that
|
||||||
nsCOMPtr<nsIDOMElement> preElement (do_QueryInterface(preNode));
|
nsCOMPtr<nsIDOMElement> preElement (do_QueryInterface(preNode));
|
||||||
if (preElement)
|
if (preElement)
|
||||||
|
{
|
||||||
preElement->SetAttribute(NS_ConvertASCIItoUCS2("_moz_quote"), NS_ConvertASCIItoUCS2("true"));
|
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:
|
// and set the selection inside it:
|
||||||
selection->Collapse(preNode, 0);
|
selection->Collapse(preNode, 0);
|
||||||
}
|
}
|
||||||
|
|
|
@ -456,13 +456,37 @@ nsTextEditRules::WillInsertBreak(nsIDOMSelection *aSelection, PRBool *aCancel, P
|
||||||
&& isMozQuote)
|
&& isMozQuote)
|
||||||
{
|
{
|
||||||
printf("It's a moz quote -- splitting\n");
|
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;
|
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));
|
res = preNode->GetParentNode(getter_AddRefs(selNode));
|
||||||
if (NS_FAILED(res)) return res;
|
if (NS_FAILED(res)) return res;
|
||||||
nsCOMPtr<nsIDOMNode> brNode;
|
nsCOMPtr<nsIDOMNode> brNode;
|
||||||
// last ePrevious param causes selection to be set before the break
|
// last ePrevious param causes selection to be set before the break
|
||||||
res = mEditor->CreateBR(selNode, newOffset, &brNode, nsIEditor::ePrevious);
|
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;
|
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 CreateMozBR(nsIDOMNode *inParent, PRInt32 inOffset, nsCOMPtr<nsIDOMNode> *outBRNode);
|
||||||
|
|
||||||
|
nsresult IsEmptyNode(nsIDOMNode *aNode,
|
||||||
|
PRBool *outIsEmptyBlock,
|
||||||
|
PRBool aMozBRDoesntCount = PR_FALSE,
|
||||||
|
PRBool aListItemsNotEmpty = PR_FALSE);
|
||||||
|
|
||||||
// data members
|
// data members
|
||||||
nsHTMLEditor *mEditor; // note that we do not refcount the editor
|
nsHTMLEditor *mEditor; // note that we do not refcount the editor
|
||||||
|
|
Загрузка…
Ссылка в новой задаче