Index: program/localization/de_DE/messages.inc
===================================================================
--- program/localization/de_DE/messages.inc	(revision 362)
+++ program/localization/de_DE/messages.inc	(working copy)
@@ -106,4 +106,6 @@
 
 $messages['folderdeleted'] = 'Ordner erfolgreich gelöscht';
 
+$messages['messageopenerror'] = 'Die Nachricht konnte nicht vom Server geladen werden';
+
 ?>
\ No newline at end of file
Index: program/localization/de_CH/messages.inc
===================================================================
--- program/localization/de_CH/messages.inc	(revision 362)
+++ program/localization/de_CH/messages.inc	(working copy)
@@ -104,5 +104,6 @@
 
 $messages['folderdeleted'] = 'Ordner erfolgreich gelöscht';
 
+$messages['messageopenerror'] = 'Die Nachricht konnte nicht vom Server geladen werden';
 
 ?>
\ No newline at end of file
Index: program/localization/en_US/messages.inc
===================================================================
--- program/localization/en_US/messages.inc	(revision 362)
+++ program/localization/en_US/messages.inc	(working copy)
@@ -108,4 +108,6 @@
 
 $messages['converting'] = 'Removing formatting from message...';
 
+$messages['messageopenerror'] = 'Could not load message from server';
+
 ?>
Index: program/js/app.js
===================================================================
--- program/js/app.js	(revision 362)
+++ program/js/app.js	(working copy)
@@ -32,7 +32,7 @@
   this.ref = 'rcube_webmail_client';
  
   // webmail client settings
-  this.dblclick_time = 600;
+  this.dblclick_time = 500;
   this.message_time = 5000;
   
   this.mbox_expression = new RegExp('[^0-9a-z\-_]', 'gi');
@@ -137,7 +137,7 @@
         // enable mail commands
         this.enable_command('list', 'checkmail', 'compose', 'add-contact', 'search', 'reset-search', true);
         
-        if (this.env.action=='show')
+        if (this.env.action=='show' || this.env.action=='preview')
           {
           this.enable_command('show', 'reply', 'reply-all', 'forward', 'moveto', 'delete', 'viewsource', 'print', 'load-attachment', true);
           if (this.env.next_uid)
@@ -145,8 +145,15 @@
           if (this.env.prev_uid)
             this.enable_command('previousmessage', true);
           }
+        
+        // make preview/message frame visible
+        if (this.env.action == 'preview' && this.env.framed && parent.rcmail)
+          {
+          this.enable_command('compose', 'add-contact', false);
+          parent.rcmail.show_messageframe(true);
+          }
 
