Bug 509616 - "improve the look of the inline attachment separator" [r=bienvenu sr=Neil ui-review=clarkbw]
authorMark Banner <bugzilla@standard8.plus.com>
Tue, 25 Aug 2009 09:20:17 +0100
changeset 3400 ef841803601bbb0fa45fe27827bc09519a0200aa
parent 3399 2093c7c10eead44201a0973c5c4025ddb89c12c5
child 3401 0adcab6df66c4c9a6a110d5222683b8c75143d2c
push idunknown
push userunknown
push dateunknown
reviewersbienvenu, Neil
bugs509616
Bug 509616 - "improve the look of the inline attachment separator" [r=bienvenu sr=Neil ui-review=clarkbw]
mail/themes/gnomestripe/mail/messageBody.css
mail/themes/pinstripe/mail/messageBody.css
mail/themes/qute/mail/messageBody.css
mailnews/db/gloda/components/jsmimeemitter.js
mailnews/mime/emitters/src/nsMimeBaseEmitter.cpp
mailnews/mime/emitters/src/nsMimeBaseEmitter.h
mailnews/mime/emitters/src/nsMimeHtmlEmitter.cpp
mailnews/mime/emitters/src/nsMimeHtmlEmitter.h
mailnews/mime/public/nsIMimeEmitter.idl
mailnews/mime/src/mimehdrs.cpp
mailnews/mime/src/mimehdrs.h
mailnews/mime/src/mimei.cpp
mailnews/mime/src/mimei.h
mailnews/mime/src/mimemoz2.cpp
mailnews/mime/src/mimemoz2.h
--- a/mail/themes/gnomestripe/mail/messageBody.css
+++ b/mail/themes/gnomestripe/mail/messageBody.css
@@ -163,8 +163,21 @@ body[selected="false"] {
 #_mailrssiframe {
   position: fixed;
   top: 0;
   left: 0;
   width: 100%;
   height: 100%;
   border: none;
 }
+
+.mimeAttachmentHeader {
+  width: 98%;
+  border-color: GrayText;
+  border-style: none;
+  border-top-style: solid;
+}
+
+.mimeAttachmentName {
+  color: GrayText;
+  font-size: 80%;
+  font-family: Arial, sans-serif;
+}
--- a/mail/themes/pinstripe/mail/messageBody.css
+++ b/mail/themes/pinstripe/mail/messageBody.css
@@ -190,8 +190,21 @@ body[selected="false"] {
 #_mailrssiframe {
   position: fixed;
   top: 0;
   left: 0;
   width: 100%;
   height: 100%;
   border: none;
 }
