diff --git modules/comment/comment.module modules/comment/comment.module
index cd9fc46..6996c1c 100644
--- modules/comment/comment.module
+++ modules/comment/comment.module
@@ -104,34 +104,18 @@ function comment_theme() {
       'arguments' => array(),
     ),
     'comment_preview' => array(
-      'arguments' => array('comment' => NULL, 'node' => NULL, 'links' => array(), 'visible' => 1),
-    ),
-    'comment_view' => array(
-      'arguments' => array('comment' => NULL, 'node' => NULL, 'links' => array(), 'visible' => 1),
+      'arguments' => array('comment' => NULL),
     ),
     'comment' => array(
       'template' => 'comment',
-      'arguments' => array('comment' => NULL, 'node' => NULL, 'links' => array()),
-    ),
-    'comment_form_box' => array(
-      'arguments' => array('edit' => NULL, 'title' => NULL),
-    ),
-    'comment_folded' => array(
-      'template' => 'comment-folded',
-      'arguments' => array('comment' => NULL, 'node' => NULL),
-    ),
-    'comment_flat_expanded' => array(
-      'arguments' => array('comment' => NULL, 'node' => NULL),
-    ),
-    'comment_thread_expanded' => array(
-      'arguments' => array('comment' => NULL, 'node' => NULL),
+      'arguments' => array('elements' => NULL),
     ),
     'comment_post_forbidden' => array(
       'arguments' => array('nid' => NULL),
     ),
     'comment_wrapper' => array(
       'template' => 'comment-wrapper',
-      'arguments' => array('content' => NULL, 'node' => NULL),
+      'arguments' => array('elements' => NULL),
     ),
     'comment_submitted' => array(
       'arguments' => array('comment' => NULL),
@@ -532,17 +516,290 @@ function comment_node_view($node, $build_mode) {
       '#attributes' => array('class' => 'links inline'),
     );
 
-    // Append the list of comments to $node->content for node detail pages.
-    if ($node->comment && (bool)menu_get_object() && empty($node->in_preview)) {
-      $node->content['comments'] = array(
-        '#markup' => comment_render($node),
-        '#sorted' => TRUE,
-      );
+    // Append the comment thread if needed.
+    comment_node_view_thread($node);
+  }
+}
+
+/**
+ * Add the list of comments to $node->content for node detail pages.
+ *
+ * @param $node 
+ *  A node object.
+ */
+
+function comment_node_view_thread(&$node) {
+  if ($node->comment && (bool)menu_get_object() && empty($node->in_preview) && user_access('access comments')) {
+    $comments = array();
+    // Only attempt to render comments if the node has visible comments.
+    // Unpublished comments are not included in $node->comment_count, so show
+    // comments unconditionally if the user is an administrator.
+    if ($node->comment_count || user_access('administer comments')) {
+      if ($cids = comment_get_thread($node)) {
+        $comments = comment_load_multiple($cids);
+        comment_prepare_thread($comments);
+        $node->content += comment_build_multiple($comments);
+        $node->content['comments']['#attached_css'][] = drupal_get_path('module', 'comment') . '/comment.css';
+        $node->content['comments']['pager']['#theme'] = 'pager';
+        
+        // If enabled, show new comment form if it's not already being displayed.
+        $reply = arg(0) == 'comment' && arg(1) == 'reply';
+        if (user_access('post comments') && $node->comment == COMMENT_NODE_OPEN && (variable_get('comment_form_location_' . $node->type, COMMENT_FORM_BELOW) == COMMENT_FORM_BELOW) && !$reply) {
+          $build = drupal_get_form('comment_form', array('nid' => $node->nid));
+          $build['#prefix'] = '<h2 class="title">' . t('Post new comment') . '</h2><div>';
+          $build['#suffix'] = '</div>';
+          $node->content['comments']['comment_form'] = $build;
+        }
+      }
     }
   }
 }
 
 /**
+ * Retrieve comment(s) for a thread.
+ *
+ * @param $node
+ *   The node whose comment(s) needs rendering.
+ *
+ * To display threaded comments in the correct order we keep a 'thread' field
+ * and order by that value. This field keeps this data in
+ * a way which is easy to update and convenient to use.
+ *
+ * A "thread" value starts at "1". If we add a child (A) to this comment,
+ * we assign it a "thread" = "1.1". A child of (A) will have "1.1.1". Next
+ * brother of (A) will get "1.2". Next brother of the parent of (A) will get
+ * "2" and so on.
+ *
+ * First of all note that the thread field stores the depth of the comment:
+ * depth 0 will be "X", depth 1 "X.X", depth 2 "X.X.X", etc.
+ *
+ * Now to get the ordering right, consider this example:
+ *
+ * 1
+ * 1.1
+ * 1.1.1
+ * 1.2
+ * 2
+ *
+ * If we "ORDER BY thread ASC" we get the above result, and this is the
+ * natural order sorted by time. However, if we "ORDER BY thread DESC"
+ * we get:
+ *
+ * 2
+ * 1.2
+ * 1.1.1
+ * 1.1
+ * 1
+ *
+ * Clearly, this is not a natural way to see a thread, and users will get
+ * confused. The natural order to show a thread by time desc would be:
+ *
+ * 2
+ * 1
+ * 1.2
+ * 1.1
+ * 1.1.1
+ *
+ * which is what we already did before the standard pager patch. To achieve
+ * this we simply add a "/" at the end of each "thread" value. This way, the
+ * thread fields will look like this:
+ *
+ * 1/
+ * 1.1/
+ * 1.1.1/
+ * 1.2/
+ * 2/
+ *
+ * we add "/" since this char is, in ASCII, higher than every number, so if
+ * now we "ORDER BY thread DESC" we get the correct order. However this would
+ * spoil the reverse ordering, "ORDER BY thread ASC" -- here, we do not need
+ * to consider the trailing "/" so we use a substring only.
+ */
+ function comment_get_thread($node) {
+  $mode = _comment_get_display_setting('mode', $node);
+  $comments_per_page = _comment_get_display_setting('comments_per_page', $node);
+
+  $query = db_select('comment', 'c')->extend('PagerDefault');
+  $query->addField('c', 'cid');
+  $query
+    ->condition('c.nid', $node->nid)
+    ->addTag('node_access')
+    ->limit($comments_per_page);
+
+  $count_query = db_select('comment', 'c');
+  $count_query->addExpression('COUNT(*)');
+  $count_query
+    ->condition('c.nid', $node->nid)
+    ->addTag('node_access');
+
+  if (!user_access('administer comments')) {
+    $query->condition('c.status', COMMENT_PUBLISHED);
+    $count_query->condition('c.status', COMMENT_PUBLISHED);
+  }
+  if ($mode === COMMENT_MODE_FLAT) {
+    $query->orderBy('c.cid', 'ASC');
+  }
+  else {
+    // See comment above. Analysis reveals that this doesn't cost too
+    // much. It scales much much better than having the whole comment
+    // structure.
+    $query->orderBy('SUBSTRING(c.thread, 1, (LENGTH(c.thread) - 1))', 'ASC');
+  }
+
+  $query->setCountQuery($count_query);
+  $cids = $query->execute()->fetchCol();
+  
+  return $cids;
+}
+
+/**
+ * Loop over comment thread, noting indentation level.
+ *
+ * @param array $comments
+ *   An array of comment objects, keyed by cid.
+ * @return void
+ *   An array of comment objects, enriched with indentation information.
+ */
+function comment_prepare_thread(&$comments) {
+  // A flag stating if we are still searching for first new comment on the thread.
+  $first_new = TRUE;
+    
+  // A counter that helps track how indented we are.
+  $divs = 0;
+  
+  foreach ($comments as $key => $comment) {
+    $comment = drupal_unpack($comment);
+    $comment->name = $comment->uid ? $comment->registered_name : $comment->name;
+    $comment->new = node_mark($comment->nid, $comment->timestamp);
+
+    if ($first_new && $comment->new != MARK_READ) {
+      // Assign the anchor only for the first new comment. This avoids duplicate
+      // id attributes on a page.
+      $first_new = FALSE;
+      $comment->first_new = TRUE; // "<a id=\"new\"></a>\n";
+    }
+    
+    // the 'divs element instructs #prefix whether to add an indent div or 
+    // close existing divs (a negative value).
+    $comment->depth = count(explode('.', $comment->thread)) - 1;
+    if ($comment->depth > $divs) {
+      $comment->divs = 1;
+      $divs++;
+    }
+    else {
+      $comment->divs = $comment->depth - $divs;
+      $divs = 0;
+    }
+    $comments[$key] = $comment;
+  }
+}
+
+/**
+ * Generate an array for rendering the given comment.
+ *
+ * @param $comment
+ *   A comment object.
+ * @param $build_mode
+ *   Build mode, e.g. 'full', 'teaser'...
+ *
+ * @return
+ *   An array as expected by drupal_render().
+ */
+function comment_build($comment, $build_mode = 'full') {
+  // $comment = (object)$comment;
+  $node = node_load($comment->nid);
+  $comment = comment_build_content($comment, $build_mode);
+
+  $build = $comment->content;
+
+  $build += array(
+    '#theme_wrapper' => 'comment',
+    '#comment' => $comment,
+    '#build_mode' => $build_mode,
+  );
+  
+  // Determine if we are showing a threaded view.
+  if (isset($comment->divs) && _comment_get_display_setting('mode', $node) == COMMENT_MODE_THREADED) {
+    $prefix = '';
+    if (!empty($comment->first_new)) {
+      $prefix .= "<a id=\"new\"></a>\n";
+    }
+    $prefix .= "<a id=\"comment-$comment->cid\"></a>\n";
+    // Add indentation or close existing divs as needed.
+    $prefix .= $comment->divs <= 0 ? str_repeat('</div>', abs($comment->divs)) : "\n" . '<div class="indented">';
+    $build['#prefix'] = $prefix;
+  }
+  return $build;
+}
+
+/**
+ * Builds a structured array representing the comment's content.
+ *
+ * The content built for the comment (field values, comments, file attachments or
+ * other comment components) will vary depending on the $build_mode parameter.
+ *
+ * @param $comment
+ *   A comment object.
+ * @param $build_mode
+ *   Build mode, e.g. 'full', 'teaser'...
+ *
+ * @return
+ *   A structured array containing the individual elements
+ *   of the comment's content.
+ */
+function comment_build_content($comment, $build_mode = 'full') {  
+  if (empty($comment->content)) {
+    $comment->content = array();
+  }
+  
+  // Build comment body.
+  $comment->content['comment_body'] = array(
+    '#markup' => check_markup($comment->comment, $comment->format, '', FALSE), 
+  );
+  
+  $comment->content['links']['comment'] = array(
+    '#theme' => 'links',
+    '#links' => comment_links($comment),
+    '#attributes' => array('class' => 'links inline'),
+  );
+
+  // Allow modules to make their own additions to the comment.
+  module_invoke_all('comment_view', $comment, $build_mode);
+
+  // Allow modules to modify the structured comment.
+  drupal_alter('comment_build', $comment, $build_mode);
+
+  return $comment;
+}
+
+/**
+ * Construct a drupal_render() style array from an array of loaded comments.
+ *
+ * @param $comments
+ *   An array of comments as returned by comment_load_multiple().
+ * @param $build_mode
+ *   Build mode, e.g. 'full', 'teaser'...
+ * @param $weight
+ *   An integer representing the weight of the first comment in the list.
+ * @return
+ *   An array in the format expected by drupal_render().
+ */
+function comment_build_multiple($comments, $build_mode = 'full', $weight = 0) {
+  $build['comments']['prelude'] = array('#markup' => '<h2 class="comments">Comments</h2>', '#weight' => -20);
+  foreach ($comments as $comment) {
+    $build['comments'][$comment->cid] = comment_build($comment, $build_mode);
+    $build['comments'][$comment->cid]['#weight'] = $weight;
+    $weight++;
+  }
+  $build['comments'] += array(
+    '#sorted' => TRUE,
+    '#attributes' => array('id' => 'comments'),
+    '#theme_wrapper' => 'comment_wrapper',
+  );
+  return $build;
+}
+
+/**
  * Implement hook_form_FORM_ID_alter().
  */
 function comment_form_node_type_form_alter(&$form, $form_state) {
@@ -878,7 +1135,7 @@ function comment_save($comment) {
   }
   else {
     // Add the comment to database. This next section builds the thread field.
-    // Also see the documentation for comment_render().
+    // Also see the documentation for comment_build().
     if ($comment->pid == 0) {
       // This is a comment with no parent comment (depth 0): we start
       // by retrieving the maximum thread level.
@@ -977,24 +1234,13 @@ function comment_link($type, $object, $build_mode) {
  *
  * @param $comment
  *   The comment to which the links will be related.
- * @param $return
- *   Not used.
  * @return
  *   An associative array containing the links.
  */
-function comment_links($comment, $return = 1) {
+function comment_links(&$comment) {
   global $user;
   $links = array();
 
-  // If viewing just this comment, link back to the in-context view.
-  if ($return) {
-    $links['comment_parent'] = array(
-      'title' => t('parent'),
-      'href' => 'comment/' . $comment->cid,
-      'fragment' => "comment-$comment->cid"
-    );
-  }
-
   $node = node_load($comment->nid);
   if ($node->comment == COMMENT_NODE_OPEN) {
     if (user_access('administer comments') && user_access('post comments')) {
@@ -1041,185 +1287,13 @@ function comment_links($comment, $return = 1) {
       $links['comment_forbidden']['html'] = TRUE;
     }
   }
+  
+  
 
   return $links;
 }
 
 /**
- * Renders comment(s).
- *
- * @param $node
- *   The node which comment(s) needs rendering.
- * @param $cid
- *   Optional, if given, only one comment is rendered.
- *
- * To display threaded comments in the correct order we keep a 'thread' field
- * and order by that value. This field keeps this data in
- * a way which is easy to update and convenient to use.
- *
- * A "thread" value starts at "1". If we add a child (A) to this comment,
- * we assign it a "thread" = "1.1". A child of (A) will have "1.1.1". Next
- * brother of (A) will get "1.2". Next brother of the parent of (A) will get
- * "2" and so on.
- *
- * First of all note that the thread field stores the depth of the comment:
- * depth 0 will be "X", depth 1 "X.X", depth 2 "X.X.X", etc.
- *
- * Now to get the ordering right, consider this example:
- *
- * 1
- * 1.1
- * 1.1.1
- * 1.2
- * 2
- *
- * If we "ORDER BY thread ASC" we get the above result, and this is the
- * natural order sorted by time. However, if we "ORDER BY thread DESC"
- * we get:
- *
- * 2
- * 1.2
- * 1.1.1
- * 1.1
- * 1
- *
- * Clearly, this is not a natural way to see a thread, and users will get
- * confused. The natural order to show a thread by time desc would be:
- *
- * 2
- * 1
- * 1.2
- * 1.1
- * 1.1.1
- *
- * which is what we already did before the standard pager patch. To achieve
- * this we simply add a "/" at the end of each "thread" value. This way, the
- * thread fields will look like this:
- *
- * 1/
- * 1.1/
- * 1.1.1/
- * 1.2/
- * 2/
- *
- * we add "/" since this char is, in ASCII, higher than every number, so if
- * now we "ORDER BY thread DESC" we get the correct order. However this would
- * spoil the reverse ordering, "ORDER BY thread ASC" -- here, we do not need
- * to consider the trailing "/" so we use a substring only.
- */
-function comment_render($node, $cid = 0) {
-  global $user;
-  $output = '';
-
-  if (user_access('access comments')) {
-    // Pre-process variables.
-    $nid = $node->nid;
-    if (empty($nid)) {
-      $nid = 0;
-    }
-
-    $mode = _comment_get_display_setting('mode', $node);
-    $comments_per_page = _comment_get_display_setting('comments_per_page', $node);
-
-    if ($cid && is_numeric($cid)) {
-      $comment = current(comment_load_multiple(array('cid' => $cid, 'status' => COMMENT_PUBLISHED)));
-      // Single comment view.
-      if ($comment) {
-        $comment->name = $comment->uid ? $comment->registered_name : $comment->name;
-        $links = module_invoke_all('link', 'comment', $comment, 1);
-        drupal_alter('link', $links, $node);
-
-        $output .= theme('comment_view', $comment, $node, $links);
-      }
-    }
-    // Only attempt to render comments if the node has visible comments.
-    // Unpublished comments are not included in $node->comment_count, so show
-    // comments unconditionally if the user is an administrator.
-    elseif ($node->comment_count || user_access('administer comments')) {
-
-      // Multiple comment view.
-      $query = db_select('comment', 'c')->extend('PagerDefault');
-      $query->addField('c', 'cid');
-      $query
-        ->condition('c.nid', $nid)
-        ->addTag('node_access')
-        ->limit($comments_per_page);
-
-      $count_query = db_select('comment', 'c');
-      $count_query->addExpression('COUNT(*)');
-      $count_query
-        ->condition('c.nid', $nid)
-        ->addTag('node_access');
-
-      if (!user_access('administer comments')) {
-        $query->condition('c.status', COMMENT_PUBLISHED);
-        $count_query->condition('c.status', COMMENT_PUBLISHED);
-      }
-      if ($mode === COMMENT_MODE_FLAT) {
-        $query->orderBy('c.cid', 'ASC');
-      }
-      else {
-        // See comment above. Analysis reveals that this doesn't cost too
-        // much. It scales much much better than having the whole comment
-        // structure.
-        $query->orderBy('SUBSTRING(c.thread, 1, (LENGTH(c.thread) - 1))', 'ASC');
-      }
-
-      $query->setCountQuery($count_query);
-      $cids = $query->execute()->fetchCol();
-
-      $divs = 0;
-      $num_rows = FALSE;
-      $render = '';
-      $comments = comment_load_multiple($cids);
-      drupal_add_css(drupal_get_path('module', 'comment') . '/comment.css');
-      foreach ($comments as $comment) {
-        $comment = drupal_unpack($comment);
-        $comment->name = $comment->uid ? $comment->registered_name : $comment->name;
-        $comment->depth = count(explode('.', $comment->thread)) - 1;
-
-        if ($mode == COMMENT_MODE_THREADED) {
-          if ($comment->depth > $divs) {
-            $divs++;
-            $render .= '<div class="indented">';
-          }
-          else {
-            while ($comment->depth < $divs) {
-              $divs--;
-              $render .= '</div>';
-            }
-          }
-        }
-
-        if ($mode == COMMENT_MODE_FLAT) {
-          $render .= theme('comment_flat_expanded', $comment, $node);
-        }
-        elseif ($mode == COMMENT_MODE_THREADED) {
-          $render .= theme('comment_thread_expanded', $comment, $node);
-        }
-        $num_rows = TRUE;
-      }
-      while ($divs-- > 0) {
-        $render .= '</div>';
-      }
-      $output .= $render;
-      $output .= theme('pager', NULL);
-    }
-
-    // If enabled, show new comment form if it's not already being displayed.
-    $reply = arg(0) == 'comment' && arg(1) == 'reply';
-    if (user_access('post comments') && $node->comment == COMMENT_NODE_OPEN && (variable_get('comment_form_location_' . $node->type, COMMENT_FORM_BELOW) == COMMENT_FORM_BELOW) && !$reply) {
-      $output .= theme('comment_form_box', array('nid' => $nid), t('Post new comment'));
-    }
-    if ($output) {
-      $output = theme('comment_wrapper', $output, $node);
-    }
-  }
-
-  return $output;
-}
-
-/**
  * Comment operations. Offer different update operations depending on
  * which comment administration page is being viewed.
  *
@@ -1395,7 +1469,7 @@ function comment_get_display_ordinal($cid, $node_type) {
   else {
     // For threaded comments, the c.thread column is used for ordering. We can
     // use the vancode for comparison, but must remove the trailing slash.
-    // @see comment_render().
+    // @see comment_build_multiple().
     $query->where('SUBSTRING(c1.thread, 1, (LENGTH(c1.thread) -1)) < SUBSTRING(c2.thread, 1, (LENGTH(c2.thread) -1))');
   }
 
@@ -1424,13 +1498,11 @@ function comment_get_display_page($cid, $node_type) {
 /**
  * Generate the basic commenting form, for appending to a node or display on a separate page.
  *
- * @param $title
- *   Not used.
  * @ingroup forms
  * @see comment_form_validate()
  * @see comment_form_submit()
  */
-function comment_form(&$form_state, $edit, $title = NULL) {
+function comment_form($form_state, $edit = array()) {
   global $user;
   $op = isset($_POST['op']) ? $_POST['op'] : '';
   $node = node_load($edit['nid']);
@@ -1438,6 +1510,7 @@ function comment_form(&$form_state, $edit, $title = NULL) {
   if (!$user->uid && variable_get('comment_anonymous_' . $node->type, COMMENT_ANONYMOUS_MAYNOT_CONTACT) != COMMENT_ANONYMOUS_MAYNOT_CONTACT) {
     drupal_add_js(drupal_get_path('module', 'comment') . '/comment.js');
   }
+
   $edit += array('name' => '', 'mail' => '', 'homepage' => '');
 
   if ($user->uid) {
@@ -1659,30 +1732,15 @@ function comment_form(&$form_state, $edit, $title = NULL) {
     $form['#after_build'] = array('comment_form_add_preview');
   }
 
-  if (empty($edit['cid']) && empty($edit['pid'])) {
-    $form['#action'] = url('comment/reply/' . $edit['nid']);
-  }
+  // TODO
+  // if (empty($edit['cid']) && empty($edit['pid'])) {
+  //     $form['#action'] = url('comment/reply/' . $edit['nid']);
+  //   }
 
   return $form;
 }
 
 /**
- * Theme the comment form box.
- *
- * @param $edit
- *   The form structure.
- * @param $title
- *   The form title.
- * @return
- *   A string containing the box output.
- */
-function theme_comment_form_box($edit, $title = NULL) {
-  $content = drupal_render(drupal_get_form('comment_form', $edit, $title));
-  $output = '<h2 class="title">' . $title . '</h2><div>' . $content . '</div>';
-  return $output;
-}
-
-/**
  * Form builder; Generate and validate a comment preview form.
  *
  * @ingroup forms
@@ -1885,65 +1943,24 @@ function comment_form_submit($form, &$form_state) {
 }
 
 /**
- * Theme a single comment block.
- *
- * @param $comment
- *   The comment object.
- * @param $node
- *   The comment node.
- * @param $links
- *   An associative array containing control links.
- * @param $visible
- *   Switches between folded/unfolded view.
- * @ingroup themeable
- */
-function theme_comment_view($comment, $node, $links = array(), $visible = TRUE) {
-  $first_new = &drupal_static(__FUNCTION__, TRUE);
-  $comment->new = node_mark($comment->nid, $comment->timestamp);
-  $output = '';
-
-  if ($first_new && $comment->new != MARK_READ) {
-    // Assign the anchor only for the first new comment. This avoids duplicate
-    // id attributes on a page.
-    $first_new = FALSE;
-    $output .= "<a id=\"new\"></a>\n";
-  }
-
-  $output .= "<a id=\"comment-$comment->cid\"></a>\n";
-
-  // Switch to folded/unfolded view of the comment.
-  if ($visible) {
-    $comment->comment = check_markup($comment->comment, $comment->format, '', FALSE);
-    // Comment API hook.
-    module_invoke_all('comment_view', $comment);
-    $output .= theme('comment', $comment, $node, $links);
-  }
-  else {
-    $output .= theme('comment_folded', $comment, $node);
-  }
-
-  return $output;
-}
-
-/**
  * Process variables for comment.tpl.php.
  *
  * @see comment.tpl.php
- * @see theme_comment()
  */
 function template_preprocess_comment(&$variables) {
-  $comment = $variables['comment'];
-  $node = $variables['node'];
+  $comment = $variables['elements']['#comment'];
+  $variables['comment'] = $comment;
+  $variables['node'] = node_load($comment->nid);
   $variables['author']    = theme('username', $comment);
-  $variables['content']   = $comment->comment;
+  $variables['content']   = $variables['elements']['#children'];
   $variables['date']      = format_date($comment->timestamp);
   $variables['links']     = isset($variables['links']) ? theme('links', $variables['links']) : '';
-  $variables['new']       = $comment->new ? t('new') : '';
+  $variables['new']       = !empty($comment->new) ? t('new') : '';
   $variables['picture']   = theme_get_setting('toggle_comment_user_picture') ? theme('user_picture', $comment) : '';
   $variables['signature'] = $comment->signature;
   $variables['submitted'] = theme('comment_submitted', $comment);
   $variables['title']     = l($comment->subject, 'comment/' . $comment->cid, array('fragment' => "comment-$comment->cid"));
-  $variables['template_files'][] = 'comment-' . $node->type;
+  $variables['template_files'][] = 'comment-' . $variables['node']->type;
   // Set status to a string representation of comment->status.
   if (isset($comment->preview)) {
     $variables['status']  = 'comment-preview';
@@ -1980,6 +1997,7 @@ function template_preprocess_comment(&$variables) {
  */
 function template_preprocess_comment_folded(&$variables) {
   $comment = $variables['comment'];
+  $variables['node'] = node_load($comment->nid);
   $variables['author'] = theme('username', $comment);
   $variables['date']   = format_date($comment->timestamp);
   $variables['new']    = $comment->new ? t('new') : '';
@@ -2006,32 +2024,6 @@ function template_preprocess_comment_folded(&$variables) {
 }
 
 /**
- * Theme comment flat expanded view.
- *
- * @param $comment
- *   The comment to be themed.
- * @param $node
- *   The comment node.
- * @ingroup themeable
- */
-function theme_comment_flat_expanded($comment, $node) {
-  return theme('comment_view', $comment, $node, module_invoke_all('link', 'comment', $comment, 0));
-}
-
-/**
- * Theme comment thread expanded view.
- *
- * @param $comment
- *   The comment to be themed.
- * @param $node
- *   The comment node.
- * @ingroup themeable
- */
-function theme_comment_thread_expanded($comment, $node) {
-  return theme('comment_view', $comment, $node, module_invoke_all('link', 'comment', $comment, 0));
-}
-
-/**
  * Theme a "you can't post comments" notice.
  *
  * @param $node
@@ -2075,6 +2067,9 @@ function theme_comment_post_forbidden($node) {
  * @see theme_comment_wrapper()
  */
 function template_preprocess_comment_wrapper(&$variables) {
+  $variables['node'] = menu_get_object();
+  $variables['content'] = $variables['elements']['#children'];
+
   // Provide contextual information.
   $variables['display_mode']  = _comment_get_display_setting('mode', $variables['node']);
   $variables['template_files'][] = 'comment-wrapper-' . $variables['node']->type;
diff --git modules/comment/comment.pages.inc modules/comment/comment.pages.inc
index 226a389..98f1e84 100644
--- modules/comment/comment.pages.inc
+++ modules/comment/comment.pages.inc
@@ -52,7 +52,7 @@ function comment_reply($node, $pid = NULL) {
   // Set the breadcrumb trail.
   drupal_set_breadcrumb(array(l(t('Home'), NULL), l($node->title, 'node/' . $node->nid)));
   $op = isset($_POST['op']) ? $_POST['op'] : '';
-  $output = '';
+  $build = array();
 
   if (user_access('access comments')) {
     // The user is previewing a comment prior to submitting it.
@@ -84,7 +84,7 @@ function comment_reply($node, $pid = NULL) {
           // Display the parent comment
           $comment = drupal_unpack($comment);
           $comment->name = $comment->uid ? $comment->registered_name : $comment->name;
-          $output .= theme('comment_view', $comment, $node);
+          $build['commment_parent'] = comment_build($comment);
         }
         else {
           drupal_set_message(t('The comment you are replying to does not exist.'), 'error');
@@ -93,7 +93,7 @@ function comment_reply($node, $pid = NULL) {
       }
       // This is the case where the comment is in response to a node. Display the node.
       elseif (user_access('access content')) {
-        $output .= drupal_render(node_build($node));
+        $build['comment_node'] = node_build($node);
       }
 
       // Should we show the reply box?
@@ -102,7 +102,8 @@ function comment_reply($node, $pid = NULL) {
         drupal_goto("node/$node->nid");
       }
       elseif (user_access('post comments')) {
-        $output .= theme('comment_form_box', array('pid' => $pid, 'nid' => $node->nid), t('Add new comment'));
+        $edit = array('nid' => $node->nid, 'pid' => $pid);
+        $build['comment_form'] = drupal_get_form('comment_form', $edit);
       }
       else {
         drupal_set_message(t('You are not authorized to post comments.'), 'error');
@@ -115,7 +116,7 @@ function comment_reply($node, $pid = NULL) {
     drupal_goto("node/$node->nid");
   }
 
-  return $output;
+  return $build;
 }
 
 /**
diff --git themes/garland/template.php themes/garland/template.php
index 1952353..97fab30 100644
--- themes/garland/template.php
+++ themes/garland/template.php
@@ -15,18 +15,6 @@ function garland_breadcrumb($breadcrumb) {
 }
 
 /**
- * Allow themable wrapping of all comments.
- */
-function garland_comment_wrapper($content, $node) {
-  if (!$content || $node->type == 'forum') {
-    return '<div id="comments">' . $content . '</div>';
-  }
-  else {
-    return '<div id="comments"><h2 class="comments">' . t('Comments') . '</h2>' . $content . '</div>';
-  }
-}
-
-/**
  * Override or insert variables into the page template.
  */
 function garland_preprocess_page(&$vars) {
