Bug 228562: shift+forward should toggle html/plain text. r+sr=bienvenu
authorMagnus Melin <mkmelin@iki.fi>
Wed, 13 May 2009 19:13:36 +0300
changeset 2622 1e7142a15a270dc1b1dcc2d7ca2647ac49ebef40
parent 2621 fa041768f27df51738699795570b40e6074377a0
child 2623 dd5b6a6114c0aa1eca1dbc122509add409b48a0c
push idunknown
push userunknown
push dateunknown
bugs228562
Bug 228562: shift+forward should toggle html/plain text. r+sr=bienvenu
mail/locales/en-US/chrome/messenger/mime.properties
mailnews/compose/src/nsMsgComposeService.cpp
mailnews/compose/src/nsMsgComposeService.h
mailnews/mime/public/nsIMimeStreamConverter.idl
mailnews/mime/src/mimedrft.cpp
mailnews/mime/src/mimemoz2.h
mailnews/mime/src/nsStreamConverter.cpp
mailnews/mime/src/nsStreamConverter.h
suite/locales/en-US/chrome/mailnews/mime.properties
--- a/mail/locales/en-US/chrome/messenger/mime.properties
+++ b/mail/locales/en-US/chrome/messenger/mime.properties
@@ -174,17 +174,17 @@ 1039=">here</A> to download the rest of 
 # default attachment name
 ## @name MIME_MSG_DEFAULT_ATTACHMENT_NAME
 ## @loc 
 # LOCALIZATION NOTE (1040): Do not translate "%s" below.
 # Place the %s where you wish the part number of the attachment to appear
 1040=Part %s
 
 # default forwarded message prefix
-## @name MIME_FORWARDED_MESSAGE_USER_WROTE
+## @name MIME_FORWARDED_MESSAGE_HTML_USER_WROTE
 ## @loc 
 1041=-------- Original Message --------
 
 # Partial Message Format2 1
 ## @name MIME_MSG_PARTIAL_FMT2_1
 ## @loc
 # LOCALIZATION NOTE (1042): In the following line, translate only the words, "Not Downloaded".
 1042=<P><CENTER><TABLE BORDER CELLSPACING=5 CELLPADDING=10 WIDTH="80%%"><TR><TD ALIGN=CENTER><FONT SIZE="+1"><B>Not Downloaded</B></FONT><HR>
