зеркало из https://github.com/mozilla/pjs.git
Bug 23394 Quote just the selected portion of a message during Reply. p=Jeff Beckley <beckley@qualcomm.com>,r=smontagu,sr=dmose
This commit is contained in:
Родитель
533ffa92cb
Коммит
d3d18d81e2
|
@ -74,7 +74,7 @@ interface nsIMsgCompFormat {
|
|||
};
|
||||
|
||||
|
||||
[scriptable, uuid(f59cf090-98d4-43fa-bc53-db4922c8370e)]
|
||||
[scriptable, uuid(930895f2-d610-43f4-9e3c-25e1d1fe4143)]
|
||||
interface nsIMsgComposeParams : nsISupports {
|
||||
attribute MSG_ComposeType type;
|
||||
attribute MSG_ComposeFormat format;
|
||||
|
@ -87,4 +87,11 @@ interface nsIMsgComposeParams : nsISupports {
|
|||
attribute nsIMsgSendListener sendListener;
|
||||
attribute string smtpPassword;
|
||||
attribute nsIMsgDBHdr origMsgHdr;
|
||||
|
||||
/**
|
||||
* HTML-formatted content to quote in the body of the message.
|
||||
* Set this to get different content than what would normally
|
||||
* appear in the body, e.g. the original message body in a reply.
|
||||
*/
|
||||
attribute AUTF8String htmlToQuote;
|
||||
};
|
||||
|
|
|
@ -59,6 +59,7 @@ REQUIRES = xpcom \
|
|||
mime \
|
||||
pref \
|
||||
intl \
|
||||
lwbrk \
|
||||
uconv \
|
||||
locale \
|
||||
unicharutil \
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
* Pierre Phaneuf <pp@ludusdesign.com>
|
||||
* Masayuki Nakano <masayuki@d-toybox.com>
|
||||
* Olivier Parniere BT Global Services / Etat francais Ministere de la Defense
|
||||
* Jeff Beckley <beckley@qualcomm.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either of the GNU General Public License Version 2 or later (the "GPL"),
|
||||
|
@ -111,6 +112,7 @@
|
|||
#include "nsIMsgProgress.h"
|
||||
#include "nsMsgFolderFlags.h"
|
||||
#include "nsIMsgDatabase.h"
|
||||
#include "nsStringStream.h"
|
||||
#include "nsIMutableArray.h"
|
||||
#include "nsArrayUtils.h"
|
||||
|
||||
|
@ -850,6 +852,8 @@ nsMsgCompose::Initialize(nsIDOMWindowInternal *aWindow, nsIMsgComposeParams *par
|
|||
params->GetSmtpPassword(getter_Copies(smtpPassword));
|
||||
mSmtpPassword = smtpPassword;
|
||||
|
||||
params->GetHtmlToQuote(mHtmlToQuote);
|
||||
|
||||
if (aWindow)
|
||||
{
|
||||
// register the compose object with the compose service
|
||||
|
@ -2087,7 +2091,8 @@ QuotingOutputStreamListener::QuotingOutputStreamListener(const char * originalMs
|
|||
nsIMsgIdentity *identity,
|
||||
const char *charset,
|
||||
PRBool charetOverride,
|
||||
PRBool quoteOriginal)
|
||||
PRBool quoteOriginal,
|
||||
const nsACString& htmlToQuote)
|
||||
{
|
||||
nsresult rv;
|
||||
mQuoteHeaders = quoteHeaders;
|
||||
|
@ -2096,8 +2101,9 @@ QuotingOutputStreamListener::QuotingOutputStreamListener(const char * originalMs
|
|||
mUnicodeBufferCharacterLength = 0;
|
||||
mUnicodeConversionBuffer = nsnull;
|
||||
mQuoteOriginal = quoteOriginal;
|
||||
mHtmlToQuote = htmlToQuote;
|
||||
|
||||
if (! mHeadersOnly)
|
||||
if (!mHeadersOnly || !mHtmlToQuote.IsEmpty())
|
||||
{
|
||||
nsString replyHeaderOriginalmessage;
|
||||
// For the built message body...
|
||||
|
@ -2318,11 +2324,24 @@ NS_IMETHODIMP QuotingOutputStreamListener::OnStartRequest(nsIRequest *request, n
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP QuotingOutputStreamListener::OnStopRequest(nsIRequest *request, nsISupports * /* ctxt */, nsresult status)
|
||||
NS_IMETHODIMP QuotingOutputStreamListener::OnStopRequest(nsIRequest *request, nsISupports *ctxt, nsresult status)
|
||||
{
|
||||
nsresult rv = NS_OK;
|
||||
nsAutoString aCharset;
|
||||
|
||||
if (!mHtmlToQuote.IsEmpty())
|
||||
{
|
||||
// If we had a selection in the original message to quote, we can add
|
||||
// it now that we are done ignoring the original body of the message
|
||||
nsCOMPtr<nsIInputStream> stream;
|
||||
rv = NS_NewCStringInputStream(getter_AddRefs(stream), mHtmlToQuote);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
mHeadersOnly = PR_FALSE;
|
||||
rv = OnDataAvailable(request, ctxt, stream, 0, mHtmlToQuote.Length());
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIMsgCompose> compose = do_QueryReferent(mWeakComposeObj);
|
||||
if (compose)
|
||||
{
|
||||
|
@ -2833,8 +2852,9 @@ nsMsgCompose::QuoteMessage(const char *msgURI)
|
|||
|
||||
// Create the consumer output stream.. this will receive all the HTML from libmime
|
||||
mQuoteStreamListener =
|
||||
new QuotingOutputStreamListener(msgURI, msgHdr, PR_FALSE, PR_FALSE, m_identity,
|
||||
m_compFields->GetCharacterSet(), mCharsetOverride, PR_FALSE);
|
||||
new QuotingOutputStreamListener(msgURI, msgHdr, PR_FALSE, !mHtmlToQuote.IsEmpty(), m_identity,
|
||||
m_compFields->GetCharacterSet(), mCharsetOverride, PR_FALSE,
|
||||
mHtmlToQuote);
|
||||
|
||||
if (!mQuoteStreamListener)
|
||||
{
|
||||
|
@ -2876,8 +2896,9 @@ nsMsgCompose::QuoteOriginalMessage(const char *originalMsgURI, PRInt32 what) //
|
|||
|
||||
// Create the consumer output stream.. this will receive all the HTML from libmime
|
||||
mQuoteStreamListener =
|
||||
new QuotingOutputStreamListener(originalMsgURI, originalMsgHdr, what != 1, !bAutoQuote, m_identity,
|
||||
mQuoteCharset.get(), mCharsetOverride, PR_TRUE);
|
||||
new QuotingOutputStreamListener(originalMsgURI, originalMsgHdr, what != 1,
|
||||
!bAutoQuote || !mHtmlToQuote.IsEmpty(), m_identity,
|
||||
mQuoteCharset.get(), mCharsetOverride, PR_TRUE, mHtmlToQuote);
|
||||
|
||||
if (!mQuoteStreamListener)
|
||||
{
|
||||
|
|
|
@ -160,6 +160,7 @@ private:
|
|||
nsCOMPtr <nsIMsgDBHdr> mOrigMsgHdr;
|
||||
|
||||
nsCString mSmtpPassword;
|
||||
nsCString mHtmlToQuote;
|
||||
|
||||
nsTObserverArray<nsCOMPtr<nsIMsgComposeStateListener> > mStateListeners;
|
||||
nsTObserverArray<nsCOMPtr<nsIMsgSendListener> > mExternalSendListeners;
|
||||
|
@ -184,7 +185,8 @@ public:
|
|||
nsIMsgIdentity *identity,
|
||||
const char *charset,
|
||||
PRBool charetOverride,
|
||||
PRBool quoteOriginal);
|
||||
PRBool quoteOriginal,
|
||||
const nsACString& htmlToQuote);
|
||||
virtual ~QuotingOutputStreamListener(void);
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
|
@ -211,6 +213,7 @@ private:
|
|||
PRInt32 mUnicodeBufferCharacterLength;
|
||||
PRUnichar* mUnicodeConversionBuffer;
|
||||
PRBool mQuoteOriginal;
|
||||
nsCString mHtmlToQuote;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -121,6 +121,18 @@ NS_IMETHODIMP nsMsgComposeParams::GetOrigMsgHdr(nsIMsgDBHdr * *aMsgHdr)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
/* attribute ACString htmlToQuote; */
|
||||
NS_IMETHODIMP nsMsgComposeParams::GetHtmlToQuote(nsACString& aHtmlToQuote)
|
||||
{
|
||||
aHtmlToQuote = mHtmlToQuote;
|
||||
return NS_OK;
|
||||
}
|
||||
NS_IMETHODIMP nsMsgComposeParams::SetHtmlToQuote(const nsACString& aHtmlToQuote)
|
||||
{
|
||||
mHtmlToQuote = aHtmlToQuote;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* attribute nsIMsgCompFields composeFields; */
|
||||
NS_IMETHODIMP nsMsgComposeParams::GetComposeFields(nsIMsgCompFields * *aComposeFields)
|
||||
{
|
||||
|
|
|
@ -57,4 +57,5 @@ public:
|
|||
nsCOMPtr<nsIMsgSendListener> mSendListener;
|
||||
nsCString mSMTPPassword;
|
||||
nsCOMPtr<nsIMsgDBHdr> mOrigMsgHdr;
|
||||
nsCString mHtmlToQuote;
|
||||
};
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
* Jean-Francois Ducarroz <ducarroz@netscape.com>
|
||||
* Pierre Phaneuf <pp@ludusdesign.com>
|
||||
* Seth Spitzer <sspitzer@netscape.com>
|
||||
* Jeff Beckley <beckley@qualcomm.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either of the GNU General Public License Version 2 or later (the "GPL"),
|
||||
|
@ -62,6 +63,7 @@
|
|||
#include "nsIDocShell.h"
|
||||
#include "nsPIDOMWindow.h"
|
||||
#include "nsIDOMDocument.h"
|
||||
#include "nsIDOMHTMLDocument.h"
|
||||
#include "nsIDOMElement.h"
|
||||
#include "nsIXULWindow.h"
|
||||
#include "nsIWindowMediator.h"
|
||||
|
@ -81,6 +83,12 @@
|
|||
#include "nsIMsgMailNewsUrl.h"
|
||||
#include "nsIInterfaceRequestorUtils.h"
|
||||
#include "nsIMsgDatabase.h"
|
||||
#include "nsIDocumentEncoder.h"
|
||||
#include "nsContentCID.h"
|
||||
#include "nsISelection.h"
|
||||
#include "nsUTF8Utils.h"
|
||||
#include "nsILineBreaker.h"
|
||||
#include "nsLWBrkCIID.h"
|
||||
|
||||
#ifdef MSGCOMP_TRACE_PERFORMANCE
|
||||
#include "prlog.h"
|
||||
|
@ -115,6 +123,10 @@ static PRBool _just_to_be_sure_we_create_only_one_compose_service_ = PR_FALSE;
|
|||
|
||||
#define PREF_MAIL_COMPOSE_MAXRECYCLEDWINDOWS "mail.compose.max_recycled_windows"
|
||||
|
||||
#define PREF_MAILNEWS_REPLY_QUOTING_SELECTION "mailnews.reply_quoting_selection"
|
||||
#define PREF_MAILNEWS_REPLY_QUOTING_SELECTION_MULTI_WORD "mailnews.reply_quoting_selection.multi_word"
|
||||
#define PREF_MAILNEWS_REPLY_QUOTING_SELECTION_ONLY_IF "mailnews.reply_quoting_selection.only_if_chars"
|
||||
|
||||
#define MAIL_ROOT_PREF "mail."
|
||||
#define MAILNEWS_ROOT_PREF "mailnews."
|
||||
#define HTMLDOMAINUPDATE_VERSION_PREF_NAME "global_html_domains.version"
|
||||
|
@ -413,6 +425,114 @@ nsMsgComposeService::DetermineComposeHTML(nsIMsgIdentity *aIdentity, MSG_Compose
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsMsgComposeService::GetOrigWindowSelection(MSG_ComposeType type, nsIMsgWindow *aMsgWindow, nsACString& aSelHTML)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
// Good hygiene
|
||||
aSelHTML.Truncate();
|
||||
|
||||
// Get the pref to see if we even should do reply quoting selection
|
||||
nsCOMPtr<nsIPrefBranch> prefs(do_GetService(NS_PREFSERVICE_CONTRACTID, &rv));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
PRBool replyQuotingSelection;
|
||||
rv = prefs->GetBoolPref(PREF_MAILNEWS_REPLY_QUOTING_SELECTION, &replyQuotingSelection);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (!replyQuotingSelection)
|
||||
return NS_ERROR_ABORT;
|
||||
|
||||
// Now delve down in to the message to get the HTML representation of the selection
|
||||
nsCOMPtr<nsIDocShell> rootDocShell;
|
||||
rv = aMsgWindow->GetRootDocShell(getter_AddRefs(rootDocShell));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIDocShellTreeNode> rootDocShellAsNode(do_QueryInterface(rootDocShell, &rv));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIDocShellTreeItem> childAsItem;
|
||||
rv = rootDocShellAsNode->FindChildWithName(NS_LITERAL_STRING("messagepane").get(),
|
||||
PR_TRUE, PR_FALSE, nsnull, nsnull, getter_AddRefs(childAsItem));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIDocShell> docShell(do_QueryInterface(childAsItem, &rv));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIDOMWindow> domWindow(do_GetInterface(childAsItem, &rv));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
nsCOMPtr<nsISelection> sel;
|
||||
rv = domWindow->GetSelection(getter_AddRefs(sel));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
PRBool requireMultipleWords = PR_TRUE;
|
||||
nsCAutoString charsOnlyIf;
|
||||
prefs->GetBoolPref(PREF_MAILNEWS_REPLY_QUOTING_SELECTION_MULTI_WORD, &requireMultipleWords);
|
||||
prefs->GetCharPref(PREF_MAILNEWS_REPLY_QUOTING_SELECTION_ONLY_IF, getter_Copies(charsOnlyIf));
|
||||
if (requireMultipleWords || !charsOnlyIf.IsEmpty())
|
||||
{
|
||||
nsAutoString selPlain;
|
||||
rv = sel->ToString(getter_Copies(selPlain));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// If "mailnews.reply_quoting_selection.multi_word" is on, then there must be at least
|
||||
// two words selected in order to quote just the selected text
|
||||
if (requireMultipleWords)
|
||||
{
|
||||
nsCOMPtr<nsILineBreaker> lineBreaker = do_GetService(NS_LBRK_CONTRACTID, &rv);
|
||||
|
||||
if (NS_SUCCEEDED(rv))
|
||||
{
|
||||
const nsPromiseFlatString& tString = PromiseFlatString(selPlain);
|
||||
const PRUint32 length = tString.Length();
|
||||
const PRUnichar* unicodeStr = tString.get();
|
||||
PRInt32 endWordPos = lineBreaker->Next(unicodeStr, length, 0);
|
||||
|
||||
// If there's not even one word, then there's not multiple words
|
||||
if (endWordPos == NS_LINEBREAKER_NEED_MORE_TEXT)
|
||||
return NS_ERROR_ABORT;
|
||||
|
||||
// If after the first word is only space, then there's not multiple words
|
||||
const PRUnichar* end;
|
||||
for (end = unicodeStr + endWordPos; NS_IsSpace(*end); end++)
|
||||
;
|
||||
if (!*end)
|
||||
return NS_ERROR_ABORT;
|
||||
}
|
||||
}
|
||||
|
||||
if (!charsOnlyIf.IsEmpty())
|
||||
{
|
||||
if (selPlain.FindCharInSet(NS_ConvertUTF8toUTF16(charsOnlyIf)) < 0)
|
||||
return NS_ERROR_ABORT;
|
||||
}
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIContentViewer> contentViewer;
|
||||
rv = docShell->GetContentViewer(getter_AddRefs(contentViewer));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIDOMDocument> domDocument;
|
||||
rv = contentViewer->GetDOMDocument(getter_AddRefs(domDocument));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIDocumentEncoder> docEncoder(do_CreateInstance(NS_HTMLCOPY_ENCODER_CONTRACTID, &rv));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = docEncoder->Init(domDocument, NS_LITERAL_STRING("text/html"), 0);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = docEncoder->SetSelection(sel);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsAutoString selHTML;
|
||||
rv = docEncoder->EncodeToString(selHTML);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
aSelHTML = NS_ConvertUTF16toUTF8(selHTML);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMsgComposeService::OpenComposeWindow(const char *msgComposeWindowURL, const char *originalMsgURI,
|
||||
MSG_ComposeType type, MSG_ComposeFormat format, nsIMsgIdentity * aIdentity, nsIMsgWindow *aMsgWindow)
|
||||
|
@ -448,6 +568,19 @@ nsMsgComposeService::OpenComposeWindow(const char *msgComposeWindowURL, const ch
|
|||
pMsgComposeParams->SetFormat(format);
|
||||
pMsgComposeParams->SetIdentity(identity);
|
||||
|
||||
// When doing a reply (except with a template) see if there's a selection that we should quote
|
||||
if (type == nsIMsgCompType::Reply ||
|
||||
type == nsIMsgCompType::ReplyAll ||
|
||||
type == nsIMsgCompType::ReplyToSender ||
|
||||
type == nsIMsgCompType::ReplyToGroup ||
|
||||
type == nsIMsgCompType::ReplyToSenderAndGroup ||
|
||||
type == nsIMsgCompType::ReplyToList)
|
||||
{
|
||||
nsCAutoString selHTML;
|
||||
if (NS_SUCCEEDED(GetOrigWindowSelection(type, aMsgWindow, selHTML)))
|
||||
pMsgComposeParams->SetHtmlToQuote(selHTML);
|
||||
}
|
||||
|
||||
if (originalMsgURI && *originalMsgURI)
|
||||
{
|
||||
if (type == nsIMsgCompType::NewsPost)
|
||||
|
|
|
@ -109,6 +109,10 @@ private:
|
|||
// hash table mapping dom windows to nsIMsgCompose objects
|
||||
nsInterfaceHashtable<nsISupportsHashKey, nsIWeakReference> mOpenComposeWindows;
|
||||
|
||||
// When doing a reply and the settings are enabled, get the HTML of the selected text
|
||||
// in the original message window so that it can be quoted instead of the entire message.
|
||||
nsresult GetOrigWindowSelection(MSG_ComposeType type, nsIMsgWindow *aMsgWindow, nsACString& aSelHTML);
|
||||
|
||||
#ifdef MSGCOMP_TRACE_PERFORMANCE
|
||||
PRIntervalTime mStartTime;
|
||||
PRIntervalTime mPreviousTime;
|
||||
|
|
|
@ -279,6 +279,10 @@ pref("mailnews.reply_header_originalmessage", "chrome://messenger/locale/messe
|
|||
|
||||
pref("mailnews.reply_to_self_check_all_ident", false);
|
||||
|
||||
pref("mailnews.reply_quoting_selection", true);
|
||||
pref("mailnews.reply_quoting_selection.only_if_chars", "");
|
||||
pref("mailnews.reply_quoting_selection.multi_word", true);
|
||||
|
||||
pref("mail.purge_threshhold", 100);
|
||||
pref("mail.prompt_purge_threshhold", false);
|
||||
pref("mail.purge.ask", true);
|
||||
|
|
Загрузка…
Ссылка в новой задаче