Index: install.php
===================================================================
RCS file: /cvs/drupal/drupal/install.php,v
retrieving revision 1.53
diff -u -p -r1.53 install.php
--- install.php	22 May 2007 07:42:36 -0000	1.53
+++ install.php	24 May 2007 01:09:32 -0000
@@ -811,7 +811,7 @@ function install_task_list($active = NUL
   if (in_array($active, array('finished', 'done'))) {
     $active = NULL;
   }
-  drupal_set_content('left', theme_task_list($tasks, $active));
+  drupal_set_content('left', theme('task_list', $tasks, $active));
 }
 
 function install_configure_form() {
Index: update.php
===================================================================
RCS file: /cvs/drupal/drupal/update.php,v
retrieving revision 1.222
diff -u -p -r1.222 update.php
--- update.php	16 May 2007 07:56:19 -0000	1.222
+++ update.php	24 May 2007 01:09:32 -0000
@@ -718,7 +718,7 @@ function update_task_list($active = NULL
     'finished' => 'Review log',
   );
 
-  drupal_set_content('left', theme_task_list($tasks, $active));
+  drupal_set_content('left', theme('task_list', $tasks, $active));
 }
 
 // Some unavoidable errors happen because the database is not yet up-to-date.
@@ -726,10 +726,10 @@ function update_task_list($active = NULL
 ini_set('display_errors', FALSE);
 
 include_once './includes/bootstrap.inc';
+drupal_maintenance_theme();
 update_fix_system_table();
 
 drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL);
-drupal_maintenance_theme();
 
 // This must happen *after* drupal_bootstrap(), since it calls
 // variable_(get|set), which only works after a full bootstrap.
