Index: modules/comment.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/comment.module,v
retrieving revision 1.455.2.1
diff -p -u -r1.455.2.1 comment.module
--- modules/comment.module	4 May 2006 11:15:13 -0000	1.455.2.1
+++ modules/comment.module	13 May 2006 11:09:42 -0000
@@ -171,10 +171,10 @@ function comment_block($op = 'list', $de
 }
 
 function theme_comment_block() {
-  $result = db_query_range(db_rewrite_sql('SELECT c.nid, c.subject, c.cid, c.timestamp FROM {comments} c INNER JOIN {node} n ON n.nid = c.nid WHERE n.status = 1 AND c.status = %d ORDER BY c.timestamp DESC', 'c'), COMMENT_PUBLISHED, 0, 10);
+  $result = db_query_range(db_rewrite_sql('SELECT c.nid, c.subject, c.cid, c.timestamp, c.thread, ncs.comment_count FROM {comments} c INNER JOIN {node} n ON n.nid = c.nid INNER JOIN {node_comment_statistics} ncs ON ncs.nid = n.nid WHERE n.status = 1 AND c.status = %d ORDER BY c.timestamp DESC', 'c'), COMMENT_PUBLISHED, 0, 10);
   $items = array();
   while ($comment = db_fetch_object($result)) {
-    $items[] = l($comment->subject, 'node/'. $comment->nid, NULL, NULL, 'comment-'. $comment->cid) .'<br />'. t('%time ago', array('%time' => format_interval(time() - $comment->timestamp)));
+    $items[] = l($comment->subject, 'node/'. $comment->nid, NULL, comment_page_query($comment), 'comment-'. $comment->cid) .'<br />'. t('%time ago', array('%time' => format_interval(time() - $comment->timestamp)));
   }
   return theme('item_list', $items);
 }
