Bug 454829 Summary page for collapsed threads and multiple selections. r=bienvenu
authorDavid Ascher <david.ascher@gmail.com>
Thu, 28 May 2009 08:48:37 +0100
changeset 2717 3c87898162a34e135e16d06ed8057249bc7a702e
parent 2716 afd0a576e7962a2df2b2453ae72a575247df8011
child 2718 2457fbd6cc1f35e2624e8517b076c828cfbe6085
push idunknown
push userunknown
push dateunknown
reviewersbienvenu
bugs454829
Bug 454829 Summary page for collapsed threads and multiple selections. r=bienvenu
mail/base/content/SearchDialog.js
mail/base/content/mailWindow.js
mail/base/content/messageWindow.js
mail/base/content/messageWindow.xul
mail/base/content/messenger.xul
mail/base/content/multimessageview.css
mail/base/content/multimessageview.xhtml
mail/base/content/selectionsummaries.js
mail/base/content/threadPane.js
mail/base/jar.mn
mail/locales/en-US/chrome/messenger/messenger.properties
mail/locales/en-US/chrome/messenger/multimessageview.dtd
mail/locales/en-US/chrome/messenger/multimessageview.properties
mail/locales/jar.mn
mail/themes/gnomestripe/jar.mn
mail/themes/gnomestripe/mail/multimessageview.css
mail/themes/pinstripe/jar.mn
mail/themes/pinstripe/mail/multimessageview.css
mail/themes/qute/jar.mn
mail/themes/qute/mail/multimessageview.css
mailnews/base/public/nsIMsgDBView.idl
mailnews/base/public/nsIMsgWindow.idl
mailnews/base/src/nsMsgDBView.cpp
suite/mailnews/messageWindow.js
suite/mailnews/search/SearchDialog.js
suite/mailnews/threadPane.js
--- a/mail/base/content/SearchDialog.js
+++ b/mail/base/content/SearchDialog.js
@@ -522,16 +522,18 @@ nsMsgSearchCommandUpdater.prototype =
   {
   },
 
   updateNextMessageAfterDelete : function()
   {
     SetNextMessageAfterDelete();
   },
 
+  summarizeSelection : function() {},
+
   QueryInterface : function(iid)
   {
     if (iid.equals(Components.interfaces.nsIMsgDBViewCommandUpdater) ||
         iid.equals(Components.interfaces.nsISupports))
       return this;
 
     throw Components.results.NS_NOINTERFACE;
   }
--- a/mail/base/content/mailWindow.js
+++ b/mail/base/content/mailWindow.js
@@ -47,20 +47,23 @@ var statusFeedback;
 var msgWindow;
 
 var msgComposeService;
 var accountManager;
 
 var gMessengerBundle;
 var gBrandBundle;
 
-var gContextMenu;
+Components.utils.import("resource://app/modules/gloda/log4moz.js");
 
+var gContextMenu;
+var gMailWindowLog = Log4Moz.getConfiguredLogger("mailWindow", Log4Moz.Level.Debug, Log4Moz.Level.Debug, Log4Moz.Level.Debug);
 var gAccountCentralLoaded = true;
 
