diff --git a/database/database.mysql b/database/database.mysql
index 6db6c4fb0584858ab14ee109395ac5f5eab518fd..bdd3d53464c736ab47d290dacac957ee86e0b14f 100644
--- a/database/database.mysql
+++ b/database/database.mysql
@@ -121,9 +121,10 @@ CREATE TABLE authmap (
 CREATE TABLE blocks (
   module varchar(64) DEFAULT '' NOT NULL,
   delta varchar(32) NOT NULL default '0',
+  theme varchar(255) NOT NULL default '',
   status tinyint(2) DEFAULT '0' NOT NULL,
   weight tinyint(1) DEFAULT '0' NOT NULL,
-  region tinyint(1) DEFAULT '0' NOT NULL,
+  region varchar(64) DEFAULT 'left' NOT NULL,
   custom tinyint(2) DEFAULT '0' NOT NULL,
   throttle tinyint(1) DEFAULT '0' NOT NULL,
   visibility tinyint(1) DEFAULT '0' NOT NULL,
@@ -805,8 +806,8 @@ REPLACE variable SET name='update_start', value='s:10:"2005-03-21";';
 
 REPLACE variable SET name='theme_default', value='s:10:"bluemarine";';
 
-REPLACE blocks SET module = 'user', delta = '0', status = '1';
-REPLACE blocks SET module = 'user', delta = '1', status = '1';
+REPLACE blocks SET module = 'user', delta = '0', theme = 'bluemarine', status = '1';
+REPLACE blocks SET module = 'user', delta = '1', theme = 'bluemarine', status = '1';
 
 INSERT INTO sequences (name, id) VALUES ('menu_mid', 1);
 
diff --git a/database/database.pgsql b/database/database.pgsql
index 166dfa8f6461f0f95edd249ced6bf1dc888d999a..6dfb853baadb6deb657dc08103e0fe538952bb2e 100644
--- a/database/database.pgsql
+++ b/database/database.pgsql
@@ -116,9 +116,10 @@ CREATE TABLE authmap (
 CREATE TABLE blocks (
   module varchar(64) NOT NULL default '',
   delta varchar(32) NOT NULL default '0',
+  theme varchar(255) NOT NULL default '',
   status smallint NOT NULL default '0',
   weight smallint NOT NULL default '0',
-  region smallint NOT NULL default '0',
+  region varchar(64) DEFAULT 'left' NOT NULL,
   custom smallint NOT NULL default '0',
   throttle smallint NOT NULL default '0',
   visibility smallint NOT NULL default '0',
@@ -798,8 +799,8 @@ INSERT INTO permission VALUES (1,'access content',0);
 INSERT INTO role (name) VALUES ('authenticated user');
 INSERT INTO permission VALUES (2,'access comments, access content, post comments, post comments without approval',0);
 
-INSERT INTO blocks(module,delta,status) VALUES('user', 0, 1);
-INSERT INTO blocks(module,delta,status) VALUES('user', 1, 1);
+INSERT INTO blocks(module,delta,theme,status) VALUES('user', 0, 'bluemarine', 1);
+INSERT INTO blocks(module,delta,theme,status) VALUES('user', 1, 'bluemarine', 1);
 
 INSERT INTO node_access VALUES (0, 0, 'all', 1, 0, 0);
 
diff --git a/database/updates.inc b/database/updates.inc
index 435af3373141ee08a4108b278bd522f7fd005628..e57ed174236b70e63bdd33d9c7ee292182c8fe7f 100644
--- a/database/updates.inc
+++ b/database/updates.inc
@@ -120,7 +120,8 @@
   "2005-05-22" => "update_141",
   "2005-07-29" => "update_142",
   "2005-07-30" => "update_143",
-  "2005-08-08" => "update_144"
+  "2005-08-08" => "update_144",
+  "2005-08-15" => "update_145"
 );
 
 function update_32() {
@@ -2550,6 +2551,28 @@ function update_144() {
   return $ret;
 }
 
+function update_145() {
+  $default_theme = variable_get('theme_default', 'bluemarine');
+  $ret = array();
+  $ret[] = update_sql("ALTER TABLE {blocks} CHANGE region region varchar(64) default 'left' NOT NULL");
+  $ret[] = update_sql("ALTER TABLE {blocks} ADD theme varchar(255) NOT NULL default ''");
+
+  // Intialize block data for default theme
+  $ret[] = update_sql("UPDATE {blocks} SET region = 'left' WHERE region = '0'");
+  $ret[] = update_sql("UPDATE {blocks} SET region = 'right' WHERE region = '1'");
+  db_query("UPDATE {blocks} SET theme = '%s'", $default_theme);
+
+  // Initialze block data for other enabled themes.
+  $themes = list_themes();
+  foreach (array_keys($themes) as $theme) {
+    if (($theme != $default_theme) && $themes[$theme]->status == 1) {
+      system_initialize_theme_blocks($theme);
+    }
+  }
+
+  return $ret;
+}
+
 function update_sql($sql) {
   $edit = $_POST["edit"];
   $result = db_query($sql);
diff --git a/includes/common.inc b/includes/common.inc
index c38743c5405d61041ee145e676e6675744f60a0b..c9b61d402a8a11a575c9cde178097eb4363a3d80 100644
--- a/includes/common.inc
+++ b/includes/common.inc
@@ -24,6 +24,50 @@
  */
 define('SAVED_DELETED', 3);
 
+/**
+ * Set content for a specified region.
+ *
+ * @param $region
+ *   Page region the content is assigned to.
+ *
+ * @param $data
+ *   Content to be set.
+ */
+function drupal_set_content($region = null, $data = null) {
+  static $content = array();
+
+  if (!is_null($region) && !is_null($data)) {
+    $content[$region][] = $data;
+  }
+  return $content;
+}
+
+/**
+ * Get assigned content.
+ *
+ * @param $region
+ *   A specified region to fetch content for.  If null, all regions will be returned.
+ *
+ * @param $delimiter
+ *   Content to be inserted between exploded array elements.
+ */
+function drupal_get_content($region = null, $delimiter = ' ') {
+  $content = drupal_set_content();
+  if (isset($region)) {
+    if (is_array($content[$region])) {
+      return implode ($delimiter, $content[$region]);
+    }
+  }
+  else {
+    foreach (array_keys($content) as $region) {
+      if (is_array($content[$region])) {
+        $content[$region] = implode ($delimiter, $content[$region]);
+      }
+    }
+    return $content;
+  }
+}
+
 /**
  * Set the breadcrumb trail for the current page.
  *
diff --git a/includes/theme.inc b/includes/theme.inc
index 559640e8ce54a6dd1fea59869b68d46f50f8a283..edbd8d58cab95645e48c9695aa61866cfb95fb2f 100644
--- a/includes/theme.inc
+++ b/includes/theme.inc
@@ -798,7 +798,7 @@ function theme_box($title, $content, $region = 'main') {
  *
  * @param $block
  *   An object populated with fields from the "blocks" database table
- *   ($block->module, $block->delta, $block->region, ...) and fields returned by
+ *   ($block->module, $block->delta ...) and fields returned by
  *   <i>module</i>_block('view') ($block->subject, $block->content, ...).
  * @return
  *   A string containing the block output.
@@ -945,6 +945,10 @@ function theme_blocks($region) {
       $output .= theme('block', $block);
     }
   }
+
+  // Add any content assigned to this region through drupal_set_content() calls.
+  $output .= drupal_get_content($region);
+
   return $output;
 }
 
diff --git a/misc/drupal.css b/misc/drupal.css
index 819f8cc9fce02bf32c5cffb2b13235f527d35a04..38367b733f56fb1b4b74d3c617ba84ae999a62e4 100644
--- a/misc/drupal.css
+++ b/misc/drupal.css
@@ -87,6 +87,12 @@ td.menu-disabled {
 .breadcrumb {
   padding-bottom: .5em
 }
+.block-region {
+  background-color: #ffff66;
+  margin-top: 4px;
+  margin-bottom: 4px;
+  padding: 3px;
+}
 .block ul {
   margin: 0;
   padding: 0 0 0.25em 1em;
@@ -343,7 +349,6 @@ tr.odd .form-item, tr.even .form-item {
   font-style: normal;
   text-decoration: line-through;
 }
-
 #node-admin-filter ul {
   list-style-type: none;
   padding: 0px;
@@ -618,3 +623,4 @@ html.js fieldset.collapsible legend a {
 html.js fieldset.collapsed legend a {
   background-image: url('menu-collapsed.png');
 }
+
diff --git a/modules/block.module b/modules/block.module
index 5ab064d800e606c9513d5ec1f13d5c44b2a85d79..4c52e7a7b1b0c497121a56d19c5f9affbf324922 100644
--- a/modules/block.module
+++ b/modules/block.module
@@ -13,8 +13,8 @@ function block_help($section) {
   switch ($section) {
     case 'admin/help#block':
       return t('
-<p>Blocks are the boxes visible in the sidebar(s) of your web site. These are usually generated automatically by modules (e.g. recent forum topics), but you can also create your own blocks.</p>
-<p>The sidebar each block appears in depends on both which theme you are using (some are left-only, some right, some both), and on the settings in block management.</p>
+<p>Blocks are the boxes visible in the sidebar(s) of your web site and other regions. These are usually generated automatically by modules (e.g. recent forum topics), but you can also create your own blocks.</p>
+<p>The region each block appears in depends on both which theme you are using (some are left-only, some right, some both, and some may offer other regions), and on the settings in block management.</p>
 <p>The block management screen lets you specify the vertical sort-order of the blocks within a sidebar. You do this by assigning a weight to each block. Lighter blocks (smaller weight) "float up" towards the top of the sidebar. Heavier ones "sink down" towards the bottom of it.</p>
 <p>A block\'s visibility depends on:</p>
 <ul>
@@ -31,8 +31,8 @@ function block_help($section) {
       return t('Controls the boxes that are displayed around the main content.');
     case 'admin/block':
       return t("
-<p>Blocks are the boxes in the left and right side bars of the web site. They are made available by modules or created manually.</p>
-<p>Only enabled blocks are shown. You can position the blocks by deciding which side of the page they will show up on (sidebar) and in which order they appear (weight).</p>
+<p>Blocks are content rendered into regions, often boxes in the left and right side bars of the web site. They are made available by modules or created manually.</p>
+<p>Only enabled blocks are shown. You can position the blocks by deciding which area of the page they will show up on (e.g., a sidebar) and in which order they appear (weight).  Highlighting on this page shows the regions where content will be rendered.</p>
 <p>If you want certain blocks to disable themselves temporarily during high server loads, check the 'Throttle' box. You can configure the auto-throttle on the <a href=\"%throttle\">throttle configuration page</a> after having enabled the throttle module.</p>
 ", array('%throttle' => url('admin/settings/throttle')));
     case 'admin/block/add':
@@ -71,6 +71,18 @@ function block_menu($may_cache) {
       'access' => user_access('administer blocks'),
       'callback' => 'block_box_add',
       'type' => MENU_LOCAL_TASK);
+    foreach (list_themes() as $key => $theme) {
+      if ($theme->status) {
+        if ($key == variable_get('theme_default', 'bluemarine')) {
+          $items[] = array('path' => 'admin/block/list/' . $key, 'title' => t('%key settings', array('%key' => $key)),
+            'access' => user_access('administer blocks'), 'type' => MENU_DEFAULT_LOCAL_TASK, 'weight' => -10);
+        }
+        else {
+          $items[] = array('path' => 'admin/block/list/' . $key, 'title' => t('%key settings', array('%key' => $key)),
+            'access' => user_access('administer blocks'), 'type' => MENU_LOCAL_TASK);
+        }
+      }
+    }
   }
 
   return $items;
@@ -112,8 +124,8 @@ function block_block($op = 'list', $delta = 0, $edit = array()) {
 function block_admin_save($edit) {
   foreach ($edit as $module => $blocks) {
     foreach ($blocks as $delta => $block) {
-      db_query("UPDATE {blocks} SET region = %d, status = %d, weight = %d, throttle = %d WHERE module = '%s' AND delta = '%s'",
-                $block['region'], $block['status'], $block['weight'], $block['throttle'], $module, $delta);
+      db_query("UPDATE {blocks} SET status = %d, weight = %d, region = '%s', throttle = %d WHERE module = '%s' AND delta = '%s' AND theme = '%s'",
+                $block['status'], $block['weight'], $block['region'], $block['throttle'], $module, $delta, $block['theme']);
     }
   }
 }
@@ -129,12 +141,18 @@ function block_admin_save($edit) {
  *   Blocks currently exported by modules, sorted by $order_by.
  */
 function _block_rehash($order_by = array('weight')) {
-  $result = db_query('SELECT * FROM {blocks} ');
+  global $theme_key;
+
+  if (empty($theme_key)) {
+    init_theme();
+  }
+
+  $result = db_query("SELECT * FROM {blocks} WHERE theme = '%s'", $theme_key);
   while ($old_block = db_fetch_object($result)) {
     $old_blocks[$old_block->module][$old_block->delta] = $old_block;
   }
 
-  db_query('DELETE FROM {blocks} ');
+  db_query("DELETE FROM {blocks} WHERE theme = '%s'", $theme_key);
 
   foreach (module_list() as $module) {
     $module_blocks = module_invoke($module, 'block', 'list');
@@ -142,6 +160,7 @@ function _block_rehash($order_by = array('weight')) {
       foreach ($module_blocks as $delta => $block) {
         $block['module'] = $module;
         $block['delta']  = $delta;
+        // If previously written to database, load values.
         if ($old_blocks[$module][$delta]) {
           $block['status'] = $old_blocks[$module][$delta]->status;
           $block['weight'] = $old_blocks[$module][$delta]->weight;
@@ -151,15 +170,19 @@ function _block_rehash($order_by = array('weight')) {
           $block['custom'] = $old_blocks[$module][$delta]->custom;
           $block['throttle'] = $old_blocks[$module][$delta]->throttle;
         }
+        // Otherwise, use any set values, or else substitute defaults.
         else {
-          $block['status'] = $block['weight'] = $block['region'] = $block['custom'] = 0;
-          $block['pages'] = '';
+          $properties = array ('status' => 0, 'weight' => 0, 'region' => 'left', 'pages' => '', 'custom' => 0);
+          foreach ($properties as $property => $default) {
+            if (!isset ($block[$property])) {
+              $block[$property] = $default;
+            }
+          }
         }
 
         // reinsert blocks into table
-        db_query("INSERT INTO {blocks} (module, delta, status, weight, region, visibility, pages, custom, throttle) VALUES ('%s', '%s', %d, %d, %d, %d, '%s', %d, %d)",
-          $block['module'], $block['delta'], $block['status'], $block['weight'], $block['region'], $block['visibility'], $block['pages'], $block['custom'], $block['throttle']);
-
+        db_query("INSERT INTO {blocks} (module, delta, theme, status, weight, region, visibility, pages, custom, throttle) VALUES ('%s', '%s', '%s', %d, %d, '%s', %d, '%s', %d, %d)",
+          $block['module'], $block['delta'], $theme_key, $block['status'], $block['weight'], $block['region'], $block['visibility'], $block['pages'], $block['custom'], $block['throttle']);
         $blocks[] = $block;
 
         // build array to sort on
@@ -178,17 +201,32 @@ function _block_rehash($order_by = array('weight')) {
  * Prepare the main block administration form.
  */
 function block_admin_display() {
+  global $theme_key, $custom_theme;
+
+  // If non-default theme configuration has been selected, set the custom theme.
+  if (arg(3)) {
+    $custom_theme = arg(3);
+    init_theme();
+  }
+
   $blocks = _block_rehash();
 
-  $header = array(t('Block'), t('Enabled'), t('Weight'), t('Sidebar'));
+  $block_regions = system_region_list($theme_key);
+
+  // Highlight regions on page, to provide visual reference.
+  foreach ($block_regions as $key => $value) {
+    drupal_set_content($key, '<div class="block-region">' . $value . '</div>');
+  }
+
+  $header = array(t('Block'), t('Enabled'), t('Weight'), t('Placement'));
   if (module_exist('throttle')) {
     $header[] = t('Throttle');
   }
   $header[] = array('data' => t('Operations'), 'colspan' => 2);
 
-  $left = array();
-  $right = array();
+  $regions = array();
   $disabled = array();
+
   foreach ($blocks as $block) {
     if ($block['module'] == 'block') {
       $delete = l(t('delete'), 'admin/block/delete/'. $block['delta']);
@@ -198,10 +236,10 @@ function block_admin_display() {
     }
 
     $row = array(array('data' => $block['info'], 'class' => 'block'),
-      form_checkbox(NULL, $block['module'] .']['. $block['delta'] .'][status', 1, $block['status']),
+      form_checkbox(NULL, $block['module'] .']['. $block['delta'] .'][status', 1, $block['status']) . form_hidden($block['module'] .']['. $block['delta'] .'][theme', $theme_key),
       form_weight(NULL, $block['module'] .']['. $block['delta'] .'][weight', $block['weight']),
-      form_radios(NULL, $block['module'] .']['. $block['delta'] .'][region', $block['region'],
-      array(t('left'), t('right'))));
+      form_select(NULL, $block['module'] .']['. $block['delta'] .'][region', isset($block['region']) ? $block['region'] : system_default_region(),
+      $block_regions));
 
     if (module_exist('throttle')) {
       $row[] = form_checkbox(NULL, $block['module'] .']['. $block['delta'] .'][throttle', 1, $block['throttle']);
@@ -209,11 +247,10 @@ function block_admin_display() {
     $row[] = l(t('configure'), 'admin/block/configure/'. $block['module'] .'/'. $block['delta']);
     $row[] = $delete;
     if ($block['status']) {
-      if ($block['region'] == 0) {
-        $left[] = $row;
-      }
-      if ($block['region'] == 1) {
-        $right[] = $row;
+      foreach ($block_regions as $key => $value) {
+        if ($block['region'] == $key) {
+          $regions[$key][] = $row;
+        }
       }
     }
     else if ($block['region'] <= 1) {
@@ -222,13 +259,13 @@ function block_admin_display() {
   }
 
   $rows = array();
-  if (count($left)) {
-    $rows[] = array(array('data' => t('Left sidebar'), 'class' => 'region', 'colspan' => (module_exist('throttle') ? 7 : 6)));
-    $rows = array_merge($rows, $left);
-  }
-  if (count($right)) {
-    $rows[] = array(array('data' => t('Right sidebar'), 'class' => 'region', 'colspan' => (module_exist('throttle') ? 7 : 6)));
-    $rows = array_merge($rows, $right);
+
+  if (count($regions)) {
+    foreach ($regions as $region => $row) {
+      $region_title = t('%region', array ('%region' => ucfirst($block_regions[$region])));
+      $rows[] = array(array('data' => $region_title, 'class' => 'region', 'colspan' => (module_exist('throttle') ? 7 : 6)));
+      $rows = array_merge($rows, $row);
+    }
   }
   if (count($disabled)) {
     $rows[] = array(array('data' => t('Disabled'), 'class' => 'region', 'colspan' => (module_exist('throttle') ? 7 : 6)));
@@ -237,7 +274,7 @@ function block_admin_display() {
   $output = theme('table', $header, $rows, array('id' => 'blocks'));
   $output .= form_submit(t('Save blocks'));
 
-  return form($output, 'post', url('admin/block'));
+  return form($output, 'post', arg(3) ? url('admin/block/list/' . $theme_key) : url('admin/block'));
 }
 
 function block_box_get($bid) {
@@ -412,39 +449,31 @@ function block_user($type, $edit, &$user, $category = NULL) {
   }
 }
 
- /**
-  * Return all blocks in the specied region for the current user. You may
-  * use this function to implement variable block regions.  The default
-  * regions are 'left', 'right' and 'all', where 'all' means both left and
-  * right.
-  *
-  * @param $region
-  *   This is a string which describes in a human readable form which region
-  *   you need.
-  *
-  * @param $regions
-  *   This is an optional array and contains map(s) from the string $region to
-  *   the numerical region value(s) in the blocks table. See default value for
-  *   examples.
-  *
-  * @return
-  *   An array of block objects, indexed with <i>module</i>_<i>delta</i>.
-  *   If you are displaying your blocks in one or two sidebars, you may check
-  *   whether this array is empty to see how many columns are going to be
-  *   displayed.
-  *
-  * @todo
-  *   Add a proper primary key (bid) to the blocks table so we don't have
-  *   to mess around with this <i>module</i>_<i>delta</i> construct.
-  *   Currently, the blocks table has no primary key defined!
-  */
-function block_list($region, $regions = array('left' => 0, 'right' => 1, 'all' => '0, 1')) {
-  global $user;
+/**
+ * Return all blocks in the specified region for the current user.
+ *
+ * @param $region
+ *   The name of a region.
+ *
+ * @return
+ *   An array of block objects, indexed with <i>module</i>_<i>delta</i>.
+ *   If you are displaying your blocks in one or two sidebars, you may check
+ *   whether this array is empty to see how many columns are going to be
+ *   displayed.
+ *
+ * @todo
+ *   Add a proper primary key (bid) to the blocks table so we don't have
+ *   to mess around with this <i>module</i>_<i>delta</i> construct.
+ *   Currently, the blocks table has no primary key defined!
+ */
+function block_list($region) {
+  global $user, $theme_key;
+
   static $blocks = array();
 
   if (!isset($blocks[$region])) {
     $blocks[$region] = array();
-    $result = db_query("SELECT * FROM {blocks} WHERE status = 1 AND region IN (%s) ORDER BY weight, module", $regions[$region]);
+    $result = db_query("SELECT * FROM {blocks} WHERE theme = '%s' AND status = 1 AND region = '%s' ORDER BY weight, module", $theme_key, $region);
     while ($block = db_fetch_array($result)) {
       // Use the user's block visibility setting, if necessary
       if ($block['custom'] != 0) {
diff --git a/modules/block/block.module b/modules/block/block.module
index 5ab064d800e606c9513d5ec1f13d5c44b2a85d79..4c52e7a7b1b0c497121a56d19c5f9affbf324922 100644
--- a/modules/block/block.module
+++ b/modules/block/block.module
@@ -13,8 +13,8 @@ function block_help($section) {
   switch ($section) {
     case 'admin/help#block':
       return t('
-<p>Blocks are the boxes visible in the sidebar(s) of your web site. These are usually generated automatically by modules (e.g. recent forum topics), but you can also create your own blocks.</p>
-<p>The sidebar each block appears in depends on both which theme you are using (some are left-only, some right, some both), and on the settings in block management.</p>
+<p>Blocks are the boxes visible in the sidebar(s) of your web site and other regions. These are usually generated automatically by modules (e.g. recent forum topics), but you can also create your own blocks.</p>
+<p>The region each block appears in depends on both which theme you are using (some are left-only, some right, some both, and some may offer other regions), and on the settings in block management.</p>
 <p>The block management screen lets you specify the vertical sort-order of the blocks within a sidebar. You do this by assigning a weight to each block. Lighter blocks (smaller weight) "float up" towards the top of the sidebar. Heavier ones "sink down" towards the bottom of it.</p>
 <p>A block\'s visibility depends on:</p>
 <ul>
@@ -31,8 +31,8 @@ function block_help($section) {
       return t('Controls the boxes that are displayed around the main content.');
     case 'admin/block':
       return t("
-<p>Blocks are the boxes in the left and right side bars of the web site. They are made available by modules or created manually.</p>
-<p>Only enabled blocks are shown. You can position the blocks by deciding which side of the page they will show up on (sidebar) and in which order they appear (weight).</p>
+<p>Blocks are content rendered into regions, often boxes in the left and right side bars of the web site. They are made available by modules or created manually.</p>
+<p>Only enabled blocks are shown. You can position the blocks by deciding which area of the page they will show up on (e.g., a sidebar) and in which order they appear (weight).  Highlighting on this page shows the regions where content will be rendered.</p>
 <p>If you want certain blocks to disable themselves temporarily during high server loads, check the 'Throttle' box. You can configure the auto-throttle on the <a href=\"%throttle\">throttle configuration page</a> after having enabled the throttle module.</p>
 ", array('%throttle' => url('admin/settings/throttle')));
     case 'admin/block/add':
@@ -71,6 +71,18 @@ function block_menu($may_cache) {
       'access' => user_access('administer blocks'),
       'callback' => 'block_box_add',
       'type' => MENU_LOCAL_TASK);
+    foreach (list_themes() as $key => $theme) {
+      if ($theme->status) {
+        if ($key == variable_get('theme_default', 'bluemarine')) {
+          $items[] = array('path' => 'admin/block/list/' . $key, 'title' => t('%key settings', array('%key' => $key)),
+            'access' => user_access('administer blocks'), 'type' => MENU_DEFAULT_LOCAL_TASK, 'weight' => -10);
+        }
+        else {
+          $items[] = array('path' => 'admin/block/list/' . $key, 'title' => t('%key settings', array('%key' => $key)),
+            'access' => user_access('administer blocks'), 'type' => MENU_LOCAL_TASK);
+        }
+      }
+    }
   }
 
   return $items;
@@ -112,8 +124,8 @@ function block_block($op = 'list', $delta = 0, $edit = array()) {
 function block_admin_save($edit) {
   foreach ($edit as $module => $blocks) {
     foreach ($blocks as $delta => $block) {
-      db_query("UPDATE {blocks} SET region = %d, status = %d, weight = %d, throttle = %d WHERE module = '%s' AND delta = '%s'",
-                $block['region'], $block['status'], $block['weight'], $block['throttle'], $module, $delta);
+      db_query("UPDATE {blocks} SET status = %d, weight = %d, region = '%s', throttle = %d WHERE module = '%s' AND delta = '%s' AND theme = '%s'",
+                $block['status'], $block['weight'], $block['region'], $block['throttle'], $module, $delta, $block['theme']);
     }
   }
 }
@@ -129,12 +141,18 @@ function block_admin_save($edit) {
  *   Blocks currently exported by modules, sorted by $order_by.
  */
 function _block_rehash($order_by = array('weight')) {
-  $result = db_query('SELECT * FROM {blocks} ');
+  global $theme_key;
+
+  if (empty($theme_key)) {
+    init_theme();
+  }
+
+  $result = db_query("SELECT * FROM {blocks} WHERE theme = '%s'", $theme_key);
   while ($old_block = db_fetch_object($result)) {
     $old_blocks[$old_block->module][$old_block->delta] = $old_block;
   }
 
-  db_query('DELETE FROM {blocks} ');
+  db_query("DELETE FROM {blocks} WHERE theme = '%s'", $theme_key);
 
   foreach (module_list() as $module) {
     $module_blocks = module_invoke($module, 'block', 'list');
@@ -142,6 +160,7 @@ function _block_rehash($order_by = array('weight')) {
       foreach ($module_blocks as $delta => $block) {
         $block['module'] = $module;
         $block['delta']  = $delta;
+        // If previously written to database, load values.
         if ($old_blocks[$module][$delta]) {
           $block['status'] = $old_blocks[$module][$delta]->status;
           $block['weight'] = $old_blocks[$module][$delta]->weight;
@@ -151,15 +170,19 @@ function _block_rehash($order_by = array('weight')) {
           $block['custom'] = $old_blocks[$module][$delta]->custom;
           $block['throttle'] = $old_blocks[$module][$delta]->throttle;
         }
+        // Otherwise, use any set values, or else substitute defaults.
         else {
-          $block['status'] = $block['weight'] = $block['region'] = $block['custom'] = 0;
-          $block['pages'] = '';
+          $properties = array ('status' => 0, 'weight' => 0, 'region' => 'left', 'pages' => '', 'custom' => 0);
+          foreach ($properties as $property => $default) {
+            if (!isset ($block[$property])) {
+              $block[$property] = $default;
+            }
+          }
         }
 
         // reinsert blocks into table
-        db_query("INSERT INTO {blocks} (module, delta, status, weight, region, visibility, pages, custom, throttle) VALUES ('%s', '%s', %d, %d, %d, %d, '%s', %d, %d)",
-          $block['module'], $block['delta'], $block['status'], $block['weight'], $block['region'], $block['visibility'], $block['pages'], $block['custom'], $block['throttle']);
-
+        db_query("INSERT INTO {blocks} (module, delta, theme, status, weight, region, visibility, pages, custom, throttle) VALUES ('%s', '%s', '%s', %d, %d, '%s', %d, '%s', %d, %d)",
+          $block['module'], $block['delta'], $theme_key, $block['status'], $block['weight'], $block['region'], $block['visibility'], $block['pages'], $block['custom'], $block['throttle']);
         $blocks[] = $block;
 
         // build array to sort on
@@ -178,17 +201,32 @@ function _block_rehash($order_by = array('weight')) {
  * Prepare the main block administration form.
  */
 function block_admin_display() {
+  global $theme_key, $custom_theme;
+
+  // If non-default theme configuration has been selected, set the custom theme.
+  if (arg(3)) {
+    $custom_theme = arg(3);
+    init_theme();
+  }
+
   $blocks = _block_rehash();
 
-  $header = array(t('Block'), t('Enabled'), t('Weight'), t('Sidebar'));
+  $block_regions = system_region_list($theme_key);
+
+  // Highlight regions on page, to provide visual reference.
+  foreach ($block_regions as $key => $value) {
+    drupal_set_content($key, '<div class="block-region">' . $value . '</div>');
+  }
+
+  $header = array(t('Block'), t('Enabled'), t('Weight'), t('Placement'));
   if (module_exist('throttle')) {
     $header[] = t('Throttle');
   }
   $header[] = array('data' => t('Operations'), 'colspan' => 2);
 
-  $left = array();
-  $right = array();
+  $regions = array();
   $disabled = array();
+
   foreach ($blocks as $block) {
     if ($block['module'] == 'block') {
       $delete = l(t('delete'), 'admin/block/delete/'. $block['delta']);
@@ -198,10 +236,10 @@ function block_admin_display() {
     }
 
     $row = array(array('data' => $block['info'], 'class' => 'block'),
-      form_checkbox(NULL, $block['module'] .']['. $block['delta'] .'][status', 1, $block['status']),
+      form_checkbox(NULL, $block['module'] .']['. $block['delta'] .'][status', 1, $block['status']) . form_hidden($block['module'] .']['. $block['delta'] .'][theme', $theme_key),
       form_weight(NULL, $block['module'] .']['. $block['delta'] .'][weight', $block['weight']),
-      form_radios(NULL, $block['module'] .']['. $block['delta'] .'][region', $block['region'],
-      array(t('left'), t('right'))));
+      form_select(NULL, $block['module'] .']['. $block['delta'] .'][region', isset($block['region']) ? $block['region'] : system_default_region(),
+      $block_regions));
 
     if (module_exist('throttle')) {
       $row[] = form_checkbox(NULL, $block['module'] .']['. $block['delta'] .'][throttle', 1, $block['throttle']);
@@ -209,11 +247,10 @@ function block_admin_display() {
     $row[] = l(t('configure'), 'admin/block/configure/'. $block['module'] .'/'. $block['delta']);
     $row[] = $delete;
     if ($block['status']) {
-      if ($block['region'] == 0) {
-        $left[] = $row;
-      }
-      if ($block['region'] == 1) {
-        $right[] = $row;
+      foreach ($block_regions as $key => $value) {
+        if ($block['region'] == $key) {
+          $regions[$key][] = $row;
+        }
       }
     }
     else if ($block['region'] <= 1) {
@@ -222,13 +259,13 @@ function block_admin_display() {
   }
 
   $rows = array();
-  if (count($left)) {
-    $rows[] = array(array('data' => t('Left sidebar'), 'class' => 'region', 'colspan' => (module_exist('throttle') ? 7 : 6)));
-    $rows = array_merge($rows, $left);
-  }
-  if (count($right)) {
-    $rows[] = array(array('data' => t('Right sidebar'), 'class' => 'region', 'colspan' => (module_exist('throttle') ? 7 : 6)));
-    $rows = array_merge($rows, $right);
+
+  if (count($regions)) {
+    foreach ($regions as $region => $row) {
+      $region_title = t('%region', array ('%region' => ucfirst($block_regions[$region])));
+      $rows[] = array(array('data' => $region_title, 'class' => 'region', 'colspan' => (module_exist('throttle') ? 7 : 6)));
+      $rows = array_merge($rows, $row);
+    }
   }
   if (count($disabled)) {
     $rows[] = array(array('data' => t('Disabled'), 'class' => 'region', 'colspan' => (module_exist('throttle') ? 7 : 6)));
@@ -237,7 +274,7 @@ function block_admin_display() {
   $output = theme('table', $header, $rows, array('id' => 'blocks'));
   $output .= form_submit(t('Save blocks'));
 
-  return form($output, 'post', url('admin/block'));
+  return form($output, 'post', arg(3) ? url('admin/block/list/' . $theme_key) : url('admin/block'));
 }
 
 function block_box_get($bid) {
@@ -412,39 +449,31 @@ function block_user($type, $edit, &$user, $category = NULL) {
   }
 }
 
- /**
-  * Return all blocks in the specied region for the current user. You may
-  * use this function to implement variable block regions.  The default
-  * regions are 'left', 'right' and 'all', where 'all' means both left and
-  * right.
-  *
-  * @param $region
-  *   This is a string which describes in a human readable form which region
-  *   you need.
-  *
-  * @param $regions
-  *   This is an optional array and contains map(s) from the string $region to
-  *   the numerical region value(s) in the blocks table. See default value for
-  *   examples.
-  *
-  * @return
-  *   An array of block objects, indexed with <i>module</i>_<i>delta</i>.
-  *   If you are displaying your blocks in one or two sidebars, you may check
-  *   whether this array is empty to see how many columns are going to be
-  *   displayed.
-  *
-  * @todo
-  *   Add a proper primary key (bid) to the blocks table so we don't have
-  *   to mess around with this <i>module</i>_<i>delta</i> construct.
-  *   Currently, the blocks table has no primary key defined!
-  */
-function block_list($region, $regions = array('left' => 0, 'right' => 1, 'all' => '0, 1')) {
-  global $user;
+/**
+ * Return all blocks in the specified region for the current user.
+ *
+ * @param $region
+ *   The name of a region.
+ *
+ * @return
+ *   An array of block objects, indexed with <i>module</i>_<i>delta</i>.
+ *   If you are displaying your blocks in one or two sidebars, you may check
+ *   whether this array is empty to see how many columns are going to be
+ *   displayed.
+ *
+ * @todo
+ *   Add a proper primary key (bid) to the blocks table so we don't have
+ *   to mess around with this <i>module</i>_<i>delta</i> construct.
+ *   Currently, the blocks table has no primary key defined!
+ */
+function block_list($region) {
+  global $user, $theme_key;
+
   static $blocks = array();
 
   if (!isset($blocks[$region])) {
     $blocks[$region] = array();
-    $result = db_query("SELECT * FROM {blocks} WHERE status = 1 AND region IN (%s) ORDER BY weight, module", $regions[$region]);
+    $result = db_query("SELECT * FROM {blocks} WHERE theme = '%s' AND status = 1 AND region = '%s' ORDER BY weight, module", $theme_key, $region);
     while ($block = db_fetch_array($result)) {
       // Use the user's block visibility setting, if necessary
       if ($block['custom'] != 0) {
diff --git a/modules/system.module b/modules/system.module
index 214fd98fa4d0d845e9063ab511692e8faff07b1d..164732c47d0e98f2741259943cc807877d6af39e 100644
--- a/modules/system.module
+++ b/modules/system.module
@@ -18,7 +18,7 @@ function system_help($section) {
     case 'admin/settings':
       return t('<p>General configuration options for your site. Set up the name of the site, e-mail address used in mail-outs, clean URL options, caching, etc.</p>');
     case 'admin/themes':
-      return t('<p>Select which themes are available to your users and specify the default theme. To configure site-wide display settings, click the "configure" task above. Alternately, to override these settings in a specific theme, click the "configure" link for the corresponding theme.</p>');
+      return t('<p>Select which themes are available to your users and specify the default theme. To configure site-wide display settings, click the "configure" task above. Alternately, to override these settings in a specific theme, click the "configure" link for the corresponding theme.  Note that different themes may have different regions available for rendering content like blocks.  If you want consistency in what your users see, you may wish to enable only one theme.</p>');
     case 'admin/themes/settings':
       return t('<p>These options control the default display settings for your entire site, across all themes. Unless they have been overridden by a specific theme, these settings will be used.</p>');
     case 'admin/themes/settings/'. arg(3):
@@ -328,15 +328,21 @@ function system_theme_data() {
 
     // Add templates to the site listing
     foreach (call_user_func($engine->name . '_templates') as $template) {
-      $template->template = TRUE;
-      $template->name = basename(dirname($template->filename));
-      $template->owner = $engine->filename;
-      $template->prefix = $engine->name;
-      // do not double-insert templates with theme files in their directory
+      // Do not double-insert templates with theme files in their directory,
+      // but do register their engine data.
       if (array_key_exists($template->name, $themes)) {
-        continue;
+        $themes[$template->name]->template = TRUE;
+        $themes[$template->name]->owner = $engine->filename;
+        $themes[$template->name]->prefix = $engine->name;
+      }
+      else {
+        $template->template = TRUE;
+        $template->name = basename(dirname($template->filename));
+        $template->owner = $engine->filename;
+        $template->prefix = $engine->name;
+
+        $themes[$template->name] = $template;
       }
-      $themes[$template->name] = $template;
     }
   }
 
@@ -368,6 +374,57 @@ function system_theme_data() {
   return $themes;
 }
 
+/**
+ * Get a list of available regions from a specified theme.
+ *
+ * @param $theme
+ *   The name of a theme.
+ * @return
+ *   An array of regions in the form $region['name'] = 'description'.
+ */
+function system_region_list($theme) {
+  static $list = array();
+
+  if(!array_key_exists($theme, $list)) {
+
+    $themes = list_themes();
+
+    if (strpos($themes[$theme]->filename, '.css')) {
+      // File is a style, which can't have its own regions; use its theme instead.
+      $theme = basename(dirname($themes[$theme]->description));
+    }
+    if (file_exists($file = dirname($themes[$theme]->filename) .'/' . $themes[$theme]->name . '.theme')) {
+      include_once($file);
+    }
+
+    $regions = function_exists($theme . '_regions') ? call_user_func($theme . '_regions') : array();
+    if (strpos($themes[$theme]->description, '.engine')) {
+      // File is a template; include its engine's regions.
+      include_once($themes[$theme]->description);
+      $theme_engine = basename($themes[$theme]->description, '.engine');
+      $engine_regions = function_exists($theme_engine . '_regions') ? call_user_func($theme_engine . '_regions') : array();
+      $regions = array_merge($engine_regions, $regions);
+    }
+
+    $list[$theme] = $regions;
+  }
+
+  return $list[$theme];
+}
+
+/**
+ * Get the name of the default region for a given theme.
+ *
+ * @param $theme
+ *   The name of a theme.
+ * @return
+ *   A string that is the region name.
+ */
+function system_default_region($theme) {
+  $regions = array_keys(system_region_list($theme));
+  return $regions[0];
+}
+
 /**
  * Returns an array of files objects of the given type from both the
  * site-wide directory (i.e. modules/) and site-specific directory
@@ -506,6 +563,10 @@ function system_listing_save($edit = array()) {
       if (($edit['type'] == 'theme') && ($edit['theme_default'] == $name)) {
         $status = 1;
       }
+      // If status is being set to 1 from 0, initialize block data for this theme if necessary.
+      if (($status == 1) && db_num_rows(db_query("SELECT status FROM {system} WHERE type = '%s' AND name = '%s' AND status = 0", $edit['type'], $name))) {
+        system_initialize_theme_blocks($name);
+      }
 
       db_query("UPDATE {system} SET status = %d, throttle = %d WHERE type = '%s' AND name = '%s'", $status, $edit['throttle'][$name], $edit['type'], $name);
     }
@@ -520,6 +581,31 @@ function system_listing_save($edit = array()) {
     drupal_goto($_GET['q']);
   }
 }
+/**
+ * Assign an initial, default set of blocks for a theme.  This function is called the first
+ * time a new theme is enabled.  The new theme gets a copy of the default theme's blocks,
+ * with the difference that if a particular region isn't available in the new theme, the block
+ * is assigned instead to the new theme's default region.
+ *
+ * @param $theme
+ *   The name of a theme.
+ */
+function system_initialize_theme_blocks($theme) {
+  $default_theme = variable_get('theme_default', 'bluemarine');
+  $regions = system_region_list($theme);
+  // Initialize theme's blocks if none already registered.
+  if (!(db_num_rows(db_query("SELECT module FROM {blocks} WHERE theme = '%s'", $theme)))) {
+    $result = db_query("SELECT * FROM {blocks} WHERE theme = '%s'", $default_theme);
+    while($block = db_fetch_array($result)) {
+      // If the region isn't supported by the theme, assign the block to the theme's default region.
+      if (!array_key_exists($block['region'], $regions)) {
+        $block['region'] = system_default_region($theme);
+      }
+      db_query("INSERT INTO {blocks} (module, delta, theme, status, weight, region, visibility, pages, custom, throttle) VALUES ('%s', '%s', '%s', %d, %d, '%s', %d, '%s', %d, %d)",
+          $block['module'], $block['delta'], $theme, $block['status'], $block['weight'], $block['region'], $block['visibility'], $block['pages'], $block['custom'], $block['throttle']);
+    }
+  }
+}
 
 function system_settings_form($form) {
   $form .= form_submit(t('Save configuration'));
diff --git a/modules/system/system.module b/modules/system/system.module
index 214fd98fa4d0d845e9063ab511692e8faff07b1d..164732c47d0e98f2741259943cc807877d6af39e 100644
--- a/modules/system/system.module
+++ b/modules/system/system.module
@@ -18,7 +18,7 @@ function system_help($section) {
     case 'admin/settings':
       return t('<p>General configuration options for your site. Set up the name of the site, e-mail address used in mail-outs, clean URL options, caching, etc.</p>');
     case 'admin/themes':
-      return t('<p>Select which themes are available to your users and specify the default theme. To configure site-wide display settings, click the "configure" task above. Alternately, to override these settings in a specific theme, click the "configure" link for the corresponding theme.</p>');
+      return t('<p>Select which themes are available to your users and specify the default theme. To configure site-wide display settings, click the "configure" task above. Alternately, to override these settings in a specific theme, click the "configure" link for the corresponding theme.  Note that different themes may have different regions available for rendering content like blocks.  If you want consistency in what your users see, you may wish to enable only one theme.</p>');
     case 'admin/themes/settings':
       return t('<p>These options control the default display settings for your entire site, across all themes. Unless they have been overridden by a specific theme, these settings will be used.</p>');
     case 'admin/themes/settings/'. arg(3):
@@ -328,15 +328,21 @@ function system_theme_data() {
 
     // Add templates to the site listing
     foreach (call_user_func($engine->name . '_templates') as $template) {
-      $template->template = TRUE;
-      $template->name = basename(dirname($template->filename));
-      $template->owner = $engine->filename;
-      $template->prefix = $engine->name;
-      // do not double-insert templates with theme files in their directory
+      // Do not double-insert templates with theme files in their directory,
+      // but do register their engine data.
       if (array_key_exists($template->name, $themes)) {
-        continue;
+        $themes[$template->name]->template = TRUE;
+        $themes[$template->name]->owner = $engine->filename;
+        $themes[$template->name]->prefix = $engine->name;
+      }
+      else {
+        $template->template = TRUE;
+        $template->name = basename(dirname($template->filename));
+        $template->owner = $engine->filename;
+        $template->prefix = $engine->name;
+
+        $themes[$template->name] = $template;
       }
-      $themes[$template->name] = $template;
     }
   }
 
@@ -368,6 +374,57 @@ function system_theme_data() {
   return $themes;
 }
 
+/**
+ * Get a list of available regions from a specified theme.
+ *
+ * @param $theme
+ *   The name of a theme.
+ * @return
+ *   An array of regions in the form $region['name'] = 'description'.
+ */
+function system_region_list($theme) {
+  static $list = array();
+
+  if(!array_key_exists($theme, $list)) {
+
+    $themes = list_themes();
+
+    if (strpos($themes[$theme]->filename, '.css')) {
+      // File is a style, which can't have its own regions; use its theme instead.
+      $theme = basename(dirname($themes[$theme]->description));
+    }
+    if (file_exists($file = dirname($themes[$theme]->filename) .'/' . $themes[$theme]->name . '.theme')) {
+      include_once($file);
+    }
+
+    $regions = function_exists($theme . '_regions') ? call_user_func($theme . '_regions') : array();
+    if (strpos($themes[$theme]->description, '.engine')) {
+      // File is a template; include its engine's regions.
+      include_once($themes[$theme]->description);
+      $theme_engine = basename($themes[$theme]->description, '.engine');
+      $engine_regions = function_exists($theme_engine . '_regions') ? call_user_func($theme_engine . '_regions') : array();
+      $regions = array_merge($engine_regions, $regions);
+    }
+
+    $list[$theme] = $regions;
+  }
+
+  return $list[$theme];
+}
+
+/**
+ * Get the name of the default region for a given theme.
+ *
+ * @param $theme
+ *   The name of a theme.
+ * @return
+ *   A string that is the region name.
+ */
+function system_default_region($theme) {
+  $regions = array_keys(system_region_list($theme));
+  return $regions[0];
+}
+
 /**
  * Returns an array of files objects of the given type from both the
  * site-wide directory (i.e. modules/) and site-specific directory
@@ -506,6 +563,10 @@ function system_listing_save($edit = array()) {
       if (($edit['type'] == 'theme') && ($edit['theme_default'] == $name)) {
         $status = 1;
       }
+      // If status is being set to 1 from 0, initialize block data for this theme if necessary.
+      if (($status == 1) && db_num_rows(db_query("SELECT status FROM {system} WHERE type = '%s' AND name = '%s' AND status = 0", $edit['type'], $name))) {
+        system_initialize_theme_blocks($name);
+      }
 
       db_query("UPDATE {system} SET status = %d, throttle = %d WHERE type = '%s' AND name = '%s'", $status, $edit['throttle'][$name], $edit['type'], $name);
     }
@@ -520,6 +581,31 @@ function system_listing_save($edit = array()) {
     drupal_goto($_GET['q']);
   }
 }
+/**
+ * Assign an initial, default set of blocks for a theme.  This function is called the first
+ * time a new theme is enabled.  The new theme gets a copy of the default theme's blocks,
+ * with the difference that if a particular region isn't available in the new theme, the block
+ * is assigned instead to the new theme's default region.
+ *
+ * @param $theme
+ *   The name of a theme.
+ */
+function system_initialize_theme_blocks($theme) {
+  $default_theme = variable_get('theme_default', 'bluemarine');
+  $regions = system_region_list($theme);
+  // Initialize theme's blocks if none already registered.
+  if (!(db_num_rows(db_query("SELECT module FROM {blocks} WHERE theme = '%s'", $theme)))) {
+    $result = db_query("SELECT * FROM {blocks} WHERE theme = '%s'", $default_theme);
+    while($block = db_fetch_array($result)) {
+      // If the region isn't supported by the theme, assign the block to the theme's default region.
+      if (!array_key_exists($block['region'], $regions)) {
+        $block['region'] = system_default_region($theme);
+      }
+      db_query("INSERT INTO {blocks} (module, delta, theme, status, weight, region, visibility, pages, custom, throttle) VALUES ('%s', '%s', '%s', %d, %d, '%s', %d, '%s', %d, %d)",
+          $block['module'], $block['delta'], $theme, $block['status'], $block['weight'], $block['region'], $block['visibility'], $block['pages'], $block['custom'], $block['throttle']);
+    }
+  }
+}
 
 function system_settings_form($form) {
   $form .= form_submit(t('Save configuration'));
diff --git a/themes/bluemarine/page.tpl.php b/themes/bluemarine/page.tpl.php
index 4cc1600738e27999117f240e07a360a01a735e20..0c634e5d549bf99f2f3c44159663886637f1e5a3 100644
--- a/themes/bluemarine/page.tpl.php
+++ b/themes/bluemarine/page.tpl.php
@@ -30,6 +30,9 @@
       </form><?php } ?>
     </td>
   </tr>
+  <tr>
+    <td colspan="2"><div><?php print $header ?></div></td>
+  </tr>
 </table>
 
 <table border="0" cellpadding="0" cellspacing="0" id="content">
diff --git a/themes/chameleon/chameleon.theme b/themes/chameleon/chameleon.theme
index cc0dce0b286e2d663c6ced1838e2b02c767b3cb2..26d5a0ddc6cbee943fe863a3ba281b326dafdee3 100644
--- a/themes/chameleon/chameleon.theme
+++ b/themes/chameleon/chameleon.theme
@@ -16,6 +16,13 @@ function chameleon_features() {
        'toggle_secondary_links');
 }
 
+function chameleon_regions() {
+  return array(
+       'left' => t('left sidebar'),
+       'right' => t('right sidebar')
+  );
+}
+
 function chameleon_page($content) {
   $language = $GLOBALS['locale'];
 
diff --git a/themes/engines/phptemplate/phptemplate.engine b/themes/engines/phptemplate/phptemplate.engine
index dde0ae2f7811ba74a3d521f9c91b95d6bc0966cf..366420fdd032c5f13a721bccd0f0b6de525ee8d4 100644
--- a/themes/engines/phptemplate/phptemplate.engine
+++ b/themes/engines/phptemplate/phptemplate.engine
@@ -17,6 +17,22 @@ function phptemplate_templates($directory = 'themes') {
   return system_listing('^page\.tpl\.php$', $directory, 'filename');
 }
 
+/**
+ * Declare the available regions implemented by this engine.
+ *
+ * @return
+ *  An array of regions.  The first array element will be used as the default region for themes.
+ */
+function phptemplate_regions() {
+  return array(
+       'left' => t('left sidebar'),
+       'right' => t('right sidebar'),
+       'content' => t('content'),
+       'header' => t('header'),
+       'footer' => t('footer')
+  );
+}
+
 /**
  * Execute a template engine call.
  *
@@ -68,6 +84,7 @@ function _phptemplate_callback($hook, $variables = array(), $file = null) {
  *   A sequential array of variables passed to the theme function.
  */
 function _phptemplate_default_variables($hook, $variables) {
+  global $theme;
   static $count = array();
   $count[$hook] = is_int($count[$hook]) ? $count[$hook] : 1;
   $variables['zebra'] = ($count[$hook] % 2) ? 'odd' : 'even';
@@ -79,7 +96,18 @@ function _phptemplate_default_variables($hook, $variables) {
     $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'))) {
+        $variables[$region] .= theme('blocks', $region);
+      }
+    }
+  }
   // Tell all templates where they are located.
   $variables['directory'] = path_to_theme();
 
@@ -128,7 +156,7 @@ function phptemplate_page($content) {
   $layout = 'none';
   global $sidebar_indicator;
   /**
-   * Sidebar_indicator tells the block counting code to count sidebars seperately.
+   * Sidebar_indicator tells the block counting code to count sidebars separately.
    */
   $sidebar_indicator = 'left';
   $sidebar_left = theme('blocks', 'left');
@@ -158,7 +186,7 @@ function phptemplate_page($content) {
     'breadcrumb'          => theme('breadcrumb', drupal_get_breadcrumb()),
     'closure'             => theme('closure'),
     'content'             => '<!-- begin content -->' . $content . '<!-- end content -->',
-    'footer_message'      => variable_get('site_footer', FALSE),
+    'footer_message'      => variable_get('site_footer', FALSE) . "\n" . theme('blocks', 'footer'),
     'head'                => drupal_get_html_head(),
     'head_title'          => implode(' | ', $head_title),
     'help'                => theme('help'),
diff --git a/themes/pushbutton/page.tpl.php b/themes/pushbutton/page.tpl.php
index dc3c6c9a57f41a1110107a78ee1b19ac76f4f6b3..88a3d2783e28436a0199974c119a0bb9bb096cc9 100644
--- a/themes/pushbutton/page.tpl.php
+++ b/themes/pushbutton/page.tpl.php
@@ -54,7 +54,10 @@
       </form>
       <?php endif; ?>
     </td>
-    </tr>
+  </tr>
+  <tr>
+    <td colspan="2"><div><?php print $header ?></div></td>
+  </tr>
 </table>
 
 <table id="content" border="0" cellpadding="15" cellspacing="0" width="100%">