@@ -198,7 +198,7 @@ function comment_link($type, $node = 0, 
           $links[] = l(format_plural($all, '1 comment', '%count comments'), "node/$node->nid", array('title' => t('Jump to the first comment of this posting.')), NULL, 'comment');
 
           if ($new) {
-            $links[] = l(format_plural($new, '1 new comment', '%count new comments'), "node/$node->nid", array('title' => t('Jump to the first new comment of this posting.')), NULL, 'new');
+            $links[] = l(format_plural($new, '1 new comment', '%count new comments'), "node/$node->nid", array('title' => t('Jump to the first new comment of this posting.')), comment_page_new_query($node->nid), 'new');
           }
         }
         else {
@@ -1097,13 +1097,22 @@ function _comment_load($cid) {
   return db_fetch_object(db_query('SELECT * FROM {comments} WHERE cid = %d', $cid));
 }
 
-function comment_num_all($nid) {
+/**
+ * get number of comments for specified node
+ */
+function comment_num_all($nid, $include_not_published = FALSE) {
   static $cache;
-
-  if (!isset($cache[$nid])) {
-    $cache[$nid] = db_result(db_query('SELECT comment_count FROM {node_comment_statistics} WHERE nid = %d', $nid));
+  $key = $include_not_published ? 'published_unpublished' : 'published';
+  
+  if (!isset($cache[$nid][$key])) {
+    if ($include_not_published || user_access('administer comments')) {
+      $cache[$nid] = db_fetch_array(db_query('SELECT COUNT(*) AS published_unpublished, ncs.comment_count AS published FROM {comments} c INNER JOIN {node_comment_statistics} ncs ON ncs.nid = c.nid WHERE c.nid = %d GROUP BY c.nid, ncs.comment_count', $nid));
+    }
+    else {
+      $cache[$nid][$key] = db_result(db_query('SELECT comment_count FROM {node_comment_statistics} WHERE nid = %d', $nid));
+    }
   }
-  return $cache[$nid];
+  return $cache[$nid][$key];
 }
 
 function comment_num_replies($pid) {
@@ -1124,25 +1133,7 @@ function comment_num_replies($pid) {
  *   to node)
  */
 function comment_num_new($nid, $timestamp = 0) {
-  global $user;
-
-  if ($user->uid) {
-    // Retrieve the timestamp at which the current user last viewed the
-    // specified node.
-    if (!$timestamp) {
-      $timestamp = node_last_viewed($nid);
-    }
-    $timestamp = ($timestamp > NODE_NEW_LIMIT ? $timestamp : NODE_NEW_LIMIT);
-
-    // Use the timestamp to retrieve the number of new comments.
-    $result = db_result(db_query('SELECT COUNT(c.cid) FROM {node} n INNER JOIN {comments} c ON n.nid = c.nid WHERE n.nid = %d AND timestamp > %d AND c.status = %d', $nid, $timestamp, COMMENT_PUBLISHED));
-
-    return $result;
-  }
-  else {
-    return 0;
-  }
-
+  return _comment_new_comments($nid, 'num', $timestamp);
 }
 
 function comment_validate($edit) {
@@ -1434,7 +1425,8 @@ function _comment_form_submit($form_valu
 function comment_form_submit($form_id, $form_values) {
   $form_values = _comment_form_submit($form_values);
   if ($cid = comment_save($form_values)) {
-    return array('node/'. $form_values['nid'], NULL, "comment-$cid");
+    $comment = db_fetch_object(db_query('SELECT c.cid, c.nid, c.timestamp, c.thread, ncs.comment_count FROM {comments} c INNER JOIN {node_comment_statistics} ncs ON ncs.nid = c.nid WHERE cid = %d', $cid));
+    return array('node/'. $form_values['nid'], comment_page_query($comment), "comment-$cid");
   }
 }
 
@@ -1696,6 +1688,130 @@ function _comment_get_display_setting($s
 }
 
 /**
+ * Return an URL query string that points to the page the comment is on.
+ * Used in links to comments (e.g. 'recent comments' block). 
+ *
+ * @param $comment 
+ *   A comment object.
+ *   Required fields: 'nid', 'timestamp', 'thread'
+ *   Optional field: 'comment_count' (to save a db query get this field by
+ *     doing a JOIN of the node_comment_statistics on the comments table)
+ */
+function comment_page_query($comment) {
+  $page = _comment_page($comment);
+  return $page ? "page=$page" : NULL;
+}
+
+/**
+ * Return an URL query string that points to the page the node's first new
+ * comment is on. Used in links to new comments ('# new' links). 
+ *
+ * @param $nid
+ *   A node ID.
+ */
+function comment_page_new_query($nid) {
+  $comments_per_page = _comment_get_display_setting('comments_per_page');
+  $comments_num = comment_num_all($nid, user_access('administer comments'));
+  if ($comments_num <= $comments_per_page) {
+    // one page of comments only
+    return NULL;
+  }
+  else {
+    // get the node's first new comment
+    $cid = _comment_new_comments($nid, 'first');
+    $comment = db_fetch_object(db_query('SELECT nid, timestamp, thread FROM {comments} WHERE cid = %d', $cid));
+    return comment_page_query($comment);
+  }
+}
+
+/**
+ * Return the page a comment is on
+ */
+function _comment_page($comment) {
+  $comments_per_page = _comment_get_display_setting('comments_per_page');
+  if (user_access('administer comments')) {
+    // For users with 'administer comments' permission
+    // we have to count published and unpublished comments.
+    $comments_num = comment_num_all($comment->nid, TRUE);
+  }
+  else {
+    $comments_num = isset($comment->comment_count) ? $comment->comment_count : comment_num_all($comment->nid);
+  }
+  if ($comments_num <= $comments_per_page) {
+    // one page of comments only
+    return 0;
+  }
+  else {
+    // Build the database query that retrieves the comment's position
+    // This follows the same sheme as in comment_render().
+    // See comments there for an explanation.
+    $query = 'SELECT COUNT(*) FROM {comments} WHERE nid = %d';
+    $query_args = array($comment->nid);
+    
+    if (!user_access('administer comments')) {
+      $query .= ' AND status = %d';
+      $query_args[] = COMMENT_PUBLISHED;
+    }
+
+    $mode = _comment_get_display_setting('mode');
+    $order = _comment_get_display_setting('sort');
+    if ($order == COMMENT_ORDER_NEWEST_FIRST) {
+      if ($mode == COMMENT_MODE_FLAT_COLLAPSED || $mode == COMMENT_MODE_FLAT_EXPANDED) {
+        $query .= ' AND timestamp > %d';
+        $query_args[] = $comment->timestamp;
+      }
+      else {
+        $query .= " AND thread > '%s'";
+        $query_args[] = $comment->thread;
+      }
+    }
+    else if ($order == COMMENT_ORDER_OLDEST_FIRST) {
+      if ($mode == COMMENT_MODE_FLAT_COLLAPSED || $mode == COMMENT_MODE_FLAT_EXPANDED) {
+        $query .= ' AND timestamp < %d';
+        $query_args[] = $comment->timestamp;
+      }
+      else {
+        $query .= " AND SUBSTRING(thread, 1, (LENGTH(thread) - 1)) < '%s'";
+        $query_args[] = substr($comment->thread, 0, -1);
+      }
+    }
+    
+    $count = db_result(db_query($query, $query_args));
+    return floor($count / $comments_per_page);
+  } 
+}
+
+/**
+ * Return the specified node's number of new comments ($key = 'num')
+ * or the first new comment ($key = 'first') for the current user
+ */
+function _comment_new_comments($nid, $key, $timestamp = 0) {
+  global $user;
+  static $cache = array();
+
+  if ($user->uid) {
+    if (!isset($cache[$nid])) {
+      // Retrieve the timestamp at which the current user last viewed the
+      // specified node.
+      if (!$timestamp) {
+        $timestamp = node_last_viewed($nid);
+      }
+      $timestamp = ($timestamp > NODE_NEW_LIMIT ? $timestamp : NODE_NEW_LIMIT);
+
+      // Use the timestamp to retrieve the number of new comments
+      // and the first new comment
+      $result = db_query('SELECT COUNT(cid) AS num, MIN(cid) AS first FROM {comments} WHERE nid = %d AND timestamp > %d AND status = %d', $nid, $timestamp, COMMENT_PUBLISHED);
+      $cache[$nid] = db_fetch_array($result);
+    }
+    return $cache[$nid][$key];
+  }
+  else {
+    return NULL;
+  }
+
+}
+
+/**
  * Updates the comment statistics for a given node.  This should be called any
  * time a comment is added, deleted, or updated.
  *
Index: modules/forum.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/forum.module,v
retrieving revision 1.328
diff -p -u -r1.328 forum.module
--- modules/forum.module	13 Apr 2006 08:25:27 -0000	1.328
+++ modules/forum.module	2 May 2006 10:36:19 -0000
@@ -993,7 +993,7 @@ function theme_forum_topic_list($tid, $t
         $rows[] = array(
           array('data' => theme('forum_icon', $topic->new, $topic->num_comments, $topic->comment_mode, $topic->sticky), 'class' => 'icon'),
           array('data' => l($topic->title, "node/$topic->nid"), 'class' => 'topic'),
-          array('data' => $topic->num_comments . ($topic->new_replies ? '<br />'. l(format_plural($topic->new_replies, '1 new', '%count new'), "node/$topic->nid", NULL, NULL, 'new') : ''), 'class' => 'replies'),
+          array('data' => $topic->num_comments . ($topic->new_replies ? '<br />'. l(format_plural($topic->new_replies, '1 new', '%count new'), "node/$topic->nid", NULL, comment_page_new_query($topic->nid), 'new') : ''), 'class' => 'replies'),
           array('data' => _forum_format($topic), 'class' => 'created'),
           array('data' => _forum_format($topic->last_reply), 'class' => 'last-reply')
         );
Index: modules/tracker.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/tracker.module,v
retrieving revision 1.129
diff -p -u -r1.129 tracker.module
--- modules/tracker.module	17 Apr 2006 20:48:26 -0000	1.129
+++ modules/tracker.module	2 May 2006 10:36:26 -0000
@@ -105,7 +105,7 @@ function tracker_page($uid = 0) {
 
       if ($new = comment_num_new($node->nid)) {
         $comments .= '<br />';
-        $comments .= l(format_plural($new, '1 new', '%count new'), "node/$node->nid", NULL, NULL, 'new');
+        $comments .= l(format_plural($new, '1 new', '%count new'), "node/$node->nid", NULL, comment_page_new_query($node->nid), 'new');
       }
     }
 
