Index: includes/theme.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/theme.inc,v
retrieving revision 1.433
diff -u -p -r1.433 theme.inc
--- includes/theme.inc	2 Sep 2008 17:38:55 -0000	1.433
+++ includes/theme.inc	3 Sep 2008 19:26:48 -0000
@@ -320,6 +320,8 @@ function _theme_process_registry(&$cache
       }
       // Check for sub-directories.
       $result[$hook]['theme paths'][] = isset($info['path']) ? $info['path'] : $path;
+      // Ensure there are no duplicates.
+      $result[$hook]['theme paths'] = array_unique($result[$hook]['theme paths']);
 
       // Check for default _preprocess_ functions. Ensure arrayness.
       if (!isset($info['preprocess functions']) || !is_array($info['preprocess functions'])) {
@@ -664,7 +666,7 @@ function theme() {
     }
 
     if ($suggestions) {
-      $template_file = drupal_discover_template($info['theme paths'], $suggestions, $extension);
+      $template_file = drupal_discover_template($hook, $info['theme paths'], $suggestions, $extension);
     }
 
     if (empty($template_file)) {
@@ -685,7 +687,7 @@ function theme() {
  * templates from themes and modules. Theming implementations can occur on
  * multiple levels. All paths are checked to account for this.
  */
-function drupal_discover_template($paths, $suggestions, $extension = '.tpl.php') {
+function drupal_discover_template($hook, $paths, $suggestions, $extension = '.tpl.php') {
   global $theme_engine;
 
   // Loop through all paths and suggestions in FIFO order.
@@ -694,7 +696,7 @@ function drupal_discover_template($paths
   foreach ($suggestions as $suggestion) {
     if (!empty($suggestion)) {
       foreach ($paths as $path) {
-        if (file_exists($file = $path . '/' . $suggestion . $extension)) {
+        if (file_exists($file = $path . '/' . $hook . '.'. $suggestion . $extension)) {
           return $file;
         }
       }
@@ -793,26 +795,50 @@ function drupal_find_theme_templates($ca
   $regex = str_replace('.', '\.', $extension) . '$';
   // Because drupal_system_listing works the way it does, we check for real
   // templates separately from checking for patterns.
-  $files = drupal_system_listing($regex, $path, 'name', 0);
+  $files = drupal_system_listing($regex, $path, 'basename', 0);
   foreach ($files as $template => $file) {
     // Ignore sub-theme templates for the current theme.
     if (strpos($file->filename, str_replace($subtheme_paths, '', $file->filename)) !== 0) {
       continue;
     }
-    // Chop off the remaining extensions if there are any. $template already
-    // has the rightmost extension removed, but there might still be more,
-    // such as with .tpl.php, which still has .tpl in $template at this point.
-    if (($pos = strpos($template, '.')) !== FALSE) {
+
+    // Chop off the extensions if there are any.
+    if (($pos = strpos($template, $extension)) !== FALSE) {
       $template = substr($template, 0, $pos);
     }
     // Transform - in filenames to _ to match function naming scheme
     // for the purposes of searching.
     $hook = strtr($template, '-', '_');
+    // Path to themed template.
+    $themed_path = dirname($file->filename);
+
+    // Check if this is a base template for the hook.
     if (isset($cache[$hook])) {
-      $templates[$hook] = array(
-        'template' => $template,
-        'path' => dirname($file->filename),
-      );
+      $templates[$hook]['template'] = $template;
+      $templates[$hook]['path']     = $themed_path;
+    }
+    // Check for template suggestions which are delimited with a ".".
+    elseif (($pos = strpos($hook, '.')) !== FALSE) {
+      $hook = substr($hook, 0, $pos);
+      if (isset($cache[$hook])) {
+        // Carry over existing theming paths.
+        if (!isset($templates[$hook]['theme paths'])) {
+          $templates[$hook]['theme paths'] = $cache[$hook]['theme paths'];
+        }
+        // Carry over existing template.
+        if (isset($cache[$hook]['template'])) {
+          $templates[$hook]['template'] = $cache[$hook]['template'];
+        }
+        // Carry over existing path.
+        if (isset($cache[$hook]['path'])) {
+          $templates[$hook]['path'] = $cache[$hook]['path'];
+        }
+        // Newly discovered suggestions must come first. The paths will be
+        // fed into drupal_discover_template() to discover the suggestions.
+        if (!in_array($themed_path, $templates[$hook]['theme paths'])) {
+          $templates[$hook]['theme paths'][] = $themed_path;
+        }
+      }
     }
   }
 
@@ -825,19 +851,42 @@ function drupal_find_theme_templates($ca
       $pattern = strtr($info['pattern'], '_', '-');
 
       $matches = preg_grep('/^' . $pattern . '/', $patterns);
+      $suggestion_paths = array();
       if ($matches) {
         foreach ($matches as $match) {
-          $file = substr($match, 0, strpos($match, '.'));
+          $file = substr($match, 0, strpos($match, $extension));
           // Put the underscores back in for the hook name and register this pattern.
-          $templates[strtr($file, '-', '_')] = array(
-            'template' => $file,
-            'path' => dirname($files[$match]->filename),
-            'arguments' => $info['arguments'],
-          );
+          $hook_file = strtr($file, '-', '_');
+          $themed_path = dirname($files[$match]->filename);
+
+          // Build paths to suggested templates to be added later. They are delimited with a ".".
+          if (strpos($hook_file, '.') !== FALSE) {
+            $base_hook = substr($hook_file, 0, strpos($hook_file, '.'));
+            $suggestion_paths[$base_hook][] = $themed_path;
+          }
+          // Register templates detected through the pattern.
+          else {
+            $templates[$hook_file]['template']  = $file;
+            $templates[$hook_file]['path']      = $themed_path;
+            $templates[$hook_file]['arguments'] = $info['arguments'];
+          }
+        }
+
+        // Register the pahs.
+        foreach ($suggestion_paths as $hook_file => $themed_paths) {
+          if (!isset($templates[$hook_file]['theme paths'])) {
+            $templates[$hook_file]['theme paths'] = array();
+          }
+          foreach ($themed_paths as $themed_path) {
+            if (!in_array($themed_path, $templates[$hook_file]['theme paths'])) {
+              $templates[$hook_file]['theme paths'][] = $themed_path;
+            }
+          }
         }
       }
     }
   }
+
   return $templates;
 }
 
@@ -1891,21 +1940,22 @@ function template_preprocess_page(&$vari
   // http://www.example.com/node/1/edit would result in the following
   // suggestions:
   //
-  // page-node-edit.tpl.php
-  // page-node-1.tpl.php
-  // page-node.tpl.php
+  // page.node-edit.tpl.php
+  // page.node-1.tpl.php
+  // page.node.tpl.php
   // page.tpl.php
   $i = 0;
   $suggestion = 'page';
   $suggestions = array();
   while ($arg = arg($i++)) {
-    $suggestions[] = $suggestion . '-' . $arg;
+    $delimit = $i === 1 ? '.' : '-';
+    $suggestions[] = $suggestion . $delimit . $arg;
     if (!is_numeric($arg)) {
-      $suggestion .= '-' . $arg;
+      $suggestion .= $delimit . $arg;
     }
   }
   if (drupal_is_front_page()) {
-    $suggestions[] = 'page-front';
+    $suggestions[] = 'page.front';
   }
 
   if ($suggestions) {
@@ -1966,8 +2016,8 @@ function template_preprocess_node(&$vari
     $variables['picture'] = '';
   }
   // Clean up name so there are no underscores.
-  $variables['template_files'][] = 'node-' . str_replace('_', '-', $node->type);
-  $variables['template_files'][] = 'node-' . $node->nid;
+  $variables['template_files'][] = str_replace('_', '-', $node->type);
+  $variables['template_files'][] = $node->nid;
 }
 
 /**
@@ -1997,8 +2047,8 @@ function template_preprocess_block(&$var
   $variables['block_zebra'] = ($block_counter[$variables['block']->region] % 2) ? 'odd' : 'even';
   $variables['block_id'] = $block_counter[$variables['block']->region]++;
 
-  $variables['template_files'][] = 'block-' . $variables['block']->region;
-  $variables['template_files'][] = 'block-' . $variables['block']->module;
-  $variables['template_files'][] = 'block-' . $variables['block']->module . '-' . $variables['block']->delta;
+  $variables['template_files'][] = $variables['block']->region;
+  $variables['template_files'][] = $variables['block']->module;
+  $variables['template_files'][] = $variables['block']->module . '-' . $variables['block']->delta;
 }
 
Index: includes/theme.maintenance.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/theme.maintenance.inc,v
retrieving revision 1.16
diff -u -p -r1.16 theme.maintenance.inc
--- includes/theme.maintenance.inc	21 Aug 2008 19:36:36 -0000	1.16
+++ includes/theme.maintenance.inc	3 Sep 2008 19:26:48 -0000
@@ -284,6 +284,6 @@ function template_preprocess_maintenance
   // Dead databases will show error messages so supplying this template will
   // allow themers to override the page and the content completely.
   if (isset($variables['db_is_active']) && !$variables['db_is_active']) {
-    $variables['template_file'] = 'maintenance-page-offline';
+    $variables['template_file'] = 'offline';
   }
 }
Index: modules/comment/comment.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/comment/comment.module,v
retrieving revision 1.647
diff -u -p -r1.647 comment.module
--- modules/comment/comment.module	21 Aug 2008 19:36:36 -0000	1.647
+++ modules/comment/comment.module	3 Sep 2008 19:26:48 -0000
@@ -1605,7 +1605,7 @@ function template_preprocess_comment(&$v
   $variables['signature'] = $comment->signature;
   $variables['submitted'] = theme('comment_submitted', $comment);
   $variables['title']     = l($comment->subject, $_GET['q'], array('fragment' => "comment-$comment->cid"));
-  $variables['template_files'][] = 'comment-' . $node->type;
+  $variables['template_files'][] = $node->type;
   // Set status to a string representation of comment->status.
   if (isset($comment->preview)) {
     $variables['status']  = 'comment-preview';
@@ -1730,7 +1730,7 @@ function theme_comment_post_forbidden($n
 function template_preprocess_comment_wrapper(&$variables) {
   // Provide contextual information.
   $variables['display_mode']  = _comment_get_display_setting('mode', $variables['node']);
-  $variables['template_files'][] = 'comment-wrapper-' . $variables['node']->type;
+  $variables['template_files'][] = $variables['node']->type;
 }
 
 /**
Index: modules/forum/forum.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/forum/forum.module,v
retrieving revision 1.461
diff -u -p -r1.461 forum.module
--- modules/forum/forum.module	11 Aug 2008 21:57:40 -0000	1.461
+++ modules/forum/forum.module	3 Sep 2008 19:26:48 -0000
@@ -702,17 +702,17 @@ function template_preprocess_forums(&$va
     // Provide separate template suggestions based on what's being output. Topic id is also accounted for.
     // Check both variables to be safe then the inverse. Forums with topic ID's take precedence.
     if ($variables['forums'] && !$variables['topics']) {
-      $variables['template_files'][] = 'forums-containers';
-      $variables['template_files'][] = 'forums-' . $variables['tid'];
-      $variables['template_files'][] = 'forums-containers-' . $variables['tid'];
+      $variables['template_files'][] = 'containers';
+      $variables['template_files'][] = $variables['tid'];
+      $variables['template_files'][] = 'containers-' . $variables['tid'];
     }
     elseif (!$variables['forums'] && $variables['topics']) {
-      $variables['template_files'][] = 'forums-topics';
-      $variables['template_files'][] = 'forums-' . $variables['tid'];
-      $variables['template_files'][] = 'forums-topics-' . $variables['tid'];
+      $variables['template_files'][] = 'topics';
+      $variables['template_files'][] = $variables['tid'];
+      $variables['template_files'][] = 'topics-' . $variables['tid'];
     }
     else {
-      $variables['template_files'][] = 'forums-' . $variables['tid'];
+      $variables['template_files'][] = $variables['tid'];
     }
 
   }
Index: modules/poll/poll.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/poll/poll.module,v
retrieving revision 1.270
diff -u -p -r1.270 poll.module
--- modules/poll/poll.module	24 Jul 2008 16:25:18 -0000	1.270
+++ modules/poll/poll.module	3 Sep 2008 19:26:48 -0000
@@ -666,7 +666,7 @@ function template_preprocess_poll_vote(&
   $variables['block'] = $form['#block'];
   // If this is a block, allow a different tpl.php to be used.
   if ($variables['block']) {
-    $variables['template_files'][] = 'poll-vote-block';
+    $variables['template_files'][] = 'block';
   }
 }
 
@@ -762,7 +762,7 @@ function template_preprocess_poll_result
 
   // If this is a block, allow a different tpl.php to be used.
   if ($variables['block']) {
-    $variables['template_files'][] = 'poll-results-block';
+    $variables['template_files'][] = 'block';
   }
 }
 
@@ -777,7 +777,7 @@ function template_preprocess_poll_result
  */
 function template_preprocess_poll_bar(&$variables) {
   if ($variables['block']) {
-    $variables['template_files'][] = 'poll-bar-block';
+    $variables['template_files'][] = 'block';
   }
   $variables['title'] = check_plain($variables['title']);
   $variables['percentage'] = round($variables['votes'] * 100 / max($variables['total_votes'], 1));
Index: modules/profile/profile.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/profile/profile.module,v
retrieving revision 1.243
diff -u -p -r1.243 profile.module
--- modules/profile/profile.module	24 Jul 2008 16:25:18 -0000	1.243
+++ modules/profile/profile.module	3 Sep 2008 19:26:48 -0000
@@ -531,7 +531,7 @@ function template_preprocess_profile_wra
   if ($field = arg(1)) {
     $variables['current_field'] = $field;
     // Supply an alternate template suggestion based on the browsable field.
-    $variables['template_files'][] = 'profile-wrapper-' . $field;
+    $variables['template_files'][] = $field;
   }
 }
 
Index: modules/search/search.pages.inc
===================================================================
RCS file: /cvs/drupal/drupal/modules/search/search.pages.inc,v
retrieving revision 1.5
diff -u -p -r1.5 search.pages.inc
--- modules/search/search.pages.inc	14 Apr 2008 17:48:41 -0000	1.5
+++ modules/search/search.pages.inc	3 Sep 2008 19:26:48 -0000
@@ -65,7 +65,7 @@ function template_preprocess_search_resu
   }
   $variables['pager'] = theme('pager', NULL, 10, 0);
   // Provide alternate search results template.
-  $variables['template_files'][] = 'search-results-' . $variables['type'];
+  $variables['template_files'][] = $variables['type'];
 }
 
 /**
@@ -101,7 +101,7 @@ function template_preprocess_search_resu
   $variables['info_split'] = $info;
   $variables['info'] = implode(' - ', $info);
   // Provide alternate search result template.
-  $variables['template_files'][] = 'search-result-' . $variables['type'];
+  $variables['template_files'][] = $variables['type'];
 }
 
 /**