--- a/mailnews/compose/src/nsMsgComposeService.cpp
+++ b/mailnews/compose/src/nsMsgComposeService.cpp
@@ -563,17 +563,17 @@ nsMsgComposeService::OpenComposeWindow(c
     nsCAutoString uriToOpen(originalMsgURI);
     uriToOpen += (uriToOpen.FindChar('?') == kNotFound) ? "?" : "&";
     uriToOpen.Append("fetchCompleteMessage=true");
     if (type == nsIMsgCompType::Redirect)
       uriToOpen.Append("&redirect=true");
 
     return LoadDraftOrTemplate(uriToOpen, type == nsIMsgCompType::ForwardInline || type == nsIMsgCompType::Draft ?
                                nsMimeOutput::nsMimeMessageDraftOrTemplate : nsMimeOutput::nsMimeMessageEditorTemplate,
-                               identity, originalMsgURI, origMsgHdr, type == nsIMsgCompType::ForwardInline, aMsgWindow);
+                               identity, originalMsgURI, origMsgHdr, type == nsIMsgCompType::ForwardInline, format, aMsgWindow);
   }
 
   nsCOMPtr<nsIMsgComposeParams> pMsgComposeParams (do_CreateInstance(NS_MSGCOMPOSEPARAMS_CONTRACTID, &rv));
   if (NS_SUCCEEDED(rv) && pMsgComposeParams)
   {
     nsCOMPtr<nsIMsgCompFields> pMsgCompFields (do_CreateInstance(NS_MSGCOMPFIELDS_CONTRACTID, &rv));
     if (NS_SUCCEEDED(rv) && pMsgCompFields)
     {
@@ -1512,30 +1512,33 @@ nsMsgComposeService::GetMsgComposeForWin
  * LoadDraftOrTemplate
  *   Helper routine used to run msgURI through libmime in order to fetch the contents for a
  *   draft or template.
  */
 nsresult
 nsMsgComposeService::LoadDraftOrTemplate(const nsACString& aMsgURI, nsMimeOutputType aOutType,
                                          nsIMsgIdentity * aIdentity, const char * aOriginalMsgURI,
                                          nsIMsgDBHdr * aOrigMsgHdr,
-                                         PRBool aAddInlineHeaders, nsIMsgWindow *aMsgWindow)
+                                         PRBool aAddInlineHeaders,
+                                         MSG_ComposeFormat format,
+                                         nsIMsgWindow *aMsgWindow)
 {
   nsresult rv;
   nsCOMPtr <nsIMsgMessageService> messageService;
   rv = GetMessageServiceFromURI(aMsgURI, getter_AddRefs(messageService));
   NS_ENSURE_SUCCESS(rv, rv);
 
   // Now, we can create a mime parser (nsIStreamConverter)!
   nsCOMPtr<nsIMimeStreamConverter> mimeConverter =
     do_CreateInstance(NS_MAILNEWS_MIME_STREAM_CONVERTER_CONTRACTID, &rv);
   NS_ENSURE_SUCCESS(rv, rv);
 
   mimeConverter->SetMimeOutputType(aOutType);  // Set the type of output for libmime
   mimeConverter->SetForwardInline(aAddInlineHeaders);
+  mimeConverter->SetOverrideComposeFormat(format == nsIMsgCompFormat::OppositeOfDefault);
   mimeConverter->SetIdentity(aIdentity);
   mimeConverter->SetOriginalMsgURI(aOriginalMsgURI);
   mimeConverter->SetOrigMsgHdr(aOrigMsgHdr);
 
   nsCOMPtr<nsIURI> url;
   PRBool fileUrl = StringBeginsWith(aMsgURI, NS_LITERAL_CSTRING("file:"));
   if (fileUrl || nsDependentCString(aMsgURI).Find("&type=application/x-message-display") >= 0)
     rv = NS_NewURI(getter_AddRefs(url), aMsgURI);
--- a/mailnews/compose/src/nsMsgComposeService.h
+++ b/mailnews/compose/src/nsMsgComposeService.h
@@ -96,16 +96,17 @@ private:
   PRInt32 mMaxRecycledWindows;
   nsMsgCachedWindowInfo *mCachedWindows;
   
   void CloseHiddenCachedWindow(nsIDOMWindowInternal *domWindow);
 
   nsresult LoadDraftOrTemplate(const nsACString& aMsgURI, nsMimeOutputType aOutType, 
                                nsIMsgIdentity * aIdentity, const char * aOriginalMsgURI, 
                                nsIMsgDBHdr * aOrigMsgHdr, PRBool aAddInlineHeaders,
+                               MSG_ComposeFormat format,
                                nsIMsgWindow *aMsgWindow);
 
   nsresult ShowCachedComposeWindow(nsIDOMWindowInternal *aComposeWindow, PRBool aShow);
 
   // 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
--- a/mailnews/mime/public/nsIMimeStreamConverter.idl
+++ b/mailnews/mime/public/nsIMimeStreamConverter.idl
@@ -30,22 +30,16 @@
  * use your version of this file under the terms of the MPL, indicate your
  * decision by deleting the provisions above and replace them with the notice
  * and other provisions required by the GPL or the LGPL. If you do not delete
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
-/*
-  I've created this interface to contain mailnews mime specific information
-  for stream converters. Most of this code is just stuff that has been moved out
-  of nsIStreamConverter.idl to make it more generic.
-*/
-
 #include "nsISupports.idl"
 #include "nsrootidl.idl"
 #include "nsIMimeHeaders.idl"
 #include "nsIMsgIdentity.idl"
 #include "nsIMsgHdr.idl"
 
 interface nsIURI;
 
@@ -71,42 +65,51 @@ interface nsMimeOutput
   const long nsMimeUnknown = 15;
 };
 
 [scriptable, uuid(FA81CAA0-6261-11d3-8311-00805F2A0107)]
 interface nsIMimeStreamConverterListener : nsISupports{
       void onHeadersReady(in nsIMimeHeaders headers);
 };
 
-[scriptable, uuid(9b1d157b-4223-42f5-9bec-11c1ec34d609)]
+/**
+ * This interface contains mailnews mime specific information for stream
+ * converters. Most of the code is just stuff that has been moved out
+ * of nsIStreamConverter.idl to make it more generic.
+ */
+[scriptable, uuid(ed861e40-6901-4bb0-b9ec-7a8e7a79bb0e)]
 interface nsIMimeStreamConverter : nsISupports {
 
-    /*
-   * This is used to set the desired mime output type on the converer.
-     */
-
+  /**
+   * Set the desired mime output type on the converer.
+   */
   void SetMimeOutputType(in nsMimeOutputType aType);
 
   void GetMimeOutputType(out nsMimeOutputType aOutFormat);
 
-  /*
-  * This is needed by libmime for MHTML link processing...the url is the URL string associated
-  * with this input stream
-  */
+  /**
+   * This is needed by libmime for MHTML link processing...the url is the URL
+   * string associated with this input stream.
+   */
   void SetStreamURI(in nsIURI aURI);
 
-  /*
-  * This is used to extract headers while parsing a message
-  */
+  /**
+   * Used to extract headers while parsing a message.
+   */
   void SetMimeHeadersListener(in nsIMimeStreamConverterListener listener, in nsMimeOutputType aType);
 
-  /*
-  * This is used for forward inline
-  */
+  /**
+   * This is used for forward inline.
+   */
   attribute PRBool forwardInline;
 
-  /*
-  * This is used for OpenDraft, OpenEditorTemplate and Forward inline (which use OpenDraft)
-  */
+  /**
+   * Use the opposite compose format, used for forward inline.
+   */
+  attribute PRBool overrideComposeFormat;
+
+  /**
+   * This is used for OpenDraft, OpenEditorTemplate and Forward inline (which use OpenDraft)
+   */
   attribute nsIMsgIdentity identity;
   attribute string originalMsgURI;
   attribute nsIMsgDBHdr origMsgHdr;
 };
--- a/mailnews/mime/src/mimedrft.cpp
+++ b/mailnews/mime/src/mimedrft.cpp
@@ -17,16 +17,17 @@
  *
  * The Initial Developer of the Original Code is
  * Netscape Communications Corporation.
  * Portions created by the Initial Developer are Copyright (C) 1998
  * the Initial Developer. All Rights Reserved.
  *
  * Contributor(s):
  *   Eric Ballet Baz BT Global Services / Etat francais Ministere de la Defense
+ *   Magnus Melin <mkmelin+mozilla@iki.fi>
  *
  * 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"),
  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
  * in which case the provisions of the GPL or the LGPL are applicable instead
  * of those above. If you wish to allow use of your version of this file only
  * under the terms of either the GPL or the LGPL, and not to allow others to
  * use your version of this file under the terms of the MPL, indicate your
@@ -186,17 +187,16 @@ CreateTheComposeWindow(nsIMsgCompFields 
                        MSG_ComposeType      composeType,
                        MSG_ComposeFormat    composeFormat,
                        nsIMsgIdentity *     identity,
                        const char *         originalMsgURI,
                        nsIMsgDBHdr *        origMsgHdr
                        )
 {
   nsresult            rv;
-  MSG_ComposeFormat   format = nsIMsgCompFormat::Default;
 
 #ifdef NS_DEBUG
   mime_dump_attachments ( attachmentList );
 #endif
 
   nsMsgAttachmentData *curAttachment = attachmentList;
   if (curAttachment)
   {
@@ -227,32 +227,28 @@ CreateTheComposeWindow(nsIMsgCompFields 
     }
   }
 
   nsCOMPtr<nsIMsgComposeService> msgComposeService =
            do_GetService(kCMsgComposeServiceCID, &rv);
   if ((NS_FAILED(rv)) || (!msgComposeService))
     return rv;
 
+  MSG_ComposeFormat format = composeFormat; // Format to actually use.
   if (identity && composeType == nsIMsgCompType::ForwardInline)
   {
     PRBool composeHtml = PR_FALSE;
     identity->GetComposeHtml(&composeHtml);
     if (composeHtml)
-      format = nsIMsgCompFormat::HTML;
+      format = (composeFormat == nsIMsgCompFormat::OppositeOfDefault) ?
+                 nsIMsgCompFormat::PlainText : nsIMsgCompFormat::HTML;
     else
-    {
-      format = nsIMsgCompFormat::PlainText;
-      /* do we we need to convert the HTML body to plain text? */
-      if (composeFormat == nsIMsgCompFormat::HTML)
-        compFields->ConvertBodyToPlainText();
-    }
+      format = (composeFormat == nsIMsgCompFormat::OppositeOfDefault) ?
+                 nsIMsgCompFormat::HTML : nsIMsgCompFormat::PlainText;
   }
-  else
-    format = composeFormat;
 
   nsCOMPtr<nsIMsgComposeParams> pMsgComposeParams (do_CreateInstance(NS_MSGCOMPOSEPARAMS_CONTRACTID, &rv));
   if (NS_SUCCEEDED(rv) && pMsgComposeParams)
   {
     pMsgComposeParams->SetType(composeType);
     pMsgComposeParams->SetFormat(format);
     pMsgComposeParams->SetIdentity(identity);
     pMsgComposeParams->SetComposeFields(compFields);
@@ -1438,31 +1434,32 @@ mime_parse_stream_complete (nsMIMESessio
               body = newBody;
               bodyLen = strlen(newBody);
             }
           }
           PR_FREEIF(mimeCharset);
         }
       }
 