+
+.mimeAttachmentHeader {
+  width: 98%;
+  border-color: GrayText;
+  border-style: none;
+  border-top-style: solid;
+}
+
+.mimeAttachmentName {
+  color: GrayText;
+  font-size: 80%;
+  font-family: Arial, sans-serif;
+}
--- a/mail/themes/qute/mail/messageBody.css
+++ b/mail/themes/qute/mail/messageBody.css
@@ -1,166 +1,179 @@
-/* ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is mozilla.org code.
- *
- * 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):
- *   Joe Hewitt <hewitt@netscape.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"),
- * 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
- * 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 ***** */
-
-/* ===== messageBody.css =================================================
-  == Styles for the body of a mail message.
-  ======================================================================= */
-
-@import url(chrome://communicator/skin/smileys.css);
-@import url(chrome://messenger/skin/messageQuotes.css);
-
-@namespace url("http://www.w3.org/1999/xhtml");
-
-mailattachcount {
-  display: none;
-}
-
-/* :::: message header ::::: */
-
-.header-part1 {
-  background-color: #EFEFEF;
-}
-
-.header-part2,
-.header-part3 {
-  background-color: #DEDEDE;
-}
-
-div.headerdisplayname {
-  display: inline;
-  font-weight: bold;
-  white-space: pre;
-}
-
-/* ::::: message text, incl. quotes ::::: */
-
-.moz-text-flowed blockquote,
-.moz-text-plain blockquote {
-  margin: 0;
-}
-
-.moz-text-plain pre {
-  margin: 0;
-  font-family: inherit;
-}
-
-.moz-text-plain[wrap="true"] {
-  white-space: pre-wrap;
-}
-
-.moz-text-plain[wrap="false"] {
-  white-space: pre;
-}
-
-.moz-text-plain[wrap="flow"] .moz-txt-sig {
-  white-space: pre-wrap;
-}
-
-.moz-text-plain[graphical-quote="false"] blockquote {
-  border-style: none;
-  padding: 0;
-}
-
-.moz-text-plain[graphical-quote="true"] .moz-txt-citetags {
-  display: none;
-}
-
-span.moz-txt-underscore {
-  text-decoration: underline;
-}
-
-span.moz-txt-formfeed {
-  display: block;
-  height: 100%;
-}
-
-/* ::::: attached images ::::: */
-.moz-attached-image[overflowing="true"] { 
-  cursor: -moz-zoom-out;
-}
-
-.moz-attached-image[isshrunk="true"] { 
-  cursor: -moz-zoom-in;
-  max-width: 100%;
-}
-
-
-/* ::::: vcard ::::: */
-
-.moz-vcard-table {
-  -moz-border-radius: 8px;
-  border: thin solid gray;
-  margin-top: 10px;
-}
-
-.moz-vcard-property {
-  font-size: 80%;
-  color: gray;
-}
-
-.moz-vcard-title-property {
-} 
-
-.moz-vcard-badge {
-  height: 24px;
-  width: 24px;
-  background-color: transparent;
-  display: block;
-  background-image: url("chrome://messenger/skin/addressbook/icons/abcard-large.png");
-}
-
-.moz-vcard-badge:hover {
-  -moz-image-region: rect(30px 30px 60px 0px);
-} 
-
-.moz-vcard-badge:focus {
-  outline: none;
-}
-
-/* New style feed summary body. */
-body[selected="false"] {
-  display: none;
-}
-
-/* Old style feeds. */
-#_mailrssiframe {
-  position: fixed;
-  top: 0;
-  left: 0;
-  width: 100%;
-  height: 100%;
-  border: none;
-}
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * 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):
+ *   Joe Hewitt <hewitt@netscape.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"),
+ * 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
+ * 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 ***** */
+
+/* ===== messageBody.css =================================================
+  == Styles for the body of a mail message.
+  ======================================================================= */
+
+@import url(chrome://communicator/skin/smileys.css);
+@import url(chrome://messenger/skin/messageQuotes.css);
+
+@namespace url("http://www.w3.org/1999/xhtml");
+
+mailattachcount {
+  display: none;
+}
+
+/* :::: message header ::::: */
+
+.header-part1 {
+  background-color: #EFEFEF;
+}
+
+.header-part2,
+.header-part3 {
+  background-color: #DEDEDE;
+}
+
+div.headerdisplayname {
+  display: inline;
+  font-weight: bold;
+  white-space: pre;
+}
+
+/* ::::: message text, incl. quotes ::::: */
+
+.moz-text-flowed blockquote,
+.moz-text-plain blockquote {
+  margin: 0;
+}
+
+.moz-text-plain pre {
+  margin: 0;
+  font-family: inherit;
+}
+
+.moz-text-plain[wrap="true"] {
+  white-space: pre-wrap;
+}
+
+.moz-text-plain[wrap="false"] {
+  white-space: pre;
+}
+
+.moz-text-plain[wrap="flow"] .moz-txt-sig {
+  white-space: pre-wrap;
+}
+
+.moz-text-plain[graphical-quote="false"] blockquote {
+  border-style: none;
+  padding: 0;
+}
+
+.moz-text-plain[graphical-quote="true"] .moz-txt-citetags {
+  display: none;
+}
+
+span.moz-txt-underscore {
+  text-decoration: underline;
+}
+
+span.moz-txt-formfeed {
+  display: block;
+  height: 100%;
+}
+
+/* ::::: attached images ::::: */
+.moz-attached-image[overflowing="true"] { 
+  cursor: -moz-zoom-out;
+}
+
+.moz-attached-image[isshrunk="true"] { 
+  cursor: -moz-zoom-in;
+  max-width: 100%;
+}
+
+
+/* ::::: vcard ::::: */
+
+.moz-vcard-table {
+  -moz-border-radius: 8px;
+  border: thin solid gray;
+  margin-top: 10px;
+}
+
+.moz-vcard-property {
+  font-size: 80%;
+  color: gray;
+}
+
+.moz-vcard-title-property {
+} 
+
+.moz-vcard-badge {
+  height: 24px;
+  width: 24px;
+  background-color: transparent;
+  display: block;
+  background-image: url("chrome://messenger/skin/addressbook/icons/abcard-large.png");
+}
+
+.moz-vcard-badge:hover {
+  -moz-image-region: rect(30px 30px 60px 0px);
+} 
+
+.moz-vcard-badge:focus {
+  outline: none;
+}
+
+/* New style feed summary body. */
+body[selected="false"] {
+  display: none;
+}
+
+/* Old style feeds. */
+#_mailrssiframe {
+  position: fixed;
+  top: 0;
+  left: 0;
+  width: 100%;
+  height: 100%;
+  border: none;
+}
+
+.mimeAttachmentHeader {
+  width: 98%;
+  border-color: GrayText;
+  border-style: none;
+  border-top-style: solid;
+}
+
+.mimeAttachmentName {
+  color: GrayText;
+  font-size: 80%;
+  font-family: Arial, sans-serif;
+}
--- a/mailnews/db/gloda/components/jsmimeemitter.js
+++ b/mailnews/db/gloda/components/jsmimeemitter.js
@@ -227,22 +227,22 @@ MimeMessageEmitter.prototype = {
   },
   addAllHeaders: function mime_emitter_addAllHeaders(aAllHeaders, aHeaderSize) {
     // This is called by the parsing code after the calls to AddHeaderField (or
     //  AddAttachmentField if the part is an attachment), and seems to serve
     //  a specialized, quasi-redundant purpose.  (nsMimeBaseEmitter creates a
     //  nsIMimeHeaders instance and hands it to the nsIMsgMailNewsUrl.)
     // nop
   },
-  writeHTMLHeaders: function mime_emitter_writeHTMLHeaders() {
+  writeHTMLHeaders: function mime_emitter_writeHTMLHeaders(aName) {
     // It does't look like this should even be part of the interface; I think
     //  only the nsMimeHtmlDisplayEmitter::EndHeader call calls this signature.
     // nop
   },
-  endHeader: function mime_emitter_endHeader() {
+  endHeader: function mime_emitter_endHeader(aName) {
   },
   updateCharacterSet: function mime_emitter_updateCharacterSet(aCharset) {
     // we do not need to worry about this.  it turns out this notification is
     //  exclusively for the benefit of the UI.  libmime, believe it or not,
     //  is actually doing the right thing under the hood and handles all the
     //  encoding issues for us.
     // so, get ready for the only time you will ever hear this:
     //  three cheers for libmime!
--- a/mailnews/mime/emitters/src/nsMimeBaseEmitter.cpp
+++ b/mailnews/mime/emitters/src/nsMimeBaseEmitter.cpp
@@ -768,42 +768,49 @@ nsMimeBaseEmitter::WriteHeaderFieldHTML(
 
   mHTMLHeaders.Append("</tr>");
 
   PR_FREEIF(newValue);
   return NS_OK;
 }
 
 nsresult
-nsMimeBaseEmitter::WriteHeaderFieldHTMLPrefix()
+nsMimeBaseEmitter::WriteHeaderFieldHTMLPrefix(const nsACString &name)
 {
   if (
       ( (mFormat == nsMimeOutput::nsMimeMessageSaveAs) && (mFirstHeaders) ) ||
       ( (mFormat == nsMimeOutput::nsMimeMessagePrintOutput) && (mFirstHeaders) )
      )
      /* DO NOTHING */ ;   // rhp: Do nothing...leaving the conditional like this so its
                           //      easier to see the logic of what is going on.
-  else
-    mHTMLHeaders.Append("<br><hr width=\"90%\" size=4><br>");
+  else {
+    mHTMLHeaders.Append("<br><fieldset class=\"mimeAttachmentHeader\">");
+    if (!name.IsEmpty()) {
+      mHTMLHeaders.Append("<legend class=\"mimeAttachmentName\">");
+      mHTMLHeaders.Append(name);
+      mHTMLHeaders.Append("</legend>");
+    }
+    mHTMLHeaders.Append("</fieldset>");
+  }
 
   mFirstHeaders = PR_FALSE;
   return NS_OK;
 }
 
 nsresult
 nsMimeBaseEmitter::WriteHeaderFieldHTMLPostfix()
 {
   mHTMLHeaders.Append("<br>");
   return NS_OK;
 }
 
 NS_IMETHODIMP
-nsMimeBaseEmitter::WriteHTMLHeaders()
+nsMimeBaseEmitter::WriteHTMLHeaders(const nsACString &name)
 {
-  WriteHeaderFieldHTMLPrefix();
+  WriteHeaderFieldHTMLPrefix(name);
 
   // Start with the subject, from date info!
   DumpSubjectFromDate();
 
   // Continue with the to and cc headers
   DumpToCC();
 
   // Do the rest of the headers, but these will only be written if
@@ -952,17 +959,17 @@ nsMimeBaseEmitter::Complete()
 }
 
 //
 // This needs to do the right thing with the stored information. It only
 // has to do the output functions, this base class will take care of the
 // memory cleanup
 //
 NS_IMETHODIMP
-nsMimeBaseEmitter::EndHeader()
+nsMimeBaseEmitter::EndHeader(const nsACString &name)
 {
   return NS_OK;
 }
 
 // body handling routines
 NS_IMETHODIMP
 nsMimeBaseEmitter::StartBody(PRBool bodyOnly, const char *msgID, const char *outCharset)
 {
--- a/mailnews/mime/emitters/src/nsMimeBaseEmitter.h
+++ b/mailnews/mime/emitters/src/nsMimeBaseEmitter.h
@@ -103,17 +103,17 @@ public:
   char                *MimeGetStringByName(const char *aHeaderName);
   char                *MimeGetStringByID(PRInt32 aID);
   char                *LocalizeHeaderName(const char *aHeaderName, const char *aDefaultName);
 
   // For header processing...
   const char          *GetHeaderValue(const char  *aHeaderName);
 
   // To write out a stored header array as HTML
-  virtual nsresult            WriteHeaderFieldHTMLPrefix();
+  virtual nsresult            WriteHeaderFieldHTMLPrefix(const nsACString &name);
   virtual nsresult            WriteHeaderFieldHTML(const char *field, const char *value);
   virtual nsresult            WriteHeaderFieldHTMLPostfix();
 
 protected:
   // Internal methods...
   void                CleanupHeaderArray(nsVoidArray *aArray);
 
   // For header output...
--- a/mailnews/mime/emitters/src/nsMimeHtmlEmitter.cpp
+++ b/mailnews/mime/emitters/src/nsMimeHtmlEmitter.cpp
@@ -132,20 +132,20 @@ PRBool nsMimeHtmlDisplayEmitter::BroadCa
   nsresult rv = GetHeaderSink(getter_AddRefs(headerSink));
   if (NS_SUCCEEDED(rv) && headerSink && mDocHeader)
     return PR_TRUE;
   else
     return PR_FALSE;
 }
 
 nsresult
-nsMimeHtmlDisplayEmitter::WriteHeaderFieldHTMLPrefix()
+nsMimeHtmlDisplayEmitter::WriteHeaderFieldHTMLPrefix(const nsACString &name)
 {
   if (!BroadCastHeadersAndAttachments() || (mFormat == nsMimeOutput::nsMimeMessagePrintOutput))
-    return nsMimeBaseEmitter::WriteHeaderFieldHTMLPrefix();
+    return nsMimeBaseEmitter::WriteHeaderFieldHTMLPrefix(name);
   else
     return NS_OK;
 }
 
 nsresult
 nsMimeHtmlDisplayEmitter::WriteHeaderFieldHTML(const char *field, const char *value)
 {
   if (!BroadCastHeadersAndAttachments() || (mFormat == nsMimeOutput::nsMimeMessagePrintOutput))
@@ -260,32 +260,32 @@ nsresult nsMimeHtmlDisplayEmitter::Broad
 
     headerNameEnumerator->Append(headerInfo->name);
   }
 
   aHeaderSink->ProcessHeaders(headerNameEnumerator, headerValueEnumerator, aFromNewsgroup);
   return rv;
 }
 
-NS_IMETHODIMP nsMimeHtmlDisplayEmitter::WriteHTMLHeaders()
+NS_IMETHODIMP nsMimeHtmlDisplayEmitter::WriteHTMLHeaders(const nsACString &name)
 {
   // if we aren't broadcasting headers OR printing...just do whatever
   // our base class does...
   if (mFormat == nsMimeOutput::nsMimeMessagePrintOutput)
   {
-    return nsMimeBaseEmitter::WriteHTMLHeaders();
+    return nsMimeBaseEmitter::WriteHTMLHeaders(name);
   }
   else if (!BroadCastHeadersAndAttachments() || !mDocHeader)
   {
     // This needs to be here to correct the output format if we are
     // not going to broadcast headers to the XUL document.
     if (mFormat == nsMimeOutput::nsMimeMessageBodyDisplay)
       mFormat = nsMimeOutput::nsMimeMessagePrintOutput;
 
-    return nsMimeBaseEmitter::WriteHTMLHeaders();
+    return nsMimeBaseEmitter::WriteHTMLHeaders(name);
   }
   else
     mFirstHeaders = PR_FALSE;
 
   PRBool bFromNewsgroups = PR_FALSE;
   for (PRInt32 j=0; j < mHeaderArray->Count(); j++)
   {
     headerInfoType *headerInfo = (headerInfoType *)mHeaderArray->ElementAt(j);
@@ -421,17 +421,17 @@ nsresult nsMimeHtmlDisplayEmitter::Gener
       CopyUTF16toUTF8(formattedDateString, formattedDate);
     }
   }
 
   return rv;
 }
 
 nsresult
-nsMimeHtmlDisplayEmitter::EndHeader()
+nsMimeHtmlDisplayEmitter::EndHeader(const nsACString &name)
 {
   if (mDocHeader && (mFormat != nsMimeOutput::nsMimeMessageFilterSniffer))
   {
     UtilityWriteCRLF("<html>");
     UtilityWriteCRLF("<head>");
 
     const char * val = GetHeaderValue(HEADER_SUBJECT); // do not free this value
     if (val)
@@ -452,17 +452,18 @@ nsMimeHtmlDisplayEmitter::EndHeader()
 
     // Stylesheet info!
     UtilityWriteCRLF("<link rel=\"important stylesheet\" href=\"chrome://messagebody/skin/messageBody.css\">");
 
     UtilityWriteCRLF("</head>");
     UtilityWriteCRLF("<body>");
   }
 
-  WriteHTMLHeaders();
+  WriteHTMLHeaders(name);
+
   return NS_OK;
 }
 
 nsresult
 nsMimeHtmlDisplayEmitter::StartAttachment(const nsACString &name,
                                           const char *contentType,
                                           const char *url,
                                           PRBool aIsExternalAttachment)
@@ -534,18 +535,25 @@ nsMimeHtmlDisplayEmitter::StartAttachmen
         (!strcmp(contentType, APPLICATION_XPKCS7_SIGNATURE)) ||
         (!strcmp(contentType, APPLICATION_PKCS7_SIGNATURE)) ||
         (!strcmp(contentType, TEXT_VCARD)))
      ) {
      mSkipAttachment = PR_TRUE;
      return NS_OK;
   }
 
