? DrupalHead.kpf
? files
? node_page_default_1.patch
? node_url.patch
? page_context.patch
? reg2.patch
? registry.patch
? registry_0.patch
? test.php
? theme_reg.patch
? themefuncs.txt
? includes/query.inc
? sites/logrus.com
? sites/all/modules
Index: index.php
===================================================================
RCS file: /cvs/drupal/drupal/index.php,v
retrieving revision 1.92
diff -u -p -r1.92 index.php
--- index.php	11 Feb 2007 09:30:50 -0000	1.92
+++ index.php	27 Mar 2007 23:32:29 -0000
@@ -31,7 +31,6 @@ if (is_int($return)) {
 elseif (isset($return)) {
   // Print any value (including an empty string) except NULL or undefined:
   print theme('page', $return);
-
 }
 
 drupal_page_footer();
Index: includes/bootstrap.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/bootstrap.inc,v
retrieving revision 1.150
diff -u -p -r1.150 bootstrap.inc
--- includes/bootstrap.inc	27 Mar 2007 05:13:53 -0000	1.150
+++ includes/bootstrap.inc	27 Mar 2007 23:32:30 -0000
@@ -922,6 +922,9 @@ function drupal_maintenance_theme() {
   drupal_add_css(drupal_get_path('module', 'system') .'/defaults.css', 'module');
   drupal_add_css(drupal_get_path('module', 'system') .'/system.css', 'module');
   $theme = '';
+
+  // Special case registry of theme functions used by the installer
+  _theme_set_registry(drupal_common_themes());
 }
 
 /**
Index: includes/common.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/common.inc,v
retrieving revision 1.624
diff -u -p -r1.624 common.inc
--- includes/common.inc	27 Mar 2007 05:13:53 -0000	1.624
+++ includes/common.inc	27 Mar 2007 23:32:32 -0000
@@ -2311,3 +2311,254 @@ function int2vancode($i = 0) {
   $length = strlen($num);
   return chr($length + ord('0') - 1) . $num;
 }
+
+/**
+ * Provide theme registration for themes across .inc files.
+ */
+function drupal_common_themes() {
+  return array(
+    // theme.inc
+    'placeholder' => array(
+      'function' => 'theme_placeholder',
+      'arguments' => array('text' => NULL)
+    ),
+    'page' => array(
+      'function' => 'theme_page',
+      'file' => 'theme.base.inc',
+      'path' => 'includes',
+      'arguments' => array('content' => NULL, 'show_blocks' => TRUE),
+    ),
+    'maintenance_page' => array(
+      'function' => 'theme_maintenance_page',
+      'arguments' => array('content' => NULL, 'messages' => TRUE),
+    ),
+    'install_page' => array(
+      'function' => 'theme_install_page',
+      'arguments' => array('content' => NULL),
+    ),
+    'task_list' => array(
+      'function' => 'theme_task_list',
+      'arguments' => array('items' => NULL, 'active' => NULL),
+    ),
+    'status_messages' => array(
+      'function' => 'theme_status_messages',
+      'arguments' => array('display' => NULL),
+    ),
+    'links' => array(
+      'function' => 'theme_links',
+      'arguments' => array('links' => NULL, 'attributes' => array('class' => 'links')),
+    ),
+    'image' => array(
+      'function' => 'theme_image',
+      'arguments' => array('path' => NULL, 'alt' => '', 'title' => '', 'attributes' => NULL, 'getsize' => TRUE),
+    ),
+    'breadcrumb' => array(
+      'function' => 'theme_breadcrumb',
+      'arguments' => array('breadcrumb' => NULL),
+    ),
+    'help' => array(
+      'function' => 'theme_help',
+      'arguments' => array(),
+    ),
+    'node' => array(
+      'function' => 'theme_node',
+      'file' => 'theme.base.inc',
+      'path' => 'includes',
+      'arguments' => array('node' => NULL, 'teaser' => FALSE, 'page' => FALSE),
+    ),
+    'submenu' => array(
+      'function' => 'theme_submenu',
+      'arguments' => array('links' => NULL),
+    ),
+    'table' => array(
+      'function' => 'theme_table',
+      'arguments' => array('header' => NULL, 'rows' => NULL, 'attributes' => array(), 'caption' => NULL),
+    ),
+    'table_select_header_cell' => array(
+      'function' => 'theme_table_select_header_cell',
+      'arguments' => array(),
+    ),
+    'tablesort_indicator' => array(
+      'function' => 'theme_tablesort_indicator',
+      'arguments' => array('style' => NULL),
+    ),
+    'box' => array(
+      'function' => 'theme_box',
+      'arguments' => array('title' => NULL, 'content' => NULL, 'region' => 'main'),
+    ),
+    'block' => array(
+      'function' => 'theme_block',
+      'file' => 'theme.base.inc',
+      'path' => 'includes',
+      'arguments' => array('block' => NULL),
+    ),
+    'mark' => array(
+      'function' => 'theme_mark',
+      'arguments' => array('type' => MARK_NEW),
+    ),
+    'item_list' => array(
+      'function' => 'theme_item_list',
+      'arguments' => array('items' => array(), 'title' => NULL, 'type' => 'ul', 'attributes' => NULL),
+    ),
+    'more_help_link' => array(
+      'function' => 'theme_more_help_link',
+      'arguments' => array('url' => NULL),
+    ),
+    'xml_icon' => array(
+      'function' => 'theme_xml_icon',
+      'arguments' => array('url' => NULL),
+    ),
+    'feed_icon' => array(
+      'function' => 'theme_feed_icon',
+      'arguments' => array('url' => NULL),
+    ),
+    'closure' => array(
+      'function' => 'theme_closure',
+      'arguments' => array('main' => 0),
+    ),
+    'blocks' => array(
+      'function' => 'theme_blocks',
+      'arguments' => array('region' => NULL),
+    ),
+    'username' => array(
+      'function' => 'theme_username',
+      'arguments' => array('object' => NULL),
+    ),
+    'progress_bar' => array(
+      'function' => 'theme_progress_bar',
+      'arguments' => array('percent' => NULL, 'message' => NULL),
+    ),
+    // from pager.inc
+    'pager' => array(
+      'function' => 'theme_pager',
+      'arguments' => array('tags' => array(), 'limit' => 10, 'element' => 0, 'parameters' => array()),
+    ),
+    'pager_first' => array(
+      'function' => 'theme_pager_first',
+      'arguments' => array('text' => NULL, 'limit' => NULL, 'element' => 0, 'parameters' => array()),
+    ),
+    'pager_previous' => array(
+      'function' => 'theme_pager_previous',
+      'arguments' => array('text' => NULL, 'limit' => NULL, 'element' => 0, 'interval' => 1, 'parameters' => array()),
+    ),
+    'pager_next' => array(
+      'function' => 'theme_pager_next',
+      'arguments' => array('text' => NULL, 'limit' => NULL, 'element' => 0, 'interval' => 1, 'parameters' => array()),
+    ),
+    'pager_last' => array(
+      'function' => 'theme_pager_last',
+      'arguments' => array('text' => NULL, 'limit' => NULL, 'element' => 0, 'parameters' => array()),
+    ),
+    'pager_list' => array(
+      'function' => 'theme_pager_list',
+      'arguments' => array('limit' => NULL, 'element' => 0, 'quantity' => 5, 'text' => '', 'parameters' => array()),
+    ), 
+    'pager_link' => array(
+      'function' => 'theme_pager_link',
+      'arguments' => array('text' => NULL, 'page_new' => NULL, 'element' => NULL, 'parameters' => array(), 'attributes' => array()),
+    ), 
+    // from locale.inc
+    'locale_admin_manage_screen' => array(
+      'function' => 'theme_locale_admin_manage_screen',
+      'arguments' => array('form' => NULL),
+    ),
+    // from menu.inc
+    'menu_item_link' => array(
+      'function' => 'theme_menu_item_link',
+      'arguments' => array('item' => NULL),
+    ),
+    'menu_tree' => array(
+      'function' => 'theme_menu_tree',
+      'arguments' => array('tree' => NULL),
+    ),
+    'menu_item' => array(
+      'function' => 'theme_menu_item',
+      'arguments' => array('link' => NULL, 'has_children' => NULL, 'menu' => ''),
+    ),
+    'menu_local_task' => array(
+      'function' => 'theme_menu_local_task',
+      'arguments' => array('link' => NULL, 'active' => FALSE),
+    ),
+    // from form.inc
+    'select' => array(
+      'function' => 'theme_select',
+      'arguments' => array('element' => NULL),
+    ),
+    'fieldset' => array(
+      'function' => 'theme_fieldset',
+      'arguments' => array('element' => NULL),
+    ),
+    'radio' => array(
+      'function' => 'theme_radio',
+      'arguments' => array('element' => NULL),
+    ),
+    'radios' => array(
+      'function' => 'theme_radios',
+      'arguments' => array('element' => NULL),
+    ),
+    'password_confirm' => array(
+      'function' => 'theme_password_confirm',
+      'arguments' => array('element' => NULL),
+    ),
+    'date' => array(
+      'function' => 'theme_date',
+      'arguments' => array('element' => NULL),
+    ),
+    'item' => array(
+      'function' => 'theme_item',
+      'arguments' => array('element' => NULL),
+    ),
+    'checkbox' => array(
+      'function' => 'theme_checkbox',
+      'arguments' => array('element' => NULL),
+    ),
+    'checkboxes' => array(
+      'function' => 'theme_checkboxes',
+      'arguments' => array('element' => NULL),
+    ),
+    'submit' => array(
+      'function' => 'theme_submit',
+      'arguments' => array('element' => NULL),
+    ),
+    'button' => array(
+      'function' => 'theme_button',
+      'arguments' => array('element' => NULL),
+    ),
+    'hidden' => array(
+      'function' => 'theme_hidden',
+      'arguments' => array('element' => NULL),
+    ),
+    'token' => array(
+      'function' => 'theme_token',
+      'arguments' => array('element' => NULL),
+    ),
+    'textfield' => array(
+      'function' => 'theme_textfield',
+      'arguments' => array('element' => NULL),
+    ),
+    'form' => array(
+      'function' => 'theme_form',
+      'arguments' => array('element' => NULL),
+    ),
+    'textarea' => array(
+      'function' => 'theme_textarea',
+      'arguments' => array('element' => NULL),
+    ),
+    'markup' => array(
+      'function' => 'theme_markup',
+      'arguments' => array('element' => NULL),
+    ),
+    'password' => array(
+      'function' => 'theme_password',
+      'arguments' => array('element' => NULL),
+    ),
+    'file' => array(
+      'function' => 'theme_file',
+      'arguments' => array('element' => NULL),
+    ),
+    'form_element' => array(
+      'function' => 'theme_form_element',
+      'arguments' => array('element' => NULL, 'value' => NULL),
+    ),
+  );
+}
Index: includes/form.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/form.inc,v
retrieving revision 1.185
diff -u -p -r1.185 form.inc
--- includes/form.inc	27 Mar 2007 05:13:53 -0000	1.185
+++ includes/form.inc	27 Mar 2007 23:32:34 -0000
@@ -457,7 +457,9 @@ function drupal_render_form($form_id, &$
   // Don't override #theme if someone already set it.
 
   if (!isset($form['#theme'])) {
-    if (theme_get_function($form_id)) {
+    init_theme();
+    $registry = theme_get_registry();
+    if ($registry[$form_id]) {
       $form['#theme'] = $form_id;
     }
   }
Index: includes/theme.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/theme.inc,v
retrieving revision 1.344
diff -u -p -r1.344 theme.inc
--- includes/theme.inc	27 Mar 2007 05:13:53 -0000	1.344
+++ includes/theme.inc	27 Mar 2007 23:32:35 -0000
@@ -72,6 +72,7 @@ function init_theme() {
   if (strpos($themes[$theme]->filename, '.theme')) {
    // file is a theme; include it
    include_once './' . $themes[$theme]->filename;
+   _theme_load_registry($theme);
   }
   elseif (strpos($themes[$theme]->description, '.engine')) {
     // file is a template; include its engine
@@ -80,10 +81,103 @@ function init_theme() {
     if (function_exists($theme_engine .'_init')) {
       call_user_func($theme_engine .'_init', $themes[$theme]);
     }
+   _theme_load_registry($theme, $theme_engine);
   }
 }
 
 /**
+ * Retrieved the stored theme registry
+ */
+function theme_get_registry($registry = NULL) {
+  static $theme_registry = NULL;
+  if ($registry !== NULL) {
+    $theme_registry = $registry;
+  }
+  
+  return $theme_registry;
+}
+
+/**
+ * Store the theme registry in memory
+ */
+function _theme_set_registry($registry) {
+  // Pass through for setting of static variable.
+  return theme_get_registry($registry);
+}
+
+/**
+ * Get the theme_registry cache from the database; if it doesn't exist, build
+ * it.
+ */
+function _theme_load_registry($theme, $theme_engine = NULL) {
+  // TODO: use a separate cache for this.
+  $cache = cache_get("theme_registry:$theme", 'cache');
+  if (isset($cache->data)) {
+    $registry = unserialize($cache->data);
+  }
+  else {
+    $registry = _theme_build_registry($theme, $theme_engine);
+    _theme_save_registry($theme, $registry);
+  }
+  _theme_set_registry($registry);
+}
+
+/**
+ * Write the theme_registry cache into the database.
+ */
+function _theme_save_registry($theme, $registry) {
+  // TODO: use a separate cache for this.
+  cache_set("theme_registry:$theme", 'cache', serialize($registry));
+}
+
+/**
+ * Process a single invocation of the themes hook.
+ */
+function _theme_process_registry(&$cache, $name, $type) {
+  $function = $name .'_themes';
+  if (function_exists($function)) {
+    $result = $function($cache);
+
+    // Automatically find paths
+    $path = drupal_get_path($type, $name);
+    foreach ($result as $hook => $info) {
+      $result[$hook]['type'] = $type;
+      if (isset($info['file'])) {
+        if (!isset($info['path'])) {
+          $result[$hook]['file'] = $path .'/'. $info['file'];
+        }
+      }
+      // If 'arguments' have been defined previously, carry them forward.
+      // This should happen if a theme overrides a Drupal defined theme
+      // function, for example.
+      if (!isset($info['arguments']) && isset($cache[$hook])) {
+        $result[$hook]['arguments'] = $cache[$hook]['arguments'];
+      }
+    }
+
+    $cache = array_merge($cache, $result);
+  }     
+}
+
+/**
+ * Rebuild the hook theme_registry cache.
+ */
+function _theme_build_registry($theme, $theme_engine) {
+  $cache = array();
+  foreach (module_implements('themes') as $module) {
+    _theme_process_registry($cache, $module, 'module');
+  }
+  
+  if ($theme_engine) {
+    _theme_process_registry($cache, $theme_engine, 'theme_engine');
+  }
+
+  _theme_process_registry($cache, $theme, 'theme');
+
+  return $cache;
+}
+
+/**
  * Provides a list of currently available themes.
  *
  * @param $refresh
@@ -159,48 +253,118 @@ function list_theme_engines($refresh = F
  *   An HTML string that generates the themed output.
  */
 function theme() {
-  static $functions;
   $args = func_get_args();
-  $function = array_shift($args);
+  $hook = array_shift($args);
+
+  static $hooks = NULL;
+  if ($hooks === NULL) {
+    init_theme();
+    $hooks = theme_get_registry();
+  }
 
-  if (!isset($functions[$function])) {
-    $functions[$function] = theme_get_function($function);
+  if (!isset($hooks[$hook])) {
+    return;
   }
-  if ($functions[$function]) {
-    return call_user_func_array($functions[$function], $args);
+
+  $info = $hooks[$hook];
+
+  if (isset($info['function'])) {
+    // The theme call is a function.
+    // Include a file if this theme function is held elsewhere.
+    if (!empty($info['file'])) {
+      include_once($info['file']);
+    }
+    return call_user_func_array($info['function'], $args);
+  }
+  else {
+    // The theme call is a template.
+    $variables = array(
+      'template_files' => array()
+    );
+    if (!empty($info['arguments'])) {
+      $count = 0;
+      foreach ($info['arguments'] as $name => $default) {
+        $variables[$name] = isset($args[$count]) ? $args[$count] : $default;
+        $count++;
+      }
+    }
+
+    // default render function and extension.
+    $render_function = 'theme_render_template';
+    $extension = '.tpl.php';
+    $variables_list = array();
+
+    // Run through the theme engine variables, if necessary
+    global $theme_engine;
+    if (isset($theme_engine)) {
+      $args = array(&$variables, $hook);
+      // Call each of our variable override functions. We allow
+      // several to create cleaner code.
+      $variables_list[] = '_'. $theme_engine .'_variables';
+      $variables_list[] = $theme_engine .'_variables';
+      $variables_list[] = '_'. $theme_engine .'_variables_'. $hook;
+      $variables_list[] = $theme_engine .'_variables_'. $hook;
+
+      if ($hooks[$hook]['type'] != 'module') {
+        if (function_exists($theme_engine .'_render_template')) {
+          $render_function = $theme_engine .'_render_template';
+        }
+        if (function_exists($extension_function = $theme_engine .'_extension')) {
+          $extension = $extension_function();
+        }
+      }
+    }
+
+    // Add theme specific variable substitution:
+    global $theme;
+    $variables_list[] = $theme .'_variables_';
+    $variables_list[] = $theme .'_variables_'. $hook;
+
+    foreach ($variables_list as $variables_function) {
+      if (function_exists($variables_function)) {
+        call_user_func_array($variables_function, $args);
+      }
+    }
+
+    // Get suggestions for alternate templates out of the variables
+    // that were set.
+    $suggestions = array();
+
+    if (isset($variables['template_files'])) {
+      $suggestions = $variables['template_files'];
+    }
+    if (isset($variables['template_file'])) {
+      $suggestions[] = $variables['template_file'];
+    }
+
+    if ($suggestions) {
+      $template_file = theme_discover_template($suggestions, $extension);
+    }
+
+    if (empty($template_file)) {
+      $template_file = $hooks[$hook]['file'] . $extension;
+      if (isset($hooks[$hook]['path'])) {
+        $template_file = $hooks[$hook]['path'] .'/'. $template_file;
+      }
+    }
+    return $render_function($template_file, $variables);
   }
 }
 
 /**
- * Determine if a theme function exists, and if so return which one was found.
- *
- * @param $function
- *   The name of the theme function to test.
- * @return
- *   The name of the theme function that should be used, or FALSE if no function exists.
+ * Choose which template file to actually render; these are all
+ * suggested templates from the theme.
  */
-function theme_get_function($function) {
-  global $theme, $theme_engine;
-
-  // Because theme() is called a lot, calling init_theme() only to have it
-  // smartly return is a noticeable performance hit. Don't do it.
-  if (!isset($theme)) {
-    init_theme();
-  }
+function theme_discover_template($suggestions, $extension = '.tpl.php') {
+  global $theme_engine;
 
-  if (($theme != '') && function_exists($theme .'_'. $function)) {
-    // call theme function
-    return $theme .'_'. $function;
-  }
-  elseif (($theme != '') && isset($theme_engine) && function_exists($theme_engine .'_'. $function)) {
-    // call engine function
-    return $theme_engine .'_'. $function;
-  }
-  elseif (function_exists('theme_'. $function)){
-    // call Drupal function
-    return 'theme_'. $function;
+  // Loop through any suggestions in FIFO order.
+  $suggestions = array_reverse($suggestions);
+  foreach ($suggestions as $suggestion) {
+    if (!empty($suggestion) && file_exists($file = path_to_theme() .'/'. $suggestion . $extension)) {
+      return $file;
+    }
   }
-  return FALSE;
 }
 
 /**
@@ -348,6 +512,26 @@ function theme_get_setting($setting_name
 }
 
 /**
+ * Render a system default template, which is essentially a PHP template.
+ *
+ * @param $file
+ *   The filename of the template to render.
+ * @param $variables
+ *   A keyed array of variables that will appear in the output.
+ *
+ * @return
+ *   The output generated by the template.
+ */
+function theme_render_template($file, $variables) {
+  extract($variables, EXTR_SKIP);  // Extract the variables to a local namespace
+  ob_start();                      // Start output buffering
+  include "./$file";               // Include the file
+  $contents = ob_get_contents();   // Get the contents of the buffer
+  ob_end_clean();                  // End buffering and discard
+  return $contents;                // Return the contents
+}
+
+/**
  * @defgroup themeable Themeable functions
  * @{
  * Functions that display HTML, and which can be customized by themes.
@@ -373,55 +557,6 @@ function theme_placeholder($text) {
   return '<em>'. check_plain($text) .'</em>';
 }
 
-/**
- * Return an entire Drupal page displaying the supplied content.
- *
- * @param $content
- *   A string to display in the main content area of the page.
- * @return
- *   A string containing the entire HTML page.
- */
-function theme_page($content) {
-  // Get blocks before so that they can alter the header (JavaScript, Stylesheets etc.)
-  $blocks = theme('blocks', 'all');
-
-  $output = "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n";
-  $output .= '<html xmlns="http://www.w3.org/1999/xhtml">';
-  $output .= '<head>';
-  $output .= ' <title>'. (drupal_get_title() ? strip_tags(drupal_get_title()) : variable_get('site_name', 'Drupal')) .'</title>';
-  $output .= drupal_get_html_head();
-  $output .= drupal_get_css();
-  $output .= drupal_get_js();
-
-  $output .= ' </head>';
-  $output .= ' <body style="background-color: #fff; color: #000;">';
-  $output .= '<table border="0" cellspacing="4" cellpadding="4"><tr><td style="vertical-align: top; width: 170px;">';
-
-  $output .= $blocks;
-  $output .= '</td><td style="vertical-align: top;">';
-
-  $output .= theme('breadcrumb', drupal_get_breadcrumb());
-  $output .= '<h1>' . drupal_get_title() . '</h1>';
-
-  if ($tabs = theme('menu_local_tasks')) {
-   $output .= $tabs;
-  }
-
-  $output .= theme('help');
-
-  $output .= theme('status_messages');
-
-  $output .= "\n<!-- begin content -->\n";
-  $output .= $content;
-  $output .= drupal_get_feeds();
-  $output .= "\n<!-- end content -->\n";
-
-  $output .= '</td></tr></table>';
-  $output .= theme('closure');
-  $output .= '</body></html>';
-
-  return $output;
-}
 
 /**
  * Generate a themed maintenance page.
@@ -458,9 +593,7 @@ function theme_maintenance_page($content
     'content' => $content,
   );
 
-  // Render simplified PHPTemplate.
-  include_once './themes/engines/phptemplate/phptemplate.engine';
-  $output = _phptemplate_render('misc/maintenance.tpl.php', $variables);
+  $output = theme_render_template('misc/maintenance.tpl.php', $variables);
 
   return $output;
 }
@@ -509,9 +642,7 @@ function theme_install_page($content) {
     $variables['messages'] .= theme('status_messages', 'status');
   }
 
-  // Render simplified PHPTemplate.
-  include_once './themes/engines/phptemplate/phptemplate.engine';
-  return _phptemplate_render('misc/maintenance.tpl.php', $variables);
+  return theme_render_template('misc/maintenance.tpl.php', $variables);
 }
 
 /**
@@ -678,66 +809,6 @@ function theme_help() {
 }
 
 /**
- * Return a themed node.
- *
- * @param $node
- *   An object providing all relevant information for displaying a node:
- *   - $node->nid: The ID of the node.
- *   - $node->type: The content type (story, blog, forum...).
- *   - $node->title: The title of the node.
- *   - $node->created: The creation date, as a UNIX timestamp.
- *   - $node->teaser: A shortened version of the node body.
- *   - $node->body: The entire node contents.
- *   - $node->changed: The last modification date, as a UNIX timestamp.
- *   - $node->uid: The ID of the author.
- *   - $node->username: The username of the author.
- * @param $teaser
- *   Whether to display the teaser only, as on the main page.
- * @param $page
- *   Whether to display the node as a standalone page. If TRUE, do not display
- *   the title because it will be provided by the menu system.
- * @return
- *   A string containing the node output.
- */
-function theme_node($node, $teaser = FALSE, $page = FALSE) {
-  if (!$node->status) {
-    $output  = '<div class="node-unpublished">';
-  }
-
-  if (module_exists('taxonomy')) {
-    $terms = taxonomy_link('taxonomy terms', $node);
-  }
-
-  if ($page == 0) {
-    $output .= t('!title by !name', array('!title' => '<h2 class="title">'. check_plain($node->title) .'</h2>', '!name' => theme('username', $node)));
-  }
-  else {
-    $output .= t('by !name', array('!name' => theme('username', $node)));
-  }
-
-  if (count($terms)) {
-    $output .= ' <small>('. theme('links', $terms) .')</small><br />';
-  }
-
-  if ($teaser && $node->teaser) {
-    $output .= $node->teaser;
-  }
-  else {
-    $output .= $node->body;
-  }
-
-  if ($node->links) {
-    $output .= '<div class="links">'. theme('links', $node->links) .'</div>';
-  }
-
-  if (!$node->status) {
-    $output .= '</div>';
-  }
-
-  return $output;
-}
-
-/**
  * Return a themed submenu, typically displayed under the tabs.
  *
  * @param $links
@@ -904,29 +975,6 @@ function theme_box($title, $content, $re
 }
 
 /**
- * Return a themed block.
- *
- * You can style your blocks by defining .block (all blocks),
- * .block-<i>module</i> (all blocks of module <i>module</i>), and
- * \#block-<i>module</i>-<i>delta</i> (specific block of module <i>module</i>
- * with delta <i>delta</i>) in your theme's CSS.
- *
- * @param $block
- *   An object populated with fields from the "blocks" database table
- *   ($block->module, $block->delta ...) and fields returned by
- *   <i>module</i>_block('view') ($block->subject, $block->content, ...).
- * @return
- *   A string containing the block output.
- */
-function theme_block($block) {
-  $output  = "<div class=\"block block-$block->module\" id=\"block-$block->module-$block->delta\">\n";
-  $output .= " <h2 class=\"title\">$block->subject</h2>\n";
-  $output .= " <div class=\"content\">$block->content</div>\n";
-  $output .= "</div>\n";
-  return $output;
-}
-
-/**
  * Return a themed marker, useful for marking new or updated
  * content.
  *
Index: modules/aggregator/aggregator.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/aggregator/aggregator.module,v
retrieving revision 1.333
diff -u -p -r1.333 aggregator.module
--- modules/aggregator/aggregator.module	27 Mar 2007 05:13:53 -0000	1.333
+++ modules/aggregator/aggregator.module	27 Mar 2007 23:32:36 -0000
@@ -26,6 +26,34 @@ function aggregator_help($section) {
 }
 
 /**
+ * Implementation of hook_themes()
+ */
+function aggregator_themes() {
+  return array(
+    'aggregator_page_list' => array(
+      'function' => 'theme_aggregator_page_list',
+      'arguments' => array('form' => NULL),
+    ),
+    'aggregator_feed' => array(
+      'function' => 'theme_aggregator_feed',
+      'arguments' => array('feed' => NULL),
+    ),
+    'aggregator_block_item' => array(
+      'function' => 'theme_aggregator_block_item',
+      'arguments' => array('item' => NULL, 'feed' => 0),
+    ),
+    'aggregator_summary_item' => array(
+      'function' => 'theme_aggregator_summary_item',
+      'arguments' => array('item' => NULL),
+    ),
+    'aggregator_page_item' => array(
+      'function' => 'theme_aggregator_page_item',
+      'arguments' => array('item' => NULL),
+    ),
+
+  );
+
+/**
  * Implementation of hook_menu().
  */
 function aggregator_menu() {
Index: modules/block/block.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/block/block.module,v
retrieving revision 1.254
diff -u -p -r1.254 block.module
--- modules/block/block.module	27 Mar 2007 05:13:53 -0000	1.254
+++ modules/block/block.module	27 Mar 2007 23:32:37 -0000
@@ -49,6 +49,18 @@ function block_help($section) {
 }
 
 /**
+ * Implementation of hook_themes()
+ */
+function block_themes() {
+  return array(
+    'block_admin_display' => array(
+      'function' => 'theme_block_admin_display',
+      'arguments' => array('form' => NULL),
+    ),
+  );
+}
+
+/**
  * Implementation of hook_perm().
  */
 function block_perm() {
Index: modules/book/book.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/book/book.module,v
retrieving revision 1.414
diff -u -p -r1.414 book.module
--- modules/book/book.module	27 Mar 2007 05:13:53 -0000	1.414
+++ modules/book/book.module	27 Mar 2007 23:32:38 -0000
@@ -20,6 +20,26 @@ function book_node_info() {
 }
 
 /**
+ * Implementation of hook_themes()
+ */
+function book_themes() {
+  return array(
+    'book_navigation' => array(
+      'function' => 'theme_book_navigation',
+      'arguments' => array('node' => NULL),
+    ),
+    'book_export_html' => array(
+      'function' => 'theme_book_export_html',
+      'arguments' => array('title' => NULL, 'content' => NULL),
+    ),
+    'book_admin_table' => array(
+      'function' => 'theme_book_admin_table',
+      'arguments' => array('form' => NULL),
+    ),
+  );
+}
+
+/**
  * Implementation of hook_perm().
  */
 function book_perm() {
Index: modules/color/color.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/color/color.module,v
retrieving revision 1.17
diff -u -p -r1.17 color.module
--- modules/color/color.module	27 Mar 2007 05:13:53 -0000	1.17
+++ modules/color/color.module	27 Mar 2007 23:32:38 -0000
@@ -2,6 +2,17 @@
 // $Id: color.module,v 1.17 2007/03/27 05:13:53 unconed Exp $
 
 /**
+ * Implementation of hook_themes()
+ */
+function color_themes() {
+  return array(
+    'color_scheme_form' => array(
+      'function' => 'theme_color_scheme_form',
+      'arguments' => array('form' => NULL),
+    ),
+  );
+}
+/**
  * Implementation of hook_form_alter().
  */
 function color_form_alter(&$form, $form_id) {
Index: modules/comment/comment.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/comment/comment.module,v
retrieving revision 1.531
diff -u -p -r1.531 comment.module
--- modules/comment/comment.module	27 Mar 2007 05:13:53 -0000	1.531
+++ modules/comment/comment.module	27 Mar 2007 23:32:40 -0000
@@ -140,6 +140,66 @@ function comment_help($section) {
    }
 }
 
+/**
+ * Implementation of hook_themes()
+ */
+function comment_themes() {
+  return array(
+    'comment_block' => array(
+      'function' => 'theme_comment_block',
+      'arguments' => array(),
+    ),
+    'comment_admin_overview' => array(
+      'function' => 'theme_comment_admin_overview',
+      'arguments' => array('form' => NULL),
+    ),
+    'comment_preview' => array(
+      'function' => 'theme_comment_preview',
+      'arguments' => array('comment' => NULL, 'links' => array(), 'visible' => 1),
+    ),
+    'comment_view' => array(
+      'function' => 'theme_comment_view',
+      'arguments' => array('comment' => NULL, 'links' => array(), 'visible' => 1),
+    ),
+    'comment_controls' => array(
+      'function' => 'theme_comment_controls',
+      'arguments' => array('form' => NULL),
+    ),
+    'comment' => array(
+      'function' => 'theme_comment',
+      'arguments' => array('comment' => NULL, 'links' => array()),
+    ),
+    'comment_folded' => array(
+      'function' => 'theme_comment_folded',
+      'arguments' => array('comment' => NULL),
+    ),
+    'comment_flat_collapsed' => array(
+      'function' => 'theme_comment_flat_collapsed',
+      'arguments' => array('comment' => NULL),
+    ),
+    'comment_flat_expanded' => array(
+      'function' => 'theme_comment_flat_expanded',
+      'arguments' => array('comment' => NULL),
+    ),
+    'comment_thread_collapsed' => array(
+      'function' => 'theme_comment_thread_collapsed',
+      'arguments' => array('comment' => NULL),
+    ),
+    'comment_thread_expanded' => array(
+      'function' => 'theme_comment_thread_expanded',
+      'arguments' => array('comment' => NULL),
+    ),
+    'comment_post_forbidden' => array(
+      'function' => 'theme_comment_post_forbidden',
+      'arguments' => array('nid' => NULL),
+    ),
+    'comment_wrapper' => array(
+      'function' => 'theme_comment_wrapper',
+      'arguments' => array('content' => NULL),
+    ),
+  );
+}
+
 function _comment_view_access($node, $cid) {
   return $node && $cid;
 }
Index: modules/drupal/drupal.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/drupal/drupal.module,v
retrieving revision 1.140
diff -u -p -r1.140 drupal.module
--- modules/drupal/drupal.module	27 Feb 2007 12:29:22 -0000	1.140
+++ modules/drupal/drupal.module	27 Mar 2007 23:32:41 -0000
@@ -46,6 +46,18 @@ print drupal_client_page();
   }
 }
 
+/**
+ * Implementation of hook_themes()
+ */
+function drupal_themes() {
+  return array(
+    'client_list' => array(
+      'function' => 'theme_client_list',
+      'arguments' => array('clients' => NULL),
+    ),
+  );
+}
+
 function drupal_sites_registry_settings() {
   // Check if all required fields are present
   if ((variable_get('site_name', 'Drupal') == 'Drupal') || (variable_get('site_name', 'Drupal') == '')) {
Index: modules/filter/filter.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/filter/filter.module,v
retrieving revision 1.166
diff -u -p -r1.166 filter.module
--- modules/filter/filter.module	12 Mar 2007 11:31:02 -0000	1.166
+++ modules/filter/filter.module	27 Mar 2007 23:32:43 -0000
@@ -48,6 +48,30 @@ function filter_help($section) {
 }
 
 /**
+ * Implementation of hook_themes()
+ */
+function filter_themes() {
+  return array(
+    'filter_admin_overview' => array(
+      'function' => 'theme_filter_admin_overview',
+      'arguments' => array('form' => NULL),
+    ),
+    'filter_admin_order' => array(
+      'function' => 'theme_filter_admin_order',
+      'arguments' => array('form' => NULL),
+    ),
+    'filter_tips' => array(
+      'function' => 'theme_filter_tips',
+      'arguments' => array('tips' => NULL, 'long' => FALSE, 'extra' => ''),
+    ),
+    'filter_tips_more_info' => array(
+      'function' => 'theme_filter_tips_more_info',
+      'arguments' => array(),
+    ),
+  );
+}
+
+/**
  * Implementation of hook_menu().
  */
 function filter_menu() {
Index: modules/forum/forum.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/forum/forum.module,v
retrieving revision 1.389
diff -u -p -r1.389 forum.module
--- modules/forum/forum.module	27 Mar 2007 05:13:53 -0000	1.389
+++ modules/forum/forum.module	27 Mar 2007 23:32:44 -0000
@@ -29,6 +29,34 @@ function forum_help($section) {
 }
 
 /**
+ * Implementation of hook_themes()
+ */
+function forum_themes() {
+  return array(
+    'forum_display' => array(
+      'function' => 'theme_forum_display',
+      'arguments' => array('forums' => NULL, 'topics' => NULL, 'parents' => NULL, 'tid' => NULL, 'sortby' => NULL, 'forum_per_page' => NULL),
+    ),
+    'forum_list' => array(
+      'function' => 'theme_forum_list',
+      'arguments' => array('forums' => NULL, 'parents' => NULL, 'tid' => NULL),
+    ),
+    'forum_topic_list' => array(
+      'function' => 'theme_forum_topic_list',
+      'arguments' => array('tid' => NULL, 'topics' => NULL, 'sortby' => NULL, 'forum_per_page' => NULL),
+    ),
+    'forum_icon' => array(
+      'function' => 'theme_forum_icon',
+      'arguments' => array('new_posts' => NULL, 'num_posts' => 0, 'comment_mode' => 0, 'sticky' => 0),
+    ),
+    'forum_topic_navigation' => array(
+      'function' => 'theme_forum_topic_navigation',
+      'arguments' => array('node' => NULL),
+    ),
+  );
+}
+
+/**
  * Implementation of hook_menu().
  */
 function forum_menu() {
Index: modules/node/node.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/node/node.module,v
retrieving revision 1.794
diff -u -p -r1.794 node.module
--- modules/node/node.module	27 Mar 2007 05:13:54 -0000	1.794
+++ modules/node/node.module	27 Mar 2007 23:32:47 -0000
@@ -46,6 +46,46 @@ function node_help($section) {
 }
 
 /**
+ * Implementation of hook_themes()
+ */
+function node_themes() {
+  return array(
+    'node_list' => array(
+      'function' => 'theme_node_list',
+      'arguments' => array('items' => NULL, 'title' => NULL),
+    ),
+    'node_search_admin' => array(
+      'function' => 'theme_node_search_admin',
+      'arguments' => array('form' => NULL),
+    ),
+    'node_filter_form' => array(
+      'function' => 'theme_node_filter_form',
+      'arguments' => array('form' => NULL),
+    ),
+    'node_filters' => array(
+      'function' => 'theme_node_filters',
+      'arguments' => array('form' => NULL),
+    ),
+    'node_admin_nodes' => array(
+      'function' => 'theme_node_admin_nodes',
+      'arguments' => array('form' => NULL),
+    ),
+    'node_form' => array(
+      'function' => 'theme_node_form',
+      'arguments' => array('form' => NULL),
+    ),
+    'node_preview' => array(
+      'function' => 'theme_node_preview',
+      'arguments' => array('node' => NULL),
+    ),
+    'node_log_message' => array(
+      'function' => 'theme_node_log_message',
+      'arguments' => array('log' => NULL),
+    ),  
+  );
+}
+
+/**
  * Implementation of hook_cron().
  */
 function node_cron() {
@@ -2350,7 +2390,6 @@ function node_revisions() {
  * Menu callback; Generate a listing of promoted nodes.
  */
 function node_page_default() {
-
   $result = pager_query(db_rewrite_sql('SELECT n.nid, n.sticky, n.created FROM {node} n WHERE n.promote = 1 AND n.status = 1 ORDER BY n.sticky DESC, n.created DESC'), variable_get('default_nodes_main', 10));
 
   if (db_num_rows($result)) {
Index: modules/poll/poll.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/poll/poll.module,v
retrieving revision 1.225
diff -u -p -r1.225 poll.module
--- modules/poll/poll.module	27 Mar 2007 05:13:54 -0000	1.225
+++ modules/poll/poll.module	27 Mar 2007 23:32:47 -0000
@@ -21,6 +21,26 @@ function poll_help($section) {
 }
 
 /**
+ * Implementation of hook_themes()
+ */
+function poll_themes() {
+  return array(
+    'poll_view_voting' => array(
+      'function' => 'theme_poll_view_voting',
+      'arguments' => array('form' => NULL),
+    ),
+    'poll_results' => array(
+      'function' => 'theme_poll_results',
+      'arguments' => array('title' => NULL, 'results' => NULL, 'votes' => NULL, 'links' => NULL, 'block' => NULL, 'nid' => NULL, 'vote' => NULL),
+    ),
+    'poll_bar' => array(
+      'function' => 'theme_poll_bar',
+      'arguments' => array('title' => NULL, 'percentage' => NULL, 'votes' => NULL, 'block' => NULL),
+    ),
+  );
+}
+
+/**
  * Implementation of hook_access().
  */
 function poll_access($op, $node) {
Index: modules/profile/profile.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/profile/profile.module,v
retrieving revision 1.195
diff -u -p -r1.195 profile.module
--- modules/profile/profile.module	27 Mar 2007 05:13:54 -0000	1.195
+++ modules/profile/profile.module	27 Mar 2007 23:32:48 -0000
@@ -52,6 +52,21 @@ function profile_help($section) {
 }
 
 /**
+ * Implementation of hook_themes()
+ */
+function profile_themes() {
+  return array(
+    'profile_block' => array(
+      'function' => 'theme_profile_block',
+      'arguments' => array('account' => NULL, 'fields' => array()),
+    ),
+    'profile_listing' => array(
+      'function' => 'theme_profile_listing',
+      'arguments' => array('account' => NULL, 'fields' => array()),
+    ),  );
+}
+
+/**
  * Implementation of hook_menu().
  */
 function profile_menu() {
Index: modules/search/search.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/search/search.module,v
retrieving revision 1.216
diff -u -p -r1.216 search.module
--- modules/search/search.module	27 Mar 2007 05:13:54 -0000	1.216
+++ modules/search/search.module	27 Mar 2007 23:32:50 -0000
@@ -112,6 +112,30 @@ function search_help($section) {
 }
 
 /**
+ * Implementation of hook_themes()
+ */
+function search_themes() {
+  return array(
+    'search_theme_form' => array(
+      'function' => 'theme_search_theme_form',
+      'arguments' => array('form' => NULL),
+    ),
+    'search_block_form' => array(
+      'function' => 'theme_search_block_form',
+      'arguments' => array('form' => NULL),
+    ),
+    'search_item' => array(
+      'function' => 'theme_search_item',
+      'arguments' => array('item' => NULL, 'type' => NULL),
+    ),
+    'search_page' => array(
+      'function' => 'theme_search_page',
+      'arguments' => array('results' => NULL, 'type' => NULL),
+    ),  
+  );
+}
+
+/**
  * Implementation of hook_perm().
  */
 function search_perm() {
Index: modules/system/system.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/system/system.module,v
retrieving revision 1.460
diff -u -p -r1.460 system.module
--- modules/system/system.module	27 Mar 2007 05:13:54 -0000	1.460
+++ modules/system/system.module	27 Mar 2007 23:32:52 -0000
@@ -48,6 +48,46 @@ function system_help($section) {
   }
 }
 
+function system_themes() {
+  return array_merge(drupal_common_themes(), array(
+    'system_theme_select_form' => array(
+      'function' => 'theme_system_theme_select_form',
+      'arguments' => array('form' => NULL),
+    ),
+    'system_themes_form' => array(
+      'function' => 'theme_system_themes_form',
+      'arguments' => array('form' => NULL),
+    ),
+    'system_modules' => array(
+      'function' => 'theme_system_modules',
+      'arguments' => array('form' => NULL),
+    ),
+    'system_modules_uninstall' => array(
+      'function' => 'theme_system_modules_uninstall',
+      'arguments' => array('form' => NULL),
+    ),
+    'status_report' => array(
+      'function' => 'theme_status_report',
+      'arguments' => array('requirements' => NULL),
+    ),
+    'admin_page' => array(
+      'function' => 'theme_admin_page',
+      'arguments' => array('blocks' => NULL),
+    ),
+    'admin_block' => array(
+      'function' => 'theme_admin_block',
+      'arguments' => array('block' => NULL),
+    ),
+    'admin_block_content' => array(
+      'function' => 'theme_admin_block_content',
+      'arguments' => array('content' => NULL),
+    ),
+    'system_admin_by_module' => array(
+      'function' => 'theme_system_admin_by_module',
+      'arguments' => array('menu_items' => NULL),
+    ),
+  ));
+}
 /**
  * Implementation of hook_perm().
  */
@@ -150,7 +190,7 @@ function system_menu() {
     'title' => t('Themes'),
     'description' => t('Change which theme your site uses or allows users to set.'),
     'page callback' => 'drupal_get_form',
-    'page arguments' => array('system_themes'),
+    'page arguments' => array('system_themes_form'),
   );
   $items['admin/build/themes/select'] = array(
     'title' => t('List'),
@@ -1143,7 +1183,7 @@ function system_settings_form_submit($fo
 /**
  * Menu callback; displays a listing of all themes.
  */
-function system_themes() {
+function system_themes_form() {
 
   drupal_clear_css_cache();
   $themes = system_theme_data();
@@ -1177,7 +1217,7 @@ function system_themes() {
   return $form;
 }
 
-function theme_system_themes($form) {
+function theme_system_themes_form($form) {
   foreach (element_children($form) as $key) {
     $row = array();
     if (isset($form[$key]['description']) && is_array($form[$key]['description'])) {
@@ -1199,7 +1239,7 @@ function theme_system_themes($form) {
 }
 
 
-function system_themes_submit($form_id, $form_values) {
+function system_themes_form_submit($form_id, $form_values) {
 
   db_query("UPDATE {system} SET status = 0 WHERE type = 'theme'");
 
Index: modules/taxonomy/taxonomy.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/taxonomy/taxonomy.module,v
retrieving revision 1.344
diff -u -p -r1.344 taxonomy.module
--- modules/taxonomy/taxonomy.module	27 Mar 2007 05:13:54 -0000	1.344
+++ modules/taxonomy/taxonomy.module	27 Mar 2007 23:32:54 -0000
@@ -14,6 +14,18 @@ function taxonomy_perm() {
 }
 
 /**
+ * Implementation of hook_themes()
+ */
+function taxonomy_themes() {
+  return array(
+    'taxonomy_term_select' => array(
+      'function' => 'theme_taxonomy_term_select',
+      'arguments' => array('element' => NULL),
+    ),
+  );
+}
+
+/**
  * Implementation of hook_link().
  *
  * This hook is extended with $type = 'taxonomy terms' to allow themes to
Index: modules/upload/upload.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/upload/upload.module,v
retrieving revision 1.156
diff -u -p -r1.156 upload.module
--- modules/upload/upload.module	27 Mar 2007 05:13:54 -0000	1.156
+++ modules/upload/upload.module	27 Mar 2007 23:32:54 -0000
@@ -23,6 +23,26 @@ function upload_help($section) {
 }
 
 /**
+ * Implementation of hook_themes()
+ */
+function upload_themes() {
+  return array(
+    'upload_attachments' => array(
+      'function' => 'theme_upload_attachments',
+      'arguments' => array('files' => NULL),
+    ),
+    'upload_form_current' => array(
+      'function' => 'theme_upload_form_current',
+      'arguments' => array('form' => NULL),
+    ),
+    'upload_form_new' => array(
+      'function' => 'theme_upload_form_new',
+      'arguments' => array('form' => NULL),
+    ),
+  );
+}
+
+/**
  * Implementation of hook_perm().
  */
 function upload_perm() {
Index: modules/user/user.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/user/user.module,v
retrieving revision 1.762
diff -u -p -r1.762 user.module
--- modules/user/user.module	27 Mar 2007 05:13:54 -0000	1.762
+++ modules/user/user.module	27 Mar 2007 23:32:58 -0000
@@ -24,6 +24,46 @@ function user_module_invoke($type, &$arr
   }
 }
 
+/**
+ * Implementation of hook_themes()
+ */
+function user_themes() {
+  return array(
+    'user_picture' => array(
+      'function' => 'theme_user_picture',
+      'arguments' => array('account' => NULL),
+    ),
+    'user_profile' => array(
+      'function' => 'theme_user_profile',
+      'arguments' => array('account' => NULL, 'fields' => NULL),
+    ),
+    'user_list' => array(
+      'function' => 'theme_user_list',
+      'arguments' => array('users' => NULL, 'title' => NULL),
+    ),
+    'user_admin_perm' => array(
+      'function' => 'theme_user_admin_perm',
+      'arguments' => array('form' => NULL),
+    ),
+    'user_admin_new_role' => array(
+      'function' => 'theme_user_admin_new_role',
+      'arguments' => array('form' => NULL),
+    ),
+    'user_admin_account' => array(
+      'function' => 'theme_user_admin_account',
+      'arguments' => array('form' => NULL),
+    ),
+    'user_filter_form' => array(
+      'function' => 'theme_user_filter_form',
+      'arguments' => array('form' => NULL),
+    ),
+    'user_filters' => array(
+      'function' => 'theme_user_filters',
+      'arguments' => array('form' => NULL),
+    ),
+  );
+}
+
 function user_external_load($authname) {
   $result = db_query("SELECT uid FROM {authmap} WHERE authname = '%s'", $authname);
 
Index: modules/watchdog/watchdog.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/watchdog/watchdog.module,v
retrieving revision 1.171
diff -u -p -r1.171 watchdog.module
--- modules/watchdog/watchdog.module	27 Feb 2007 12:29:22 -0000	1.171
+++ modules/watchdog/watchdog.module	27 Mar 2007 23:32:58 -0000
@@ -28,6 +28,18 @@ function watchdog_help($section) {
 }
 
 /**
+ * Implementation of hook_themes()
+ */
+function watchdog_themes() {
+  return array(
+    'watchdog_form_overview' => array(
+      'function' => 'theme_watchdog_form_overview',
+      'arguments' => array('form' => NULL),
+    ),
+  );
+}
+
+/**
  * Implementation of hook_menu().
  */
 function watchdog_menu() {
Index: themes/engines/phptemplate/phptemplate.engine
===================================================================
RCS file: /cvs/drupal/drupal/themes/engines/phptemplate/phptemplate.engine,v
retrieving revision 1.60
diff -u -p -r1.60 phptemplate.engine
--- themes/engines/phptemplate/phptemplate.engine	27 Mar 2007 05:13:55 -0000	1.60
+++ themes/engines/phptemplate/phptemplate.engine	27 Mar 2007 23:32:59 -0000
@@ -13,6 +13,67 @@ function phptemplate_init($template) {
   }
 }
 
+/**
+ * @return
+ *  Array of template features
+ */
+function phptemplate_features() {
+  return array(
+    'toggle_logo',
+    'toggle_comment_user_picture',
+    'toggle_favicon',
+    'toggle_mission',
+    'toggle_name',
+    'toggle_node_user_picture',
+    'toggle_search',
+    'toggle_slogan'
+  );
+}
+
+/**
+ * Implementation of hook_themes to tell Drupal what templates the engine
+ * and the current theme use.
+ */
+function phptemplate_themes($existing) {
+  $templates = array(
+    'regions' => array('function' => 'phptemplate_regions'),
+    'box' => array('file' => 'box'),
+    'node' => array('file' => 'node'),
+    'comment' => array('file' => 'comment'),
+    'block' => array('file' => 'block'),
+  );
+
+  // Check for template overrides.
+  $files = drupal_system_listing('\.tpl\.php$', path_to_theme(), 'name', 0);
+
+  foreach ($files as $template => $file) {
+    // chop off the .tpl
+    $template = substr($template, 0, -4);
+    if (isset($existing[$template])) {
+      $templates[$template] = array(
+        'file' => $template,
+        'path' => dirname($file->filename),
+      );
+    }
+  }
+
+  // Check for function overrides.
+  global $theme;
+  foreach ($existing as $hook => $info) {
+    if (function_exists($theme .'_'. $hook)) {
+      $templates[$hook] = array(
+        'function' => $theme .'_'. $hook,
+      );
+    }
+    else if (function_exists('phptemplate_'. $hook)) {
+      $templates[$hook] = array(
+        'function' => 'phptemplate_'. $hook,
+      );
+    }
+  }
+  return $templates;
+}
+
 function phptemplate_templates($directory = 'themes') {
   return drupal_system_listing('^page\.tpl\.php$', $directory, 'filename');
 }
@@ -34,55 +95,6 @@ function phptemplate_regions() {
 }
 
 /**
- * Execute a template engine call.
- *
- * Each call to the template engine has two parts. Namely preparing
- * the variables, and then doing something with them.
- *
- * The first step is done by all template engines / themes, the second
- * step is dependent on the engine used.
- *
- * @param $hook
- *   The name of the theme function being executed.
- * @param $variables
- *   A sequential array of variables passed to the theme function.
- * @param $suggestions
- *   An array of suggested template files to use. If none of the files are found, the
- *   default $hook.tpl.php will be used.
- * @return
- *  The HTML generated by the template system.
- */
-function _phptemplate_callback($hook, $variables = array(), $suggestions = array()) {
-  global $theme_engine;
-
-  $variables = array_merge($variables, _phptemplate_default_variables($hook, $variables));
-
-  // Allow specified variables to be overridden
-  $variables_function = '_'. $theme_engine .'_variables';
-  if (function_exists($variables_function)) {
-    $variables = array_merge($variables, call_user_func($variables_function, $hook, $variables));
-  }
-
-  if (isset($variables['template_files'])) {
-    $suggestions = array_merge($suggestions, $variables['template_files']);
-  }
-
-  if (isset($variables['template_file'])) {
-    $suggestions[] = $variables['template_file'];
-  }
-
-  $hook_function = '_'. $theme_engine .'_'. $hook;
-  $default_function = '_'. $theme_engine .'_default';
-  if (function_exists($hook_function)) {
-    return call_user_func($hook_function, $variables, $suggestions);
-  }
-  elseif (function_exists($default_function)) {
-    return call_user_func($default_function, $hook, $variables, $suggestions);
-  }
-
-}
-
-/**
  * Adds additional helper variables to all templates.
  *
  * Counts how many times certain hooks have been called. Sidebar left / right are special cases.
@@ -92,66 +104,29 @@ function _phptemplate_callback($hook, $v
  * @param $variables
  *   A sequential array of variables passed to the theme function.
  */
-function _phptemplate_default_variables($hook, $variables) {
+function _phptemplate_variables(&$variables, $hook) {
   global $theme, $sidebar_indicator;
   static $count = array();
 
+  // Create variables so anything which is themed can be zebra striped automatically.
   $count[$hook] = isset($count[$hook]) && is_int($count[$hook]) ? $count[$hook] : 1;
   $variables['zebra'] = ($count[$hook] % 2) ? 'odd' : 'even';
   $variables['id'] = $count[$hook]++;
 
-  if ($hook == 'block') {
-    $count['block_counter'][$sidebar_indicator] = isset($count['block_counter'][$sidebar_indicator]) && is_int($count['block_counter'][$sidebar_indicator]) ? $count['block_counter'][$sidebar_indicator] : 1;
-    $variables['block_zebra'] = ($count['block_counter'][$sidebar_indicator] % 2) ? 'odd' : 'even';
-    $variables['block_id'] = $count['block_counter'][$sidebar_indicator]++;
-  }
-  elseif ($hook == 'page') {
-    $regions = system_region_list($theme);
-    // Load all region content assigned via blocks.
-    foreach (array_keys($regions) as $region) {
-      // Skip blocks in this region that have already been loaded.
-      // This pre-loading is necessary because phptemplate uses variable names different from
-      // the region names, e.g., 'sidebar_left' instead of 'left'.
-      if (!in_array($region, array('left', 'right', 'footer'))) {
-        isset($variables[$region]) ? $variables[$region] .= theme('blocks', $region) : $variables[$region] = theme('blocks', $region);
-      }
-    }
-  }
   // Tell all templates where they are located.
   $variables['directory'] = path_to_theme();
   $variables['is_front'] = drupal_is_front_page();
-
-  return $variables;
-}
-
-/**
- * @return
- *  Array of template features
- */
-function phptemplate_features() {
-  return array(
-    'toggle_logo',
-    'toggle_comment_user_picture',
-    'toggle_favicon',
-    'toggle_mission',
-    'toggle_name',
-    'toggle_node_user_picture',
-    'toggle_search',
-    'toggle_slogan'
-  );
 }
 
 /**
- * Prepare the values passed to the theme_page function to be passed
- * into a pluggable template engine. Uses the arg() function to
- * generate a series of page template files suggestions based on the
- * current path. If none are found, the default page.tpl.php is used.
+ * Prepare the variables passed to the page.tpl.php template Uses the arg() 
+ * function to generate a series of page template files suggestions based on 
+ * the current path. 
  */
-function phptemplate_page($content, $show_blocks = TRUE) {
-
+function _phptemplate_variables_page(&$variables) {
   /* Set title and breadcrumb to declared values */
   if (drupal_is_front_page()) {
-    $mission = filter_xss_admin(theme_get_setting('mission'));
+    $variables['mission'] = filter_xss_admin(theme_get_setting('mission'));
   }
 
   /* Add favicon */
@@ -159,26 +134,44 @@ function phptemplate_page($content, $sho
     drupal_set_html_head('<link rel="shortcut icon" href="'. check_url(theme_get_setting('favicon')) .'" type="image/x-icon" />');
   }
 
-  // Populate sidebars
+  /**
+  * Populate sidebars.
+  */
+  $variables['sidebar_left'] = NULL;
+  $variables['sidebar_right'] = NULL;
   $layout = 'none';
-  if ($show_blocks) {
+  if ($variables['show_blocks']) {
     global $sidebar_indicator;
     /**
      * Sidebar_indicator tells the block counting code to count sidebars separately.
      */
     $sidebar_indicator = 'left';
-    $sidebar_left = theme('blocks', 'left');
-    if ($sidebar_left != '') {
+    $variables['sidebar_left'] = theme('blocks', 'left');
+    if ($variables['sidebar_left'] != '') {
       $layout = 'left';
     }
 
     $sidebar_indicator = 'right';
-    $sidebar_right = theme('blocks', 'right');
-    if ($sidebar_right != '') {
-      $layout = ($layout == 'left') ? 'both' : 'right';
+    $variables['sidebar_right'] = theme('blocks', 'right');
+    if ($variables['sidebar_right'] != '') {
+      $variables['layout'] = ($layout == 'left') ? 'both' : 'right';
     }
     $sidebar_indicator = NULL;
   }
+  $variables['layout'] = $layout;
+
+  global $theme;
+  // Populate the rest of the regions.
+  $regions = system_region_list($theme);
+  // Load all region content assigned via blocks.
+  foreach (array_keys($regions) as $region) {
+    // Skip blocks in this region that have already been loaded.
+    // This pre-loading is necessary because phptemplate uses variable names different from
+    // the region names, e.g., 'sidebar_left' instead of 'left'.
+    if (!in_array($region, array('left', 'right', 'footer'))) {
+      isset($variables[$region]) ? $variables[$region] .= theme('blocks', $region) : $variables[$region] = theme('blocks', $region);
+    }
+  }
 
   // Construct page title
   if (drupal_get_title()) {
@@ -190,35 +183,29 @@ function phptemplate_page($content, $sho
       $head_title[] = variable_get('site_slogan', '');
     }
   }
+  $variables['head_title'] = implode(' | ', $head_title);
 
-  $variables = array(
-    'base_path'           => base_path(),
-    'breadcrumb'          => theme('breadcrumb', drupal_get_breadcrumb()),
-    'closure'             => theme('closure'),
-    'content'             => $content,
-    'feed_icons'          => drupal_get_feeds(),
-    'footer_message'      => filter_xss_admin(variable_get('site_footer', FALSE)) . "\n" . theme('blocks', 'footer'),
-    'head'                => drupal_get_html_head(),
-    'head_title'          => implode(' | ', $head_title),
-    'help'                => theme('help'),
-    'language'            => $GLOBALS['language'],
-    'layout'              => isset($layout) ? $layout : NULL,
-    'logo'                => theme_get_setting('logo'),
-    'messages'            => theme('status_messages'),
-    'mission'             => isset($mission) ? $mission : '',
-    'primary_links'       => menu_primary_links(),
-    'search_box'          => (theme_get_setting('toggle_search') ? drupal_get_form('search_theme_form') : ''),
-    'secondary_links'     => menu_secondary_links(),
-    'sidebar_left'        => !empty($sidebar_left) ? $sidebar_left : '',
-    'sidebar_right'       => !empty($sidebar_right) ? $sidebar_right : '',
-    'site_name'           => (theme_get_setting('toggle_name') ? variable_get('site_name', 'Drupal') : ''),
-    'site_slogan'         => (theme_get_setting('toggle_slogan') ? variable_get('site_slogan', '') : ''),
-    'css'                 => drupal_add_css(),
-    'styles'              => drupal_get_css(),
-    'scripts'             => drupal_get_js(),
-    'tabs'                => theme('menu_local_tasks'),
-    'title'               => drupal_get_title()
-  );
+  $variables['base_path'] = base_path();
+  $variables['breadcrumb'] = theme('breadcrumb', drupal_get_breadcrumb());
+  $variables['closure'] = theme('closure');
+  $variables['feed_icons'] = drupal_get_feeds();
+  $variables['footer_message'] = filter_xss_admin(variable_get('site_footer', FALSE)) . "\n" . theme('blocks', 'footer');
+  $variables['head'] = drupal_get_html_head();
+  $variables['help'] = theme('help');
+  $variables['language'] = $GLOBALS['language'];
+  $variables['logo'] = theme_get_setting('logo');
+  $variables['messages'] = theme('status_messages');
+  $variables['mission'] = isset($mission) ? $mission : '';
+  $variables['primary_links'] = menu_primary_links();
+  $variables['search_box'] = (theme_get_setting('toggle_search') ? drupal_get_form('search_theme_form') : '');
+  $variables['secondary_links'] = menu_secondary_links();
+  $variables['site_name'] = (theme_get_setting('toggle_name') ? variable_get('site_name', 'Drupal') : '');
+  $variables['site_slogan'] = (theme_get_setting('toggle_slogan') ? variable_get('site_slogan', '') : '');
+  $variables['css'] = drupal_add_css();
+  $variables['styles'] = drupal_get_css();
+  $variables['scripts'] = drupal_get_js();
+  $variables['tabs'] = theme('menu_local_tasks');
+  $variables['title'] = drupal_get_title();
 
   if ((arg(0) == 'node') && is_numeric(arg(1))) {
     $variables['node'] = node_load(arg(1));
@@ -236,7 +223,7 @@ function phptemplate_page($content, $sho
   // page.tpl.php
   $i = 0;
   $suggestion = 'page';
-  $suggestions = array($suggestion);
+  $suggestions = array();
   while ($arg = arg($i++)) {
     $suggestions[] = $suggestion . '-' . $arg;
     if (!is_numeric($arg)) {
@@ -247,43 +234,40 @@ function phptemplate_page($content, $sho
     $suggestions[] = 'page-front';
   }
 
-  return _phptemplate_callback('page', $variables, $suggestions);
+  if ($suggestions) {
+    $variables['template_files'] = $suggestions;
+  }
 }
 
 /*
  * Prepare the values passed to the theme_node function to be passed
- * into a pluggable template engine.
+ * into standard template files.
  */
-function phptemplate_node($node, $teaser = 0, $page = 0) {
+function _phptemplate_variables_node(&$variables) {
+  $node = $variables['node'];
   if (module_exists('taxonomy')) {
-    $taxonomy = taxonomy_link('taxonomy terms', $node);
+    $variables['taxonomy'] = taxonomy_link('taxonomy terms', $node);
   }
   else {
-    $taxonomy = array();
+    $variables['taxonomy'] = array();
   }
-  if ($teaser && $node->teaser) {
-    $content = $node->teaser;
+
+  if ($variables['teaser'] && $node->teaser) {
+    $variables['content'] = $node->teaser;
   }
   elseif (isset($node->body)) {
-    $content = $node->body;
+    $variables['content'] = $node->body;
   }
   else {
-    $content = '';
+    $variables['content'] = '';
   }
 
-  $variables = array(
-    'content'        => $content,
-    'date'           => format_date($node->created),
-    'links'          => !empty($node->links) ? theme('links', $node->links, array('class' => 'links inline')) : '',
-    'name'           => theme('username', $node),
-    'node'           => $node,  // we pass the actual node to allow more customization
-    'node_url'       => url('node/'. $node->nid),
-    'page'           => $page,
-    'taxonomy'       => $taxonomy,
-    'teaser'         => $teaser,
-    'terms'          => theme('links', $taxonomy, array('class' => 'links inline')),
-    'title'          => check_plain($node->title)
-  );
+  $variables['date'] = format_date($node->created);
+  $variables['links'] = !empty($node->links) ? theme('links', $node->links, array('class' => 'links inline')) : '';
+  $variables['name'] = theme('username', $node);
+  $variables['node_url'] = url('node/'. $node->nid);
+  $variables['terms'] = theme('links', $variables['taxonomy'], array('class' => 'links inline'));
+  $variables['title'] = check_plain($node->title);
 
   // Flatten the node object's member fields.
   $variables = array_merge((array)$node, $variables);
@@ -298,27 +282,26 @@ function phptemplate_node($node, $teaser
     $variables['picture'] = '';
   }
 
-  return _phptemplate_callback('node', $variables, array('node-' . $node->type));
+  $variables['template_files'][] = 'node-'. $node->type;
 }
 
 /**
  * Prepare the values passed to the theme_comment function to be passed
  * into a pluggable template engine.
  */
-function phptemplate_comment($comment, $links = 0) {
-  return _phptemplate_callback('comment', array(
-    'author'    => theme('username', $comment),
-    'comment'   => $comment,
-    'content'   => $comment->comment,
-    'date'      => format_date($comment->timestamp),
-    'links'     => isset($links) ? theme('links', $links) : '',
-    'new'       => $comment->new ? t('new') : '',
-    'picture'   => theme_get_setting('toggle_comment_user_picture') ? theme('user_picture', $comment) : '',
-    'submitted' => t('Submitted by !a on @b.',
+// function phptemplate_comment($comment, $links = 0) {
+function phptemplate_variables_comment(&$variables) {
+  $variables['author'] = theme('username', $comment);
+  $variables['comment'] = $comment;
+  $variables['content'] = $comment->comment;
+  $variables['date'] = format_date($comment->timestamp);
+  $variables['links'] = isset($variables['links']) ? theme('links', $variables['links']) : '';
+  $variables['new'] = $comment->new ? t('new') : '';
+  $variables['picture'] = theme_get_setting('toggle_comment_user_picture') ? theme('user_picture', $comment) : '';
+  $variables['submitted'] = t('Submitted by !a on @b.',
                       array('!a' => theme('username', $comment),
-                            '@b' => format_date($comment->timestamp))),
-    'title'     => l($comment->subject, $_GET['q'], array('fragment' => "comment-$comment->cid"))
-  ));
+                            '@b' => format_date($comment->timestamp)));
+  $variables['title'] = l($comment->subject, $_GET['q'], array('fragment' => "comment-$comment->cid"));
 }
 
 /**
@@ -327,82 +310,14 @@ function phptemplate_comment($comment, $
  * series of template file suggestions. If none are found, the default
  * block.tpl.php is used.
  */
-function phptemplate_block($block) {
-  $suggestions[] = 'block';
-  $suggestions[] = 'block-' . $block->region;
-  $suggestions[] = 'block-' . $block->module;
-  $suggestions[] = 'block-' . $block->module . '-' . $block->delta;
-
-  return _phptemplate_callback('block', array('block' => $block), $suggestions);
+function phptemplate_variables_block(&$variables) {
+  global $sidebar_indicator;
+  $count['block_counter'][$sidebar_indicator] = isset($count['block_counter'][$sidebar_indicator]) && is_int($count['block_counter'][$sidebar_indicator]) ? $count['block_counter'][$sidebar_indicator] : 1;
+
+  $variables['block_zebra'] = ($count['block_counter'][$sidebar_indicator] % 2) ? 'odd' : 'even';
+
+  $variables['block_id'] = $count['block_counter'][$sidebar_indicator]++;
+  $variables['template_files'][] = 'block-' . $variables['block']->region;
+  $variables['template_files'][] = 'block-' . $variables['block']->module;
+  $variables['template_files'][] = 'block-' . $variables['block']->module . '-' . $variables['block']->delta;
 }
-
-/**
- * Prepare the values passed to the theme_box function to be passed
- * into a pluggable template engine.
- */
-function phptemplate_box($title, $content, $region = 'main') {
-  return _phptemplate_callback('box', array(
-    'content' =>   $content,
-    'region'  =>   $region,
-    'title'   =>   $title
-  ));
-}
-
-/**
- * Default callback for PHPTemplate.
- *
- * Load a template file, and pass the variable array to it.
- * If the suggested file is not found, PHPTemplate will attempt to use
- * a $hook.tpl.php file in the template directory, and failing that a
- * $hook.tpl.php in the PHPTemplate directory.
- *
- * @param $hook
- *   The name of the theme function being executed.
- * @param $variables
- *   A sequential array of variables passed to the theme function.
- * @param $suggestions
- *   An array of suggested template files to use.
- */
-function _phptemplate_default($hook, $variables, $suggestions = array(), $extension = '.tpl.php') {
-  global $theme_engine;
-
-  // Loop through any suggestions in FIFO order.
-  $suggestions = array_reverse($suggestions);
-  foreach ($suggestions as $suggestion) {
-    if (!empty($suggestion) && file_exists(path_to_theme() .'/'. $suggestion . $extension)) {
-      $file = path_to_theme() .'/'. $suggestion . $extension;
-      break;
-    }
-  }
-
-  if (!isset($file)) {
-    if (file_exists(path_to_theme() ."/$hook$extension")) {
-      $file = path_to_theme() ."/$hook$extension";
-    }
-    else {
-      if (in_array($hook, array('node', 'block', 'box', 'comment'))) {
-        $file = path_to_engine() .'/'. $hook . $extension;
-      }
-      else {
-        $variables['hook'] = $hook;
-        watchdog('error', t('%engine.engine was instructed to override the %name theme function, but no valid template file was found.', array('%engine' => $theme_engine, '%name' => $hook)));
-        $file = path_to_engine() .'/default'. $extension;
-      }
-    }
-  }
-
-  if (isset($file)) {
-    return call_user_func('_'. $theme_engine .'_render', $file, $variables);
-  }
-}
-
-function _phptemplate_render($file, $variables) {
-  extract($variables, EXTR_SKIP);  // Extract the variables to a local namespace
-  ob_start();                      // Start output buffering
-  include "./$file";               // Include the file
-  $contents = ob_get_contents();   // Get the contents of the buffer
-  ob_end_clean();                  // End buffering and discard
-  return $contents;                // Return the contents
-}
-
-?>
Index: themes/garland/template.php
===================================================================
RCS file: /cvs/drupal/drupal/themes/garland/template.php,v
retrieving revision 1.6
diff -u -p -r1.6 template.php
--- themes/garland/template.php	20 Mar 2007 19:07:55 -0000	1.6
+++ themes/garland/template.php	27 Mar 2007 23:32:59 -0000
@@ -1,4 +1,6 @@
 <?php
+// $Id
+
 /**
  * Sets the body-tag class attribute.
  *
@@ -53,22 +55,17 @@ function phptemplate_comment_wrapper($co
 /**
  * Override or insert PHPTemplate variables into the templates.
  */
-function _phptemplate_variables($hook, $vars) {
-  if ($hook == 'page') {
-
-    if ($secondary = menu_secondary_local_tasks()) {
-      $output = '<span class="clear"></span>';
-      $output .= "<ul class=\"tabs secondary\">\n". $secondary ."</ul>\n";
-      $vars['tabs2'] = $output;
-    }
+function phptemplate_variables_page(&$vars) {
+  if ($secondary = menu_secondary_local_tasks()) {
+    $output = '<span class="clear"></span>';
+    $output .= "<ul class=\"tabs secondary\">\n". $secondary ."</ul>\n";
+    $vars['tabs2'] = $output;
+  }
 
-    // Hook into color.module
-    if (module_exists('color')) {
-      _color_page_alter($vars);
-    }
-    return $vars;
+  // Hook into color.module
+  if (module_exists('color')) {
+    _color_page_alter($vars);
   }
-  return array();
 }
 
 /**