-      // Since we have body text, then we should set the compose fields with
-      // this data.
-      //       if (composeFormat == nsIMsgCompFormat::PlainText)
-      //         fields->SetTheForcePlainText(PR_TRUE);
-
+      PRBool convertToPlainText = PR_FALSE;
       if (forward_inline)
       {
         if (mdd->identity)
         {
-          PRBool bFormat;
-          mdd->identity->GetComposeHtml(&bFormat);
-          if (bFormat)
+          PRBool identityComposeHTML;
+          mdd->identity->GetComposeHtml(&identityComposeHTML);
+          if ((identityComposeHTML && !mdd->overrideComposeFormat) ||
+              (!identityComposeHTML && mdd->overrideComposeFormat))
           {
+            // In the end, we're going to compose in HTML mode...
+
             if (body && composeFormat == nsIMsgCompFormat::PlainText)
             {
+              // ... but the message body is currently plain text.
+
               //We need to convert the plain/text to HTML in order to escape any HTML markup
               char *escapedBody = MsgEscapeHTML(body);
               if (escapedBody)
               {
                 PR_Free(body);
                 body = escapedBody;
                 bodyLen = strlen(body);
               }
@@ -1474,25 +1471,38 @@ mime_parse_stream_complete (nsMIMESessio
                 *newbody = 0;
                 PL_strcatn(newbody, newbodylen, "<PRE>");
                 PL_strcatn(newbody, newbodylen, body);
                 PL_strcatn(newbody, newbodylen, "</PRE>");
                 PR_Free(body);
                 body = newbody;
               }
             }
+            // Body is now HTML, set the format too (so headers are inserted in
+            // correct format).
             composeFormat = nsIMsgCompFormat::HTML;
           }
+          else if ((identityComposeHTML && mdd->overrideComposeFormat) || !identityComposeHTML)
+          {
+            // In the end, we're going to compose in plain text mode...
+
+            if (composeFormat == nsIMsgCompFormat::HTML)
+            {
+              // ... but the message body is currently HTML.
+              // We'll do the conversion later on when headers have been
+              // inserted, body has been set and converted to unicode.
+              convertToPlainText = PR_TRUE;
+            }
+          }
         }
 
         mime_insert_forwarded_message_headers(&body, mdd->headers, composeFormat,
           mdd->mailcharset);
+
       }
