diff -urp privatemsg/privatemsg-recipients.tpl.php privatemsg_thread/privatemsg-recipients.tpl.php
--- privatemsg/privatemsg-recipients.tpl.php	2008-06-10 09:38:27.000000000 +0100
+++ privatemsg_thread/privatemsg-recipients.tpl.php	2008-09-05 23:35:52.863600000 +0100
@@ -3,5 +3,5 @@
   drupal_add_css(drupal_get_path('module', 'privatemsg').'/styles/privatemsg-recipients.css');
 ?>
 <div class="message-participants">
-  <?php print $recipients; ?>
+  <?php print $participants; ?>
 </div>
\ No newline at end of file
diff -urp privatemsg/privatemsg.module privatemsg_thread/privatemsg.module
--- privatemsg/privatemsg.module	2008-09-03 06:33:29.000000000 +0100
+++ privatemsg_thread/privatemsg.module	2008-09-09 03:54:09.111501700 +0100
@@ -186,24 +186,27 @@ function privatemsg_preprocess_privatems
 
 function privatemsg_preprocess_privatemsg_to(&$vars) {
   global $user;
-  // Replicates Facebook display for participants of a message.
   $to = array();
-  if (isset($vars['message']['recipients'])) {
-    foreach ($vars['message']['recipients'] as $uid => $account) {
-      if ($vars['message']['author']->uid == $account->uid) {
-        continue; // Skip putting author in the recipients list for now.
+  if (isset($vars['message']['participants'])) {
+    foreach ($vars['message']['participants'] as $uid => $account) {
+      if ($account->uid == $user->uid) {
+        $last = theme('username', $account);
+      }
+      else{
+        $to[]= theme('username', $account);
       }
-      $to[]= theme('username', $account);
     }
   }
-  $recipients = implode(', ', $to);
+  if (!($last) && count($to) > 0) {
+    $last = array_pop($to);
+  }
 
-  $you = theme('username', $vars['message']['author']);
-  if (drupal_strlen($recipients)) {
-    $recipients .= " and ";
+  $participants = implode(', ', $to);
+  if (drupal_strlen($participants)) {
+    $participants .= " and ";
   }
 
-  $vars['recipients'] = 'Between '. $recipients . $you;
+  $vars['participants'] = 'Between '. $participants . $last;
 }
 
 /**
@@ -284,14 +287,15 @@ function privatemsg_list($uid = NULL) {
     if (arg(1) != 'sent') {
       unset($head['new']);
     }
-
+    unset($head['thread_id']);
+    
     $messages = array();
     while ($row = db_fetch_array($result)) {
       $unread = '';
       if (isset($row['new']) && $row['new'] ) {
         $unread = ' privatemsg-unread';
       }
-      $row['subject'] = '<span class="privatemsg-list-subject'. $unread.'">' . l($row['subject'], 'messages/view/'. $row['id']) . '</span>';
+      $row['subject'] = '<span class="privatemsg-list-subject'. $unread.'">' . l($row['subject'], 'messages/view/'. $row['thread_id']) . '</span>';
       if (isset($row['author']) && $row['author']) {
         $row['author'] = '<span class="privatemsg-list-from' .  $unread.'">' . theme('username', user_load($row['author'])) . '</span>';
       }
@@ -305,6 +309,7 @@ function privatemsg_list($uid = NULL) {
         unset($row['new']);
       }
       unset($row['id']);
+      unset($row['thread_id']);
       $messages[] = $row;
     }
     $content = theme('table', $head, $messages);
@@ -387,23 +392,35 @@ function privatemsg_set_new_status($acco
   }
 }
 
-function privatemsg_view($pmid) {
+function privatemsg_view($thread_id) {
   global $user;
-  // Loads the message object.
-  $message = _privatemsg_load($pmid, $user->uid);
-  privatemsg_set_new_status($user, $pmid);
-  // Loads the list of recipients.
-  $query = _privatemsg_assemble_query('privatemsg_recipients', $message['thread_id']);
-  $result = db_query($query);
-  while ($row = db_fetch_object($result)) {
-    $message['recipients'][] = user_load($row->uid);
+  $output = '';
+  // Load the message object.
+  $query = _privatemsg_assemble_query('privatemsg_messages', $thread_id, $user->uid);
+  $conversation = db_query($query);
+  $message_count = 0;
+  while ($result = db_fetch_array($conversation)) {
+    $pmid = $result['mid'];
+    $message = _privatemsg_load($pmid, $user->uid);
+    privatemsg_set_new_status($user, $pmid);
+    $message['author'] = user_load($message['author']);
+    // Some tasks only need to be done once - on the first message of a thread.
+    if ($message_count == 0) {
+      $subject = $message['subject'];
+      drupal_set_title($subject);
+      // Load the list of participants.
+      $query = _privatemsg_assemble_query('privatemsg_participants', $message['thread_id']);
+      $participants = db_query($query);
+      while ($result = db_fetch_object($participants)) {
+        $message['participants'][] = user_load($result->uid);
+      }
+      $output = theme('privatemsg_to', $message);
+    }
+    $output .= theme('privatemsg_view', $message);
+    $message_count++;
   }
 
-  $message['author'] = user_load($message['author']);
-//  $message['recipient'] = user_load($message['recipient']);
-//  $output =  '<pre>'. print_r($message, 1) .'</pre>';
-  $output = theme('privatemsg_to', $message);
-  return $output . theme('privatemsg_view', $message);
+  return $output;
 }
 
 function privatemsg_new(&$form_state, $user = NULL) {
@@ -510,6 +527,9 @@ function pm_send_validate($form, &$form_
   $message['subject']   = $form_values['subject'];
   $message['author']    = $user;
   $message['timestamp'] = time();
+  if (isset($form_values['thread_id']) && $form_values['thread_id']) {
+    $message['thread_id'] = $form_values['thread_id'];
+  }
 
 //  drupal_set_message('<pre>'. print_r('one', 1) .' </pre>');
 
@@ -601,7 +621,6 @@ function pm_send($form, &$form_state) {
   }
 
   drupal_set_message('A private message has been sent to '. $form_state['values']['recipient']);
-//  $form_state['rebuild'] = TRUE; // Rebuild this message for ease of use.
 }
 
 function privatemsg_render_preview($message) {
@@ -645,7 +664,8 @@ function pm_preview($form, &$form_state)
 function privatemsg_privatemsg_list_sent_alter(&$fragments, $account) {
   $fragments['primary_table'] = '{pm_message} pm';
 
-  $fragments['select'][]      = 'pm.mid as id';
+  $fragments['select'][]      = 'MAX(pm.mid) as id';
+  $fragments['select'][]      = 'pmi.thread_id';
   $fragments['select'][]      = 'pm.subject';
   if ($account->uid != $GLOBALS['user']->uid) {
     $fragments['select'][] = 'pmi.author';
@@ -654,7 +674,8 @@ function privatemsg_privatemsg_list_sent
   $fragments['select'][] = 'pmi.timestamp';
   $fragments['inner_join'][]  = 'INNER JOIN {pm_index} pmi ON pm.mid = pmi.mid';
   $fragments['where'][]       = 'pmi.author = %d';
-  $order = 'pmi.timestamp';
+  $fragments['group_by'][]  = 'pmi.thread_id';
+  $order = 'MAX(pmi.timestamp)';
   $sort = 'desc';
   if (isset($_GET['order'])) {
     switch ($_GET['order']) {
@@ -680,7 +701,8 @@ function privatemsg_privatemsg_list_sent
 function privatemsg_privatemsg_list_alter(&$fragments, $account) {
   $fragments['primary_table'] = '{pm_message} pm';
 
-  $fragments['select'][]      = 'pmi.mid as id';
+  $fragments['select'][]      = 'MAX(pmi.mid) as id';
+  $fragments['select'][]      = 'pmi.thread_id';
   $fragments['select'][]      = 'pm.subject';
   $fragments['select'][]      = 'pmi.author';
   if ($account->uid != $GLOBALS['user']->uid) {
@@ -690,6 +712,7 @@ function privatemsg_privatemsg_list_alte
   $fragments['select'][] = 'pmi.new';
   $fragments['inner_join'][]  = 'INNER JOIN {pm_index} pmi ON pm.mid = pmi.mid';
   $fragments['where'][]       = 'pmi.recipient = %d';
+  $fragments['group_by'][]  = 'pmi.thread_id';
   $order = 'pmi.new';
   $sort = 'desc';
   if (isset($_GET['order'])) {
@@ -705,11 +728,11 @@ function privatemsg_privatemsg_list_alte
         break;
       case ('received'):
       default:
-        $order = 'pmi.timestamp';
+        $order = 'MAX(pmi.timestamp)';
     }
     $sort = isset($_GET['sort']) && ($_GET['sort'] == 'asc' || $_GET['sort'] == 'desc') ? $_GET['sort'] : 'desc';
   }
-  $fragments['order_by'][]  = $order . ' ' . $sort . ', pmi.mid DESC';
+  $fragments['order_by'][]  = $order . ' ' . $sort . ', MAX(pmi.mid) DESC';
   $fragments['query_args'][]  = $account->uid;
 
 }
@@ -729,14 +752,36 @@ function privatemsg_privatemsg_load_alte
   $fragments['query_args'][]  = $uid;
 }
 
-function privatemsg_privatemsg_recipients_alter(&$fragments, $thread_id) {
+function privatemsg_privatemsg_messages_alter(&$fragments, $thread_id, $uid) {
+  $fragments['primary_table'] = '{pm_index} pmi';
+
+  $fragments['select'][]      = 'DISTINCT(pmi.mid) as mid';
+  $fragments['where'][]       = 'pmi.thread_id = %d';
+  $fragments['query_args'][]  = $thread_id;
+  if (!(user_access('read all private messages'))) {
+    $fragments['where'][]       = 'pmi.author = %d';
+    $fragments['query_args'][]  = $uid;
+    $fragments['union_select'][]      = 'DISTINCT(pmi.mid) as mid';
+    $fragments['union_where'][]       = 'pmi.thread_id = %d';
+    $fragments['union_where'][]       = 'pmi.recipient = %d';
+    $fragments['query_args'][]  = $thread_id;
+    $fragments['query_args'][]  = $uid;
+  }
+  $fragments['order_by'][]  = 'mid ASC';
+}
+
+function privatemsg_privatemsg_participants_alter(&$fragments, $thread_id) {
   $fragments['primary_table'] = '{pm_index} pmi';
 
   $fragments['select'][]      = 'pmi.recipient as uid';
   $fragments['where'][]       = 'pmi.thread_id = %d';
+  $fragments['union_select'][] = 'pmi.author as uid';
+  $fragments['union_where'][] = 'pmi.thread_id = %d';
+  $fragments['query_args'][]  = $thread_id;
   $fragments['query_args'][]  = $thread_id;
 }
 
+
 function privatemsg_privatemsg_unread_count_alter(&$fragments, $account) {
   $fragments['primary_table'] = '{pm_index} pmi';
 
diff -urp privatemsg/privatemsgapi/privatemsgapi.inc privatemsg_thread/privatemsgapi/privatemsgapi.inc
--- privatemsg/privatemsgapi/privatemsgapi.inc	2008-07-27 01:50:39.000000000 +0100
+++ privatemsg_thread/privatemsgapi/privatemsgapi.inc	2008-09-08 23:09:31.557000000 +0100
@@ -67,6 +67,9 @@ function _privatemsg_assemble_query($que
   $SELECT = array();
   $INNER_JOIN = array();
   $WHERE = array();
+  $UNION_SELECT = array();
+  $UNION_INNER_JOIN = array();
+  $UNION_WHERE = array();
   $GROUP_BY = array();
   $ORDER_BY = array();
   $QUERY_ARGS = array();
@@ -76,6 +79,9 @@ function _privatemsg_assemble_query($que
     'select'      => $SELECT,
     'inner_join'  => $INNER_JOIN,
     'where'       => $WHERE,
+    'union_select'       => $UNION_SELECT,
+    'union_inner_join'  => $UNION_INNER_JOIN,
+    'union_where'       => $UNION_WHERE,
     'group_by'    => $GROUP_BY,
     'order_by'    => $ORDER_BY,
     'query_args'  => $QUERY_ARGS,
@@ -103,6 +109,9 @@ function _privatemsg_assemble_query($que
   $SELECT = $fragments['select'];
   $INNER_JOIN = $fragments['inner_join'];
   $WHERE = $fragments['where'];
+  $UNION_SELECT = $fragments['union_select'];
+  $UNION_INNER_JOIN = $fragments['union_inner_join'];
+  $UNION_WHERE = $fragments['union_where'];
   $GROUP_BY = $fragments['group_by'];
   $ORDER_BY = $fragments['order_by'];
   $QUERY_ARGS = $fragments['query_args'];
@@ -124,6 +133,18 @@ function _privatemsg_assemble_query($que
       $str_where = '('. implode(') AND (', $WHERE) .')';
       $query .= " WHERE {$str_where}";
     }
+    if (!empty($UNION_SELECT)) {
+      $str_union_select = implode(", ", $UNION_SELECT);
+      $query .= "UNION SELECT {$str_union_select} FROM ". $primary_table;
+    }
+    if (!empty($UNION_INNER_JOIN)) {
+      $str_union_inner_join = implode(' ', $UNION_INNER_JOIN);
+      $query .= " {$str_union_inner_join}";
+    }
+    if (!empty($UNION_WHERE)) {
+      $str_union_where = '('. implode(') AND (', $UNION_WHERE) .')';
+      $query .= " WHERE {$str_union_where}";
+    }
     if (!empty($GROUP_BY)) {
       $str_group_by = ' GROUP BY '. implode(", ", $GROUP_BY) ;
       $query .= " {$str_group_by}";
