From 6118727dffad0f750c68606bb8f3071018466d10 Mon Sep 17 00:00:00 2001 From: "jfrancis%netscape.com" Date: Wed, 12 Jun 2002 14:12:32 +0000 Subject: [PATCH] bug 83378: plaintext mail reply editong problem in quotes --- editor/libeditor/html/nsHTMLEditRules.cpp | 155 ++++++++++++++------ editor/libeditor/html/nsHTMLEditRules.h | 1 + editor/libeditor/text/nsPlaintextEditor.cpp | 3 +- 3 files changed, 111 insertions(+), 48 deletions(-) diff --git a/editor/libeditor/html/nsHTMLEditRules.cpp b/editor/libeditor/html/nsHTMLEditRules.cpp index 13f2a370f00e..b1ba9c9741d4 100644 --- a/editor/libeditor/html/nsHTMLEditRules.cpp +++ b/editor/libeditor/html/nsHTMLEditRules.cpp @@ -1424,8 +1424,7 @@ nsresult nsHTMLEditRules::WillInsertBreak(nsISelection *aSelection, PRBool *aCancel, PRBool *aHandled) { if (!aSelection || !aCancel || !aHandled) { return NS_ERROR_NULL_POINTER; } - nsCOMPtr selection(aSelection); - nsCOMPtr selPriv(do_QueryInterface(selection)); + nsCOMPtr selPriv(do_QueryInterface(aSelection)); // initialize out param *aCancel = PR_FALSE; *aHandled = PR_FALSE; @@ -1453,51 +1452,9 @@ nsHTMLEditRules::WillInsertBreak(nsISelection *aSelection, PRBool *aCancel, PRBo // should we abort this if we encounter table cell boundaries? if (mFlags & nsIPlaintextEditor::eEditorMailMask) { - nsCOMPtr citeNode, selNode, leftCite, rightCite; - PRInt32 selOffset, newOffset; - res = mHTMLEditor->GetStartNodeAndOffset(aSelection, address_of(selNode), &selOffset); + res = SplitMailCites(aSelection, bPlaintext, aHandled); if (NS_FAILED(res)) return res; - res = GetTopEnclosingMailCite(selNode, address_of(citeNode), bPlaintext); - if (NS_FAILED(res)) return res; - if (citeNode) - { - nsCOMPtr brNode; - res = mHTMLEditor->SplitNodeDeep(citeNode, selNode, selOffset, &newOffset, - PR_TRUE, address_of(leftCite), address_of(rightCite)); - if (NS_FAILED(res)) return res; - res = citeNode->GetParentNode(getter_AddRefs(selNode)); - if (NS_FAILED(res)) return res; - res = mHTMLEditor->CreateBR(selNode, newOffset, address_of(brNode)); - if (NS_FAILED(res)) return res; - // want selection before the break, and on same line - selPriv->SetInterlinePosition(PR_TRUE); - res = aSelection->Collapse(selNode, newOffset); - if (NS_FAILED(res)) return res; - // if citeNode wasn't a block, we also want another break before it - if (IsInlineNode(citeNode)) - { - res = mHTMLEditor->CreateBR(selNode, newOffset, address_of(brNode)); - if (NS_FAILED(res)) return res; - } - // delete any empty cites - PRBool bEmptyCite = PR_FALSE; - if (leftCite) - { - res = mHTMLEditor->IsEmptyNode(leftCite, &bEmptyCite, PR_TRUE, PR_FALSE); - if (NS_SUCCEEDED(res) && bEmptyCite) - res = mHTMLEditor->DeleteNode(leftCite); - if (NS_FAILED(res)) return res; - } - if (rightCite) - { - res = mHTMLEditor->IsEmptyNode(rightCite, &bEmptyCite, PR_TRUE, PR_FALSE); - if (NS_SUCCEEDED(res) && bEmptyCite) - res = mHTMLEditor->DeleteNode(rightCite); - if (NS_FAILED(res)) return res; - } - *aHandled = PR_TRUE; - return NS_OK; - } + if (*aHandled) return NS_OK; } // smart splitting rules @@ -1586,6 +1543,110 @@ nsHTMLEditRules::DidInsertBreak(nsISelection *aSelection, nsresult aResult) } +nsresult +nsHTMLEditRules::SplitMailCites(nsISelection *aSelection, PRBool aPlaintext, PRBool *aHandled) +{ + if (!aSelection || !aHandled) + return NS_ERROR_NULL_POINTER; + nsCOMPtr selPriv(do_QueryInterface(aSelection)); + nsCOMPtr citeNode, selNode, leftCite, rightCite; + PRInt32 selOffset, newOffset; + nsresult res = mHTMLEditor->GetStartNodeAndOffset(aSelection, address_of(selNode), &selOffset); + if (NS_FAILED(res)) return res; + res = GetTopEnclosingMailCite(selNode, address_of(citeNode), aPlaintext); + if (NS_FAILED(res)) return res; + if (citeNode) + { + if (IsInlineNode(citeNode)) + { + // this is getting messy. If our selection is just before a break, nudge it to be + // just after it. This does two things for us. It saves us the trouble of having to add + // a break here ourselves to preserve the "blockness" of the inline span mailquote, and + // it means the break wont end up making an empty line that happens to be inside a + // mailquote. The latter can confuse a user if they click there and start typing, + // because being in the mailquote may affect wrapping behavior, or font color, etc. + nsWSRunObject wsObj(mHTMLEditor, selNode, newOffset); + nsCOMPtr visNode; + PRInt32 visOffset=0; + PRInt16 wsType; + res = wsObj.NextVisibleNode(selNode, selOffset, address_of(visNode), &visOffset, &wsType); + if (NS_FAILED(res)) return res; + if (wsType==nsWSRunObject::eBreak) + { + // ok, we are just before a break. is it inside the mailquote? + PRInt32 unused; + if (nsHTMLEditUtils::IsDescendantOf(visNode, citeNode, &unused)) + { + // it is. so lets reset our selection to be just after it. + res = mHTMLEditor->GetNodeLocation(visNode, address_of(selNode), &selOffset); + if (NS_FAILED(res)) return res; + ++selOffset; + } + } + } + + nsCOMPtr brNode; + res = mHTMLEditor->SplitNodeDeep(citeNode, selNode, selOffset, &newOffset, + PR_TRUE, address_of(leftCite), address_of(rightCite)); + if (NS_FAILED(res)) return res; + res = citeNode->GetParentNode(getter_AddRefs(selNode)); + if (NS_FAILED(res)) return res; + res = mHTMLEditor->CreateBR(selNode, newOffset, address_of(brNode)); + if (NS_FAILED(res)) return res; + // want selection before the break, and on same line + selPriv->SetInterlinePosition(PR_TRUE); + res = aSelection->Collapse(selNode, newOffset); + if (NS_FAILED(res)) return res; + // if citeNode wasn't a block, we might also want another break before it. + // We need to examine the content both before the br we just added and also + // just after it. If we dont have another br or block boundary adjacent, + // then we will ned a 2nd br added to achieve blank line that user expects. + if (IsInlineNode(citeNode)) + { + nsWSRunObject wsObj(mHTMLEditor, selNode, newOffset); + nsCOMPtr visNode; + PRInt32 visOffset=0; + PRInt16 wsType; + res = wsObj.PriorVisibleNode(selNode, newOffset, address_of(visNode), &visOffset, &wsType); + if (NS_FAILED(res)) return res; + if ((wsType==nsWSRunObject::eNormalWS) || + (wsType==nsWSRunObject::eText) || + (wsType==nsWSRunObject::eSpecial)) + { + nsWSRunObject wsObjAfterBR(mHTMLEditor, selNode, newOffset+1); + res = wsObj.NextVisibleNode(selNode, newOffset, address_of(visNode), &visOffset, &wsType); + if (NS_FAILED(res)) return res; + if ((wsType==nsWSRunObject::eNormalWS) || + (wsType==nsWSRunObject::eText) || + (wsType==nsWSRunObject::eSpecial)) + { + res = mHTMLEditor->CreateBR(selNode, newOffset, address_of(brNode)); + if (NS_FAILED(res)) return res; + } + } + } + // delete any empty cites + PRBool bEmptyCite = PR_FALSE; + if (leftCite) + { + res = mHTMLEditor->IsEmptyNode(leftCite, &bEmptyCite, PR_TRUE, PR_FALSE); + if (NS_SUCCEEDED(res) && bEmptyCite) + res = mHTMLEditor->DeleteNode(leftCite); + if (NS_FAILED(res)) return res; + } + if (rightCite) + { + res = mHTMLEditor->IsEmptyNode(rightCite, &bEmptyCite, PR_TRUE, PR_FALSE); + if (NS_SUCCEEDED(res) && bEmptyCite) + res = mHTMLEditor->DeleteNode(rightCite); + if (NS_FAILED(res)) return res; + } + *aHandled = PR_TRUE; + } + return NS_OK; +} + + nsresult nsHTMLEditRules::WillDeleteSelection(nsISelection *aSelection, nsIEditor::EDirection aAction, @@ -2837,7 +2898,7 @@ nsHTMLEditRules::WillMakeList(nsISelection *aSelection, continue; } - // need to make a list to put things in if we haven't already + // need to make a list to put things in if we haven't already, if (!curList) { res = SplitAsNeeded(aListType, address_of(curParent), &offset); diff --git a/editor/libeditor/html/nsHTMLEditRules.h b/editor/libeditor/html/nsHTMLEditRules.h index 4581a7da457f..710c555d178c 100644 --- a/editor/libeditor/html/nsHTMLEditRules.h +++ b/editor/libeditor/html/nsHTMLEditRules.h @@ -130,6 +130,7 @@ protected: nsresult WillLoadHTML(nsISelection *aSelection, PRBool *aCancel); nsresult WillInsertBreak(nsISelection *aSelection, PRBool *aCancel, PRBool *aHandled); nsresult DidInsertBreak(nsISelection *aSelection, nsresult aResult); + nsresult SplitMailCites(nsISelection *aSelection, PRBool aPlaintext, PRBool *aHandled); nsresult WillDeleteSelection(nsISelection *aSelection, nsIEditor::EDirection aAction, PRBool *aCancel, PRBool *aHandled); nsresult JoinBlocks(nsISelection *aSelection, nsCOMPtr *aLeftBlock, diff --git a/editor/libeditor/text/nsPlaintextEditor.cpp b/editor/libeditor/text/nsPlaintextEditor.cpp index 82f160130970..7cc1c64aa5a9 100644 --- a/editor/libeditor/text/nsPlaintextEditor.cpp +++ b/editor/libeditor/text/nsPlaintextEditor.cpp @@ -1685,7 +1685,8 @@ nsPlaintextEditor::InsertAsQuotation(const nsAString& aQuotedText, // It's best to put a blank line after the quoted text so that mails // written without thinking won't be so ugly. - quotedStuff.Append(PRUnichar('\n')); + if (!aQuotedText.IsEmpty() && (aQuotedText.Last() != PRUnichar('\n'))) + quotedStuff.Append(PRUnichar('\n')); nsCOMPtr preNode; // get selection