Index: includes/bootstrap.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/bootstrap.inc,v
retrieving revision 1.165
diff -u -p -r1.165 bootstrap.inc
--- includes/bootstrap.inc	8 May 2007 16:36:55 -0000	1.165
+++ includes/bootstrap.inc	24 May 2007 01:09:33 -0000
@@ -961,28 +961,12 @@ function _drupal_cache_init($phase) {
  * unavailable and theme_maintenance_page() must be used in its place.
  */
 function drupal_maintenance_theme() {
-  global $theme;
-  require_once './includes/path.inc';
-  require_once './includes/theme.inc';
-  require_once './includes/common.inc';
-  require_once './includes/unicode.inc';
-  require_once './modules/filter/filter.module';
-  unicode_check();
-  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
-  $themes = drupal_common_themes();
-  foreach ($themes as $hook => $info) {
-    if (!isset($info['file']) && !isset($info['function'])) {
-      $themes[$hook]['function'] = 'theme_'. $hook;
-      $themes[$hook]['theme path'] = 'misc';
-    }
-  }
-  _theme_set_registry($themes);
+  require_once './includes/maintenance.inc';
+  require_once './includes/theme.admin.inc';
+  _drupal_maintenance_theme();
 }
 
+
 /**
  * Return the name of the localisation function. Use in code that needs to
  * run both during installation and normal operation.
Index: includes/common.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/common.inc,v
retrieving revision 1.641
diff -u -p -r1.641 common.inc
--- includes/common.inc	15 May 2007 20:19:47 -0000	1.641
+++ includes/common.inc	24 May 2007 01:09:34 -0000
@@ -2325,7 +2325,7 @@ function element_children($element) {
 /**
  * Provide theme registration for themes across .inc files.
  */
-function drupal_common_themes() {
+function drupal_common_theme() {
   return array(
     // theme.inc
     'placeholder' => array(
@@ -2335,12 +2335,6 @@ function drupal_common_themes() {
       'arguments' => array('content' => NULL, 'show_blocks' => TRUE, 'show_messages' => TRUE),
       'file' => 'page',
     ),
-    'maintenance_page' => array(
-      'arguments' => array('content' => NULL, 'show_messages' => TRUE),
-    ),
-    'install_page' => array(
-      'arguments' => array('content' => NULL),
-    ),
     'task_list' => array(
       'arguments' => array('items' => NULL, 'active' => NULL),
     ),
Index: includes/maintenance.inc
===================================================================
RCS file: includes/maintenance.inc
diff -N includes/maintenance.inc
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ includes/maintenance.inc	24 May 2007 01:09:34 -0000
@@ -0,0 +1,188 @@
+<?php
+// $Id: bootstrap.inc,v 1.165 2007/05/08 16:36:55 dries Exp $
+
+/**
+ * @file
+ * Functions and theme preprocessors for the maintenance theme.
+ */
+
+function _drupal_maintenance_theme() {
+  require_once './includes/path.inc';
+  require_once './includes/theme.inc';
+  require_once './includes/common.inc';
+  require_once './includes/unicode.inc';
+  require_once './includes/file.inc';
+  require_once './modules/filter/filter.module';
+  unicode_check();
+
+  $theme_name = variable_get('maintenance_theme', 'garland');
+  list($themes, $engines) = drupal_theme_data();
+  if (isset($themes[$theme_name])) {
+    $theme = $themes[$theme_name];
+  }
+  else {
+    // Fall back to Garland. If Garland doesn't exist, they've deleted files
+    // they should not have and this will crash horribly and that is not our
+    // problem.
+    $theme = $themes['garland'];
+  }
+  
+  // Massage some data into place.
+  if (isset($theme->info['stylesheet'])) {
+    $theme->stylesheet = $theme->info['stylesheet'];
+  }
+  if (isset($theme->info['engine'])) {
+    $theme->engine = $theme->info['engine'];
+  }
+  if (isset($theme->info['base theme'])) {
+    $theme->base_theme = $theme->info['base theme'];
+  }
+
+  _init_theme($theme, array(), 'drupal_maintenance_registry');  
+  
+  drupal_add_css(drupal_get_path('module', 'system') .'/defaults.css', 'module');
+  drupal_add_css(drupal_get_path('module', 'system') .'/system.css', 'module');
+  global $theme;
+  $theme = '';
+}
+
+/**
+ * Special function to create the theme registry. Since there isn't a database
+ * we have to build it from components we know will be loaded.
+ */
+function drupal_maintenance_registry($theme) {
+  // The maintenance theme MUST be a 'base' theme.
+  
+  // Special case building of the registry when we have no modules
+  // and no database.
+  $registry = array();
+  _theme_process_registry($registry, 'drupal_common', 'module', 'system', 'includes');
+  _theme_process_registry($registry, 'drupal_maintenance_common', 'module', 'system', 'modules/system');
+  
+  if ($theme->engine) {
+    _theme_process_registry($registry, $theme->engine, 'theme_engine', $theme->name, dirname($theme->filename));
+  }
+  _theme_process_registry($registry, $theme->name, 'theme', $theme->name, dirname($theme->filename));
+
+  return $registry;
+}
+
+/**
+ * Specific implementation of hook_theme. Specifies maintenance-only theme
+ * implementations.
+ */
+function drupal_maintenance_common_theme() {
+  return array(
+    'maintenance_page' => array(
+      'arguments' => array('content' => NULL, 'show_messages' => TRUE),
+      'path' => 'includes',
+      'file' => 'maintenance_page',
+    ),
+    'install_page' => array(
+      'arguments' => array('content' => NULL),
+      'path' => 'includes',
+      'file' => 'maintenance_page',
+    ),
+  );
+}
+
+/**
+ * Generate a themed maintenance page.
+ *
+ * Note: Listed params are for theme('maintenance_page')
+ *
+ * @param $content
+ *   The page content to show.
+ * @param $show_messages
+ *   Whether to output status and error messages.
+ *   FALSE can be useful to postpone the messages to a subsequent page.
+ */
+function template_preprocess_maintenance_page(&$variables) {
+  // Set required headers.
+  drupal_set_header('Content-Type: text/html; charset=utf-8');
+  drupal_set_html_head('<style type="text/css" media="all">@import "'. base_path() .'misc/maintenance.css";</style>');
+  drupal_set_html_head('<style type="text/css" media="all">@import "'. base_path() . drupal_get_path('module', 'system') .'/defaults.css";</style>');
+  drupal_set_html_head('<style type="text/css" media="all">@import "'. base_path() . drupal_get_path('module', 'system') .'/system.css";</style>');
+  drupal_set_html_head('<link rel="shortcut icon" href="'. base_path() .'misc/favicon.ico" type="image/x-icon" />');
+
+  // Prepare variables.
+  $variables += array(
+    'head_title' => strip_tags(drupal_get_title()),
+    'head' => drupal_get_html_head(),
+    'styles' => '',
+    'scripts' => drupal_get_js(),
+    'sidebar_left' => drupal_get_content('left'),
+    'sidebar_right' => drupal_get_content('right'),
+    'base_path' => base_path(),
+    'path_to_theme' => base_path() .'themes/garland/minnelli',
+    'logo' => base_path() .'themes/garland/minnelli/logo.png',
+    'site_title' => t('Drupal'),
+    'title' => drupal_get_title(),
+    'messages' => !empty($variables['show_messages']) ? theme('status_messages') : '',
+  );
+}
+ 
+/**
+ * Preprocess the install page.
+ *
+ * Note: Listed params are for theme('install_page')
+ *
+ * @param $content
+ *   The page content to show.
+ */
+function template_preprocess_install_page(&$variables) {
+  drupal_set_header('Content-Type: text/html; charset=utf-8');
+  drupal_add_css('misc/maintenance.css', 'module', 'all', FALSE);
+  drupal_set_html_head('<link rel="shortcut icon" href="'. base_path() .'misc/favicon.ico" type="image/x-icon" />');
+
+  $variables += array(
+    'head_title' => strip_tags(drupal_get_title()),
+    'head' => drupal_get_html_head(),
+    'styles' => drupal_get_css(),
+    'scripts' => drupal_get_js(),
+    'sidebar_left' => drupal_get_content('left'),
+    'sidebar_right' => drupal_get_content('right'),
+    'base_path' => base_path(),
+    'path_to_theme' => base_path() .'themes/garland/minnelli',
+    'logo' => base_path() .'themes/garland/minnelli/logo.png',
+    'site_title' => st('Drupal Installation'),
+    'title' => drupal_get_title(),
+    'messages' => '',
+  );
+
+  // Special handling of error messages
+  $messages = drupal_set_message();
+  if (isset($messages['error'])) {
+    $title = count($messages['error']) > 1 ? st('The following errors must be resolved before you can continue the installation process') : st('The following error must be resolved before you can continue the installation process');
+    $variables['messages'] .= '<h3>'. $title .':</h3>';
+    $variables['messages'] .= theme('status_messages', 'error');
+  }
+
+  // Special handling of status messages
+  if (isset($messages['status'])) {
+    $warnings = count($messages['status']) > 1 ? st('The following installation warnings should be carefully reviewed, but in most cases may be safely ignored') : st('The following installation warning should be carefully reviewed, but in most cases may be safely ignored');
+    $variables['messages'] .= '<h4>'. $title .':</h4>';
+    $variables['messages'] .= theme('status_messages', 'status');
+  }
+}
+
+/**
+ * Return a themed list of maintenance tasks to perform.
+ */
+function theme_task_list($items, $active = NULL) {
+  $done = isset($items[$active]) || $active == NULL;
+  $output = '<ol class="task-list">';
+  foreach ($items as $k => $item) {
+    if ($active == $k) {
+      $class = 'active';
+      $done = false;
+    }
+    else {
+      $class = $done ? 'done' : '';
+    }
+    $output .= '<li class="'. $class .'">'. $item .'</li>';
+  }
+  $output .= '</ol>';
+  return $output;
+}
+
Index: includes/maintenance_page.tpl.php
===================================================================
RCS file: includes/maintenance_page.tpl.php
diff -N includes/maintenance_page.tpl.php
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ includes/maintenance_page.tpl.php	24 May 2007 01:09:34 -0000
@@ -0,0 +1,59 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+  <head>
+    <title><?php print $head_title ?></title>
+    <?php print $head ?>
+    <?php print $styles ?>
+    <?php print $scripts ?>
+    <style type="text/css" media="all">@import "<?php print $path_to_theme ?>/style.css";</style>
+    <!--[if lt IE 7]>
+    <style type="text/css" media="all">@import "<?php print $path_to_theme ?>/fix-ie.css";</style>
+    <![endif]-->
+  </head>
+  <body class="<?php
+  $classes = array('', 'sidebar-left', 'sidebar-right', 'sidebar-both');
+  print $classes[((bool)$sidebar_left) + 2 * ((bool)$sidebar_right)];
+  ?>">
+
+<!-- Layout -->
+  <div id="header-region" class="clear-block"></div>
+
+    <div id="wrapper">
+    <div id="container" class="clear-block">
+
+      <div id="header">
+        <div id="logo-floater">
+          <h1><a href="<?php print check_url($base_path) ?>"><img src="<?php print check_url($logo) ?>" alt="Drupal" id="logo" /><span><?php print $site_title ?></span></a></h1>
+        </div>
+      </div> <!-- /header -->
+
+      <?php if ($sidebar_left): ?>
+        <div id="sidebar-left" class="sidebar">
+          <?php print $sidebar_left ?>
+        </div>
+      <?php endif; ?>
+
+      <div id="center"><div id="squeeze"><div class="right-corner"><div class="left-corner">
+          <?php if ($title): print '<h2>'. $title .'</h2>'; endif; ?>
+
+          <?php if ($messages): print $messages; endif; ?>
+          <?php print $content ?>
+          <span class="clear"></span>
+
+          <!--partial-->
+
+      </div></div></div></div> <!-- /.left-corner, /.right-corner, /#squeeze, /#center -->
+
+      <?php if ($sidebar_right): ?>
+        <div id="sidebar-right" class="sidebar">
+          <?php print $sidebar_right ?>
+        </div>
+      <?php endif; ?>
+
+    </div> <!-- /container -->
+  </div>
+<!-- /layout -->
+
+  </body>
+</html>
Index: includes/theme.admin.inc
===================================================================
RCS file: includes/theme.admin.inc
diff -N includes/theme.admin.inc
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ includes/theme.admin.inc	24 May 2007 01:09:34 -0000
@@ -0,0 +1,246 @@
+<?php
+// $Id$
+/**
+ * @file
+ * Seldom used administrative functions that are put aside so they aren't loaded
+ * all the time.
+ *
+ */
+/**
+ * Provide sensible defaults for theme info files.
+ */
+function drupal_theme_default() {
+  // Prepare defaults for themes.
+  return array(
+    'regions' => array(
+      'left' => 'Left sidebar',
+      'right' => 'Right sidebar',
+      'content' => 'Content',
+      'header' => 'Header',
+      'footer' => 'Footer',
+    ),
+    'description' => '',
+    'features' => array(
+      'comment_user_picture',
+      'favicon',
+      'mission',
+      'logo',
+      'name',
+      'node_user_picture',
+      'search',
+      'slogan'
+    ),
+    'stylesheet' => 'style.css',
+    'screenshot' => 'screenshot.png',
+  );
+}
+
+/**
+ * Recursive function to find the top level base theme. Themes can inherit
+ * templates and function implementations from earlier themes; this function
+ * finds the top level parent that has no ancestor, or returns NULL if there
+ * isn't a valid parent.
+ */
+function drupal_find_base_theme($themes, $key, $used_keys = array()) {
+  $base_key = $themes[$key]->info['base theme'];
+  // Does the base theme exist?
+  if (!isset($themes[$base_key])) {
+    return NULL;
+  }
+
+  // Is the base theme itself a child of another theme?
+  if (isset($themes[$base_key]->info['base theme'])) {
+    // Prevent loops.
+    if ($used_keys[$base_key]) {
+      return NULL;
+    }
+    $used_keys[$base_key] = TRUE;
+    return drupal_find_base_theme($themes, $base_key, $used_keys);
+  }
+  // If we get here, then this is our parent theme.
+  return $base_key;
+}
+
+/**
+ * Read Drupal's theme info from the themes directories. No database required.
+ * Since this returns two pieces of data, call this function like this:
+ * list($themes, $engines) = drupal_theme_data();
+ *
+ * @return array($themes, $engines)
+ *   An array containing first the themes info and second the theme engine info.
+ */
+function drupal_theme_data() {
+  // Find themes
+  $themes = drupal_system_listing('\.info$', 'themes');
+
+  // Find theme engines
+  $engines = drupal_system_listing('\.engine$', 'themes/engines');
+
+  $defaults = drupal_theme_default();
+
+  $sub_themes = array();
+  // Read info files for each theme
+  foreach ($themes as $key => $theme) {
+    $themes[$key]->info = drupal_parse_info_file($theme->filename) + $defaults;
+    if (!empty($themes[$key]->info['base theme'])) {
+      $sub_themes[] = $key;
+    }
+    if (empty($themes[$key]->info['engine'])) {
+      $filename = dirname($themes[$key]->filename) .'/'. $themes[$key]->name .'.theme';
+      if (file_exists($filename)) {
+        $themes[$key]->owner = $filename;
+        $themes[$key]->prefix = $key;
+      }
+    }
+    else {
+      $engine = $themes[$key]->info['engine'];
+      if (isset($engines[$engine])) {
+        $themes[$key]->owner = $engines[$engine]->filename;
+        $themes[$key]->prefix = $engines[$engine]->name;
+        $themes[$key]->template = TRUE;
+      }
+    }
+
+    // Give the stylesheet proper path information.
+    if (!empty($themes[$key]->info['stylesheet'])) {
+      $themes[$key]->info['stylesheet'] = dirname($themes[$key]->filename) .'/'. $themes[$key]->info['stylesheet'];
+    }
+    // Give the screenshot proper path information.
+    if (!empty($themes[$key]->info['screenshot'])) {
+      $themes[$key]->info['screenshot'] = dirname($themes[$key]->filename) .'/'. $themes[$key]->info['screenshot'];
+    }
+  }
+
+  // Now that we've established all our master themes, go back and fill in
+  // data for subthemes.
+  foreach ($sub_themes as $key) {
+    $base_key = drupal_find_base_theme($themes, $key);
+    if (!$base_key) {
+      continue;
+    }
+    // Copy the 'owner' and 'engine' over if the top level theme uses a
+    // theme engine.
+    if (isset($themes[$base_key]->owner)) {
+      if (isset($themes[$base_key]->info['engine'])) {
+        $themes[$key]->info['engine'] = $themes[$base_key]->info['engine'];
+        $themes[$key]->owner = $themes[$base_key]->owner;
+        $themes[$key]->prefix = $themes[$base_key]->prefix;
+      }
+      else {
+        $themes[$key]->prefix = $key;
+      }
+    }
+  }
+  
+  return array($themes, $engines);
+}
+
+
+/**
+ * Process a single invocation of the theme hook. $type will be one
+ * of 'module', 'theme_engine' or 'theme' and it tells us some
+ * important information.
+ *
+ * Because $cache is a reference, the cache will be continually
+ * expanded upon; new entries will replace old entries in the
+ * array_merge, but we are careful to ensure some data is carried
+ * forward, such as the arguments a theme hook needs.
+ */
+function _theme_process_registry(&$cache, $name, $type, $theme, $path) {
+  $function = $name .'_theme';
+  if (function_exists($function)) {
+    $result = $function($cache, $type, $theme, $path);
+
+    foreach ($result as $hook => $info) {
+      $result[$hook]['type'] = $type;
+      $result[$hook]['theme path'] = $path;
+      // if function and file are left out, default to standard naming
+      // conventions.
+      if (!isset($info['file']) && !isset($info['function'])) {
+        $result[$hook]['function'] = ($type == 'module' ? 'theme_' : $name .'_') . $hook;
+      }
+      // If a path is set in the info, use what was set. Otherwise use the
+      // default path. This is mostly so system.module can declare theme
+      // functions on behalf of core .include files.
+      if (isset($info['file']) && !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'];
+      }
+      // Check for default _preprocess_ functions. Ensure arrayness.
+      if (!isset($info['preprocess functions']) || !is_array($info['preprocess functions'])) {
+        $info['preprocess functions'] = array();
+        $prefix = ($type == 'module' ? 'template' : $name);
+        // theme engines get an extra set that come before the normally named preprocess.
+        if ($type == 'theme_engine') {
+          if (function_exists($prefix .'_engine_preprocess')) {
+            $info['preprocess functions'][] = $prefix .'_engine_preprocess';
+          }
+          if (function_exists($prefix .'_engine_preprocess_'. $hook)) {
+            $info['preprocess functions'][] = $prefix .'_engine_preprocess_'. $hook;
+          }
+        }
+
+        // It would be too much of a performance hit to let every module have
+        // a generic preprocess function; themes and theme engines can do that.
+        if ($type != 'module' && function_exists($prefix .'_preprocess')) {
+          $info['preprocess functions'][] = $prefix .'_preprocess';
+        }
+        if (function_exists($prefix .'_preprocess_'. $hook)) {
+          $info['preprocess functions'][] = $prefix .'_preprocess_'. $hook;
+        }
+      }
+      if (isset($cache[$hook]['preprocess functions']) && is_array($cache[$hook]['preprocess functions']) && empty($cache[$hook]['override preprocess functions'])) {
+        $info['preprocess functions'] = array_merge($cache[$hook]['preprocess functions'], $info['preprocess functions']);
+      }
+      $result[$hook]['preprocess functions'] = $info['preprocess functions'];
+    }
+
+    // Merge the newly created theme hooks into the existing cache.
+    $cache = array_merge($cache, $result);
+  }
+}
+
+/**
+ * Rebuild the hook theme_registry cache.
+ *
+ * @param $theme
+ *   The loaded $theme object.
+ * @param $base_theme
+ *   An array of loaded $theme objects representing the ancestor themes in
+ *   oldest first order.
+ * @param theme_engine
+ *   The name of the theme engine.
+ */
+function _theme_build_registry($theme, $base_theme, $theme_engine) {
+  $cache = array();
+  // First, process the theme hooks advertised by modules. This will
+  // serve as the basic registry.
+  foreach (module_implements('theme') as $module) {
+    _theme_process_registry($cache, $module, 'module', $module, drupal_get_path('module', $module));
+  }
+
+  // Process each base theme.
+  foreach ($base_theme as $base) {
+    // If the theme uses a theme engine, process its hooks.
+    $base_path = dirname($base->filename);
+    if ($theme_engine) {
+      _theme_process_registry($cache, $theme_engine, 'base_theme_engine', $base->name, $base_path);
+    }
+    _theme_process_registry($cache, $base->name, 'base_theme', $base->name, $base_path);
+  }
+
+  // And then the same thing, but for the theme.
+  if ($theme_engine) {
+    _theme_process_registry($cache, $theme_engine, 'theme_engine', $theme->name, dirname($theme->filename));
+  }
+
+  // Finally, hooks provided by the theme itself.
+  _theme_process_registry($cache, $theme->name, 'theme', $theme->name, dirname($theme->filename));
+
+  return $cache;
+}
Index: includes/theme.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/theme.inc,v
retrieving revision 1.356
diff -u -p -r1.356 theme.inc
--- includes/theme.inc	22 May 2007 19:56:00 -0000	1.356
+++ includes/theme.inc	24 May 2007 01:09:35 -0000
@@ -92,9 +92,12 @@ function init_theme() {
  *    the same information as the $theme object. It should be in
  *    'oldest first' order, meaning the top level of the chain will
  *    be first.
+ * @param $database_available
+ *    Set to false if there is no database available; if no database is
+ *    available, the theme registry will not be loaded from cache.
  */
-function _init_theme($theme, $base_theme = array()) {
-  global $theme_info, $base_theme_info, $theme_engine, $theme_path;
+function _init_theme($theme, $base_theme = array(), $registry_callback = NULL) {
+  global $theme_info, $base_theme_info, $theme_engine, $theme_path, $theme_no_database;
   $theme_info = $theme;
   $base_theme_info = $base_theme;
 
@@ -116,7 +119,6 @@ function _init_theme($theme, $base_theme
   }
 
   $theme_engine = NULL;
-
   // Initialize the theme.
   if (isset($theme->engine)) {
     // Include the engine.
@@ -143,7 +145,15 @@ function _init_theme($theme, $base_theme
       include_once './'. $theme->owner;
     }
   }
-  _theme_load_registry($theme, $base_theme, $theme_engine);
+
+  if (isset($registry_callback) && function_exists($registry_callback)) {
+    $theme_no_database = TRUE;
+    _theme_set_registry($registry_callback($theme));
+  }
+  else {
+    $theme_no_database = FALSE;
+    _theme_load_registry($theme, $base_theme, $theme_engine);
+  }
 }
 
 /**
@@ -189,6 +199,7 @@ function _theme_load_registry($theme, $b
   }
   else {
     // If not, build one and cache it.
+    require_once './includes/theme.admin.inc';
     $registry = _theme_build_registry($theme, $base_theme, $theme_engine);
     _theme_save_registry($theme, $registry);
   }
@@ -212,115 +223,6 @@ function drupal_rebuild_theme_registry()
 }
 
 /**
- * Process a single invocation of the theme hook. $type will be one
- * of 'module', 'theme_engine' or 'theme' and it tells us some
- * important information.
- *
- * Because $cache is a reference, the cache will be continually
- * expanded upon; new entries will replace old entries in the
- * array_merge, but we are careful to ensure some data is carried
- * forward, such as the arguments a theme hook needs.
- */
-function _theme_process_registry(&$cache, $name, $type, $theme, $path) {
-  $function = $name .'_theme';
-  if (function_exists($function)) {
-    $result = $function($cache, $type, $theme, $path);
-
-    foreach ($result as $hook => $info) {
-      $result[$hook]['type'] = $type;
-      $result[$hook]['theme path'] = $path;
-      // if function and file are left out, default to standard naming
-      // conventions.
-      if (!isset($info['file']) && !isset($info['function'])) {
-        $result[$hook]['function'] = ($type == 'module' ? 'theme_' : $name .'_') . $hook;
-      }
-      // If a path is set in the info, use what was set. Otherwise use the
-      // default path. This is mostly so system.module can declare theme
-      // functions on behalf of core .include files.
-      if (isset($info['file']) && !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'];
-      }
-      // Check for default _preprocess_ functions. Ensure arrayness.
-      if (!isset($info['preprocess functions']) || !is_array($info['preprocess functions'])) {
-        $info['preprocess functions'] = array();
-        $prefix = ($type == 'module' ? 'template' : $name);
-        // theme engines get an extra set that come before the normally named preprocess.
-        if ($type == 'theme_engine') {
-          if (function_exists($prefix .'_engine_preprocess')) {
-            $info['preprocess functions'][] = $prefix .'_engine_preprocess';
-          }
-          if (function_exists($prefix .'_engine_preprocess_'. $hook)) {
-            $info['preprocess functions'][] = $prefix .'_engine_preprocess_'. $hook;
-          }
-        }
-
-        // It would be too much of a performance hit to let every module have
-        // a generic preprocess function; themes and theme engines can do that.
-        if ($type != 'module' && function_exists($prefix .'_preprocess')) {
-          $info['preprocess functions'][] = $prefix .'_preprocess';
-        }
-        if (function_exists($prefix .'_preprocess_'. $hook)) {
-          $info['preprocess functions'][] = $prefix .'_preprocess_'. $hook;
-        }
-      }
-      if (isset($cache[$hook]['preprocess functions']) && is_array($cache[$hook]['preprocess functions']) && empty($cache[$hook]['override preprocess functions'])) {
-        $info['preprocess functions'] = array_merge($cache[$hook]['preprocess functions'], $info['preprocess functions']);
-      }
-      $result[$hook]['preprocess functions'] = $info['preprocess functions'];
-    }
-
-    // Merge the newly created theme hooks into the existing cache.
-    $cache = array_merge($cache, $result);
-  }
-}
-
-/**
- * Rebuild the hook theme_registry cache.
- *
- * @param $theme
- *   The loaded $theme object.
- * @param $base_theme
- *   An array of loaded $theme objects representing the ancestor themes in
- *   oldest first order.
- * @param theme_engine
- *   The name of the theme engine.
- */
-function _theme_build_registry($theme, $base_theme, $theme_engine) {
-  $cache = array();
-  // First, process the theme hooks advertised by modules. This will
-  // serve as the basic registry.
-  foreach (module_implements('theme') as $module) {
-    _theme_process_registry($cache, $module, 'module', $module, drupal_get_path('module', $module));
-  }
-
-  // Process each base theme.
-  foreach ($base_theme as $base) {
-    // If the theme uses a theme engine, process its hooks.
-    $base_path = dirname($base->filename);
-    if ($theme_engine) {
-      _theme_process_registry($cache, $theme_engine, 'base_theme_engine', $base->name, $base_path);
-    }
-    _theme_process_registry($cache, $base->name, 'base_theme', $base->name, $base_path);
-  }
-
-  // And then the same thing, but for the theme.
-  if ($theme_engine) {
-    _theme_process_registry($cache, $theme_engine, 'theme_engine', $theme->name, dirname($theme->filename));
-  }
-
-  // Finally, hooks provided by the theme itself.
-  _theme_process_registry($cache, $theme->name, 'theme', $theme->name, dirname($theme->filename));
-
-  return $cache;
-}
-
-/**
  * Provides a list of currently available themes.
  *
  * @param $refresh
@@ -488,7 +390,7 @@ function theme() {
     }
 
     // default render function and extension.
-    $render_function = 'theme_render_template';
+    $render_function = 'drupal_render_template';
     $extension = '.tpl.php';
 
     // Run through the theme engine variables, if necessary
@@ -705,7 +607,7 @@ function theme_get_setting($setting_name
  * @return
  *   The output generated by the template.
  */
-function theme_render_template($file, $variables) {
+function drupal_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
@@ -786,116 +688,6 @@ function theme_placeholder($text) {
 }
 
 /**
- * Generate a themed maintenance page.
- *
- * Note: this function is not themable.
- *
- * @param $content
- *   The page content to show.
- * @param $show_messages
- *   Whether to output status and error messages.
- *   FALSE can be useful to postpone the messages to a subsequent page.
- */
-function theme_maintenance_page($content, $show_messages = TRUE) {
-  // Set required headers.
-  drupal_set_header('Content-Type: text/html; charset=utf-8');
-  drupal_set_html_head('<style type="text/css" media="all">@import "'. base_path() .'misc/maintenance.css";</style>');
-  drupal_set_html_head('<style type="text/css" media="all">@import "'. base_path() . drupal_get_path('module', 'system') .'/defaults.css";</style>');
-  drupal_set_html_head('<style type="text/css" media="all">@import "'. base_path() . drupal_get_path('module', 'system') .'/system.css";</style>');
-  drupal_set_html_head('<link rel="shortcut icon" href="'. base_path() .'misc/favicon.ico" type="image/x-icon" />');
-
-  // Prepare variables.
-  $variables = array(
-    'head_title' => strip_tags(drupal_get_title()),
-    'head' => drupal_get_html_head(),
-    'styles' => '',
-    'scripts' => drupal_get_js(),
-    'sidebar_left' => drupal_get_content('left'),
-    'sidebar_right' => drupal_get_content('right'),
-    'base_path' => base_path(),
-    'path_to_theme' => base_path() .'themes/garland/minnelli',
-    'logo' => base_path() .'themes/garland/minnelli/logo.png',
-    'site_title' => t('Drupal'),
-    'title' => drupal_get_title(),
-    'messages' => $show_messages ? theme('status_messages') : '',
-    'content' => $content,
-  );
-
-  $output = theme_render_template('misc/maintenance.tpl.php', $variables);
-
-  return $output;
-}
-
-/**
- * Generate a themed installation page.
- *
- * Note: this function is not themable.
- *
- * @param $content
- *   The page content to show.
- */
-function theme_install_page($content) {
-  drupal_set_header('Content-Type: text/html; charset=utf-8');
-  drupal_add_css('misc/maintenance.css', 'module', 'all', FALSE);
-  drupal_set_html_head('<link rel="shortcut icon" href="'. base_path() .'misc/favicon.ico" type="image/x-icon" />');
-
-  $variables = array(
-    'head_title' => strip_tags(drupal_get_title()),
-    'head' => drupal_get_html_head(),
-    'styles' => drupal_get_css(),
-    'scripts' => drupal_get_js(),
-    'sidebar_left' => drupal_get_content('left'),
-    'sidebar_right' => drupal_get_content('right'),
-    'base_path' => base_path(),
-    'path_to_theme' => base_path() .'themes/garland/minnelli',
-    'logo' => base_path() .'themes/garland/minnelli/logo.png',
-    'site_title' => st('Drupal Installation'),
-    'title' => drupal_get_title(),
-    'messages' => '',
-    'content' => $content,
-  );
-
-  // Special handling of error messages
-  $messages = drupal_set_message();
-  if (isset($messages['error'])) {
-    $title = count($messages['error']) > 1 ? st('The following errors must be resolved before you can continue the installation process') : st('The following error must be resolved before you can continue the installation process');
-    $variables['messages'] .= '<h3>'. $title .':</h3>';
-    $variables['messages'] .= theme('status_messages', 'error');
-  }
-
-  // Special handling of status messages
-  if (isset($messages['status'])) {
-    $warnings = count($messages['status']) > 1 ? st('The following installation warnings should be carefully reviewed, but in most cases may be safely ignored') : st('The following installation warning should be carefully reviewed, but in most cases may be safely ignored');
-    $variables['messages'] .= '<h4>'. $title .':</h4>';
-    $variables['messages'] .= theme('status_messages', 'status');
-  }
-
-  return theme_render_template('misc/maintenance.tpl.php', $variables);
-}
-
-/**
- * Return a themed list of maintenance tasks to perform.
- *
- * Note: this function is not themable.
- */
-function theme_task_list($items, $active = NULL) {
-  $done = isset($items[$active]) || $active == NULL;
-  $output = '<ol class="task-list">';
-  foreach ($items as $k => $item) {
-    if ($active == $k) {
-      $class = 'active';
-      $done = false;
-    }
-    else {
-      $class = $done ? 'done' : '';
-    }
-    $output .= '<li class="'. $class .'">'. $item .'</li>';
-  }
-  $output .= '</ol>';
-  return $output;
-}
-
-/**
  * Return a themed set of status and/or error messages. The messages are grouped
  * by type.
  *
@@ -1614,3 +1406,4 @@ function template_preprocess_block(&$var
   $variables['template_files'][] = 'block-' . $variables['block']->module;
   $variables['template_files'][] = 'block-' . $variables['block']->module .'-'. $variables['block']->delta;
 }
+
Index: misc/maintenance.tpl.php
===================================================================
RCS file: misc/maintenance.tpl.php
diff -N misc/maintenance.tpl.php
--- misc/maintenance.tpl.php	5 Mar 2007 16:15:22 -0000	1.2
+++ /dev/null	1 Jan 1970 00:00:00 -0000
@@ -1,59 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
-  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml">
-  <head>
-    <title><?php print $head_title ?></title>
-    <?php print $head ?>
-    <?php print $styles ?>
-    <?php print $scripts ?>
-    <style type="text/css" media="all">@import "<?php print $path_to_theme ?>/style.css";</style>
-    <!--[if lt IE 7]>
-    <style type="text/css" media="all">@import "<?php print $path_to_theme ?>/fix-ie.css";</style>
-    <![endif]-->
-  </head>
-  <body class="<?php
-  $classes = array('', 'sidebar-left', 'sidebar-right', 'sidebar-both');
-  print $classes[((bool)$sidebar_left) + 2 * ((bool)$sidebar_right)];
-  ?>">
-
-<!-- Layout -->
-  <div id="header-region" class="clear-block"></div>
-
-    <div id="wrapper">
-    <div id="container" class="clear-block">
-
-      <div id="header">
-        <div id="logo-floater">
-          <h1><a href="<?php print check_url($base_path) ?>"><img src="<?php print check_url($logo) ?>" alt="Drupal" id="logo" /><span><?php print $site_title ?></span></a></h1>
-        </div>
-      </div> <!-- /header -->
-
-      <?php if ($sidebar_left): ?>
-        <div id="sidebar-left" class="sidebar">
-          <?php print $sidebar_left ?>
-        </div>
-      <?php endif; ?>
-
-      <div id="center"><div id="squeeze"><div class="right-corner"><div class="left-corner">
-          <?php if ($title): print '<h2>'. $title .'</h2>'; endif; ?>
-
-          <?php if ($messages): print $messages; endif; ?>
-          <?php print $content ?>
-          <span class="clear"></span>
-
-          <!--partial-->
-
-      </div></div></div></div> <!-- /.left-corner, /.right-corner, /#squeeze, /#center -->
-
-      <?php if ($sidebar_right): ?>
-        <div id="sidebar-right" class="sidebar">
-          <?php print $sidebar_right ?>
-        </div>
-      <?php endif; ?>
-
-    </div> <!-- /container -->
-  </div>
-<!-- /layout -->
-
-  </body>
-</html>
Index: modules/system/system.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/system/system.module,v
retrieving revision 1.481
diff -u -p -r1.481 system.module
--- modules/system/system.module	23 May 2007 08:00:46 -0000	1.481
+++ modules/system/system.module	24 May 2007 01:09:37 -0000
@@ -49,7 +49,7 @@ function system_help($section) {
 }
 
 function system_theme() {
-  return array_merge(drupal_common_themes(), array(
+  return array_merge(drupal_common_theme(), array(
     'system_theme_select_form' => array(
       'arguments' => array('form' => NULL),
     ),
@@ -999,42 +999,12 @@ function system_get_files_database(&$fil
   }
 }
 
-function system_theme_default() {
-  // Prepare defaults for themes.
-  return array(
-    'regions' => array(
-      'left' => 'Left sidebar',
-      'right' => 'Right sidebar',
-      'content' => 'Content',
-      'header' => 'Header',
-      'footer' => 'Footer',
-    ),
-    'description' => '',
-    'features' => array(
-      'comment_user_picture',
-      'favicon',
-      'mission',
-      'logo',
-      'name',
-      'node_user_picture',
-      'search',
-      'slogan'
-    ),
-    'stylesheet' => 'style.css',
-    'screenshot' => 'screenshot.png',
-  );
-}
-
 /**
  * Collect data about all currently available themes
  */
 function system_theme_data() {
-  // Find themes
-  $themes = drupal_system_listing('\.info$', 'themes');
-
-  // Find theme engines
-  $engines = drupal_system_listing('\.engine$', 'themes/engines');
-
+  require_once './includes/theme.admin.inc';
+  list($themes, $engines) = drupal_theme_data();
   // Remove all theme engines from the system table
   db_query("DELETE FROM {system} WHERE type = 'theme_engine'");
 
@@ -1045,62 +1015,6 @@ function system_theme_data() {
     db_query("INSERT INTO {system} (name, type, filename, status, throttle, bootstrap) VALUES ('%s', '%s', '%s', %d, %d, %d)", $engine->name, 'theme_engine', $engine->filename, 1, 0, 0);
   }
 
-  $defaults = system_theme_default();
-
-  $sub_themes = array();
-  // Read info files for each theme
-  foreach ($themes as $key => $theme) {
-    $themes[$key]->info = drupal_parse_info_file($theme->filename) + $defaults;
-    if (!empty($themes[$key]->info['base theme'])) {
-      $sub_themes[] = $key;
-    }
-    if (empty($themes[$key]->info['engine'])) {
-      $filename = dirname($themes[$key]->filename) .'/'. $themes[$key]->name .'.theme';
-      if (file_exists($filename)) {
-        $themes[$key]->owner = $filename;
-        $themes[$key]->prefix = $key;
-      }
-    }
-    else {
-      $engine = $themes[$key]->info['engine'];
-      if (isset($engines[$engine])) {
-        $themes[$key]->owner = $engines[$engine]->filename;
-        $themes[$key]->prefix = $engines[$engine]->name;
-        $themes[$key]->template = TRUE;
-      }
-    }
-
-    // Give the stylesheet proper path information.
-    if (!empty($themes[$key]->info['stylesheet'])) {
-      $themes[$key]->info['stylesheet'] = dirname($themes[$key]->filename) .'/'. $themes[$key]->info['stylesheet'];
-    }
-    // Give the screenshot proper path information.
-    if (!empty($themes[$key]->info['screenshot'])) {
-      $themes[$key]->info['screenshot'] = dirname($themes[$key]->filename) .'/'. $themes[$key]->info['screenshot'];
-    }
-  }
-
-  // Now that we've established all our master themes, go back and fill in
-  // data for subthemes.
-  foreach ($sub_themes as $key) {
-    $base_key = system_find_base_theme($themes, $key);
-    if (!$base_key) {
-      continue;
-    }
-    // Copy the 'owner' and 'engine' over if the top level theme uses a
-    // theme engine.
-    if (isset($themes[$base_key]->owner)) {
-      if (isset($themes[$base_key]->info['engine'])) {
-        $themes[$key]->info['engine'] = $themes[$base_key]->info['engine'];
-        $themes[$key]->owner = $themes[$base_key]->owner;
-        $themes[$key]->prefix = $themes[$base_key]->prefix;
-      }
-      else {
-        $themes[$key]->prefix = $key;
-      }
-    }
-  }
-
   // Extract current files from database.
   system_get_files_database($themes, 'theme');
 
@@ -1118,32 +1032,6 @@ function system_theme_data() {
 }
 
 /**
- * Recursive function to find the top level base theme. Themes can inherit
- * templates and function implementations from earlier themes; this function
- * finds the top level parent that has no ancestor, or returns NULL if there
- * isn't a valid parent.
- */
-function system_find_base_theme($themes, $key, $used_keys = array()) {
-  $base_key = $themes[$key]->info['base theme'];
-  // Does the base theme exist?
-  if (!isset($themes[$base_key])) {
-    return NULL;
-  }
-
-  // Is the base theme itself a child of another theme?
-  if (isset($themes[$base_key]->info['base theme'])) {
-    // Prevent loops.
-    if ($used_keys[$base_key]) {
-      return NULL;
-    }
-    $used_keys[$base_key] = TRUE;
-    return system_find_base_theme($themes, $base_key, $used_keys);
-  }
-  // If we get here, then this is our parent theme.
-  return $base_key;
-}
-
-/**
  * Get a list of available regions from a specified theme.
  *
  * @param $theme_key
Index: sites/default/default.settings.php
===================================================================
RCS file: /cvs/drupal/drupal/sites/default/default.settings.php,v
retrieving revision 1.1
diff -u -p -r1.1 default.settings.php
--- sites/default/default.settings.php	8 May 2007 16:36:55 -0000	1.1
+++ sites/default/default.settings.php	24 May 2007 01:09:37 -0000
@@ -165,6 +165,17 @@ ini_set('url_rewriter.tags',        '');
 # );
 
 /**
+ * Maintenance theme:
+ *
+ * The maintenance theme can only be set in settings.php, since it is used
+ * when a database is not guaranteed to be present. To change your maintenance
+ * theme, copy maintenance_page.tpl.php into your theme, and modify as it suits
+ * you. Remember, there is no database guaranteed, and not all of the Drupal API
+ * will be available, so be careful what you put in it.
+ */
+# $conf['maintenance_theme'] = 'garland';
+
+/**
  * String overrides:
  *
  * To override specific strings on your site with or without enabling locale
Index: themes/engines/phptemplate/phptemplate.engine
===================================================================
RCS file: /cvs/drupal/drupal/themes/engines/phptemplate/phptemplate.engine,v
retrieving revision 1.65
diff -u -p -r1.65 phptemplate.engine
--- themes/engines/phptemplate/phptemplate.engine	6 May 2007 05:47:52 -0000	1.65
+++ themes/engines/phptemplate/phptemplate.engine	24 May 2007 01:09:37 -0000
@@ -73,5 +73,8 @@ function phptemplate_engine_preprocess(&
 
   // Tell all templates where they are located.
   $variables['directory'] = path_to_theme();
-  $variables['is_front'] = drupal_is_front_page();
+  global $theme_no_database;
+  if (!$theme_no_database) {
+    $variables['is_front'] = drupal_is_front_page();
+  }
 }