-      // setting the charset while we are creating the composition fields
-      //fields->SetCharacterSet(NS_ConvertASCIItoUTF16(mdd->mailcharset));
 
       // convert from UTF-8 to UTF-16
       if (body)
       {
         fields->SetBody(NS_ConvertUTF8toUTF16(body));
         PR_Free(body);
       }
 
@@ -1510,17 +1520,23 @@ mime_parse_stream_complete (nsMIMESessio
                                          nsIMsgCompType::Template;
         CreateTheComposeWindow(fields, newAttachData, msgComposeType,
                                composeFormat, mdd->identity,
                                mdd->originalMsgURI, mdd->origMsgHdr);
       }
       else
       {
         if (mdd->forwardInline)
+        {
+          if (convertToPlainText)
+            fields->ConvertBodyToPlainText();
+          if (mdd->overrideComposeFormat)
+            composeFormat = nsIMsgCompFormat::OppositeOfDefault;
           CreateTheComposeWindow(fields, newAttachData, nsIMsgCompType::ForwardInline, composeFormat, mdd->identity, mdd->originalMsgURI, mdd->origMsgHdr);
+        }
         else
         {
           fields->SetDraftId(mdd->url_name);
           CreateTheComposeWindow(fields, newAttachData, nsIMsgCompType::Draft, composeFormat, mdd->identity, mdd->originalMsgURI, mdd->origMsgHdr);
         }
       }
     }
     else