-  if (!mFirst)
-    UtilityWrite("<hr width=\"90%\" size=4>");
+  if (!mFirst) {
+    UtilityWrite("<br><fieldset class=\"mimeAttachmentHeader\">");
+    if (!name.IsEmpty()) {
+      UtilityWrite("<legend class=\"mimeAttachmentName\">");
+      UtilityWrite(name);
+      UtilityWrite("</legend>");
+    }
+    UtilityWrite("</fieldset>");
+  }
 
   mFirst = PR_FALSE;
 
   UtilityWrite("<center>");
   UtilityWrite("<table border>");
   UtilityWrite("<tr>");
   UtilityWrite("<td>");
 
--- a/mailnews/mime/emitters/src/nsMimeHtmlEmitter.h
+++ b/mailnews/mime/emitters/src/nsMimeHtmlEmitter.h
@@ -53,32 +53,32 @@
 class nsMimeHtmlDisplayEmitter : public nsMimeBaseEmitter {
 public:
     nsMimeHtmlDisplayEmitter ();
     nsresult Init();
 
     virtual       ~nsMimeHtmlDisplayEmitter (void);
 
     // Header handling routines.
-    NS_IMETHOD    EndHeader();
+    NS_IMETHOD    EndHeader(const nsACString &name);
 
     // Attachment handling routines
     NS_IMETHOD    StartAttachment(const nsACString &name,
                                   const char *contentType, const char *url,
                                   PRBool aIsExternalAttachment);
     NS_IMETHOD    AddAttachmentField(const char *field, const char *value);
     NS_IMETHOD    EndAttachment();
     NS_IMETHOD    EndAllAttachments();
 
     // Body handling routines
     NS_IMETHOD    WriteBody(const nsACString &buf, PRUint32 *amountWritten);
     NS_IMETHOD    EndBody();
-    NS_IMETHOD WriteHTMLHeaders();
+    NS_IMETHOD    WriteHTMLHeaders(const nsACString &name);
 
-    virtual nsresult            WriteHeaderFieldHTMLPrefix();
+    virtual nsresult            WriteHeaderFieldHTMLPrefix(const nsACString &name);
     virtual nsresult            WriteHeaderFieldHTML(const char *field, const char *value);
     virtual nsresult            WriteHeaderFieldHTMLPostfix();
 
 protected:
     PRBool        mFirst;  // Attachment flag...
     PRBool        mSkipAttachment;  // attachments we shouldn't show...
 
     nsCOMPtr<nsIMsgHeaderSink> mHeaderSink;
--- a/mailnews/mime/public/nsIMimeEmitter.idl
+++ b/mailnews/mime/public/nsIMimeEmitter.idl
@@ -38,17 +38,17 @@
 #include "nsrootidl.idl"
 
 interface nsIOutputStream;
 interface nsIInputStream;
 interface nsIURI;
 interface nsIStreamListener;
 interface nsIChannel;
 
-[scriptable, uuid(39E329E2-357F-11d3-8EFD-00A024A7D144)]
+[scriptable, uuid(eb9beb09-44de-4ad2-a560-f572b1afd534)]
 interface nsMimeHeaderDisplayTypes
 {
     const long MicroHeaders = 0;
     const long NormalHeaders = 1;
     const long AllHeaders = 2;
 };
 
 %{C++
@@ -68,18 +68,32 @@ interface nsIMimeEmitter : nsISupports {
     // Set the output stream/listener for processed data.
     void setPipe(in nsIInputStream inputStream, in nsIOutputStream outStream);
 
     // Header handling routines.
     void startHeader(in PRBool rootMailHeader, in PRBool headerOnly,
                      [const] in string msgID, [const] in string outCharset);
     void addHeaderField([const] in string field, [const] in string value);
     void addAllHeaders(in ACString allheaders);
-    void writeHTMLHeaders(); // Book case this with an EndHeader call.
-    void endHeader();
+
+    /**
+     * Write the HTML Headers for the current attachment.
+     * Note: Book case this with an EndHeader call.
+     *
+     * @param name The name of this attachment.
+     */
+    void writeHTMLHeaders([const] in AUTF8String name);
+
+    /**
+     * Finish writing the headers for the current attachment.
+     *
+     * @param name The name of this attachment.
+     */
+    void endHeader([const] in AUTF8String name);
+
     void updateCharacterSet([const] in string aCharset);
 
     // Attachment handling routines.
     void startAttachment([const] in AUTF8String name,
                          [const] in string contentType,
                          [const] in string url, in PRBool aNotDownloaded);
     void addAttachmentField([const] in string field, [const] in string value);
     void endAttachment();
--- a/mailnews/mime/src/mimehdrs.cpp
+++ b/mailnews/mime/src/mimehdrs.cpp
@@ -55,17 +55,17 @@
 #include "nsNetCID.h"
 #include "nsServiceManagerUtils.h"
 #include "nsMemory.h"
 #include <ctype.h>
 
 // Forward declares...
 PRInt32 MimeHeaders_build_heads_list(MimeHeaders *hdrs);
 
-static void
+void
 MimeHeaders_convert_header_value(MimeDisplayOptions *opt, nsCString &value,
                                  PRBool convert_charset_only)
 {
   char        *converted;
 
   if (value.IsEmpty())
     return;
 
@@ -497,18 +497,18 @@ MimeHeaders_get_parameter (const char *h
     return nsnull;
 
   nsCString result;
   rv = mimehdrpar->GetParameterInternal(header_value, parm_name, charset,
                                         language, getter_Copies(result));
   return NS_SUCCEEDED(rv) ? PL_strdup(result.get()) : nsnull;
 }
 
-#define MimeHeaders_write(OPT,DATA,LENGTH) \
-    MimeOptions_write((OPT), (DATA), (LENGTH), PR_TRUE);
+#define MimeHeaders_write(OPT,NAME,DATA,LENGTH) \
+    MimeOptions_write((OPT), (NAME), (DATA), (LENGTH), PR_TRUE);
 
 
 #define MimeHeaders_grow_obuffer(hdrs, desired_size) \
   ((((long) (desired_size)) >= ((long) (hdrs)->obuffer_size)) ? \
    mime_GrowBuffer ((desired_size), sizeof(char), 255, \
            &(hdrs)->obuffer, &(hdrs)->obuffer_size) \
    : 0)
 
@@ -818,26 +818,30 @@ MimeHeaders_write_raw_headers (MimeHeade
 
   if (hdrs && !hdrs->done_p)
   {
     hdrs->done_p = PR_TRUE;
     status = MimeHeaders_build_heads_list(hdrs);
     if (status < 0) return 0;
   }
 
+  nsCString name;
+  name.Adopt(MimeHeaders_get_name(hdrs, opt));
+  MimeHeaders_convert_header_value(opt, name, false);
+
   if (!dont_write_content_type)
   {
     char nl[] = MSG_LINEBREAK;
     if (hdrs)
     {
-      status = MimeHeaders_write(opt, hdrs->all_headers,
-                   hdrs->all_headers_fp);
+      status = MimeHeaders_write(opt, name, hdrs->all_headers,
+                                 hdrs->all_headers_fp);
       if (status < 0) return status;
     }
-    status = MimeHeaders_write(opt, nl, strlen(nl));
+    status = MimeHeaders_write(opt, name, nl, strlen(nl));
     if (status < 0) return status;
   }
   else if (hdrs)
   {
     PRInt32 i;
     for (i = 0; i < hdrs->heads_size; i++)
     {
       char *head = hdrs->heads[i];
@@ -848,23 +852,23 @@ MimeHeaders_write_raw_headers (MimeHeade
       NS_ASSERTION(head, "1.22 <rhp@netscape.com> 22 Aug 1999 08:48");
       if (!head) continue;
 
       /* Don't write out any Content- header. */
       if (!PL_strncasecmp(head, "Content-", 8))
       continue;
 
       /* Write out this (possibly multi-line) header. */
-      status = MimeHeaders_write(opt, head, end - head);
+      status = MimeHeaders_write(opt, name, head, end - head);
       if (status < 0) return status;
     }
   }
 
   if (hdrs)
-    MimeHeaders_compact (hdrs);
+    MimeHeaders_compact(hdrs);
 
   return 0;
 }
 
 // XXX Fix this XXX //
 char *
 MimeHeaders_open_crypto_stamp(void)
 {
--- a/mailnews/mime/src/mimehdrs.h
+++ b/mailnews/mime/src/mimehdrs.h
@@ -106,9 +106,15 @@ extern char *MimeHeaders_make_crypto_sta
  */
 extern char *MimeHeaders_get_name(MimeHeaders *hdrs, MimeDisplayOptions *opt);
 
 extern char *mime_decode_filename(char *name, const char* charset,
                                   MimeDisplayOptions *opt);
 
 extern "C"  char * MIME_StripContinuations(char *original);
 
+/**
+ * Convert this value to a unicode string, based on the charset.
+ */
+extern void MimeHeaders_convert_header_value(MimeDisplayOptions *opt,
+                                             nsCString &value,
+                                             PRBool convert_charset_only);
 #endif /* _MIMEHDRS_H_ */
--- a/mailnews/mime/src/mimei.cpp
+++ b/mailnews/mime/src/mimei.cpp
@@ -83,16 +83,17 @@
 #include "prenv.h"
 #include "plstr.h"
 #include "prlink.h"
 #include "prprf.h"
 #include "mimecth.h"
 #include "mimebuf.h"
 #include "nsIServiceManager.h"
 #include "mimemoz2.h"
+#include "comi18n.h"
 #include "nsIMimeContentTypeHandler.h"
 #include "nsIComponentManager.h"
 #include "nsCategoryManagerUtils.h"
 #include "nsXPCOMCID.h"
 #include "nsISimpleMimeConverter.h"
 #include "nsSimpleMimeConverterStub.h"
 #include "nsVoidArray.h"
 #include "nsMimeStringResources.h"
@@ -1678,40 +1679,60 @@ mime_parse_url_options(const char *url, 
   return 0;
 }
 
 
 /* Some output-generation utility functions...
  */
 
 int
-MimeOptions_write(MimeDisplayOptions *opt, const char *data, PRInt32 length,
-          PRBool user_visible_p)
+MimeOptions_write(MimeDisplayOptions *opt, nsCString &name, const char *data,
+                  PRInt32 length, PRBool user_visible_p)
 {
   int status = 0;
   void* closure = 0;
   if (!opt || !opt->output_fn || !opt->state)
   return 0;
 
   closure = opt->output_closure;
   if (!closure) closure = opt->stream_closure;
 
 //  PR_ASSERT(opt->state->first_data_written_p);
 
   if (opt->state->separator_queued_p && user_visible_p)
   {
     opt->state->separator_queued_p = PR_FALSE;
     if (opt->state->separator_suppressed_p)
-    opt->state->separator_suppressed_p = PR_FALSE;
-    else
-    {
-      char sep[] = "<BR><HR WIDTH=\"90%\" SIZE=4><BR>";
+      opt->state->separator_suppressed_p = PR_FALSE;
+    else {
+      char *sep = "<BR><FIELDSET CLASS=\"mimeAttachmentHeader\">";
       int lstatus = opt->output_fn(sep, strlen(sep), closure);
       opt->state->separator_suppressed_p = PR_FALSE;
       if (lstatus < 0) return lstatus;
+
+      if (!name.IsEmpty()) {
+          sep = "<LEGEND CLASS=\"mimeAttachmentName\">";
+          lstatus = opt->output_fn(sep, strlen(sep), closure);
+          opt->state->separator_suppressed_p = PR_FALSE;
+          if (lstatus < 0) return lstatus;
+
+          lstatus = opt->output_fn(name.get(), name.Length(), closure);
+          opt->state->separator_suppressed_p = PR_FALSE;
+          if (lstatus < 0) return lstatus;
+
+          sep = "</LEGEND>";
+          lstatus = opt->output_fn(sep, strlen(sep), closure);
+          opt->state->separator_suppressed_p = PR_FALSE;
+          if (lstatus < 0) return lstatus;
+      }
+
+      sep = "</FIELDSET><BR/>";
+      lstatus = opt->output_fn(sep, strlen(sep), closure);
+      opt->state->separator_suppressed_p = PR_FALSE;
+      if (lstatus < 0) return lstatus;
     }
   }
   if (user_visible_p)
   opt->state->separator_suppressed_p = PR_FALSE;
 
   if (length > 0)
   {
     status = opt->output_fn(data, length, closure);
@@ -1741,17 +1762,20 @@ MimeObject_write(MimeObject *obj, const 
   }
   if (!obj->options->state->first_data_written_p)
   {
     int status = MimeObject_output_init(obj, 0);
     if (status < 0) return status;
     NS_ASSERTION(obj->options->state->first_data_written_p, "1.1 <rhp@netscape.com> 19 Mar 1999 12:00");
   }
 
-  return MimeOptions_write(obj->options, output, length, user_visible_p);
+  nsCString name;
+  name.Adopt(MimeHeaders_get_name(obj->headers, obj->options));
+  MimeHeaders_convert_header_value(obj->options, name, false);
+  return MimeOptions_write(obj->options, name, output, length, user_visible_p);
 }
 
 int
 MimeObject_write_separator(MimeObject *obj)
 {
   if (obj->options && obj->options->state &&
       // we never want separators if we are asking for pure bodies
       !obj->options->write_pure_bodies)
--- a/mailnews/mime/src/mimei.h
+++ b/mailnews/mime/src/mimei.h
@@ -418,26 +418,26 @@ extern int MimeObject_output_init(MimeOb
 
 /* The `user_visible_p' argument says whether the output that has just been
    written will cause characters or images to show up on the screen, that
    is, it should be PR_FALSE if the stuff being written is merely structural
    HTML or whitespace ("<P>", "</TABLE>", etc.)  This information is used
    when making the decision of whether a separating <HR> is needed.
  */
 extern int MimeObject_write(MimeObject *, const char *data, PRInt32 length,
-              PRBool user_visible_p);
-extern int MimeOptions_write(MimeDisplayOptions *,
-               const char *data, PRInt32 length,
-               PRBool user_visible_p);
+                            PRBool user_visible_p);
+extern int MimeOptions_write(MimeDisplayOptions *, nsCString &name,
+                             const char *data, PRInt32 length,
+                             PRBool user_visible_p);
 
 /* Writes out the right kind of HR (or rather, queues it for writing.) */
 extern int MimeObject_write_separator(MimeObject *);
 
 extern PRBool MimeObjectChildIsMessageBody(MimeObject *obj,
-                      PRBool *isAlterOrRelated);
+                                           PRBool *isAlterOrRelated);
 
 /* This is the data tagged to contexts and the declaration needs to be
    in a header file since more than mimemoz.c needs to see it now...
    */
 #ifdef HAVE_MIME_DATA_SLOT
 # define LOCK_LAST_CACHED_MESSAGE
 #endif
 
--- a/mailnews/mime/src/mimemoz2.cpp
+++ b/mailnews/mime/src/mimemoz2.cpp
@@ -564,18 +564,18 @@ MimeGetAttachmentList(MimeObject *tobj, 
 
   isAnInlineMessage = mime_typep(obj, (MimeObjectClass *) &mimeMessageClass);
 
   cobj = (MimeContainer*) obj;
   n = CountTotalMimeAttachments(cobj);
   if (n <= 0)
     return n;
 
-  //in case of an inline message (as body), we need an extra slot for the message itself
-  //that we will fill later...
+  // in case of an inline message (as body), we need an extra slot for the
+  // message itself that we will fill later...
   if (isAnInlineMessage)
     n ++;
 
   *data = (nsMsgAttachmentData *)PR_Malloc( (n + 1) * sizeof(nsMsgAttachmentData));
   if (!*data)
     return NS_ERROR_OUT_OF_MEMORY;
 
   attIndex = 0;
@@ -1909,17 +1909,30 @@ mimeEmitterEndHeader(MimeDisplayOptions 
 
   mime_stream_data  *msd = GetMSD(opt);
   if (!msd)
     return NS_ERROR_FAILURE;
 
   if (msd->output_emitter)
   {
     nsIMimeEmitter *emitter = (nsIMimeEmitter *)msd->output_emitter;
-    return emitter->EndHeader();
+
+    nsCString name;
+    nsMsgAttachmentData *attachments = NULL;
+    if (msd->format_out == nsMimeOutput::nsMimeMessageSplitDisplay ||
+        msd->format_out == nsMimeOutput::nsMimeMessageHeaderDisplay ||
+        msd->format_out == nsMimeOutput::nsMimeMessageBodyDisplay) {
+      nsresult rv = MimeGetAttachmentList(msd->obj, msd->url_name, &attachments);
+      if (NS_SUCCEEDED(rv) && attachments && attachments->real_name)
+        name.Assign(attachments->real_name);
+    }
+
+    MimeHeaders_convert_header_value(opt, name, false);
+    MimeFreeAttachmentList(attachments);
+    return emitter->EndHeader(name);
   }
 
   return NS_ERROR_FAILURE;
 }
 
 extern "C" nsresult
 mimeEmitterUpdateCharacterSet(MimeDisplayOptions *opt, const char *aCharset)
 {
--- a/mailnews/mime/src/mimemoz2.h
+++ b/mailnews/mime/src/mimemoz2.h
@@ -181,24 +181,26 @@ extern "C" nsIMimeEmitter   *GetMimeEmit
 // To support 2 types of emitters...we need these routines :-(
 extern "C" nsresult     mimeSetNewURL(nsMIMESession *stream, char *url);
 extern "C" nsresult     mimeEmitterAddAttachmentField(MimeDisplayOptions *opt, const char *field, const char *value);
 extern "C" nsresult     mimeEmitterAddHeaderField(MimeDisplayOptions *opt, const char *field, const char *value);
 extern "C" nsresult     mimeEmitterAddAllHeaders(MimeDisplayOptions *opt, const char *allheaders, const PRInt32 allheadersize);
 extern "C" nsresult     mimeEmitterStartAttachment(MimeDisplayOptions *opt, const char *name, const char *contentType, const char *url,
                                                    PRBool aIsExternalAttachment);
 extern "C" nsresult     mimeEmitterEndAttachment(MimeDisplayOptions *opt);
-extern "C" nsresult      mimeEmitterEndAllAttachments(MimeDisplayOptions *opt);
+extern "C" nsresult     mimeEmitterEndAllAttachments(MimeDisplayOptions *opt);
 extern "C" nsresult     mimeEmitterStartBody(MimeDisplayOptions *opt, PRBool bodyOnly, const char *msgID, const char *outCharset);
 extern "C" nsresult     mimeEmitterEndBody(MimeDisplayOptions *opt);
 extern "C" nsresult     mimeEmitterEndHeader(MimeDisplayOptions *opt);
 extern "C" nsresult     mimeEmitterStartHeader(MimeDisplayOptions *opt, PRBool rootMailHeader, PRBool headerOnly, const char *msgID,
                                                const char *outCharset);
 extern "C" nsresult     mimeEmitterUpdateCharacterSet(MimeDisplayOptions *opt, const char *aCharset);
 
+extern "C" nsresult     MimeGetAttachmentList(MimeObject *tobj, const char *aMessageURL, nsMsgAttachmentData **data);
+
 /* To Get the connnection to prefs service manager */
 extern "C" nsIPrefBranch      *GetPrefBranch(MimeDisplayOptions *opt);
 
 // Get the text converter...
 mozITXTToHTMLConv           *GetTextConverter(MimeDisplayOptions *opt);
 
 nsresult
 HTML2Plaintext(const nsString& inString, nsString& outString,