+
 function OnMailWindowUnload()
 {
   MailOfflineMgr.uninit();
   ClearPendingReadTimer();
 
   var searchSession = GetSearchSession();
   if (searchSession)
   {
@@ -310,16 +313,17 @@ nsMsgStatusFeedback.prototype =
     if (this._meteorsSpinning) {
       // In this function, we expect that the maximum for each progress is 100,
       // i.e. we are dealing with percentages. Hence we can combine several
       // processes running at the same time.
       let currentProgress = 0;
       let progressCount = 0;
 
       // For each activity that is in progress, get its status.
+
       this._activeProcesses.forEach(function (element) {
           if (element.state ==
               Components.interfaces.nsIActivityProcess.STATE_INPROGRESS &&
               element.percentComplete != -1) {
             currentProgress += element.percentComplete;
             ++progressCount;
           }
         });
--- a/mail/base/content/messageWindow.js
+++ b/mail/base/content/messageWindow.js
@@ -180,16 +180,18 @@ nsMsgDBViewCommandUpdater.prototype =
     goUpdateCommand("button_goForward");
   },
 
   updateNextMessageAfterDelete : function()
   {
     SetNextMessageAfterDelete();
   },
 
+  summarizeSelection : function() {},
+
   QueryInterface : function(iid)
   {
     if (iid.equals(Components.interfaces.nsIMsgDBViewCommandUpdater) ||
         iid.equals(Components.interfaces.nsISupports))
       return this;
 
     throw Components.results.NS_NOINTERFACE;
   }
--- a/mail/base/content/messageWindow.xul
+++ b/mail/base/content/messageWindow.xul
@@ -171,16 +171,22 @@
     <deck id="msgNotificationBar"/>
 
     <!-- message view -->
     <browser id="messagepane" context="mailContext" tooltip="aHTMLTooltip"
              style="height: 0px; min-height: 1px" flex="1" name="messagepane"
              disablesecurity="true" disablehistory="true" type="content-primary"
              onresize="return messagePaneOnResize(event);" autofind="false"
              src="about:blank" onclick="return contentAreaClick(event);" />
+    <iframe id="htmlpane"
+             style="height: 0px; min-height: 1px" flex="1" name="htmlpane"
+             hidden="true"
+             disablesecurity="true" disablehistory="true"
+             onresize="return htmlPaneOnResize(event);" autofind="false"
+             src="about:blank"/>
     <splitter id="attachment-splitter" collapse="after" resizebefore="closest" resizeafter="closest" collapsed="true"/>
     <hbox id="attachmentView"/>
     <findbar id="FindToolbar" browserid="messagepane"/>
   </vbox>
   <panel id="customizeToolbarSheetPopup" noautohide="true">
     <iframe id="customizeToolbarSheetIFrame"
             style="&dialog.style;"
 #ifdef MOZILLA_1_9_1_BRANCH
--- a/mail/base/content/messenger.xul
+++ b/mail/base/content/messenger.xul
@@ -67,24 +67,26 @@
         onunload="OnUnloadMessenger()"
         screenX="10" screenY="10"
         persist="width height screenX screenY sizemode"
         windowtype="mail:3pane">
 
 <stringbundleset id="stringbundleset">
   <stringbundle id="bundle_brand" src="chrome://branding/locale/brand.properties"/>
   <stringbundle id="bundle_search" src="chrome://messenger/locale/search.properties"/>
+  <stringbundle id="bundle_multimessages" src="chrome://messenger/locale/multimessageview.properties"/>
 </stringbundleset>
 
 <script type="application/javascript" src="chrome://global/content/globalOverlay.js"/>
 <script type="application/x-javascript" src="chrome://messenger/content/widgetglue.js"/>
 <script type="application/x-javascript" src="chrome://messenger/content/commandglue.js"/>
 <script type="application/x-javascript" src="chrome://messenger/content/shareglue.js"/>
 <script type="application/x-javascript" src="chrome://messenger/content/msgViewNavigation.js"/>
 <script type="application/x-javascript" src="chrome://messenger/content/mailWindow.js"/>
+<script type="application/x-javascript" src="chrome://messenger/content/selectionsummaries.js"/>
 <script type="application/x-javascript" src="chrome://messenger/content/msgMail3PaneWindow.js"/>
 <script type="application/x-javascript" src="chrome://messenger/content/specialTabs.js"/>
 <script type="application/x-javascript" src="chrome://messenger/content/mail3PaneWindowCommands.js"/>
 <script type="application/x-javascript" src="chrome://global/content/contentAreaUtils.js"/>
 <script type="application/x-javascript" src="chrome://communicator/content/nsContextMenu.js"/>
 <script type="application/x-javascript" src="chrome://messenger/content/mailContextMenus.js"/>
 <script type="application/x-javascript" src="chrome://messenger/content/accountUtils.js"/>
 <script type="application/x-javascript" src="chrome://messenger/content/searchBar.js"/>
@@ -325,28 +327,39 @@
                 </deck> <!-- displayDeck -->
 
                 <!-- if you change this id, please change GetThreadAndMessagePaneSplitter() and MsgToggleMessagePane() -->
                 <splitter id="threadpane-splitter" collapse="after" persist="state" collapsed="true"
                           onmouseup="OnMouseUpThreadAndMessagePaneSplitter()"/>
 
                 <vbox id="messagepanebox" flex="2" minheight="100" height="200"
                       minwidth="100" width="200" persist="height width">
-
-                  <hbox id="msgHeaderView"/>
-                  <hbox id="editMessageBox"/>
-                  <deck id="msgNotificationBar"/>
-                  <browser id="messagepane" context="mailContext" autofind="false"
-                           minheight="1" flex="1" name="messagepane" tooltip="aHTMLTooltip"
-                           disablehistory="true" type="content-primary" src="about:blank"
-                           onresize="return messagePaneOnResize(event);"
-                           disablesecurity="true" onclick="return contentAreaClick(event);"/>
-                  <splitter id="attachment-splitter" collapse="after" resizebefore="closest" resizeafter="closest" collapsed="true"/>
-                  <hbox id="attachmentView"/>
-                  <findbar id="FindToolbar" browserid="messagepane"/>
+                  
+                  <!-- This next iframe is used to display summaries of -->
+                  <!-- multiple selected messages or collapsed threads -->
+                  <iframe id="multimessage"
+                           style="height: 0px; min-height: 1px"
+                           flex="1" name="multimessage"
+                           hidden="true"
+                           disablesecurity="true" disablehistory="true"
+                           src="chrome://messenger/content/multimessageview.xhtml"
+                           autofind="false"/>
+                  <vbox id="singlemessage" flex="1">
+                    <hbox id="msgHeaderView"/>
+                    <hbox id="editMessageBox"/>
+                    <deck id="msgNotificationBar"/>
+                    <browser id="messagepane" context="mailContext" autofind="false"
+                             minheight="1" flex="1" name="messagepane" tooltip="aHTMLTooltip"
+                             disablehistory="true" type="content-primary" src="about:blank"
+                             onresize="return messagePaneOnResize(event);"
+                             disablesecurity="true" onclick="return contentAreaClick(event);"/>
+                    <splitter id="attachment-splitter" collapse="after" resizebefore="closest" resizeafter="closest" collapsed="true"/>
+                    <hbox id="attachmentView"/>
+                    <findbar id="FindToolbar" browserid="messagepane"/>
+                  </vbox>
                 </vbox>
               </box>
             </vbox>
           </box>
         </box> <!-- end of mailContent -->
       </tabpanels>
     </tabmail>
   </hbox>
new file mode 100644
--- /dev/null
+++ b/mail/base/content/multimessageview.css
@@ -0,0 +1,301 @@
+/* Generic (cross-platform) multimessage view CSS.  Some bits will be overriden
+  by theme specific files */
+
+body {
+  font-family: sans-serif;
+  margin: 0px;
+  padding: 1ex 1em;
+}
+
+.star {
+  width: 16px;
+  height: 16px;
+  display: inline-block;
+  margin-left: 1ex;
+}
+
+#markButton {
+  width: 5em;
+}
+
+#multimessageview {
+  font-size: small;
+}
+
+#messages {
+  -moz-border-radius: 0.4ex;
+  border: 1px solid ThreeDShadow;
+  padding: 1ex 1em;
+  margin: 0px;
+  font-size: small;
+}
+
+#messagelist {
+  width: 100%;
+  display: table;
+}
+
+.message {
+  display: table-row;
+}
+
+.message > .header {
+  display: table-cell;
+  padding: 0.6ex 0px;
+}
+
+.subject {
+  display: inline-block;
+}
+
+.sender {
+  display: inline-block;
+}
+
+.author {
+  display: inline;
+  color: grey;
+}
+
+.count, .date {
+  display: table-cell;
+  padding: 0px 1em;
+  white-space: nowrap;
+  text-align: right;
+  color: InactiveCaptionText;
+}
+
+.wrappedsender, .wrappedsubject {
+  padding-right: 18px;
+  padding-top: 6px;
+}
+
+.message.unread > .header > .wrappedsubject > .subject,
+.unread  .subject_and_author,
+.message.unread > .header > .wrappedsender > .sender  {
+  font-weight: bold;
+}
+
+.message > .header > .wrappedsender > .sender:hover,
+.message > .header > .wrappedsubject > .subject:hover {
+  text-decoration: underline;
+  cursor: pointer;
+}
+
+.message > .header > .snippet, .message .tags {
+  margin-left: 2em;
+}
+
+.message > .header > .snippet {
+  color: GrayText;
+}
+
+.message > .header > .senders {
+  color: GrayText;
+}
+
+.info {
+  font-size: small;
+}
+
+.heading.info {
+  font-size: medium;
+  font-weight: normal;
+}
+
+.tags {
+  padding-top: 2px;
+}
+
+.tag {
+  padding: 0.2ex 0.2em;
+  margin-right: 0.5em;
+  -moz-margin-start: 0px;
+  background-image: url("chrome://messenger/skin/tagbg.png");
+  color: InfoText;
+  -moz-border-radius: 2px;
+}
+
+
+#buttonbox {
+  display: table-cell;
+  text-align: right;
+  padding-bottom: 1ex;
+  font-size: 11px;
+  font-family: Lucida Grande;
+  border: 1px solid transparent; 
+}
+
+#headingwrappertable {
+  display: table;
+  width: 100%;
+}
+
+#headingwrapper {
+  display: table-row;
+  margin-bottom: 1em;
+  border: 1px solid transparent; 
+}
+
+.heading {
+  display: table-cell;
+  font-weight: bold;
+  font-size: medium;
+  margin: 0.5em;
+  border: 1px solid transparent;
+  padding-right: 1em;
+}
+
+
+.button {
+  display: inline;
+}
+
+#trash {
+  min-height: 16px !important;
+  min-width: 21px !important;
+  padding: 0px;
+}
+
+.hidden {
+  display: none;
+}
+
+
+#column {
+  float: right;
+  right: 1em;
+  top: 1em;
+}
+
+#foldericon {
+  z-index: -1;
+  min-width: 128px;
+  min-height: 128px;
+  background-image: url("chrome://messenger/skin/icons/largefolder.jpg"); 
+  background-repeat: no-repeat;
+}
+
+#tagpie {
+    display: block;
+}
+
+#tagdots {
+    display: block;
+    text-align: center;
+    padding: 1em;
+}
+
+ .section_heading {
+  font-weight: bold;
+  padding-bottom: .5em;
+  color: #555;
+}
+
+#header {
+  border: 1px solid transparent;
+}
+
+.stats {
+  padding: 1em;
+  padding-top: 3em;
+  text-align: center;
+  font-size: small;
+}
+
+#mozupdate {
+  clear: both;
+  -moz-border-radius: 0.4ex;
+  border: 1px solid #FFD8B9;
+  left: 1em;
+  right: 1em;
+  padding: 0.5em;
+}
+
+a {
+  color: darkblue;
+  font-weight: bold;
+}
+
+a:hover {
+  text-decoration: underline; 
+}
+
+#unread, #authors, #threads, #last_selected_wrapper {
+  display: inline-block; 
+  padding: 1ex 1em;
+  margin: 0px;
+  margin-right: 1em;
+  margin-bottom: 1em;
+  font-size: small;
+  -moz-border-radius: 0.4ex;
+  border: 1px solid ThreeDShadow;
+}
+
+#last_selected_wrapper, #unread {
+  min-width: 40em;
+}
+
+#authors, #threads {
+  vertical-align: top;
+}
+
+#topten {
+  vertical-align: top;
+}
+
+#remotecontent {
+  -moz-border-radius: 0.4ex;
+  border: 1px solid ThreeDShadow;
+  background-color: #fafafa;
+  padding: 1ex 1em;
+  margin: 0px;
+  font-size: smaller;
+}
+
+.messagecount {
+  display: inline-block;
+  white-space: nowrap;
+  overflow: hidden;
+}
+
+.author, .subject {
+  display: inline;
+  overflow: hidden;
+  margin-right: 1em;
+}
+
+.subject_and_author {
+  white-space: nowrap;
+  overflow: hidden;
+  width: 38em;
+  margin-right: 1em;
+}
+
+.link:hover {
+  text-decoration: underline;
+  cursor: pointer;
+}
+
+.sparkline {
+  margin-left: .5em;
+}
+
+#last_selected_wrapper {
+  border: 1px solid orange;
+}
+
+.last_selected {
+  font-weight: normal;
+  display: inline;
+}
+
+.hidden {
+  visibility: hidden;
+  display: none !important; 
+}
+
+.histogram {
+  display: inline;
+  padding-left: 1em;
+}
new file mode 100644
--- /dev/null
+++ b/mail/base/content/multimessageview.xhtml
@@ -0,0 +1,90 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
+
+<!-- ***** 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 Thunderbird multiple message summary pane.
+   -
+   - The Initial Developer of the Original Code is
+   - Mozilla Messaging.
+   - Portions created by the Initial Developer are Copyright (C) 2009
+   - the Initial Developer. All Rights Reserved.
+   -
+   - Contributor(s):
+   -   David Ascher <dascher@mozillamessaging.com>
+   -
+   - Alternatively, the contents of this file may be used under the terms of
+   - either 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 LGPL or the GPL. 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 ***** -->
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
+                      "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"
+  [
+  <!ENTITY % brandDTD SYSTEM "chrome://branding/locale/brand.dtd">
+  %brandDTD;
+  <!ENTITY % globalDTD SYSTEM "chrome://global/locale/global.dtd">
+  %globalDTD;
+  <!ENTITY % startDTD SYSTEM "chrome://messenger/locale/multimessageview.dtd">
+  %startDTD;
+  ]>
+
+<html xmlns="http://www.w3.org/1999/xhtml"
+      xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+    <head>
+        <link rel="stylesheet" media="screen" type="text/css"
+              href="chrome://messenger/skin/messageHeader.css"/>
+        <link rel="stylesheet" media="screen" type="text/css"
+              href="chrome://messenger/skin/multimessageview.css"/>
+        <link rel="stylesheet" media="screen" type="text/css"
+              href="chrome://messenger/skin/tagColors.css"/>
+        <script type="application/x-javascript"
+                src="chrome://messenger/content/multimessageview.js"></script>
+        <title>&window.title;</title>
+    </head>
+<body>
+    <div id="multimessageview">
+        <div id="headingwrappertable">
+            <div id="headingwrapper">
+                <div class="heading" id="heading">&selectedmessages.label;</div>
+                <div id="buttonbox"
+                     xmlns:html="http://www.w3.org/1999/xhtml"
+                     xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+                    <hbox id="buttonhbox" align="start">
+                        <button id="archive" class="multimessage button"
+                                onclick="window.top.MsgArchiveSelectedMessages(null)">&archive.label;</button>
+                        <button id="trash" class="multimessage button trashButton"
+                                onclick="window.top.DefaultController.doCommand('cmd_delete');"/>
+                    </hbox>
+                </div>
+            </div>
+        </div>
+        <div id="messages">
+            <div id="messagelist"/>
+            <p>
+                <span class="info" id="size"></span> <span class="info" id="notice"></span>
+            </p>
+        </div>
+    </div>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/mail/base/content/selectionsummaries.js
@@ -0,0 +1,759 @@
+/* ***** 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 multiple message preview pane
+ *
+ * The Initial Developer of the Original Code is
+ *   Mozilla Messaging
+ * Portions created by the Initial Developer are Copyright (C) 2009
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   David Ascher <dascher@mozillamessaging.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either 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 ***** */
+
+
+Components.utils.import("resource://gre/modules/DownloadUtils.jsm");
+Components.utils.import("resource://gre/modules/PluralForm.jsm");
+Components.utils.import("resource://app/modules/gloda/mimemsg.js");
+
+let gSelectionSummaryStrings = {
+  selectedNMessages: "selectedNMessages",
+  acrossNThreads: "acrossNThreads",
+  numMsgs: "numMsgs",
+  countUnread: "countUnread",
+  Nmessages: "Nmessages",
+  messagesSize: "messagesSize",
+  yesterday: "yesterday",
+  noticeText: "noticeText",
+  noSubject: "noSubject",
+}
+
+/**
+ * loadSelectionSummaryStrings does the routine localization of non-pluralized
+ * strings, populating the gSelectionSummaryStrings array based on the current
+ * locale.
+ */
+function loadSelectionSummaryStrings()
+{
+  // convert strings to those in the string bundle
+  let getStr = function(string) document.getElementById("bundle_multimessages").getString(string);
+  var strBundleService = Components.classes["@mozilla.org/intl/stringbundle;1"].getService();
+  strBundleService = strBundleService.QueryInterface(Components.interfaces.nsIStringBundleService);
+    for (let [name, value] in Iterator(gSelectionSummaryStrings))
+      gSelectionSummaryStrings[name] = typeof value == "string" ?
+        getStr(value) : value.map(gSelectionSummaryStrings);
+}
+
+loadSelectionSummaryStrings();
+
+/**
+ * pickMessagePane is the toggle to figure out whether to use the standard
+ * message pane used to display message bodies (& headers), or whether to
+ * display an HTML iframe used for the multiple message summaries.
+ *
+ * @param visiblePaneId
+ *        the ID of the pane that we want to make be the visible one.
+ * @return the DOM element corresponding to the selected pane.
+ *
+ */
+function pickMessagePane(visiblePaneId)
+{
+  var paneIds = ['singlemessage', 'multimessage'];
+  // when we want to do folder and account summaries, we just need to add
+  // XUL elements for them, and add them to this list.
+  //               'foldersummary', 'accountsummary'];
+  for (let [,paneId] in Iterator(paneIds))
+    document.getElementById(paneId).hidden = paneId != visiblePaneId;
+
+  return document.getElementById(visiblePaneId);
+}
+
+// Ah, wouldn't it be nice if there was platform code to do the following...
+
+/**
+ * the equivalent of jQuery's addClass.  Avoids duplicates, nothing fancy.
+ *
+ * @param node
+ *        any old DOM node
+ * @param classname
+ *        a string, which will be added as a CSS class
+ */
+function _mm_addClass(node, classname)
+{
+  let classes = [];
+  if (node.hasAttribute('class'))
+    classes = node.getAttribute('class').split(' ');
+
+  for each (klass in classes) {
+    if (klass == classname) // already have it
+      return;
+  }
+  classes.push(classname);
+  node.setAttribute('class', classes.join(' '));
+}
+
+/**
+ * the equivalent of jQuery's removeClass.  Doesn't freak if the class name
+ * isn't in the class attribute.
+ *
+ * @param node
+ *        any old DOM node
+ * @param classname
+ *        a string, which will be removed from the class set.
+ */
+function _mm_removeClass(node, classname)
+{
+  if (! node.hasAttribute('class'))
+    return;
+  let classes = node.getAttribute('class').split(' ');
+  let newclasses = [];
+  for each (klass in classes) {
+    if (klass != classname)
+      newclasses.push(klass);
+  }
+  node.setAttribute('class', newclasses.join(' '));
+}
+
+
+/**
+ * the MultiMessageSummary class is responsible for populating the message pane
+ * with a reasonable summary of a set of messages that span more than one
+ * thread.
+ *
+ * It uses the same multimessage iframe as ThreadSummary, so both it
+ * and ThreadSummary should be careful to clean up the other's work
+ * before inserting their DOM nodes into the frame.
+ *
+ * There's a two phase process: build the framework based on what's available
+ * from the msgHdr itself, and then spawn an aysnc Gloda query which will
+ * fetch the snippets, tags, etc.
+ *
+ * @param msgURIs
+ *        array of message URIs
+ */
+
+function MultiMessageSummary(msgURIs) {
+  this._msgURIs = msgURIs;
+}
+
+MultiMessageSummary.prototype = {
+  init: function() {
+    this._msgHdrs = new Array();
+    this._glodaQueries = [];
+    this._headerNodes = {};
+    this._snippetNodes = {};
+    this._tagsNodes = {};
+    for (var i = 0; i < this._msgURIs.length; ++i)
+      this._msgHdrs.push(messenger.msgHdrFromURI(this._msgURIs[i]));
+
+    this.summarize();
+  },
+
+  /**
+   * Given a name (as one sees in email headers), strip eventual
+   * leading/trailing quotes (both single and double).
+   *
+   * @param senderName
+   *     name which might be quoted
+   * @return
+   *     name without quotes
+   **/
+  stripQuotes: function(senderName) {
+    if ((senderName[0] == "'" && senderName[senderName.length-1] == "'") ||
+        (senderName[0] == '"' && senderName[senderName.length-1] == '"'))
+      senderName = senderName.slice(1, -1);
+    return senderName;
+  },
+
+  /**
+   * Fill in the summary pane describing the selected messages
+   **/
+  summarize: function() {
+    let htmlpane = pickMessagePane('multimessage');
+    // First, we group the messages in threads.
+    // count threads
+    let threads = {};
+    let numThreads = 0;
+    for (let [,msgHdr] in Iterator(this._msgHdrs))
+    {
+      if (! threads[msgHdr.threadId]) {
+        threads[msgHdr.threadId] = [msgHdr];
+        numThreads += 1;
+      }
+      else
+      {
+        threads[msgHdr.threadId].push(msgHdr);
+      }
+    }
+
+    // set the heading based on the number of messages & threads
+    let heading = htmlpane.contentDocument.getElementById('heading');
+    _mm_addClass(heading, "heading");
+    _mm_addClass(heading, "info");
+
+    let numMessages = this._msgURIs.length;
+    let messagesTitle = PluralForm.get(numMessages, gSelectionSummaryStrings["selectedNMessages"]).replace('#1', numMessages);
+    messagesTitle +=  PluralForm.get(numThreads, gSelectionSummaryStrings["acrossNThreads"]).replace('#1', numThreads);
+
+    heading.innerHTML = messagesTitle;
+
+    // clear the messages list
+    let messagesElt = htmlpane.contentDocument.getElementById('messagelist');
+    while (messagesElt.firstChild)
+      messagesElt.removeChild(messagesElt.firstChild);
+
+    let MAXCOUNT = 100;
+    let count = 0;
+    let maxCountExceeded = false;
+    // we could consider sorting differently someday
+    for (let [thread,msgs] in Iterator(threads))
+    {
+      count += 1;
+      if (count > MAXCOUNT) {
+        maxCountExceeded = true;
+        break;
+      }
+      let countUnread = 0;
+      let countStarred = 0;
+      let header, subject, tags, countNode;
+      let msg = htmlpane.contentDocument.createElement("div");
+      _mm_addClass(msg, "message");
+      // we'll mark the thread unread if any messages in it are unread
+
+      for (let [, msgHdr] in Iterator(msgs)) {
+        if (! msgHdr.isRead)
+          countUnread += 1;
+        if (msgHdr.isFlagged)
+          countStarred += 1;
+      }
+
+      if (countUnread)
+        _mm_addClass(msg, 'unread');
+
+      header = htmlpane.contentDocument.createElement("div");
+      _mm_addClass(header, "header");
+
+      if (countStarred) {
+        _mm_addClass(msg, "starred");
+      }
+
+      let subjectText = msgs[0].mime2DecodedSubject || gSelectionSummaryStrings['noSubject'];
+      // Someday, we might want to handle multi-subject threads
+      subject = htmlpane.contentDocument.createElement("div");
+      _mm_addClass(subject, "subject");
+      subject.innerHTML = escapeXMLchars(subjectText);
+
+
+      let authorText = " " + msgs[0].mime2DecodedAuthor;
+      // Someday, we might want to handle multi-subject threads
+      let author = htmlpane.contentDocument.createElement("div");
+      _mm_addClass(author, "author");
+      author.innerHTML = escapeXMLchars(authorText);
+
+      let wrappedsubject = htmlpane.contentDocument.createElement("div");
+      _mm_addClass(wrappedsubject, 'wrappedsubject');
+      let star = htmlpane.contentDocument.createElement("div");
+      _mm_addClass(star, "star");
+      wrappedsubject.appendChild(subject);
+      wrappedsubject.appendChild(author);
+
+      header.appendChild(wrappedsubject);
+
+      // this feels ugly -- is there a better way to pass in data?
+      subject.msgs = msgs;
+      subject.addEventListener("click", function() {
+        selectMultipleMessagesByMsgHdr(this.msgs)
+      }, true);
+      _mm_addClass(subject, "link");
+
+      msg.appendChild(header);
+
+      let snippet = htmlpane.contentDocument.createElement("div");
+      _mm_addClass(snippet, "snippet");
+      header.appendChild(snippet);
+
+      tags = htmlpane.contentDocument.createElement("div");
+      _mm_addClass(tags, "tags");
+      header.appendChild(tags);
+
+      // use the first msgHdr in the thread for key purposes for snippets
+      this._snippetNodes[msgs[0].messageKey + msgs[0].folder.URI] = snippet;
+      // for tags, stars, and read/unread status, we want to map
+      // from all messages to one node
+      for each (msgHdr in msgs) {
+        this._headerNodes[msgHdr.messageKey + msgHdr.folder.URI] = header;
+        this._tagsNodes[msgHdr.messageKey + msgHdr.folder.URI] = tags;
+      }
+
+      let numMsgs = msgs.length;
+      countNode = htmlpane.contentDocument.createElement("div");
+      _mm_addClass(countNode, 'count');
+      if (numMsgs > 1) {
+        let label = "(";
+        label += PluralForm.get(numMsgs, gSelectionSummaryStrings["numMsgs"]).replace('#1', numMsgs);
+        if (countUnread)
+          label += PluralForm.get(numMsgs, gSelectionSummaryStrings["countUnread"]).replace('#1', countUnread);
+        label += ")";
+        countNode.innerHTML = label;
+      }
+      msg.appendChild(countNode);
+      countNode.appendChild(star);
+      messagesElt.appendChild(msg);
+    }
+    this.computeSize();
+    this.notifyMaxCountExceeded(numMessages, MAXCOUNT);
+
+    this._glodaQueries.push(Gloda.getMessageCollectionForHeaders(this._msgHdrs, this));
+  },
+
+  /**
+   * compute the size of the messages in the selection and display it
+   * in the element of id "size"
+  **/
+  computeSize: function() {
+    let htmlpane = pickMessagePane('multimessage');
+    let numThreads = 0;
+    let numBytes = 0;
+
+    for (let [,msgHdr] in Iterator(this._msgHdrs))
+      numBytes += msgHdr.messageSize; // XXX do something about news?
+    let [size, unit] = DownloadUtils.convertByteUnits(numBytes);
+    let sizeText = replaceInsert(gSelectionSummaryStrings.messagesSize, 1, size);
+    sizeText = replaceInsert(sizeText, 2, unit);
+    htmlpane.contentDocument.getElementById('size').innerHTML = sizeText;
+  },
+
+  /** compute the size of the messages in the selection and display it
+   * in the element of id "size"
+  **/
+  notifyMaxCountExceeded: function(numMessages, maxCount) {
+    let htmlpane = pickMessagePane('multimessage');
+    let notice = htmlpane.contentDocument.getElementById('notice');
+    if (numMessages > maxCount)
+    {
+      let noticeText = gSelectionSummaryStrings.noticeText;
+      noticeText = replaceInsert(noticeText, 1, numMessages);
+      noticeText = replaceInsert(noticeText, 2, maxCount);
+      notice.innerHTML = noticeText;
+      _mm_removeClass(notice, 'hidden');
+    } else {
+      _mm_addClass(notice, 'hidden');
+    }
+  },
+
+  // these are listeners for the gloda collections.
+  onItemsAdded: function(aItems) {
+  },
+  onItemsModified: function(aItems) {
+    this.processItems(aItems);
+  },
+  onItemsRemoved: function(aItems) {
+  },
+
+  /**
+   * Given a set of items from a gloda collection, process them and update
+   * the display accordingly.
+   *
+   * @param aItems
+   *        contents of a gloda collection
+  **/
+  processItems: function(aItems) {
+    var tagService = Components.classes["@mozilla.org/messenger/tagservice;1"]
+                     .getService(Components.interfaces.nsIMsgTagService);
+
+    let seenTagNode = {};
+    for (let [,glodaMsg] in Iterator(aItems)) {
+      let messageKey = glodaMsg.messageKey;
+      let domkey = messageKey + glodaMsg.folder.uri;
+
+      if (this._headerNodes) {
+        let headerNode = this._headerNodes[domkey];
+        // unread and starred will get set if any of the messages in a
+        // collapsed thread qualify
+        if (headerNode) {
+          if (! glodaMsg.read)
+            _mm_addClass(headerNode, "unread");
+          else
+            _mm_removeClass(headerNode, "unread");
+          if (glodaMsg.starred)
+            _mm_addClass(headerNode, "starred");
+          else
+            _mm_removeClass(headerNode, "starred");
+        }
+      }
+      if (this._snippetNodes) {
+        let snippetNode = this._snippetNodes[domkey];
+
+        MsgHdrToMimeMessage(glodaMsg.folderMessage, null, function(aMsgHdr, aMimeMsg) {
+          if (aMimeMsg == null)
+            return;
+
+          let text = Gloda.getMessageContent(glodaMsg, aMimeMsg).getContentSnippet(101);
+          if (snippetNode && text)
+          {
+            let kSnippetLength = 100;
+            if (text.length > kSnippetLength)
+              text = text.substring(0, kSnippetLength) + "\u2026"; // ellipsis
+            snippetNode.innerHTML = escapeXMLchars(text);
+          }
+        });
+
+      }
+      if (this._tagsNodes) {
+        // for tags, we need to do some fancy stuff, to figure out the set
+        // of tags that correspond to all of the messages in a collapsed
+        // thread.
+        let key = messageKey + glodaMsg.folder.uri;
+        let tagsNode = this._tagsNodes[key];
+        if (tagsNode) {
+          if (! seenTagNode[tagsNode]) {
+            // We haven't processed a message from this thread before
+            while (tagsNode.childNodes.length) {
+              // get rid of all tags
+              tagsNode.removeChild(tagsNode.firstChild);
+            }
+            seenTagNode[tagsNode] = {};
+          }
+          for each (let [,tag] in Iterator(glodaMsg.tags)) {
+            // have we already added this tag to the thread?
+            if (!(seenTagNode[tagsNode][tag.tag])) {
+              let tagNode = tagsNode.ownerDocument.createElement('span');
+              // see tagColors.css
+              let colorClass = "blc-" + tagService.getColorForKey(tag.key).substr(1);
+              _mm_addClass(tagNode, "tag " + tag.tag + " " + colorClass);
+              tagNode.innerHTML = tag.tag;
+              tagsNode.appendChild(tagNode);
+              seenTagNode[tagsNode][tag.tag] = true;
+            }
+          }
+        }
+      }
+    }
+  },
+
+  onQueryCompleted: function(aCollection) {
+    if (aCollection.items.length) {
+      this.processItems(aCollection.items);
+    }
+  }
+}
+
+
+/**
+ * the ThreadSummary class is responsible for populating the message pane
+ * with a reasonable summary of a set of messages that are are in a single
+ * thread.
+ *
+ * It uses the same multimessage iframe as MultiMessageSummary, so both it
+ * and MultiMessageSummary should be careful to clean up the other's work
+ * before inserting their DOM nodes into the frame.
+ *
+ * There's a two phase process: build the framework based on what's available
+ * from the msgHdr itself, and then spawn an aysnc Gloda query which will
+ * fetch the snippets, tags, etc.
+ *
+ * @param msgURIs
+ *        array of message URIs
+ */
+
+function ThreadSummary(msgURIs)
+{
+  this._msgURIs = msgURIs;
+}
+
+ThreadSummary.prototype = {
+  __proto__: MultiMessageSummary.prototype,
+
+  summarize: function() {
+    this._headerNodes = {};
+    this._snippetNodes = {};
+
+    let htmlpane = pickMessagePane('multimessage');
+
+    let firstMsgHdr = messenger.msgHdrFromURI(this._msgURIs[0]);
+    let numMessages = this._msgURIs.length;
+    let subject = (firstMsgHdr.mime2DecodedSubject || gSelectionSummaryStrings["noSubject"])
+       + " "
+       + PluralForm.get(numMessages, gSelectionSummaryStrings["Nmessages"]).replace('#1', numMessages);
+    let heading = htmlpane.contentDocument.getElementById('heading');
+    heading.setAttribute("class", "heading");
+    heading.innerHTML = escapeXMLchars(subject);
+
+    let messagesElt = htmlpane.contentDocument.getElementById('messagelist');
+    while (messagesElt.firstChild)
+      messagesElt.removeChild(messagesElt.firstChild);
+
+    let headerParser = Components.classes["@mozilla.org/messenger/headerparser;1"]
+                                    .getService(Components.interfaces.nsIMsgHeaderParser);
+    let msgHdrs = new Array();
+    let count = 0;
+    const MAXCOUNT = 100;
+    let maxCountExceeded = false;
+    for (var i = 0; i < this._msgURIs.length; ++i)
+    {
+      count += 1;
+      if (count > MAXCOUNT) {
+        maxCountExceeded = true;
+        break;
+      }
+      let msgHdr, msg, header, sender, snippet, tags;
+      msgHdr = messenger.msgHdrFromURI(this._msgURIs[i]);
+      msgHdrs.push(msgHdr);
+      msg = htmlpane.contentDocument.createElement("div");
+      let key = msgHdr.messageKey + msgHdr.folder.URI;
+
+      _mm_addClass(msg, "message");
+
+      if (! msgHdr.isRead)
+        _mm_addClass(msg, "unread");
+
+      header = htmlpane.contentDocument.createElement("div");
+      _mm_addClass(header, "header");
+      if (msgHdr.isFlagged)
+        _mm_addClass(msg, "starred");
+
+      let senderName = headerParser.extractHeaderAddressNames(msgHdr.mime2DecodedAuthor);
+      senderName = this.stripQuotes(senderName);
+      sender = htmlpane.contentDocument.createElement("div");
+      sender.msgHdr = msgHdr;
+      _mm_addClass(sender, "sender");
+      sender.addEventListener("click", function(e) {
+        // if the msg is the first message in a collapsed thread, we need to
+        // uncollapse it.
+        let origRowCount = gDBView.rowCount;
+        let viewIndex = gDBView.findIndexOfMsgHdr(e.target.msgHdr, true);
+        gDBView.selectFolderMsgByKey(this.folder, this.msgKey);
+        if (gDBView.rowCount != origRowCount)
+          gDBView.selectionChanged();
+      }, true);
+      _mm_addClass(sender, "link");
+      sender.innerHTML = escapeXMLchars(senderName); // escape?
+      sender.folder = msgHdr.folder;
+      sender.msgKey = msgHdr.messageKey;
+
+      let wrappedsender = htmlpane.contentDocument.createElement("div");
+      _mm_addClass(wrappedsender, "wrappedsender");
+      let star = htmlpane.contentDocument.createElement("div");
+      _mm_addClass(star, "star");
+      wrappedsender.appendChild(sender);
+
+      header.appendChild(wrappedsender);
+
+      snippet = htmlpane.contentDocument.createElement("div");
+      _mm_addClass(snippet, "snippet");
+      header.appendChild(snippet);
+
+      tags = htmlpane.contentDocument.createElement("div");
+      _mm_addClass(tags, "tags");
+      header.appendChild(tags);
+
+      this._headerNodes[key] = msg;
+      this._snippetNodes[key] = snippet;
+      this._tagsNodes[key] = tags;
+
+      msg.appendChild(header);
+      let dateNode = htmlpane.contentDocument.createElement("div");
+      dateNode.innerHTML = makeFriendlyDateAgo(new Date(msgHdr.date/1000));
+      dateNode.appendChild(star);
+      _mm_addClass(dateNode, "date");
+      msg.appendChild(dateNode);
+      messagesElt.appendChild(msg);
+    }
+    // stash somewhere so it doesn't get GC'ed
+    this._glodaQueries.push(Gloda.getMessageCollectionForHeaders(msgHdrs, this));
+    this.notifyMaxCountExceeded(numMessages, MAXCOUNT);
+
+    this.computeSize();
+  }
+}
+
+// We use a global to prevent GC of gloda collection (and we reuse it to prevent
+// leaks).  Without a global, the GC is aggressive enough that the gloda query
+// is gone before it returns.
+var gSummary;
+
+
+/**
+ * Given an array of message URIs which are all in the
+ * same thread, summarize them.
+ *
+ * @param selectedMsgUris
+ *        array of message URIs
+ */
+function summarizeThread(selectedMsgUris)
+{
+  if (selectedMsgUris.length == 0)
+    return;
+
+  gSummary = new ThreadSummary(selectedMsgUris);
+  gSummary.init();
+}
+
+/**
+ * Given an array of message URIs, cause the message pane
+ * to display a summary of them.
+ *
+ * @param selectedMsgUris
+ *        array of message URIs
+ */
+function summarizeMultipleSelection(selectedMsgUris)
+{
+  if (selectedMsgUris.length == 0)
+    return;
+
+  gSummary = new MultiMessageSummary(selectedMsgUris);
+  gSummary.init();
+}
+
+/**
+ * Given an array of nsMsgHdrs, select all of them.  This will uncollapse
+ * threads that are collapsed as necessary.
+ *
+ * @param msgHdrs
+ *        array of msgHdr's
+ */
+function selectMultipleMessagesByMsgHdr(msgHdrs)
+{
+  let treeView = gDBView.QueryInterface(Components.interfaces.nsITreeView);
+  if (msgHdrs.length == 1) {
+    gDBView.selectFolderMsgByKey(msgHdrs[0].folder, msgHdrs[0].messageKey);
+  } else {
+    let treeSelection = treeView.selection;
+    treeSelection.clearSelection();
+    for (let [, msgHdr] in Iterator(msgHdrs))
+    {
+      let viewIndex = gDBView.findIndexOfMsgHdr(msgHdr, false);
+      let thread = gDBView.getThreadContainingIndex(viewIndex);
+      let flags = gDBView.getFlagsAt(viewIndex);
+
+      if (flags & Components.interfaces.nsMsgMessageFlags.Elided)
+        treeView.toggleOpenState(viewIndex);
+
+      treeSelection.rangedSelect(viewIndex, viewIndex, true);
+    }
+  }
+}
+
+/**
+ * Helper function to generate a localized "friendly" representation of
+ * time relative to the present.  If the time input is "today", it returns
+ * a string corresponding to just the time.  If it's yesterday, it returns
+ * "yesterday" (localized).  If it's in the last week, it returns the day
+ * of the week. If it's before that, it returns the date.
+ *
+ * @param time
+ *        the time (better be in the past!)
+ * @return The string with a "human-friendly" representation of that time
+ *        relative to now.
+ */
+function makeFriendlyDateAgo(time)
+{
+  let dts = Components.classes["@mozilla.org/intl/scriptabledateformat;1"]
+                      .getService(Components.interfaces.nsIScriptableDateFormat);
+
+  // Figure out when today begins
+  let now = new Date();
+  let today = new Date(now.getFullYear(), now.getMonth(),
+                       now.getDate());
+
+  // Get the end time to display
+  let end = time;
+
+  // Figure out if the end time is from today, yesterday,
+  // this week, etc.
+  let dateTime;
+  let kDayInMsecs = 24 * 60 * 60 * 1000;
+  let k6DaysInMsecs = 6 * kDayInMsecs;
+  if (end >= today) {
+    // activity finished after today started, show the time
+    dateTime = dts.FormatTime("", dts.timeFormatNoSeconds,
+                                  end.getHours(), end.getMinutes(),0);
+  } else if (today - end < kDayInMsecs) {
+    // activity finished after yesterday started, show yesterday
+    dateTime = gSelectionSummaryStrings.yesterday;
+  } else if (today - end < k6DaysInMsecs) {
+    // activity finished after last week started, show day of week
+    dateTime = end.toLocaleFormat("%A");
+  } else if (now.getFullYear() == end.getFullYear()) {
+    // activity must have been from some time ago.. show month/day
+    let month = end.toLocaleFormat("%B");
+    // Remove leading 0 by converting the date string to a number
+    let date = Number(end.toLocaleFormat("%d"));
+    //dateTime = replaceInsert(this.text.monthDate, 1, month);
+    dateTime = replaceInsert("#1 #2", 1, month);
+    dateTime = replaceInsert(dateTime, 2, date);
+  } else {
+    // not this year, so show year as wel
+    let month = end.toLocaleFormat("%B");
+    let year = end.toLocaleFormat("%Y");
+    // Remove leading 0 by converting the date string to a number
+    let date = Number(end.toLocaleFormat("%d"));
+    //dateTime = replaceInsert(this.text.monthDate, 1, month);
+    dateTime = replaceInsert("#1 #2 #3", 1, month);
+    dateTime = replaceInsert(dateTime, 2, date);
+    dateTime = replaceInsert(dateTime, 3, year);
+  }
+  return dateTime;
+}
+
+/**
+ * Helper function to replace a placeholder string with a real string
+ *
+ * @param aText
+ *        Source text containing placeholder (e.g., #1)
+ * @param aIndex
+ *        Index number of placeholder to replace
+ * @param aValue
+ *        New string to put in place of placeholder
+ * @return The string with placeholder replaced with the new string
+ */
+function replaceInsert(aText, aIndex, aValue)
+{
+  return aText.replace("#" + aIndex, aValue);
+}
+
+/**
+ * Helper function to escape some XML chars, so they display properly in
+ * innerHTML.
+ *
+ * @param s
+ *        input text
+ * @return The string with <, >, and & replaced by the corresponding entities.
+ */
+function escapeXMLchars(s)
+{
+    return s.replace(/[<>&]/g, function(s) {
+        switch (s) {
+            case "<": return "&lt;";
+            case ">": return "&gt;";
+            case "&": return "&amp;";
+            default: throw Error("Unexpected match");
+            }
+        }
+    );
+}
+
--- a/mail/base/content/threadPane.js
+++ b/mail/base/content/threadPane.js
@@ -111,22 +111,46 @@ nsMsgDBViewCommandUpdater.prototype =
     goUpdateCommand("button_junk");
   },
 
   updateNextMessageAfterDelete : function()
   {
     SetNextMessageAfterDelete();
   },
 