@@ -1537,17 +1553,24 @@ mime_parse_stream_complete (nsMIMESessio
         CreateTheComposeWindow(fields, newAttachData, nsIMsgCompType::Template, nsIMsgCompFormat::Default, mdd->identity, nsnull, mdd->origMsgHdr);
       }
       else
       {
 #ifdef NS_DEBUG
         printf("Time to create the composition window WITHOUT a body!!!!\n");
 #endif
         if (mdd->forwardInline)
-          CreateTheComposeWindow(fields, newAttachData, nsIMsgCompType::ForwardInline, nsIMsgCompFormat::Default, mdd->identity, mdd->originalMsgURI, mdd->origMsgHdr);
+        {
+          MSG_ComposeFormat composeFormat = (mdd->overrideComposeFormat) ?
+            nsIMsgCompFormat::OppositeOfDefault : nsIMsgCompFormat::Default;
+          CreateTheComposeWindow(fields, newAttachData,
+                                 nsIMsgCompType::ForwardInline, composeFormat,
+                                 mdd->identity, mdd->originalMsgURI,
+                                 mdd->origMsgHdr);
+        }
         else
         {
           fields->SetDraftId(mdd->url_name);
           CreateTheComposeWindow(fields, newAttachData, nsIMsgCompType::Draft, nsIMsgCompFormat::Default, mdd->identity, nsnull, mdd->origMsgHdr);
         }
       }
     }
   }
@@ -2013,16 +2036,17 @@ mime_bridge_create_draft_stream(
       urlString.Cut(typeIndex, sizeof("&type=application/x-message-display") - 1);
 
     mdd->url_name = ToNewCString(urlString);
     if (!(mdd->url_name))
       goto FAIL;
   }
 
   newPluginObj2->GetForwardInline(&mdd->forwardInline);
+  newPluginObj2->GetOverrideComposeFormat(&mdd->overrideComposeFormat);
   newPluginObj2->GetIdentity(getter_AddRefs(mdd->identity));
   newPluginObj2->GetOriginalMsgURI(&mdd->originalMsgURI);
   newPluginObj2->GetOrigMsgHdr(getter_AddRefs(mdd->origMsgHdr));
   mdd->format_out = format_out;
   mdd->options = new  MimeDisplayOptions ;
   if (!mdd->options)
     goto FAIL;
 
--- a/mailnews/mime/src/mimemoz2.h
+++ b/mailnews/mime/src/mimemoz2.h
@@ -151,16 +151,17 @@ struct mime_draft_data
   nsMsgAttachedFile   *curAttachment;       // temp
 
   nsCOMPtr <nsILocalFile> tmpFile;
   nsCOMPtr <nsIOutputStream> tmpFileStream;      // output file handle
 
   MimeDecoderData     *decoder_data;
   char                *mailcharset;        // get it from CHARSET of Content-Type
   PRBool              forwardInline;
+  PRBool              overrideComposeFormat; // Override compose format (for forward inline).
   nsCOMPtr<nsIMsgIdentity>      identity;
   char                *originalMsgURI;     // the original URI of the message we are currently processing
   nsCOMPtr<nsIMsgDBHdr>         origMsgHdr;
 };
 
 ////////////////////////////////////////////////////////////////
 // Bridge routines for legacy mime code
 ////////////////////////////////////////////////////////////////
