diff --git a/editor/base/nsHTMLEditRules.cpp b/editor/base/nsHTMLEditRules.cpp index 9510e5d3f18..5e95fd27b43 100644 --- a/editor/base/nsHTMLEditRules.cpp +++ b/editor/base/nsHTMLEditRules.cpp @@ -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; - nsCOMPtrnodeAsText; - 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
, or
, 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 iter; - nsCOMPtr 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 node; - nsCOMPtr 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; - nsCOMPtrnodeAsText; - 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, diff --git a/editor/base/nsHTMLEditRules.h b/editor/base/nsHTMLEditRules.h index 043288a77e3..6c038fd5654 100644 --- a/editor/base/nsHTMLEditRules.h +++ b/editor/base/nsHTMLEditRules.h @@ -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); diff --git a/editor/base/nsHTMLEditor.cpp b/editor/base/nsHTMLEditor.cpp index 99a218674f6..00321c92e50 100644 --- a/editor/base/nsHTMLEditor.cpp +++ b/editor/base/nsHTMLEditor.cpp @@ -4676,8 +4676,11 @@ nsHTMLEditor::InsertAsPlaintextQuotation(const nsString& aQuotedText, // Do this after the insertion, so that nsCOMPtr 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); } diff --git a/editor/base/nsTextEditRules.cpp b/editor/base/nsTextEditRules.cpp index ef498132002..b27d44149a3 100644 --- a/editor/base/nsTextEditRules.cpp +++ b/editor/base/nsTextEditRules.cpp @@ -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 outLeftNode; + nsCOMPtr 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 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 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, nsCOMPtrnodeAsText; + 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
, or
, 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 iter; + nsCOMPtr 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 node; + nsCOMPtr 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; + nsCOMPtrnodeAsText; + 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; +} diff --git a/editor/base/nsTextEditRules.h b/editor/base/nsTextEditRules.h index b7d0821f1d1..d319b89bb21 100644 --- a/editor/base/nsTextEditRules.h +++ b/editor/base/nsTextEditRules.h @@ -160,6 +160,10 @@ protected: nsresult CreateMozBR(nsIDOMNode *inParent, PRInt32 inOffset, nsCOMPtr *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 diff --git a/editor/libeditor/html/nsHTMLEditRules.cpp b/editor/libeditor/html/nsHTMLEditRules.cpp index 9510e5d3f18..5e95fd27b43 100644 --- a/editor/libeditor/html/nsHTMLEditRules.cpp +++ b/editor/libeditor/html/nsHTMLEditRules.cpp @@ -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; - nsCOMPtrnodeAsText; - 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
, or
, 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 iter; - nsCOMPtr 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 node; - nsCOMPtr 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; - nsCOMPtrnodeAsText; - 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, diff --git a/editor/libeditor/html/nsHTMLEditRules.h b/editor/libeditor/html/nsHTMLEditRules.h index 043288a77e3..6c038fd5654 100644 --- a/editor/libeditor/html/nsHTMLEditRules.h +++ b/editor/libeditor/html/nsHTMLEditRules.h @@ -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); diff --git a/editor/libeditor/html/nsHTMLEditor.cpp b/editor/libeditor/html/nsHTMLEditor.cpp index 99a218674f6..00321c92e50 100644 --- a/editor/libeditor/html/nsHTMLEditor.cpp +++ b/editor/libeditor/html/nsHTMLEditor.cpp @@ -4676,8 +4676,11 @@ nsHTMLEditor::InsertAsPlaintextQuotation(const nsString& aQuotedText, // Do this after the insertion, so that nsCOMPtr 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); } diff --git a/editor/libeditor/text/nsTextEditRules.cpp b/editor/libeditor/text/nsTextEditRules.cpp index ef498132002..b27d44149a3 100644 --- a/editor/libeditor/text/nsTextEditRules.cpp +++ b/editor/libeditor/text/nsTextEditRules.cpp @@ -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 outLeftNode; + nsCOMPtr 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 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 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, nsCOMPtrnodeAsText; + 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
, or
, 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 iter; + nsCOMPtr 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 node; + nsCOMPtr 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; + nsCOMPtrnodeAsText; + 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; +} diff --git a/editor/libeditor/text/nsTextEditRules.h b/editor/libeditor/text/nsTextEditRules.h index b7d0821f1d1..d319b89bb21 100644 --- a/editor/libeditor/text/nsTextEditRules.h +++ b/editor/libeditor/text/nsTextEditRules.h @@ -160,6 +160,10 @@ protected: nsresult CreateMozBR(nsIDOMNode *inParent, PRInt32 inOffset, nsCOMPtr *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