-        if (this.env.action=='show' && this.env.blockedobjects)
+        if ((this.env.action=='show' || this.env.action=='preview') && this.env.blockedobjects)
           {
           if (this.gui_objects.remoteobjectsmsg)
             this.gui_objects.remoteobjectsmsg.style.display = 'block';
@@ -623,7 +630,7 @@
         
       case 'load-images':
         if (this.env.uid)
-          this.show_message(this.env.uid, true);
+          this.show_message(this.env.uid, true, this.env.action=='preview');
         break;
 
       case 'load-attachment':
@@ -632,7 +639,7 @@
         // open attachment in frame if it's of a supported mimetype
         if (this.env.uid && props.mimetype && find_in_array(props.mimetype, this.mimetypes)>=0)
           {
-          this.attachment_win = window.open(this.env.comm_path+'&_action=get'+url+'&_frame=1', 'rcubemailattachment');
+          this.attachment_win = window.open(this.env.comm_path+'&_action=get&'+qstring+'&_frame=1', 'rcubemailattachment');
           if (this.attachment_win)
             {
             setTimeout(this.ref+'.attachment_win.focus()', 10);
@@ -653,12 +660,12 @@
 
       case 'nextmessage':
         if (this.env.next_uid)
-          this.show_message(this.env.next_uid);
+          this.show_message(this.env.next_uid, false, this.env.action=='preview');
         break;
 
       case 'previousmessage':
         if (this.env.prev_uid)
-          this.show_message(this.env.prev_uid);
+          this.show_message(this.env.prev_uid, false, this.env.action=='preview');
         break;
       
       case 'checkmail':
@@ -1028,6 +1035,9 @@
 
   this.msglist_select = function(list)
     {
+    if (this.preview_timer)
+      clearTimeout(this.preview_timer);
+
     var selected = list.selection.length==1;
     if (this.env.mailbox == this.env.drafts_mailbox)
       {
@@ -1038,17 +1048,26 @@
       {
       this.enable_command('show', 'reply', 'reply-all', 'forward', 'print', selected);
       this.enable_command('delete', 'moveto', list.selection.length>0 ? true : false);
+
+      // start timer for message preview (wait for double click)
+      if (selected && this.env.contentframe)
+        this.preview_timer = setTimeout(this.ref+'.msglist_get_preview()', this.dblclick_time + 10);
+      else if (this.env.contentframe)
+        this.show_messageframe(false);
       }
-   };
+    };
 
 
   this.msglist_dbl_click = function(list)
     {
+      if (this.preview_timer)
+        clearTimeout(this.preview_timer);
+
     var uid = list.get_single_selection();
     if (uid && this.env.mailbox == this.env.drafts_mailbox)
       this.goto_url('compose', '_draft_uid='+uid+'&_mbox='+urlencode(this.env.mailbox), true);
     else if (uid)
-      this.show_message(uid);
+      this.show_message(uid, false, false);
     };
 
 
@@ -1061,18 +1080,28 @@
     };
 
 
+  this.msglist_get_preview = function()
+  {
+    var uid = this.get_single_uid();
+    if (uid && this.env.contentframe)
+      this.show_message(uid, false, true);
+    else if (this.env.contentframe)
+      this.show_messageframe(false);
+  };
 
+
   /*********************************************************/
   /*********     (message) list functionality      *********/
   /*********************************************************/
 
 
   // when user doble-clicks on a row
-  this.show_message = function(id, safe)
+  this.show_message = function(id, safe, preview)
     {
     var add_url = '';
+    var action = preview ? 'preview': 'show';
     var target = window;
-    if (this.env.contentframe && window.frames && window.frames[this.env.contentframe])
+    if (preview && this.env.contentframe && window.frames && window.frames[this.env.contentframe])
       {
       target = window.frames[this.env.contentframe];
       add_url = '&_framed=1';
@@ -1083,13 +1112,26 @@
 
     if (id)
       {
-      this.set_busy(true, 'loading');
-      target.location.href = this.env.comm_path+'&_action=show&_uid='+id+'&_mbox='+urlencode(this.env.mailbox)+add_url;
+      var url = '&_action='+action+'&_uid='+id+'&_mbox='+urlencode(this.env.mailbox)+add_url;
+      if (action == 'preview' && String(target.location.href).indexOf(url) >= 0)
+        this.show_messageframe(true);
+      else
+        {
+        this.set_busy(true, 'loading');
+        target.location.href = this.env.comm_path+url;
+        }
       }
     };
 
 
+  this.show_messageframe = function(show)
+    {
+    var frm;
+    if (this.env.contentframe && (frm = rcube_find_object(this.env.contentframe)))
+      frm.style.display = show ? 'block' : 'none';
+    };
 
+
   // list a specific page
   this.list_page = function(page)
     {
Index: program/steps/mail/show.inc
===================================================================
--- program/steps/mail/show.inc	(revision 362)
+++ program/steps/mail/show.inc	(working copy)
@@ -30,12 +30,18 @@
   $MESSAGE = array('UID' => get_input_value('_uid', RCUBE_INPUT_GET));
   $MESSAGE['headers'] = $IMAP->get_headers($MESSAGE['UID']);
   $MESSAGE['structure'] = $IMAP->get_structure($MESSAGE['UID']);
-    
+  
   // go back to list if message not found (wrong UID)
   if (!$MESSAGE['headers'] || !$MESSAGE['structure'])
     {
-    $_action = 'list';
-    return;
+    show_message('messageopenerror', 'error');
+    if ($_action=='preview' && template_exists('messagepreview'))
+        parse_template('messagepreview');
+    else
+      {
+      $_action = 'list';
+      return;
+      }
     }
 
   $MESSAGE['subject'] = $IMAP->decode_header($MESSAGE['headers']->subject);
@@ -123,28 +129,6 @@
 
 
 
-// return an HTML iframe for loading mail content
-function rcmail_messagecontent_frame($attrib)
-  {
-  global $COMM_PATH, $OUTPUT, $GET_URL, $JS_OBJECT_NAME;
-  
-  // allow the following attributes to be added to the <iframe> tag
-  $attrib_str = create_attrib_string($attrib);
-  $framename = 'rcmailcontentwindow';
-  
-  $out = sprintf('<iframe src="%s" name="%s"%s>%s</iframe>'."\n",
-         $GET_URL,
-         $framename,
-         $attrib_str,
-         rcube_label('loading'));
-
-
-  $OUTPUT->add_script("$JS_OBJECT_NAME.set_env('contentframe', '$framename');");
-
-  return $out;
-  }
-
-
 function rcmail_remote_objects_msg($attrib)
   {
   global $CONFIG, $OUTPUT, $JS_OBJECT_NAME;
@@ -169,8 +153,10 @@
   }
 
 
-if ($_action=='print')
+if ($_action=='print' && template_exists('printmessage'))
   parse_template('printmessage');
+else if ($_action=='preview' && template_exists('messagepreview'))
+    parse_template('messagepreview');
 else
   parse_template('message');
 ?>
\ No newline at end of file
Index: program/steps/mail/func.inc
===================================================================
--- program/steps/mail/func.inc	(revision 362)
+++ program/steps/mail/func.inc	(working copy)
@@ -557,6 +557,27 @@
   }
 
 
+// return an HTML iframe for loading mail content
+function rcmail_messagecontent_frame($attrib)
+  {
+  global $OUTPUT, $JS_OBJECT_NAME;
+  
+  if (empty($attrib['id']))
+    $attrib['id'] = 'rcmailcontentwindow';
+
+  // allow the following attributes to be added to the <iframe> tag
+  $attrib_str = create_attrib_string($attrib, array('id', 'class', 'style', 'src', 'width', 'height', 'frameborder'));
+  $framename = $attrib['id'];
+
+  $out = sprintf('<iframe name="%s"%s></iframe>'."\n",
+         $framename,
+         $attrib_str);
+
+  $OUTPUT->add_script("$JS_OBJECT_NAME.set_env('contentframe', '$framename');");
+
+  return $out;
+  }
+
 // return code for search function
 function rcmail_search_form($attrib)
   {
Index: skins/default/templates/mail.html
===================================================================
--- skins/default/templates/mail.html	(revision 362)
+++ skins/default/templates/mail.html	(working copy)
@@ -52,6 +52,10 @@
   attachmentIcon="/images/icons/attachment.png" />
 </div>
 
+<div id="mailpreviewframe">
+<roundcube:object name="messagecontentframe" id="messagecontframe" width="100%" height="100%" frameborder="0" src="/watermark.html" />
+</div>
+
 <div id="listcontrols">
 <roundcube:label name="select" />:&nbsp;
 <roundcube:button command="select-all" label="all" classAct="active" />&nbsp;
Index: skins/default/mail.css
===================================================================
--- skins/default/mail.css	(revision 362)
+++ skins/default/mail.css	(working copy)
@@ -111,16 +111,42 @@
   top: 85px;
   left: 200px;
   right: 40px;
-  bottom: 40px;
+  height: 210px;
   border: 1px solid #999999;
   background-color: #F9F9F9;
   overflow: auto;
   /* css hack for IE */
   width: expression((parseInt(document.documentElement.clientWidth)-240)+'px');
-  height: expression((parseInt(document.documentElement.clientHeight)-125)+'px');
 }
 
+#mailpreviewframe
+{
+  position: absolute;
+  top: 300px;
+  left: 200px;
+  right: 40px;
+  bottom: 40px;
+  border: 1px solid #999999;
+  background-color: #F9F9F9;
+  /* css hack for IE */
+  width: expression((parseInt(document.documentElement.clientWidth)-240)+'px');
+  height: expression((parseInt(document.documentElement.clientHeight)-340)+'px');
+}
 
+#messagecontframe
+{
+  width: 100%;
+  height: 100%;
+  border: 0;
+}
+
+/*\*/
+html>body*#messagecontframe
+{
+  height: 40%;
+}
+/**/
+
 #messagepartframe
 {
   border: 1px solid #999999;
@@ -385,8 +411,7 @@
 
 #messagelist tbody tr td
 {
-  height: 16px !important;
-  height: 20px;
+  height: 16px;
   padding: 2px;
   padding-right: 4px;
   font-size: 11px;
@@ -461,12 +486,6 @@
   background-color: #CC3333;
 }
 
-#messagelist tr.focused td
-{
-  border-bottom: thin dotted;
-  border-top: thin dotted;
-}
-
 #messagelist tr.unfocused td
 {
   font-weight: bold;
@@ -575,7 +594,7 @@
 #messageframe
 {
   position: absolute;
-  top: 85px;
+  top: 95px;
   left: 200px;
   right: 40px;
   bottom: 40px;
@@ -588,6 +607,12 @@
   height: expression((parseInt(document.documentElement.clientHeight)-125)+'px');
 }
 
+div.messageheaderbox
+{
+  margin: 6px 8px 0px 8px;
+  border: 1px solid #ccc;
+}
+
 table.headers-table
 {
   width: 100%;
Index: CHANGELOG
===================================================================
--- CHANGELOG	(revision 362)
+++ CHANGELOG	(working copy)
@@ -1,12 +1,19 @@
 CHANGELOG RoundCube Webmail
 ---------------------------
 
+2006/11/09 (thomasb)
+----------
+- Implemented preview pane
+- Little bugfix in HTML encoding
+- Fixed encoding issues and delete-on-reply problem
+- Corrected template parsing
+
+
 2006/11/07 (estadtherr)
 ----------
 - Upgraded to TinyMCE v2.0.8
 - Fixed CSS path for editor popups
 
-
 2006/09/26 (estadtherr)
 ----------
 - Added spellchecker plugin to TinyMCE configuration
Index: index.php
===================================================================
--- index.php	(revision 362)
+++ index.php	(working copy)
@@ -262,7 +262,7 @@
   {
   include_once('program/steps/mail/func.inc');
   
-  if ($_action=='show' || $_action=='print')
+  if ($_action=='show' || $_action=='preview' || $_action=='print')
     include('program/steps/mail/show.inc');
 
   if ($_action=='get')