+  summarizeSelection: function()
+  {
+    let selectedMsgUris = GetSelectedMessages();
+    if (!selectedMsgUris || (selectedMsgUris.length == 1)) {
+      pickMessagePane("singlemessage");
+      return;
+    }
+
+    if (! gPrefBranch.getBoolPref("mail.operate_on_msgs_in_collapsed_threads")) {
+      ClearMessagePane();
+      return;
+    }
+
+    let firstThreadId = messenger.msgHdrFromURI(selectedMsgUris[0]).threadId;
+    for (let i = 1; i < selectedMsgUris.length; ++i)
+    {
+      let msgHdr = messenger.msgHdrFromURI(selectedMsgUris[i]);
+      if (msgHdr.threadId != firstThreadId) // at least more than one thread
+        return summarizeMultipleSelection(selectedMsgUris);
+    }
+    // must be just one thread.
+    summarizeThread(selectedMsgUris);
+  },
+
   QueryInterface : function(iid)
    {
      if (iid.equals(Components.interfaces.nsIMsgDBViewCommandUpdater) ||
          iid.equals(Components.interfaces.nsISupports))
        return this;
-	  
+
      throw Components.results.NS_NOINTERFACE;
     }
 }
 
 function HandleColumnClick(columnID)
 {
   const columnMap = {dateCol: 'byDate',
                      receivedCol: 'byReceived',
--- a/mail/base/jar.mn
+++ b/mail/base/jar.mn
@@ -69,15 +69,18 @@ messenger.jar:
 *   content/messenger/viewSourceOverlay.xul         (content/viewSourceOverlay.xul)
 *   content/messenger/configEditorOverlay.xul       (content/configEditorOverlay.xul)
     content/messenger/composerOverlay.css           (content/composerOverlay.css)
     content/messenger/threadPane.js                 (content/threadPane.js)
 #ifdef XP_MACOSX
     content/messenger/macMenuOverlay.xul            (content/macMenuOverlay.xul)
 #endif
 *   content/messenger/baseMenuOverlay.xul           (content/baseMenuOverlay.xul)
+    content/messenger/selectionsummaries.js         (content/selectionsummaries.js)
+    content/messenger/multimessageview.css          (content/multimessageview.css)
+    content/messenger/multimessageview.xhtml        (content/multimessageview.xhtml)
 
 comm.jar:
 % content communicator %content/communicator/ xpcnativewrappers=yes
 *  content/communicator/contentAreaClick.js         (content/contentAreaClick.js)
 *  content/communicator/utilityOverlay.xul          (content/utilityOverlay.xul)
 *  content/communicator/utilityOverlay.js           (content/utilityOverlay.js)
 *  content/communicator/nsContextMenu.js            (content/nsContextMenu.js)
--- a/mail/locales/en-US/chrome/messenger/messenger.properties
+++ b/mail/locales/en-US/chrome/messenger/messenger.properties
@@ -169,17 +169,16 @@ inboxFolderName=Inbox
 trashFolderName=Trash
 sentFolderName=Sent
 draftsFolderName=Drafts
 templatesFolderName=Templates
 outboxFolderName=Outbox
 junkFolderName=Junk
 archivesFolderName=Archives
 
-
 # Error message for special folder deletion on imap accounts
 # LOCALIZATION NOTE (specialFolderDeletionErr): Do not translate "IMAP" in the line below
 specialFolderDeletionErr=Deletion of special folder %S is not allowed for IMAP accounts.
 specialFolderDeletionErrTitle=Special Folder Deletion
 
 # "Normal" priority is often blank,
 # depending on the consumers of these strings
 priorityLowest=Lowest
new file mode 100644
--- /dev/null
+++ b/mail/locales/en-US/chrome/messenger/multimessageview.dtd
@@ -0,0 +1,3 @@
+<!ENTITY window.title             "Message Summary">
+<!ENTITY selectedmessages.label   "Selected Messages">
+<!ENTITY archive.label            "archive">
new file mode 100644
--- /dev/null
+++ b/mail/locales/en-US/chrome/messenger/multimessageview.properties
@@ -0,0 +1,19 @@
+# LOCALIZATION NOTE (selectedNMessages, acrossNThreads): Semi-colon list of plural forms.
+# See: http://developer.mozilla.org/en/docs/Localization_and_Plurals
+# #1 number of messages
+# example: Selected: 23 messages
+selectedNMessages=Selected: #1 message;Selected: #1 messages
+# #1 number of threads
+# example: across 3 threads
+acrossNThreads= across #1 thread; across #1 threads
+
+numMsgs=#1 message;#1 messages
+countUnread=, #1 unread;, #1 unread
+Nmessages=(#1 message);(#1 messages)
+
+noSubject=(no subject)
+
+# thread and multiple message selection summaries
+messagesSize=These messages take up: #1 #2.
+yesterday=yesterday
+noticeText= (Note: #1 messages are selected, the first #2 are shown)
--- a/mail/locales/jar.mn
+++ b/mail/locales/jar.mn
@@ -1,21 +1,24 @@
+
 #filter substitution
 
 @AB_CD@.jar:
 % locale messenger @AB_CD@ %locale/@AB_CD@/messenger/
 % override chrome://mozapps/locale/downloads/settingsChange.dtd chrome://messenger/locale/downloads/settingsChange.dtd
 % override chrome://global/locale/netError.dtd chrome://messenger/locale/netError.dtd
   locale/@AB_CD@/messenger/credits.dtd                                  (%chrome/messenger/credits.dtd)
   locale/@AB_CD@/messenger/aboutDialog.dtd                              (%chrome/messenger/aboutDialog.dtd)
   locale/@AB_CD@/messenger/aboutRights.dtd                              (%chrome/messenger/aboutRights.dtd)
   locale/@AB_CD@/messenger/aboutRights.properties                       (%chrome/messenger/aboutRights.properties)
   locale/@AB_CD@/messenger/systemIntegrationDialog.dtd                  (%chrome/messenger/systemIntegrationDialog.dtd)  
   locale/@AB_CD@/messenger/virtualFolderProperties.dtd                  (%chrome/messenger/virtualFolderProperties.dtd)
   locale/@AB_CD@/messenger/virtualFolderListDialog.dtd                  (%chrome/messenger/virtualFolderListDialog.dtd)
+  locale/@AB_CD@/messenger/multimessageview.properties                  (%chrome/messenger/multimessageview.properties)
+  locale/@AB_CD@/messenger/multimessageview.dtd                         (%chrome/messenger/multimessageview.dtd)
   locale/@AB_CD@/messenger/mailOverlay.dtd                              (%chrome/messenger/mailOverlay.dtd)
   locale/@AB_CD@/messenger/messenger.dtd                                (%chrome/messenger/messenger.dtd)
   locale/@AB_CD@/messenger/baseMenuOverlay.dtd                          (%chrome/messenger/baseMenuOverlay.dtd)
   locale/@AB_CD@/messenger/tabmail.dtd                                  (%chrome/messenger/tabmail.dtd)
   locale/@AB_CD@/messenger/msgAccountCentral.dtd                        (%chrome/messenger/msgAccountCentral.dtd)
   locale/@AB_CD@/messenger/SearchDialog.dtd                             (%chrome/messenger/SearchDialog.dtd)
   locale/@AB_CD@/messenger/AccountManager.dtd                           (%chrome/messenger/AccountManager.dtd)
   locale/@AB_CD@/messenger/AccountWizard.dtd                            (%chrome/messenger/AccountWizard.dtd)
--- a/mail/themes/gnomestripe/jar.mn
+++ b/mail/themes/gnomestripe/jar.mn
@@ -20,16 +20,17 @@ classic.jar:
   skin/classic/messenger/junkMail.css                         (mail/junkMail.css)
   skin/classic/messenger/folderMenus.css                      (mail/folderMenus.css)
   skin/classic/messenger/folderPane.css                       (mail/folderPane.css)
   skin/classic/messenger/subscribe.css                        (mail/subscribe.css)
   skin/classic/messenger/virtualFolderListDialog.css          (mail/virtualFolderListDialog.css)
   skin/classic/messenger/searchDialog.css                     (mail/searchDialog.css)
   skin/classic/messenger/msgSelectOffline.css                 (mail/msgSelectOffline.css)
   skin/classic/messenger/filterDialog.css                     (mail/filterDialog.css)
+  skin/classic/messenger/multimessageview.css                 (mail/multimessageview.css)
   skin/classic/messenger/dialogs.css                          (mail/dialogs.css)
   skin/classic/messenger/newmailalert.css                     (mail/newmailalert.css)
 * skin/classic/messenger/tabmailBindings.xml                  (mail/tabmailBindings.xml)
   skin/classic/messenger/tabmail.css                          (mail/tabmail.css)
   skin/classic/messenger/editContactOverlay.css               (mail/editContactOverlay.css)
   skin/classic/messenger/starred48.png                        (mail/starred48.png)
   skin/classic/messenger/contactStarred.png                   (mail/contactStarred.png)
   skin/classic/messenger/starContact.png                      (mail/starContact.png)
new file mode 100644
--- /dev/null
+++ b/mail/themes/gnomestripe/mail/multimessageview.css
@@ -0,0 +1,61 @@
+@import url("chrome://messenger/content/multimessageview.css");
+
+/* gnomestripe-specific overrides for multimessageview.css*/
+
+/* mostly it's about CSS colors not being reliable */
+
+body {
+  background-color: white;
+}
+
+.heading.info {
+  color: CaptionText;
+}
+
+.count, .date {
+  color: InactiveCaptionText;
+}
+
+.info,
+.message > .header > .snippet,
+.message > .header > .senders {
+  color: GrayText;
+}
+
+
+/* buttons are always tricky */
+
+
+.button {
+  -moz-appearance: button;
+  font: message-box;
+  min-width: 32px !important;
+  margin-bottom: 2em;
+}
+
+/* and every trash is different */
+
+#trash {
+  min-height: 28px !important;
+  min-width: 32px !important;
+  padding: 0px;
+}
+
+.trashButton {
+  padding: 2px;
+  list-style-image: url("moz-icon://stock/gtk-delete?size=menu");
+  min-height: 16px !important;
+  min-width: 16px !important;
+  width: 16px;
+  height: 16px;
+}
+
+.star {
+  width: 12px;
+  height: 12px;
+  margin-right: 0.5em;
+}
+
+.starred .star {
+  background-image: url("chrome://messenger/skin/icons/flag-col.png");
+}
--- a/mail/themes/pinstripe/jar.mn
+++ b/mail/themes/pinstripe/jar.mn
@@ -1,10 +1,11 @@
 classic.jar:
 % skin messenger classic/1.0 %skin/classic/messenger/
+  skin/classic/messenger/multimessageview.css                    (mail/multimessageview.css)
   skin/classic/messenger/dialogs.css                             (mail/dialogs.css)
   skin/classic/messenger/messenger.css                           (mail/messenger.css)
   skin/classic/messenger/primaryToolbar.css                      (mail/primaryToolbar.css)
   skin/classic/messenger/accountCentral.css                      (mail/accountCentral.css)
   skin/classic/messenger/accountCreation.css                     (mail/accountCreation.css)
   skin/classic/messenger/accountManage.css                       (mail/accountManage.css)
   skin/classic/messenger/accountWizard.css                       (mail/accountWizard.css)
   skin/classic/messenger/messageHeader.css                       (mail/messageHeader.css)
new file mode 100644
--- /dev/null
+++ b/mail/themes/pinstripe/mail/multimessageview.css
@@ -0,0 +1,72 @@
+@import url("chrome://messenger/content/multimessageview.css");
+
+/* pinstripe-specific overrides for multimessageview.css*/
+
+.button {
+  vertical-align: middle;
+  margin: 0px 2px;
+  -moz-margin-start: 0px;
+  -moz-margin-end: 5px;
+  -moz-appearance: none;
+  border: 1px solid #5F5F5F;
+  -moz-border-radius: 4px;
+  background: url(chrome://global/skin/icons/white-gray-gradient.gif) #A09E9D repeat-x top center;
+  min-height: 0;
+  min-width: 0;
+  padding: 3px;
+  min-height: 16px;
+}
+
+.button:hover:active:not([disabled="true"]) {
+   background-image: url(chrome://global/skin/icons/white-gray-gradient-active.gif);
+}
+
+.dualButton { 
+  -moz-appearance: dualbutton;
+}
+
+.dualButton > .button-menubutton-button {
+  -moz-appearance: none;
+  padding: 0;
+  margin: 0;
+  -moz-padding-start: 0px;
+  -moz-padding-end: 0px;
+  -moz-margin-start: 0px;
+  -moz-margin-end: 0px;
+  min-width: 1em;
+  min-height: 1ex;
+}
+
+.multimessage {
+  min-height: 15px;
+  margin-top: 3px;
+  margin-bottom: 3px;
+}
+
+.starred .star {
+  background-image: url("chrome://messenger/skin/icons/flaggedmail.png");
+}
+
+.info {
+  color: GrayText;
+}
+
+.heading.info {
+  color: GrayText;
+}
+
+#trash {
+  min-height: 22px !important;
+  min-width: 28px !important;
+  padding-left: 3px;
+}
+
+.trashButton {
+  padding: 2px;
+  list-style-image: url("chrome://messenger/skin/icons/folder-trash.png");
+  min-height: 16px !important;
+  min-width: 16px !important;
+  width: 16px;
+  height: 16px;
+}
+
--- a/mail/themes/qute/jar.mn
+++ b/mail/themes/qute/jar.mn
@@ -1,216 +1,217 @@
-classic.jar:
-+ skin/classic/global/tree.css                                (mail/tree.css)
-+ skin/classic/global/tree/sort-asc.gif                       (mail/icons/sort-asc.gif)
-+ skin/classic/global/tree/sort-dsc.gif                       (mail/icons/sort-dsc.gif)
-  skin/classic/communicator/smileys.css                       (mail/smileys.css)
-% skin messenger classic/1.0 %skin/classic/messenger/
-  skin/classic/messenger/primaryToolbar.css                   (mail/primaryToolbar.css)
-  skin/classic/messenger/accountCentral.css                   (mail/accountCentral.css)
+classic.jar:
++ skin/classic/global/tree.css                                (mail/tree.css)
++ skin/classic/global/tree/sort-asc.gif                       (mail/icons/sort-asc.gif)
++ skin/classic/global/tree/sort-dsc.gif                       (mail/icons/sort-dsc.gif)
+  skin/classic/communicator/smileys.css                       (mail/smileys.css)
+% skin messenger classic/1.0 %skin/classic/messenger/
+  skin/classic/messenger/primaryToolbar.css                   (mail/primaryToolbar.css)
+  skin/classic/messenger/accountCentral.css                   (mail/accountCentral.css)
   skin/classic/messenger/accountCreation.css                  (mail/accountCreation.css)
-  skin/classic/messenger/accountManage.css                    (mail/accountManage.css)
-  skin/classic/messenger/accountWizard.css                    (mail/accountWizard.css)
-  skin/classic/messenger/messageHeader.css                    (mail/messageHeader.css)
-  skin/classic/messenger/messageBody.css                      (mail/messageBody.css)
-  skin/classic/messenger/messageQuotes.css                    (mail/messageQuotes.css)
-  skin/classic/messenger/messenger.css                        (mail/messenger.css)
-  skin/classic/messenger/mailWindow1.css                      (mail/mailWindow1.css)
-  skin/classic/messenger/tagColors.css                        (mail/tagColors.css)
-  skin/classic/messenger/messageWindow.css                    (mail/messageWindow.css)
-  skin/classic/messenger/searchBox.css                        (mail/searchBox.css)
-  skin/classic/messenger/junkMail.css                         (mail/junkMail.css)
-  skin/classic/messenger/folderMenus.css                      (mail/folderMenus.css)
-  skin/classic/messenger/folderPane.css                       (mail/folderPane.css)
-  skin/classic/messenger/subscribe.css                        (mail/subscribe.css)
-  skin/classic/messenger/virtualFolderListDialog.css          (mail/virtualFolderListDialog.css)
-  skin/classic/messenger/searchDialog.css                     (mail/searchDialog.css)
-  skin/classic/messenger/msgSelectOffline.css                 (mail/msgSelectOffline.css)
-  skin/classic/messenger/filterDialog.css                     (mail/filterDialog.css)
-  skin/classic/messenger/dialogs.css                          (mail/dialogs.css)
-  skin/classic/messenger/newmailalert.css                     (mail/newmailalert.css)
-* skin/classic/messenger/tabmailBindings.xml                  (mail/tabmailBindings.xml)
-  skin/classic/messenger/tabmail.css                          (mail/tabmail.css)
-  skin/classic/messenger/editContactOverlay.css               (mail/editContactOverlay.css)
-  skin/classic/messenger/starred48.png                        (mail/starred48.png)
-  skin/classic/messenger/contactStarred.png                   (mail/contactStarred.png)
-  skin/classic/messenger/starContact.png                      (mail/starContact.png)
-  skin/classic/messenger/activity/activity.css                   (mail/activity/activity.css)
-  skin/classic/messenger/activity/buttons.png                    (mail/activity/buttons.png)  
-  skin/classic/messenger/activity/defaultProcessIcon.png         (mail/activity/defaultProcessIcon.png)
-  skin/classic/messenger/activity/defaultEventIcon.png           (mail/activity/defaultEventIcon.png)
-  skin/classic/messenger/activity/defaultWarningIcon.png         (mail/activity/defaultWarningIcon.png)
-  skin/classic/messenger/activity/undoIcon.png                   (mail/activity/undoIcon.png)
-  skin/classic/messenger/activity/syncMailIcon.png               (mail/activity/syncMailIcon.png)
-  skin/classic/messenger/activity/sendMailIcon.png               (mail/activity/sendMailIcon.png)
-  skin/classic/messenger/activity/removeItemIcon.png             (mail/activity/removeItemIcon.png)
-  skin/classic/messenger/activity/addItemIcon.png                (mail/activity/addItemIcon.png)
-  skin/classic/messenger/activity/moveMailIcon.png               (mail/activity/moveMailIcon.png)
-  skin/classic/messenger/activity/copyMailIcon.png               (mail/activity/copyMailIcon.png)
-  skin/classic/messenger/activity/deleteMailIcon.png             (mail/activity/deleteMailIcon.png)
-  skin/classic/messenger/activity/compactMailIcon.png            (mail/activity/compactMailIcon.png)
-  skin/classic/messenger/activity/indexMailIcon.png              (mail/activity/indexMailIcon.png)
-  skin/classic/messenger/addressbook/addressbook.css          (mail/addrbook/addressbook.css)
-  skin/classic/messenger/addressbook/abContactsPanel.css      (mail/addrbook/abContactsPanel.css)
-  skin/classic/messenger/addressbook/cardDialog.css           (mail/addrbook/cardDialog.css)
-  skin/classic/messenger/addressbook/abResultsPane.css        (mail/addrbook/abResultsPane.css)
-  skin/classic/messenger/addressbook/icons/abcard.png         (mail/addrbook/abcard.png)
-  skin/classic/messenger/addressbook/icons/addrbook.png       (mail/addrbook/addrbook.png)
-  skin/classic/messenger/addressbook/icons/ablist.png         (mail/addrbook/ablist.png)
-  skin/classic/messenger/addressbook/icons/addressbook-toolbar.png         (mail/addrbook/addressbook-toolbar.png)
-  skin/classic/messenger/addressbook/icons/addressbook-toolbar-small.png   (mail/addrbook/addressbook-toolbar-small.png)
-  skin/classic/messenger/addressbook/icons/abcard-large.png   (mail/addrbook/abcard-large.png)
-  skin/classic/messenger/addressbook/icons/remote-addrbook.png (mail/addrbook/remote-addrbook.png)
-  skin/classic/messenger/addressbook/icons/remote-addrbook-error.png      (mail/addrbook/remote-addrbook-error.png)
-  skin/classic/messenger/addressbook/icons/secure-remote-addrbook.png     (mail/addrbook/secure-remote-addrbook.png)
-  skin/classic/messenger/messengercompose/messengercompose.css (mail/compose/messengercompose.css)
-  skin/classic/messenger/messengercompose/compose-toolbar.png  (mail/compose/compose-toolbar.png)
-  skin/classic/messenger/messengercompose/compose-toolbar-small.png   (mail/compose/compose-toolbar-small.png)
-  skin/classic/messenger/messengercompose/format-buttons.png  (mail/compose/format-buttons.png)
-% skin messenger-newsblog classic/1.0 %skin/classic/messenger-newsblog/
-  skin/classic/messenger-newsblog/feed-subscriptions.css      (mail/newsblog/feed-subscriptions.css)
-  skin/classic/messenger-newsblog/icons/rss-feed.png          (mail/newsblog/rss-feed.png)
-  skin/classic/messenger-newsblog/icons/server-rss.png        (mail/newsblog/server-rss.png)
-  skin/classic/messenger/preferences/preferences.css          (mail/preferences/preferences.css)
-  skin/classic/messenger/preferences/general.png              (mail/preferences/general.png)
-  skin/classic/messenger/preferences/display.png              (mail/preferences/display.png)
-  skin/classic/messenger/preferences/composition.png          (mail/preferences/composition.png)
-  skin/classic/messenger/preferences/security.png             (mail/preferences/security.png)
-  skin/classic/messenger/preferences/attachments.png          (mail/preferences/attachments.png)
-  skin/classic/messenger/preferences/advanced.png             (mail/preferences/advanced.png)
-  skin/classic/messenger/preferences/background.png           (mail/preferences/background.png)
-  skin/classic/messenger/preferences/hover.png                (mail/preferences/hover.png)
-  skin/classic/messenger/preferences/selected.png             (mail/preferences/selected.png)
-  skin/classic/messenger/smime/msgCompSMIMEOverlay.css        (mail/smime/msgCompSMIMEOverlay.css)
-  skin/classic/messenger/smime/msgHdrViewSMIMEOverlay.css     (mail/smime/msgHdrViewSMIMEOverlay.css)
-  skin/classic/messenger/smime/msgReadSMIMEOverlay.css        (mail/smime/msgReadSMIMEOverlay.css)
-  skin/classic/messenger/smime/msgReadSecurityInfo.css        (mail/smime/msgReadSecurityInfo.css)
-  skin/classic/messenger/smime/msgCompSecurityInfo.css        (mail/smime/msgCompSecurityInfo.css)
-  skin/classic/messenger/smime/certFetchingStatus.css         (mail/smime/certFetchingStatus.css)
-  skin/classic/messenger/smime/icons/hdrCryptoNotOk.png       (mail/smime/hdrCryptoNotOk.png)
-  skin/classic/messenger/smime/icons/hdrCryptoOk.png          (mail/smime/hdrCryptoOk.png)
-  skin/classic/messenger/smime/icons/hdrSignNotOk.png         (mail/smime/hdrSignNotOk.png)
-  skin/classic/messenger/smime/icons/hdrSignOk.png            (mail/smime/hdrSignOk.png)
-  skin/classic/messenger/smime/icons/hdrSignUnknown.png       (mail/smime/hdrSignUnknown.png)
-  skin/classic/messenger/smime/icons/sbCryptoNotOk.png        (mail/smime/sbCryptoNotOk.png)
-  skin/classic/messenger/smime/icons/sbCryptoOk.png           (mail/smime/sbCryptoOk.png)
-  skin/classic/messenger/smime/icons/sbSignNotOk.png          (mail/smime/sbSignNotOk.png)
-  skin/classic/messenger/smime/icons/sbSignOk.png             (mail/smime/sbSignOk.png)
-  skin/classic/messenger/smime/icons/sbSignUnknown.png        (mail/smime/sbSignUnknown.png)
-  skin/classic/messenger/icons/new-mail-alert.png             (mail/icons/new-mail-alert.png)
-  skin/classic/messenger/icons/readmail.png                   (mail/icons/readmail.png)
-  skin/classic/messenger/icons/mail-toolbar.png               (mail/icons/mail-toolbar.png)
-  skin/classic/messenger/icons/mail-toolbar-small.png         (mail/icons/mail-toolbar-small.png)
-  skin/classic/messenger/icons/folder.png                     (mail/icons/folder.png)
-  skin/classic/messenger/icons/message.png                    (mail/icons/message.png)
-  skin/classic/messenger/icons/attachment-deleted.png         (mail/icons/attachment-deleted.png)
-  skin/classic/messenger/icons/attachment-deleted-large.png   (mail/icons/attachment-deleted-large.png)
-  skin/classic/messenger/icons/attachment-col.png             (mail/icons/attachment-col.png)
-  skin/classic/messenger/icons/attachment.png                 (mail/icons/attachment.png)
-  skin/classic/messenger/icons/junk-col.png                   (mail/icons/junk-col.png)
-  skin/classic/messenger/icons/thread-col.png                 (mail/icons/thread-col.png)
-  skin/classic/messenger/icons/thread-col-sorta.png           (mail/icons/thread-col-sorta.png)
-  skin/classic/messenger/icons/thread-col-sortd.png           (mail/icons/thread-col-sortd.png)
-  skin/classic/messenger/icons/thread.png                     (mail/icons/thread.png)
-  skin/classic/messenger/icons/thread-ignored.png             (mail/icons/thread-ignored.png)
-  skin/classic/messenger/icons/message-ignored.png            (mail/icons/message-ignored.png)
-  skin/classic/messenger/icons/thread-watched.png             (mail/icons/thread-watched.png)
-  skin/classic/messenger/icons/flag-col.png                   (mail/icons/flag-col.png)
-  skin/classic/messenger/icons/flag.png                       (mail/icons/flag.png)
-  skin/classic/messenger/icons/flag-empty.png                 (mail/icons/flag-empty.png)
-  skin/classic/messenger/icons/server.png                     (mail/icons/server.png)
-  skin/classic/messenger/icons/readcol.png                    (mail/icons/readcol.png)
-  skin/classic/messenger/icons/unreadmail.png                 (mail/icons/unreadmail.png)
-  skin/classic/messenger/icons/Search-bar.png                 (mail/icons/Search-bar.png)
-  skin/classic/messenger/icons/search-arrow.gif               (mail/icons/search-arrow.gif)
-  skin/classic/messenger/icons/quick-search-clear.png         (mail/icons/quick-search-clear.png)
-  skin/classic/messenger/icons/close-button.png               (mail/icons/close-button.png)
-  skin/classic/messenger/icons/remote-blocked.png             (mail/icons/remote-blocked.png)
-  skin/classic/messenger/icons/phishing.png                   (mail/icons/phishing.png)
-  skin/classic/messenger/icons/junk.png                       (mail/icons/junk.png)
-  skin/classic/messenger/icons/check.gif                      (mail/icons/check.gif)
-  skin/classic/messenger/icons/notchecked.gif                 (mail/icons/notchecked.gif)
-  skin/classic/messenger/icons/online.png                     (mail/icons/online.png)
-  skin/classic/messenger/icons/offline.png                    (mail/icons/offline.png)
-  skin/classic/messenger/icons/row.png                        (mail/icons/row.png)
+  skin/classic/messenger/accountManage.css                    (mail/accountManage.css)
+  skin/classic/messenger/accountWizard.css                    (mail/accountWizard.css)
+  skin/classic/messenger/messageHeader.css                    (mail/messageHeader.css)
+  skin/classic/messenger/messageBody.css                      (mail/messageBody.css)
+  skin/classic/messenger/messageQuotes.css                    (mail/messageQuotes.css)
+  skin/classic/messenger/messenger.css                        (mail/messenger.css)
+  skin/classic/messenger/mailWindow1.css                      (mail/mailWindow1.css)
+  skin/classic/messenger/tagColors.css                        (mail/tagColors.css)
+  skin/classic/messenger/messageWindow.css                    (mail/messageWindow.css)
+  skin/classic/messenger/searchBox.css                        (mail/searchBox.css)
+  skin/classic/messenger/junkMail.css                         (mail/junkMail.css)
+  skin/classic/messenger/folderMenus.css                      (mail/folderMenus.css)
+  skin/classic/messenger/folderPane.css                       (mail/folderPane.css)
+  skin/classic/messenger/subscribe.css                        (mail/subscribe.css)
+  skin/classic/messenger/virtualFolderListDialog.css          (mail/virtualFolderListDialog.css)
+  skin/classic/messenger/searchDialog.css                     (mail/searchDialog.css)
+  skin/classic/messenger/msgSelectOffline.css                 (mail/msgSelectOffline.css)
+  skin/classic/messenger/filterDialog.css                     (mail/filterDialog.css)
+  skin/classic/messenger/dialogs.css                          (mail/dialogs.css)
+  skin/classic/messenger/multimessageview.css                 (mail/multimessageview.css)
+  skin/classic/messenger/newmailalert.css                     (mail/newmailalert.css)
+* skin/classic/messenger/tabmailBindings.xml                  (mail/tabmailBindings.xml)
+  skin/classic/messenger/tabmail.css                          (mail/tabmail.css)
+  skin/classic/messenger/editContactOverlay.css               (mail/editContactOverlay.css)
+  skin/classic/messenger/starred48.png                        (mail/starred48.png)
+  skin/classic/messenger/contactStarred.png                   (mail/contactStarred.png)
+  skin/classic/messenger/starContact.png                      (mail/starContact.png)
+  skin/classic/messenger/activity/activity.css                   (mail/activity/activity.css)
+  skin/classic/messenger/activity/buttons.png                    (mail/activity/buttons.png)  
+  skin/classic/messenger/activity/defaultProcessIcon.png         (mail/activity/defaultProcessIcon.png)
+  skin/classic/messenger/activity/defaultEventIcon.png           (mail/activity/defaultEventIcon.png)
+  skin/classic/messenger/activity/defaultWarningIcon.png         (mail/activity/defaultWarningIcon.png)
+  skin/classic/messenger/activity/undoIcon.png                   (mail/activity/undoIcon.png)
+  skin/classic/messenger/activity/syncMailIcon.png               (mail/activity/syncMailIcon.png)
+  skin/classic/messenger/activity/sendMailIcon.png               (mail/activity/sendMailIcon.png)
+  skin/classic/messenger/activity/removeItemIcon.png             (mail/activity/removeItemIcon.png)
+  skin/classic/messenger/activity/addItemIcon.png                (mail/activity/addItemIcon.png)
+  skin/classic/messenger/activity/moveMailIcon.png               (mail/activity/moveMailIcon.png)
+  skin/classic/messenger/activity/copyMailIcon.png               (mail/activity/copyMailIcon.png)
+  skin/classic/messenger/activity/deleteMailIcon.png             (mail/activity/deleteMailIcon.png)
+  skin/classic/messenger/activity/compactMailIcon.png            (mail/activity/compactMailIcon.png)
+  skin/classic/messenger/activity/indexMailIcon.png              (mail/activity/indexMailIcon.png)
+  skin/classic/messenger/addressbook/addressbook.css          (mail/addrbook/addressbook.css)
+  skin/classic/messenger/addressbook/abContactsPanel.css      (mail/addrbook/abContactsPanel.css)
+  skin/classic/messenger/addressbook/cardDialog.css           (mail/addrbook/cardDialog.css)
+  skin/classic/messenger/addressbook/abResultsPane.css        (mail/addrbook/abResultsPane.css)
+  skin/classic/messenger/addressbook/icons/abcard.png         (mail/addrbook/abcard.png)
+  skin/classic/messenger/addressbook/icons/addrbook.png       (mail/addrbook/addrbook.png)
+  skin/classic/messenger/addressbook/icons/ablist.png         (mail/addrbook/ablist.png)
+  skin/classic/messenger/addressbook/icons/addressbook-toolbar.png         (mail/addrbook/addressbook-toolbar.png)
+  skin/classic/messenger/addressbook/icons/addressbook-toolbar-small.png   (mail/addrbook/addressbook-toolbar-small.png)
+  skin/classic/messenger/addressbook/icons/abcard-large.png   (mail/addrbook/abcard-large.png)
+  skin/classic/messenger/addressbook/icons/remote-addrbook.png (mail/addrbook/remote-addrbook.png)
+  skin/classic/messenger/addressbook/icons/remote-addrbook-error.png      (mail/addrbook/remote-addrbook-error.png)
+  skin/classic/messenger/addressbook/icons/secure-remote-addrbook.png     (mail/addrbook/secure-remote-addrbook.png)
+  skin/classic/messenger/messengercompose/messengercompose.css (mail/compose/messengercompose.css)
+  skin/classic/messenger/messengercompose/compose-toolbar.png  (mail/compose/compose-toolbar.png)
+  skin/classic/messenger/messengercompose/compose-toolbar-small.png   (mail/compose/compose-toolbar-small.png)
+  skin/classic/messenger/messengercompose/format-buttons.png  (mail/compose/format-buttons.png)
+% skin messenger-newsblog classic/1.0 %skin/classic/messenger-newsblog/
+  skin/classic/messenger-newsblog/feed-subscriptions.css      (mail/newsblog/feed-subscriptions.css)
+  skin/classic/messenger-newsblog/icons/rss-feed.png          (mail/newsblog/rss-feed.png)
+  skin/classic/messenger-newsblog/icons/server-rss.png        (mail/newsblog/server-rss.png)
+  skin/classic/messenger/preferences/preferences.css          (mail/preferences/preferences.css)
+  skin/classic/messenger/preferences/general.png              (mail/preferences/general.png)
+  skin/classic/messenger/preferences/display.png              (mail/preferences/display.png)
+  skin/classic/messenger/preferences/composition.png          (mail/preferences/composition.png)
+  skin/classic/messenger/preferences/security.png             (mail/preferences/security.png)
+  skin/classic/messenger/preferences/attachments.png          (mail/preferences/attachments.png)
+  skin/classic/messenger/preferences/advanced.png             (mail/preferences/advanced.png)
+  skin/classic/messenger/preferences/background.png           (mail/preferences/background.png)
+  skin/classic/messenger/preferences/hover.png                (mail/preferences/hover.png)
+  skin/classic/messenger/preferences/selected.png             (mail/preferences/selected.png)
+  skin/classic/messenger/smime/msgCompSMIMEOverlay.css        (mail/smime/msgCompSMIMEOverlay.css)
+  skin/classic/messenger/smime/msgHdrViewSMIMEOverlay.css     (mail/smime/msgHdrViewSMIMEOverlay.css)
+  skin/classic/messenger/smime/msgReadSMIMEOverlay.css        (mail/smime/msgReadSMIMEOverlay.css)
+  skin/classic/messenger/smime/msgReadSecurityInfo.css        (mail/smime/msgReadSecurityInfo.css)
+  skin/classic/messenger/smime/msgCompSecurityInfo.css        (mail/smime/msgCompSecurityInfo.css)
+  skin/classic/messenger/smime/certFetchingStatus.css         (mail/smime/certFetchingStatus.css)
+  skin/classic/messenger/smime/icons/hdrCryptoNotOk.png       (mail/smime/hdrCryptoNotOk.png)
+  skin/classic/messenger/smime/icons/hdrCryptoOk.png          (mail/smime/hdrCryptoOk.png)
+  skin/classic/messenger/smime/icons/hdrSignNotOk.png         (mail/smime/hdrSignNotOk.png)
+  skin/classic/messenger/smime/icons/hdrSignOk.png            (mail/smime/hdrSignOk.png)
+  skin/classic/messenger/smime/icons/hdrSignUnknown.png       (mail/smime/hdrSignUnknown.png)
+  skin/classic/messenger/smime/icons/sbCryptoNotOk.png        (mail/smime/sbCryptoNotOk.png)
+  skin/classic/messenger/smime/icons/sbCryptoOk.png           (mail/smime/sbCryptoOk.png)
+  skin/classic/messenger/smime/icons/sbSignNotOk.png          (mail/smime/sbSignNotOk.png)
+  skin/classic/messenger/smime/icons/sbSignOk.png             (mail/smime/sbSignOk.png)
+  skin/classic/messenger/smime/icons/sbSignUnknown.png        (mail/smime/sbSignUnknown.png)
+  skin/classic/messenger/icons/new-mail-alert.png             (mail/icons/new-mail-alert.png)
+  skin/classic/messenger/icons/readmail.png                   (mail/icons/readmail.png)
+  skin/classic/messenger/icons/mail-toolbar.png               (mail/icons/mail-toolbar.png)
+  skin/classic/messenger/icons/mail-toolbar-small.png         (mail/icons/mail-toolbar-small.png)
+  skin/classic/messenger/icons/folder.png                     (mail/icons/folder.png)
+  skin/classic/messenger/icons/message.png                    (mail/icons/message.png)
+  skin/classic/messenger/icons/attachment-deleted.png         (mail/icons/attachment-deleted.png)
+  skin/classic/messenger/icons/attachment-deleted-large.png   (mail/icons/attachment-deleted-large.png)
+  skin/classic/messenger/icons/attachment-col.png             (mail/icons/attachment-col.png)
+  skin/classic/messenger/icons/attachment.png                 (mail/icons/attachment.png)
+  skin/classic/messenger/icons/junk-col.png                   (mail/icons/junk-col.png)
+  skin/classic/messenger/icons/thread-col.png                 (mail/icons/thread-col.png)
+  skin/classic/messenger/icons/thread-col-sorta.png           (mail/icons/thread-col-sorta.png)
+  skin/classic/messenger/icons/thread-col-sortd.png           (mail/icons/thread-col-sortd.png)
+  skin/classic/messenger/icons/thread.png                     (mail/icons/thread.png)
+  skin/classic/messenger/icons/thread-ignored.png             (mail/icons/thread-ignored.png)
+  skin/classic/messenger/icons/message-ignored.png            (mail/icons/message-ignored.png)
+  skin/classic/messenger/icons/thread-watched.png             (mail/icons/thread-watched.png)
+  skin/classic/messenger/icons/flag-col.png                   (mail/icons/flag-col.png)
+  skin/classic/messenger/icons/flag.png                       (mail/icons/flag.png)
+  skin/classic/messenger/icons/flag-empty.png                 (mail/icons/flag-empty.png)
+  skin/classic/messenger/icons/server.png                     (mail/icons/server.png)
+  skin/classic/messenger/icons/readcol.png                    (mail/icons/readcol.png)
+  skin/classic/messenger/icons/unreadmail.png                 (mail/icons/unreadmail.png)
+  skin/classic/messenger/icons/Search-bar.png                 (mail/icons/Search-bar.png)
+  skin/classic/messenger/icons/search-arrow.gif               (mail/icons/search-arrow.gif)
+  skin/classic/messenger/icons/quick-search-clear.png         (mail/icons/quick-search-clear.png)
+  skin/classic/messenger/icons/close-button.png               (mail/icons/close-button.png)
+  skin/classic/messenger/icons/remote-blocked.png             (mail/icons/remote-blocked.png)
+  skin/classic/messenger/icons/phishing.png                   (mail/icons/phishing.png)
+  skin/classic/messenger/icons/junk.png                       (mail/icons/junk.png)
+  skin/classic/messenger/icons/check.gif                      (mail/icons/check.gif)
+  skin/classic/messenger/icons/notchecked.gif                 (mail/icons/notchecked.gif)
+  skin/classic/messenger/icons/online.png                     (mail/icons/online.png)
+  skin/classic/messenger/icons/offline.png                    (mail/icons/offline.png)
+  skin/classic/messenger/icons/row.png                        (mail/icons/row.png)
   skin/classic/messenger/icons/secure.png                     (mail/icons/secure.png)
   skin/classic/messenger/icons/insecure.png                   (mail/icons/insecure.png)
   skin/classic/messenger/icons/identity.png                   (mail/icons/identity.png)
   skin/classic/messenger/icons/tick.png                       (mail/icons/tick.png)
   skin/classic/messenger/icons/error.png                      (mail/icons/error.png)
   skin/classic/messenger/icons/cancel.png                     (mail/icons/cancel.png)
-  skin/classic/messenger/icons/alltabs-box-overflow-end-bkgnd.png           (mail/icons/alltabs-box-overflow-end-bkgnd.png)
-  skin/classic/messenger/icons/alltabs-box-overflow-end-bkgnd-animate.png   (mail/icons/alltabs-box-overflow-end-bkgnd-animate.png)
-  skin/classic/messenger/icons/alltabs-box-overflow-end-bkgnd-hover.png     (mail/icons/alltabs-box-overflow-end-bkgnd-hover.png)
-  skin/classic/messenger/icons/alltabs-box-overflow-start-bkgnd.png         (mail/icons/alltabs-box-overflow-start-bkgnd.png)
-  skin/classic/messenger/icons/alltabs-box-overflow-start-bkgnd-animate.png (mail/icons/alltabs-box-overflow-start-bkgnd-animate.png)
-  skin/classic/messenger/icons/alltabs-box-overflow-start-bkgnd-hover.png   (mail/icons/alltabs-box-overflow-start-bkgnd-hover.png)
-  skin/classic/messenger/icons/tab-arrow-end.png                  (mail/icons/tab-arrow-end.png)
-  skin/classic/messenger/icons/tab-arrow-end-bkgnd-animate.png    (mail/icons/tab-arrow-end-bkgnd-animate.png)
-  skin/classic/messenger/icons/tab-arrow-end-bkgnd-disabled.png   (mail/icons/tab-arrow-end-bkgnd-disabled.png)
-  skin/classic/messenger/icons/tab-arrow-end-bkgnd-enabled.png    (mail/icons/tab-arrow-end-bkgnd-enabled.png)
-  skin/classic/messenger/icons/tab-arrow-end-bkgnd-hover.png      (mail/icons/tab-arrow-end-bkgnd-hover.png)
-  skin/classic/messenger/icons/tab-arrow-start.png                (mail/icons/tab-arrow-start.png)
-  skin/classic/messenger/icons/tab-arrow-start-bkgnd-animate.png  (mail/icons/tab-arrow-start-bkgnd-animate.png)
-  skin/classic/messenger/icons/tab-arrow-start-bkgnd-disabled.png (mail/icons/tab-arrow-start-bkgnd-disabled.png)
-  skin/classic/messenger/icons/tab-arrow-start-bkgnd-enabled.png  (mail/icons/tab-arrow-start-bkgnd-enabled.png)
-  skin/classic/messenger/icons/tab-arrow-start-bkgnd-hover.png    (mail/icons/tab-arrow-start-bkgnd-hover.png)
-  skin/classic/messenger/icons/tabmail-tabs-bkgnd.png             (mail/icons/tabmail-tabs-bkgnd.png)
-  skin/classic/messenger/icons/tabDragIndicator.png               (mail/icons/tabDragIndicator.png)
-  skin/classic/messenger/icons/tab-left.png                       (mail/icons/tab-left.png)
-  skin/classic/messenger/icons/tab-left-bkgnd.png                 (mail/icons/tab-left-bkgnd.png)
-  skin/classic/messenger/icons/tab-middle.png                     (mail/icons/tab-middle.png)
-  skin/classic/messenger/icons/tab-middle-bkgnd.png               (mail/icons/tab-middle-bkgnd.png)
-  skin/classic/messenger/icons/tab-right.png                      (mail/icons/tab-right.png)
-  skin/classic/messenger/icons/tab-right-bkgnd.png                (mail/icons/tab-right-bkgnd.png)
-  skin/classic/messenger/icons/tabstrip-bottom.png                (mail/icons/tabstrip-bottom.png)
-% skin communicator classic/1.0 %skin/classic/communicator/
-  skin/classic/communicator/communicator.css                      (mail/communicator.css)
-  skin/classic/communicator/icons/smileys/smiley-smile.png        (mail/icons/smiley-smile.png)
-  skin/classic/communicator/icons/smileys/smiley-frown.png        (mail/icons/smiley-frown.png)
-  skin/classic/communicator/icons/smileys/smiley-wink.png         (mail/icons/smiley-wink.png)
-  skin/classic/communicator/icons/smileys/smiley-tongue-out.png  (mail/icons/smiley-tongue-out.png)
-  skin/classic/communicator/icons/smileys/smiley-laughing.png (mail/icons/smiley-laughing.png)
-  skin/classic/communicator/icons/smileys/smiley-embarassed.png  (mail/icons/smiley-embarassed.png)
-  skin/classic/communicator/icons/smileys/smiley-undecided.png   (mail/icons/smiley-undecided.png)
-  skin/classic/communicator/icons/smileys/smiley-surprised.png   (mail/icons/smiley-surprised.png)
-  skin/classic/communicator/icons/smileys/smiley-kiss.png     (mail/icons/smiley-kiss.png)
-  skin/classic/communicator/icons/smileys/smiley-yell.png     (mail/icons/smiley-yell.png)
-  skin/classic/communicator/icons/smileys/smiley-cool.png     (mail/icons/smiley-cool.png)
-  skin/classic/communicator/icons/smileys/smiley-money-mouth.png (mail/icons/smiley-money-mouth.png)
-  skin/classic/communicator/icons/smileys/smiley-foot-in-mouth.png (mail/icons/smiley-foot-in-mouth.png)
-  skin/classic/communicator/icons/smileys/smiley-innocent.png (mail/icons/smiley-innocent.png)
-  skin/classic/communicator/icons/smileys/smiley-cry.png      (mail/icons/smiley-cry.png)
-  skin/classic/communicator/icons/smileys/smiley-sealed.png   (mail/icons/smiley-sealed.png)
-  skin/classic/messenger/accountcentral/read-messages.png     (mail/accountcentral/read-messages.png)
-  skin/classic/messenger/accountcentral/write-message.png     (mail/accountcentral/write-message.png)
-  skin/classic/messenger/accountcentral/create-account.png    (mail/accountcentral/create-account.png)
-  skin/classic/messenger/accountcentral/account-settings.png  (mail/accountcentral/account-settings.png)
-  skin/classic/messenger/accountcentral/search-messages.png   (mail/accountcentral/search-messages.png)
-  skin/classic/messenger/accountcentral/manage-filters.png    (mail/accountcentral/manage-filters.png)
-  skin/classic/messenger/accountcentral/offline-settings.png  (mail/accountcentral/offline-settings.png)
-  skin/classic/messenger/accountcentral/manage-imap.png       (mail/accountcentral/manage-imap.png)
-  skin/classic/messenger/accountcentral/manage-newsgroups.png (mail/accountcentral/manage-newsgroups.png)
-  skin/classic/messenger/accountcentral/manage-rss.png        (mail/accountcentral/manage-rss.png)
-  skin/classic/messenger/icons/arrow-dn-grey.png              (mail/icons/arrow-dn-grey.png)
-  skin/classic/messenger/icons/arrow-dn-black.png             (mail/icons/arrow-dn-black.png)
-  skin/classic/messenger/icons/arrow-dn-blue.png              (mail/icons/arrow-dn-blue.png)
-  skin/classic/messenger/icons/arrow/arrow-left.png           (mail/icons/arrow/arrow-left.png)
-  skin/classic/messenger/icons/arrow/arrow-right.png          (mail/icons/arrow/arrow-right.png)
-  skin/classic/messenger/icons/arrow/arrow-up.png             (mail/icons/arrow/arrow-up.png)
-  skin/classic/messenger/icons/arrow/arrow-down.png           (mail/icons/arrow/arrow-down.png)
-  skin/classic/messenger/icons/arrow/arrow-left-dim.png       (mail/icons/arrow/arrow-left-dim.png)
-  skin/classic/messenger/icons/arrow/arrow-right-dim.png      (mail/icons/arrow/arrow-right-dim.png)
-  skin/classic/messenger/icons/arrow/arrow-up-dim.png         (mail/icons/arrow/arrow-up-dim.png)
-  skin/classic/messenger/icons/arrow/arrow-down-dim.png       (mail/icons/arrow/arrow-down-dim.png)
-  skin/classic/messenger/icons/chevron.png                    (mail/icons/chevron.png)
-  skin/classic/messenger/icons/croppedchevron.png             (mail/icons/croppedchevron.png)
-  skin/classic/messenger/tagbg.png                            (mail/tagbg.png)
-  icon.png                                                    (mail/icon.png)
-  preview.png                                                 (mail/preview.png)
-% skin editor classic/1.0 %skin/classic/editor/
-  skin/classic/editor/editor.css                              (editor/editor.css)
-  skin/classic/editor/EditorDialog.css                        (editor/EditorDialog.css)
-  skin/classic/editor/icons/img-align-bottom.gif              (editor/img-align-bottom.gif)
-  skin/classic/editor/icons/img-align-left.gif                (editor/img-align-left.gif)
-  skin/classic/editor/icons/img-align-middle.gif              (editor/img-align-middle.gif)
-  skin/classic/editor/icons/img-align-right.gif               (editor/img-align-right.gif)
-  skin/classic/editor/icons/img-align-top.gif                 (editor/img-align-top.gif)
+  skin/classic/messenger/icons/alltabs-box-overflow-end-bkgnd.png           (mail/icons/alltabs-box-overflow-end-bkgnd.png)
+  skin/classic/messenger/icons/alltabs-box-overflow-end-bkgnd-animate.png   (mail/icons/alltabs-box-overflow-end-bkgnd-animate.png)
+  skin/classic/messenger/icons/alltabs-box-overflow-end-bkgnd-hover.png     (mail/icons/alltabs-box-overflow-end-bkgnd-hover.png)
+  skin/classic/messenger/icons/alltabs-box-overflow-start-bkgnd.png         (mail/icons/alltabs-box-overflow-start-bkgnd.png)
+  skin/classic/messenger/icons/alltabs-box-overflow-start-bkgnd-animate.png (mail/icons/alltabs-box-overflow-start-bkgnd-animate.png)
+  skin/classic/messenger/icons/alltabs-box-overflow-start-bkgnd-hover.png   (mail/icons/alltabs-box-overflow-start-bkgnd-hover.png)
+  skin/classic/messenger/icons/tab-arrow-end.png                  (mail/icons/tab-arrow-end.png)
+  skin/classic/messenger/icons/tab-arrow-end-bkgnd-animate.png    (mail/icons/tab-arrow-end-bkgnd-animate.png)
+  skin/classic/messenger/icons/tab-arrow-end-bkgnd-disabled.png   (mail/icons/tab-arrow-end-bkgnd-disabled.png)
+  skin/classic/messenger/icons/tab-arrow-end-bkgnd-enabled.png    (mail/icons/tab-arrow-end-bkgnd-enabled.png)
+  skin/classic/messenger/icons/tab-arrow-end-bkgnd-hover.png      (mail/icons/tab-arrow-end-bkgnd-hover.png)
+  skin/classic/messenger/icons/tab-arrow-start.png                (mail/icons/tab-arrow-start.png)
+  skin/classic/messenger/icons/tab-arrow-start-bkgnd-animate.png  (mail/icons/tab-arrow-start-bkgnd-animate.png)
+  skin/classic/messenger/icons/tab-arrow-start-bkgnd-disabled.png (mail/icons/tab-arrow-start-bkgnd-disabled.png)
+  skin/classic/messenger/icons/tab-arrow-start-bkgnd-enabled.png  (mail/icons/tab-arrow-start-bkgnd-enabled.png)
+  skin/classic/messenger/icons/tab-arrow-start-bkgnd-hover.png    (mail/icons/tab-arrow-start-bkgnd-hover.png)
+  skin/classic/messenger/icons/tabmail-tabs-bkgnd.png             (mail/icons/tabmail-tabs-bkgnd.png)
+  skin/classic/messenger/icons/tabDragIndicator.png               (mail/icons/tabDragIndicator.png)
+  skin/classic/messenger/icons/tab-left.png                       (mail/icons/tab-left.png)
+  skin/classic/messenger/icons/tab-left-bkgnd.png                 (mail/icons/tab-left-bkgnd.png)
+  skin/classic/messenger/icons/tab-middle.png                     (mail/icons/tab-middle.png)
+  skin/classic/messenger/icons/tab-middle-bkgnd.png               (mail/icons/tab-middle-bkgnd.png)
+  skin/classic/messenger/icons/tab-right.png                      (mail/icons/tab-right.png)
+  skin/classic/messenger/icons/tab-right-bkgnd.png                (mail/icons/tab-right-bkgnd.png)
+  skin/classic/messenger/icons/tabstrip-bottom.png                (mail/icons/tabstrip-bottom.png)
+% skin communicator classic/1.0 %skin/classic/communicator/
+  skin/classic/communicator/communicator.css                      (mail/communicator.css)
+  skin/classic/communicator/icons/smileys/smiley-smile.png        (mail/icons/smiley-smile.png)
+  skin/classic/communicator/icons/smileys/smiley-frown.png        (mail/icons/smiley-frown.png)
+  skin/classic/communicator/icons/smileys/smiley-wink.png         (mail/icons/smiley-wink.png)
+  skin/classic/communicator/icons/smileys/smiley-tongue-out.png  (mail/icons/smiley-tongue-out.png)
+  skin/classic/communicator/icons/smileys/smiley-laughing.png (mail/icons/smiley-laughing.png)
+  skin/classic/communicator/icons/smileys/smiley-embarassed.png  (mail/icons/smiley-embarassed.png)
+  skin/classic/communicator/icons/smileys/smiley-undecided.png   (mail/icons/smiley-undecided.png)
+  skin/classic/communicator/icons/smileys/smiley-surprised.png   (mail/icons/smiley-surprised.png)
+  skin/classic/communicator/icons/smileys/smiley-kiss.png     (mail/icons/smiley-kiss.png)
+  skin/classic/communicator/icons/smileys/smiley-yell.png     (mail/icons/smiley-yell.png)
+  skin/classic/communicator/icons/smileys/smiley-cool.png     (mail/icons/smiley-cool.png)
+  skin/classic/communicator/icons/smileys/smiley-money-mouth.png (mail/icons/smiley-money-mouth.png)
+  skin/classic/communicator/icons/smileys/smiley-foot-in-mouth.png (mail/icons/smiley-foot-in-mouth.png)
+  skin/classic/communicator/icons/smileys/smiley-innocent.png (mail/icons/smiley-innocent.png)
+  skin/classic/communicator/icons/smileys/smiley-cry.png      (mail/icons/smiley-cry.png)
+  skin/classic/communicator/icons/smileys/smiley-sealed.png   (mail/icons/smiley-sealed.png)
+  skin/classic/messenger/accountcentral/read-messages.png     (mail/accountcentral/read-messages.png)
+  skin/classic/messenger/accountcentral/write-message.png     (mail/accountcentral/write-message.png)
+  skin/classic/messenger/accountcentral/create-account.png    (mail/accountcentral/create-account.png)
+  skin/classic/messenger/accountcentral/account-settings.png  (mail/accountcentral/account-settings.png)
+  skin/classic/messenger/accountcentral/search-messages.png   (mail/accountcentral/search-messages.png)
+  skin/classic/messenger/accountcentral/manage-filters.png    (mail/accountcentral/manage-filters.png)
+  skin/classic/messenger/accountcentral/offline-settings.png  (mail/accountcentral/offline-settings.png)
+  skin/classic/messenger/accountcentral/manage-imap.png       (mail/accountcentral/manage-imap.png)
+  skin/classic/messenger/accountcentral/manage-newsgroups.png (mail/accountcentral/manage-newsgroups.png)
+  skin/classic/messenger/accountcentral/manage-rss.png        (mail/accountcentral/manage-rss.png)
+  skin/classic/messenger/icons/arrow-dn-grey.png              (mail/icons/arrow-dn-grey.png)
+  skin/classic/messenger/icons/arrow-dn-black.png             (mail/icons/arrow-dn-black.png)
+  skin/classic/messenger/icons/arrow-dn-blue.png              (mail/icons/arrow-dn-blue.png)
+  skin/classic/messenger/icons/arrow/arrow-left.png           (mail/icons/arrow/arrow-left.png)
+  skin/classic/messenger/icons/arrow/arrow-right.png          (mail/icons/arrow/arrow-right.png)
+  skin/classic/messenger/icons/arrow/arrow-up.png             (mail/icons/arrow/arrow-up.png)
+  skin/classic/messenger/icons/arrow/arrow-down.png           (mail/icons/arrow/arrow-down.png)
+  skin/classic/messenger/icons/arrow/arrow-left-dim.png       (mail/icons/arrow/arrow-left-dim.png)
+  skin/classic/messenger/icons/arrow/arrow-right-dim.png      (mail/icons/arrow/arrow-right-dim.png)
+  skin/classic/messenger/icons/arrow/arrow-up-dim.png         (mail/icons/arrow/arrow-up-dim.png)
+  skin/classic/messenger/icons/arrow/arrow-down-dim.png       (mail/icons/arrow/arrow-down-dim.png)
+  skin/classic/messenger/icons/chevron.png                    (mail/icons/chevron.png)
+  skin/classic/messenger/icons/croppedchevron.png             (mail/icons/croppedchevron.png)
+  skin/classic/messenger/tagbg.png                            (mail/tagbg.png)
+  icon.png                                                    (mail/icon.png)
+  preview.png                                                 (mail/preview.png)
+% skin editor classic/1.0 %skin/classic/editor/
+  skin/classic/editor/editor.css                              (editor/editor.css)
+  skin/classic/editor/EditorDialog.css                        (editor/EditorDialog.css)
+  skin/classic/editor/icons/img-align-bottom.gif              (editor/img-align-bottom.gif)
+  skin/classic/editor/icons/img-align-left.gif                (editor/img-align-left.gif)
+  skin/classic/editor/icons/img-align-middle.gif              (editor/img-align-middle.gif)
+  skin/classic/editor/icons/img-align-right.gif               (editor/img-align-right.gif)
+  skin/classic/editor/icons/img-align-top.gif                 (editor/img-align-top.gif)
new file mode 100644
--- /dev/null
+++ b/mail/themes/qute/mail/multimessageview.css
@@ -0,0 +1,55 @@
+@import url("chrome://messenger/content/multimessageview.css");
+
+/* qute-specific overrides for multimessageview.css*/
+
+/* mostly it's about CSS colors not being reliable */
+
+body {
+  background-color: white;
+}
+
+.heading.info {
+  color: ButtonText;
+}
+
+
+.info,
+.count, .date,
+.message > .header > .snippet,
+.message > .header > .senders {
+  color: GrayText;
+}
+
+/* buttons aren't reliable either */
+
+.button {
+  -moz-appearance: button;
+  font: message-box;
+  min-width: 32px !important;
+}
+
+
+/* and trash icon URLs aren't either */
+
+#trash {
+  min-height: 28px !important;
+  min-width: 32px !important;
+  padding: 0px;
+}
+
+.trashButton {
+  list-style-image: url("chrome://messenger/skin/icons/folder.png") !important;
+  -moz-image-region: rect(0px 144px 16px 128px);
+  width: 16px;
+  height: 16px;
+}
+
+.star {
+  width: 12px;
+  height: 12px;
+  margin-right: 0.5em;
+}
+
+.starred .star {
+  background-image: url("chrome://messenger/skin/icons/flag-col.png");
+}
--- a/mailnews/base/public/nsIMsgDBView.idl
+++ b/mailnews/base/public/nsIMsgDBView.idl
@@ -414,17 +414,17 @@ interface nsIMsgDBView : nsISupports
    */
   attribute AString curCustomColumn;
 };
 
 /* this interface is rapidly morphing from a command updater interface into a more generic
    FE updater interface to handle changes in the view 
 */
 
-[scriptable, uuid(65FC9AD5-0912-11d5-9901-001083010E9B)]
+[scriptable, uuid(ce8f52ee-e742-4b31-8bdd-2b3a8168a117)]
 interface nsIMsgDBViewCommandUpdater : nsISupports
 {
   /* Eventually we'll flush this out into some kind of rich interface
   which may take specifc selection changed type notifications like
   no selections, single selection, multi-selection, etc. For starters,
   we are going to keep it generic. The back end will only push an update
   command status when the # of selected items changes.
   */
@@ -434,9 +434,15 @@ interface nsIMsgDBViewCommandUpdater : n
   /* displayed message has changed */
   void displayMessageChanged(in nsIMsgFolder aFolder, in AString aSubject, in ACString aKeywords);
 
   /**
   * allows the backend to tell the front end to re-determine 
   * which message we should selet after a delete or move
   */
   void updateNextMessageAfterDelete();
+  
+  /**
+  * tell the front end that the selection has changed, and may need to be
+  * resummarized
+  */
+  void summarizeSelection();
 };
--- a/mailnews/base/public/nsIMsgWindow.idl
+++ b/mailnews/base/public/nsIMsgWindow.idl
@@ -48,17 +48,17 @@ interface nsIInterfaceRequestor;
 
 [scriptable, uuid(7B8F4A65-CFC4-4b3f-BF5C-152AA8D5CD10)]
 interface nsIMsgWindowCommands : nsISupports {
   void selectFolder(in ACString folderUri);
   void selectMessage(in ACString messageUri);
   void clearMsgPane();
 };
 
-[scriptable, uuid(7e8fbaaa-d2f1-4751-af8e-8213fdb60a02)]
+[scriptable, uuid(7e8fbaaa-d2f1-4751-af8e-8213fdb60a03)]
 interface nsIMsgWindow : nsISupports {
   attribute nsIMsgStatusFeedback statusFeedback;
   attribute nsIMsgWindowCommands windowCommands;
   attribute nsIMsgHeaderSink msgHeaderSink;
   attribute nsITransactionManager transactionManager;
   attribute nsIMsgFolder openFolder;
   
   /**
--- a/mailnews/base/src/nsMsgDBView.cpp
+++ b/mailnews/base/src/nsMsgDBView.cpp
@@ -1066,26 +1066,22 @@ NS_IMETHODIMP nsMsgDBView::SelectionChan
     else
       numSelected = 0; // selection seems bogus, so set to 0.
   }
   else {
     // if we have zero or multiple items selected, we shouldn't be displaying any message
     m_currentlyDisplayedMsgKey = nsMsgKey_None;
     m_currentlyDisplayedMsgUri.Truncate();
     m_currentlyDisplayedViewIndex = nsMsgViewIndex_None;
-
-    // if we used to have one item selected, and now we have zero or more than one, we should clear the message pane.
-    nsCOMPtr<nsIMsgWindow> msgWindow(do_QueryReferent(mMsgWindowWeak));
-    nsCOMPtr <nsIMsgWindowCommands> windowCommands;
-    if ((mNumSelectedRows == 1) && (numSelected != 1) && msgWindow
-        && NS_SUCCEEDED(msgWindow->GetWindowCommands(getter_AddRefs(windowCommands)))
-        && windowCommands) {
-      windowCommands->ClearMsgPane();
-    }
-  }
+  }
+
+  // let the front-end adjust the message pane appropriately with either
+  // the message body, or a summary of the selection
+  if (mCommandUpdater)
+    mCommandUpdater->SummarizeSelection();
 
   // determine if we need to push command update notifications out to the UI or not.
 
   // we need to push a command update notification iff, one of the following conditions are met
   // (1) the selection went from 0 to 1
   // (2) it went from 1 to 0
   // (3) it went from 1 to many
   // (4) it went from many to 1 or 0
@@ -2186,16 +2182,17 @@ NS_IMETHODIMP nsMsgDBView::GetIndicesFor
 }
 
 NS_IMETHODIMP nsMsgDBView::GetURIsForSelection(PRUint32 *length, char ***uris)
 {
   nsresult rv = NS_OK;
 
   NS_ENSURE_ARG_POINTER(length);
   *length = 0;
+  
   NS_ENSURE_ARG_POINTER(uris);
   *uris = nsnull;
 
   nsMsgViewIndexArray selection;
   GetSelectedIndices(selection);
   PRUint32 numIndices = selection.Length();
   if (!numIndices) return NS_OK;
 
@@ -4482,35 +4479,39 @@ nsresult nsMsgDBView::ExpansionDelta(nsM
   else
     *expansionDelta = - (PRInt32) (numChildren - 1);
 
   return NS_OK;
 }
 
 nsresult nsMsgDBView::ToggleExpansion(nsMsgViewIndex index, PRUint32 *numChanged)
 {
+  nsresult rv;
   NS_ENSURE_ARG(numChanged);
   *numChanged = 0;
   nsMsgViewIndex threadIndex = GetThreadIndex(index);
   if (threadIndex == nsMsgViewIndex_None)
   {
     NS_ASSERTION(PR_FALSE, "couldn't find thread");
     return NS_MSG_MESSAGE_NOT_FOUND;
   }
   PRInt32  flags = m_flags[threadIndex];
 
   // if not a thread, or doesn't have children, no expand/collapse
   // If we add sub-thread expand collapse, this will need to be relaxed
   if (!(flags & MSG_VIEW_FLAG_ISTHREAD) || !(flags & MSG_VIEW_FLAG_HASCHILDREN))
     return NS_MSG_MESSAGE_NOT_FOUND;
   if (flags & nsMsgMessageFlags::Elided)
-    return ExpandByIndex(threadIndex, numChanged);
+    rv = ExpandByIndex(threadIndex, numChanged);
   else
-    return CollapseByIndex(threadIndex, numChanged);
-
+    rv = CollapseByIndex(threadIndex, numChanged);
+    
+  // if we collaps/uncollapse a thread, this changes the selected URIs
+  SelectionChanged();
+  return rv;
 }
 
 nsresult nsMsgDBView::ExpandAndSelectThread()
 {
     nsresult rv;
 
     NS_ASSERTION(mTreeSelection, "no tree selection");
     if (!mTreeSelection) return NS_ERROR_UNEXPECTED;
--- a/suite/mailnews/messageWindow.js
+++ b/suite/mailnews/messageWindow.js
@@ -179,16 +179,18 @@ nsMsgDBViewCommandUpdater.prototype =
     goUpdateCommand("button_goForward");
   },
 
   updateNextMessageAfterDelete : function()
   {
     SetNextMessageAfterDelete();
   },
 
+  summarizeSelection: function() {},
+
   QueryInterface : function(iid)
   {
     if (iid.equals(Components.interfaces.nsIMsgDBViewCommandUpdater) ||
         iid.equals(Components.interfaces.nsISupports))
       return this;
 	  
     throw Components.results.NS_NOINTERFACE;
   }
--- a/suite/mailnews/search/SearchDialog.js
+++ b/suite/mailnews/search/SearchDialog.js
@@ -522,16 +522,18 @@ nsMsgSearchCommandUpdater.prototype =
   {
   },
 
   updateNextMessageAfterDelete : function()
   {
     SetNextMessageAfterDelete();
   },
 
+  summarizeSelection: function() {},
+
   QueryInterface : function(iid)
   {
     if (iid.equals(Components.interfaces.nsIMsgDBViewCommandUpdater) ||
         iid.equals(Components.interfaces.nsISupports))
       return this;
 
     throw Components.results.NS_NOINTERFACE;
   }
--- a/suite/mailnews/threadPane.js
+++ b/suite/mailnews/threadPane.js
@@ -111,16 +111,18 @@ nsMsgDBViewCommandUpdater.prototype =
     goUpdateCommand("button_junk");
   },
 
   updateNextMessageAfterDelete : function()
   {
     SetNextMessageAfterDelete();
   },
 
+  summarizeSelection: function() {},
+
   QueryInterface : function(iid)
    {
      if (iid.equals(Components.interfaces.nsIMsgDBViewCommandUpdater) ||
          iid.equals(Components.interfaces.nsISupports))
        return this;
 	  
      throw Components.results.NS_NOINTERFACE;
     }