--- a/mailnews/mime/src/nsStreamConverter.cpp
+++ b/mailnews/mime/src/nsStreamConverter.cpp
@@ -525,16 +525,17 @@ nsStreamConverter::InternalCleanup(void)
 nsStreamConverter::nsStreamConverter()
 {
   // Init member variables...
   mWrapperOutput = PR_FALSE;
   mBridgeStream = NULL;
   mOutputFormat = "text/html";
   mAlreadyKnowOutputType = PR_FALSE;
   mForwardInline = PR_FALSE;
+  mOverrideComposeFormat = PR_FALSE;
 
   mPendingRequest = nsnull;
   mPendingContext = nsnull;
 }
 
 nsStreamConverter::~nsStreamConverter()
 {
   InternalCleanup();
@@ -788,16 +789,32 @@ nsStreamConverter::SetMimeHeadersListene
 NS_IMETHODIMP
 nsStreamConverter::SetForwardInline(PRBool forwardInline)
 {
   mForwardInline = forwardInline;
   return NS_OK;
 }
 
 NS_IMETHODIMP
+nsStreamConverter::GetOverrideComposeFormat(PRBool *aResult)
+{
+  if (!aResult)
+    return NS_ERROR_NULL_POINTER;
+  *aResult = mOverrideComposeFormat;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsStreamConverter::SetOverrideComposeFormat(PRBool aOverrideComposeFormat)
+{
+  mOverrideComposeFormat = aOverrideComposeFormat;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
 nsStreamConverter::GetForwardInline(PRBool *result)
 {
   if (!result) return NS_ERROR_NULL_POINTER;
   *result = mForwardInline;
   return NS_OK;
 }
 
 NS_IMETHODIMP
--- a/mailnews/mime/src/nsStreamConverter.h
+++ b/mailnews/mime/src/nsStreamConverter.h
@@ -95,16 +95,17 @@ private:
   nsCString                     mOutputFormat;
   nsCString                     mRealContentType; // if we know the content type for real, this will be set (used by attachments)
 
   nsCString                     mOverrideFormat;  // this is a possible override for emitter creation
   PRBool                        mWrapperOutput;   // Should we output the frame split message display 
 
   nsCOMPtr<nsIMimeStreamConverterListener>  mMimeStreamConverterListener;
   PRBool                        mForwardInline;
+  PRBool                        mOverrideComposeFormat;
   nsCOMPtr<nsIMsgIdentity>      mIdentity;
   nsCString                     mOriginalMsgURI;
   nsCOMPtr<nsIMsgDBHdr>         mOrigMsgHdr;
 
   nsCString                     mFromType;
   nsCString                     mToType;
 #ifdef DEBUG_mscott  
   PRTime mConvertContentTime;
--- a/suite/locales/en-US/chrome/mailnews/mime.properties
+++ b/suite/locales/en-US/chrome/mailnews/mime.properties
@@ -174,17 +174,17 @@ 1039=">here</A> to download the rest of 
 # default attachment name
 ## @name MIME_MSG_DEFAULT_ATTACHMENT_NAME
 ## @loc 
 # LOCALIZATION NOTE (1040): Do not translate "%s" below.
 # Place the %s where you wish the part number of the attachment to appear
 1040=Part %s
 
 # default forwarded message prefix
-## @name MIME_FORWARDED_MESSAGE_USER_WROTE
+## @name MIME_FORWARDED_MESSAGE_HTML_USER_WROTE
 ## @loc 
 1041=-------- Original Message --------
 
 # Partial Message Format2 1
 ## @name MIME_MSG_PARTIAL_FMT2_1
 ## @loc
 # LOCALIZATION NOTE (1042): In the following line, translate only the words, "Not Downloaded".
 1042=<P><CENTER><TABLE BORDER CELLSPACING=5 CELLPADDING=10 WIDTH="80%%"><TR><TD ALIGN=CENTER><FONT SIZE="+1"><B>Not Downloaded</B></FONT><HR>