Index: CHANGELOG.txt
===================================================================
RCS file: /cvs/drupal/drupal/CHANGELOG.txt,v
retrieving revision 1.309
diff -u -p -r1.309 CHANGELOG.txt
--- CHANGELOG.txt	16 May 2009 19:07:02 -0000	1.309
+++ CHANGELOG.txt	21 May 2009 10:53:43 -0000
@@ -115,6 +115,10 @@ Drupal 7.0, xxxx-xx-xx (development vers
     * Site mission is replaced with the highlighted content block region and 
       separate RSS feed description settings.
     * The footer message setting was removed in favor of custom blocks. 
+    * Made the main page content a block which can be moved and ordered
+      with other blocks in the same region.
+    * Blocks can now return structured arrays for later rendering just 
+      like page callbacks.
 - Upgraded the core JavaScript library to jQuery version 1.3.2.
 - Upgraded the jQuery Forms library to 2.21.
 
Index: install.php
===================================================================
RCS file: /cvs/drupal/drupal/install.php,v
retrieving revision 1.168
diff -u -p -r1.168 install.php
--- install.php	12 May 2009 08:37:44 -0000	1.168
+++ install.php	21 May 2009 10:53:44 -0000
@@ -1001,7 +1001,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_add_to_region('left', theme_task_list($tasks, $active));
 }
 
 /**
Index: update.php
===================================================================
RCS file: /cvs/drupal/drupal/update.php,v
retrieving revision 1.283
diff -u -p -r1.283 update.php
--- update.php	16 May 2009 20:25:19 -0000	1.283
+++ update.php	21 May 2009 10:53:44 -0000
@@ -694,7 +694,7 @@ function update_task_list($active = NULL
     'finished' => 'Review log',
   );
 
-  drupal_set_content('left', theme('task_list', $tasks, $active));
+  drupal_add_to_region('left', theme('task_list', $tasks, $active));
 }
 
 /**
Index: includes/common.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/common.inc,v
retrieving revision 1.906
diff -u -p -r1.906 common.inc
--- includes/common.inc	20 May 2009 06:03:06 -0000	1.906
+++ includes/common.inc	21 May 2009 10:53:44 -0000
@@ -56,14 +56,14 @@ define('JS_DEFAULT', 0);
 define('JS_THEME', 100);
 
 /**
- * Set content for a specified region.
+ * Add content to a specified region.
  *
  * @param $region
- *   Page region the content is assigned to.
+ *   Page region the content is added to.
  * @param $data
- *   Content to be set.
+ *   Content to be added.
  */
-function drupal_set_content($region = NULL, $data = NULL) {
+function drupal_add_to_region($region = NULL, $data = NULL) {
   static $content = array();
 
   if (!is_null($region) && !is_null($data)) {
@@ -73,7 +73,7 @@ function drupal_set_content($region = NU
 }
 
 /**
- * Get assigned content.
+ * Get assigned content for a given region.
  *
  * @param $region
  *   A specified region to fetch content for. If NULL, all regions will be
@@ -81,8 +81,8 @@ function drupal_set_content($region = NU
  * @param $delimiter
  *   Content to be inserted between exploded array elements.
  */
-function drupal_get_content($region = NULL, $delimiter = ' ') {
-  $content = drupal_set_content();
+function drupal_get_region($region = NULL, $delimiter = ' ') {
+  $content = drupal_add_to_region();
   if (isset($region)) {
     if (isset($content[$region]) && is_array($content[$region])) {
       return implode($delimiter, $content[$region]);
@@ -372,7 +372,8 @@ function drupal_not_found() {
     $return = t('The requested page could not be found.');
   }
 
-  $page = drupal_get_page($return);
+  drupal_set_content($return);
+  $page = element_info('page');
   // To conserve CPU and bandwidth, omit the blocks.
   $page['#show_blocks'] = FALSE;
 
@@ -3205,24 +3206,25 @@ function drupal_alter($type, &$data) {
 }
 
 /**
- * Retrieve a $page element that is ready for decorating.
+ * Set the main page content value for later use.
  *
- * Used by menu callbacks in order to populate the page with content
- * and behavior (e.g. #show_blocks).
+ * Given the nature of the Drupal page handling, this will be called once with
+ * a string or array. We store that and return it later as the block is being
+ * displayed.
  *
  * @param $content
  *   A string or renderable array representing the body of the page.
  * @return
- *   A $page element that should be decorated and then passed to drupal_render_page().
- *
- * @see drupal_render_page().
+ *   A renderable array representing the body of the page.
  */
-function drupal_get_page($content = NULL) {
-  // Initialize page array with defaults. @see hook_elements() - 'page' element.
-  $page = element_info('page');
-  $page['content'] = is_array($content) ? $content : array('main' => array('#markup' => $content));
-
-  return $page;
+function drupal_set_content($content = NULL) {
+  $content_block = &drupal_static(__FUNCTION__, NULL);
+  if (!empty($content)) {
+    $content_block = (is_array($content) ? $content : array('main' => array('#markup' => $content)));
+  }
+  else {
+    return $content_block;
+  }
 }
 
 /**
@@ -3232,17 +3234,19 @@ function drupal_get_page($content = NULL
  *   A string or array representing the content of a page. The array consists of
  *   the following keys:
  *   - #type: Value is always 'page'. This pushes the theming through page.tpl.php (required).
- *   - content: A renderable array as built by the menu callback (required).
  *   - #show_blocks: A marker which suppresses left/right regions if FALSE (optional).
  *   - #show_messages: Suppress drupal_get_message() items. Used by Batch API (optional).
  *
  * @see hook_page_alter()
- * @see drupal_get_page()
+ * @see element_info('page')
  */
 function drupal_render_page($page) {
-  // Allow menu callbacks to return strings, or bare content arrays.
-  if (is_string($page) || empty($page['content'])) {
-    $page = drupal_get_page($page);
+  // Allow menu callbacks to return strings or arbitrary arrays to render.
+  // If the array returned is not of #type page directly, we need to fill
+  // in the page with defaults.
+  if (is_string($page) || (is_array($page) && (!isset($page['#type']) || ($page['#type'] != 'page')))) {
+    drupal_set_content($page);
+    $page = element_info('page');
   }
   // Modules alter the $page as needed. Blocks are populated into regions like
   // 'left', 'footer', etc.
Index: includes/theme.maintenance.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/theme.maintenance.inc,v
retrieving revision 1.27
diff -u -p -r1.27 theme.maintenance.inc
--- includes/theme.maintenance.inc	17 May 2009 10:42:16 -0000	1.27
+++ includes/theme.maintenance.inc	21 May 2009 10:53:44 -0000
@@ -220,10 +220,10 @@ function template_preprocess_maintenance
   $theme_data = _system_theme_data();
   $regions = $theme_data[$theme]->info['regions'];
 
-  // Get all region content set with drupal_set_content().
+  // Get all region content set with drupal_add_to_region().
   foreach (array_keys($regions) as $region) {
     // Assign region to a region variable.
-    $region_content = drupal_get_content($region);
+    $region_content = drupal_get_region($region);
     isset($variables[$region]) ? $variables[$region] .= $region_content : $variables[$region] = $region_content;
   }
 
Index: modules/block/block.admin.inc
===================================================================
RCS file: /cvs/drupal/drupal/modules/block/block.admin.inc,v
retrieving revision 1.38
diff -u -p -r1.38 block.admin.inc
--- modules/block/block.admin.inc	16 May 2009 15:23:15 -0000	1.38
+++ modules/block/block.admin.inc	21 May 2009 10:53:44 -0000
@@ -85,6 +85,8 @@ function block_admin_display_form(&$form
       );
     }
   }
+  // Do not allow disabling the main system content block.
+  unset($form['system_main']['region']['#options'][BLOCK_REGION_NONE]);
 
   $form['submit'] = array(
     '#type' => 'submit',
Index: modules/block/block.install
===================================================================
RCS file: /cvs/drupal/drupal/modules/block/block.install,v
retrieving revision 1.23
diff -u -p -r1.23 block.install
--- modules/block/block.install	13 May 2009 19:42:14 -0000	1.23
+++ modules/block/block.install	21 May 2009 10:53:44 -0000
@@ -178,6 +178,16 @@ function block_schema() {
  */
 function block_install() {
   drupal_install_schema('block');
+  
+  // Block should go first so that other modules can alter its output 
+  // during hook_page_alter(). Almost everything on the page is a block,
+  // so before block module runs, there will not be much to alter.
+  db_update('system')
+    ->fields(array(
+      'weight' => -5,
+    ))
+    ->condition('name', 'block')
+    ->execute();
 }
 
 /**
@@ -186,3 +196,16 @@ function block_install() {
 function block_uninstall() {
   drupal_uninstall_schema('block');
 }
+
+/**
+ * Set system.weight to a low value for block module.
+ * 
+ * Block should go first so that other modules can alter its output 
+ * during hook_page_alter(). Almost everything on the page is a block,
+ * so before block module runs, there will not be much to alter.
+ */
+function block_update_7000() {
+  $ret = array();
+  $ret[] = update_sql("UPDATE {system} SET weight = -5 WHERE name = 'block'");
+  return $ret;
+}
Index: modules/block/block.js
===================================================================
RCS file: /cvs/drupal/drupal/modules/block/block.js,v
retrieving revision 1.8
diff -u -p -r1.8 block.js
--- modules/block/block.js	27 Apr 2009 20:19:35 -0000	1.8
+++ modules/block/block.js	21 May 2009 10:53:44 -0000
@@ -25,10 +25,18 @@ Drupal.behaviors.blockDrag = {
     // Add a handler so when a row is dropped, update fields dropped into new regions.
     tableDrag.onDrop = function () {
       dragObject = this;
-      if ($(dragObject.rowObject.element).prev('tr').is('.region-message')) {
-        var regionRow = $(dragObject.rowObject.element).prev('tr').get(0);
-        var regionName = regionRow.className.replace(/([^ ]+[ ]+)*region-([^ ]+)-message([ ]+[^ ]+)*/, '$2');
-        var regionField = $('select.block-region-select', dragObject.rowObject.element);
+      var regionRow = $(dragObject.rowObject.element).prev('tr').get(0);
+      var regionName = regionRow.className.replace(/([^ ]+[ ]+)*region-([^ ]+)-message([ ]+[^ ]+)*/, '$2');
+      var regionField = $('select.block-region-select', dragObject.rowObject.element);
+      // Check whether the newly picked region is available for this block.
+      if ($('option[value=' + regionName + ']', regionField).length == 0) {
+        // If not, alert the user and keep the block in its old region setting.
+        alert(Drupal.t('The block cannot be placed in this region.'));
+        // Simulate that there was a selected element change, so the row is put
+        // back to from where the user tried to drag it.
+        regionField.change();
+      }
+      else if ($(dragObject.rowObject.element).prev('tr').is('.region-message')) {
         var weightField = $('select.block-weight', dragObject.rowObject.element);
         var oldRegionName = weightField[0].className.replace(/([^ ]+[ ]+)*block-weight-([^ ]+)([ ]+[^ ]+)*/, '$2');
 
Index: modules/block/block.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/block/block.module,v
retrieving revision 1.332
diff -u -p -r1.332 block.module
--- modules/block/block.module	16 May 2009 15:23:15 -0000	1.332
+++ modules/block/block.module	21 May 2009 10:53:44 -0000
@@ -241,7 +241,7 @@ function block_page_alter($page) {
   // Load all region content assigned via blocks.
   foreach (array_keys($regions) as $region) {
     // Prevent left and right regions from rendering blocks when 'show_blocks' == FALSE.
-    if ($page['#show_blocks'] || ($region != 'left' && $region != 'right')) {
+    if (!empty($page['#show_blocks']) || ($region != 'left' && $region != 'right')) {
       // Assign blocks to region.
       if ($blocks = block_get_blocks_by_region($region)) {
         $page[$region]['blocks'] = $blocks;
@@ -760,6 +760,11 @@ function template_preprocess_block(&$var
   $variables['block_zebra'] = ($block_counter[$variables['block']->region] % 2) ? 'odd' : 'even';
   $variables['block_id'] = $block_counter[$variables['block']->region]++;
 
+  if (is_array($variables['block']->content)) {
+    // Render the block contents if it is not already rendered.
+    $variables['block']->content = drupal_render($variables['block']->content);
+  }
+
   $variables['template_files'][] = 'block-' . $variables['block']->region;
   $variables['template_files'][] = 'block-' . $variables['block']->module;
   $variables['template_files'][] = 'block-' . $variables['block']->module . '-' . $variables['block']->delta;
Index: modules/blog/blog.pages.inc
===================================================================
RCS file: /cvs/drupal/drupal/modules/blog/blog.pages.inc,v
retrieving revision 1.18
diff -u -p -r1.18 blog.pages.inc
--- modules/blog/blog.pages.inc	26 Apr 2009 19:44:38 -0000	1.18
+++ modules/blog/blog.pages.inc	21 May 2009 10:53:44 -0000
@@ -60,7 +60,7 @@ function blog_page_user($account) {
   }
   drupal_add_feed(url('blog/' . $account->uid . '/feed'), t('RSS - !title', array('!title' => $title)));
 
-  return drupal_get_page($build);
+  return $build;
 }
 
 /**
@@ -104,7 +104,7 @@ function blog_page_last() {
   }
   drupal_add_feed(url('blog/feed'), t('RSS - blogs'));
 
-  return drupal_get_page($build);
+  return $build;
 }
 
 /**
Index: modules/node/node.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/node/node.module,v
retrieving revision 1.1050
diff -u -p -r1.1050 node.module
--- modules/node/node.module	20 May 2009 05:39:45 -0000	1.1050
+++ modules/node/node.module	21 May 2009 10:53:44 -0000
@@ -1327,7 +1327,7 @@ function node_show($node, $message = FAL
   node_tag_new($node->nid);
 
   // For markup consistency with other pages, use node_build_multiple() rather than node_build().
-  return drupal_get_page(node_build_multiple(array($node), FALSE));
+  return node_build_multiple(array($node), FALSE);
 }
 
 /**
@@ -2090,7 +2090,7 @@ function node_page_default() {
     );
   }
   drupal_set_title('');
-  return drupal_get_page($build);
+  return $build;
 }
 
 /**
Index: modules/simpletest/tests/common.test
===================================================================
RCS file: /cvs/drupal/drupal/modules/simpletest/tests/common.test,v
retrieving revision 1.38
diff -u -p -r1.38 common.test
--- modules/simpletest/tests/common.test	16 May 2009 13:26:31 -0000	1.38
+++ modules/simpletest/tests/common.test	21 May 2009 10:53:44 -0000
@@ -362,12 +362,12 @@ class DrupalHTTPRequestTestCase extends 
 }
 
 /**
- * Testing drupal_set_content and drupal_get_content.
+ * Testing drupal_add_to_region and drupal_get_region.
  */
 class DrupalSetContentTestCase extends DrupalWebTestCase {
   public static function getInfo() {
     return array(
-      'name' => t('Drupal set/get content'),
+      'name' => t('Drupal set/get regions'),
       'description' => t('Performs tests on setting and retrieiving content from theme regions.'),
       'group' => t('System')
     );
@@ -386,22 +386,22 @@ class DrupalSetContentTestCase extends D
     // Set some random content for each region available.
     foreach ($block_regions as $region) {
       $first_chunk = $this->randomName(32);
-      drupal_set_content($region, $first_chunk);
+      drupal_add_to_region($region, $first_chunk);
       $second_chunk = $this->randomName(32);
-      drupal_set_content($region, $second_chunk);
-      // Store the expected result for a drupal_get_content call for this region.
+      drupal_add_to_region($region, $second_chunk);
+      // Store the expected result for a drupal_get_region call for this region.
       $values[$region] = $first_chunk . $delimiter . $second_chunk;
     }
 
-    // Ensure drupal_get_content returns expected results when fetching all regions.
-    $content = drupal_get_content(NULL, $delimiter);
+    // Ensure drupal_get_region returns expected results when fetching all regions.
+    $content = drupal_get_region(NULL, $delimiter);
     foreach ($content as $region => $region_content) {
       $this->assertEqual($region_content, $values[$region], t('@region region text verified when fetching all regions', array('@region' => $region)));
     }
 
-    // Ensure drupal_get_content returns expected results when fetching a single region.
+    // Ensure drupal_get_region returns expected results when fetching a single region.
     foreach ($block_regions as $region) {
-      $region_content = drupal_get_content($region, $delimiter);
+      $region_content = drupal_get_region($region, $delimiter);
       $this->assertEqual($region_content, $values[$region], t('@region region text verified when fetching single region.', array('@region' => $region)));
     }
   }
Index: modules/system/system.admin.inc
===================================================================
RCS file: /cvs/drupal/drupal/modules/system/system.admin.inc,v
retrieving revision 1.146
diff -u -p -r1.146 system.admin.inc
--- modules/system/system.admin.inc	16 May 2009 20:10:50 -0000	1.146
+++ modules/system/system.admin.inc	21 May 2009 10:53:44 -0000
@@ -179,7 +179,9 @@ function system_themes_form() {
     }
     else {
       // Ensure this theme is compatible with this version of core.
-      if (!isset($theme->info['core']) || $theme->info['core'] != DRUPAL_CORE_COMPATIBILITY) {
+      // Require the 'content' region to make sure the main page 
+      // content has a common place in all themes.
+      if (!isset($theme->info['core']) || ($theme->info['core'] != DRUPAL_CORE_COMPATIBILITY) || (!isset($theme->info['regions']['content']))) {
         $incompatible_core[] = $theme->name;
       }
       if (version_compare(phpversion(), $theme->info['php']) < 0) {
@@ -1882,7 +1884,8 @@ function system_batch_page() {
   elseif (isset($output)) {
     // Force a page without blocks or messages to
     // display a list of collected messages later.
-    $page = drupal_get_page($output);
+    drupal_set_content($output);
+    $page = element_info('page');
     $page['#show_blocks'] = FALSE;
     $page['#show_messages'] = FALSE;
     return $page;
Index: modules/system/system.install
===================================================================
RCS file: /cvs/drupal/drupal/modules/system/system.install,v
retrieving revision 1.327
diff -u -p -r1.327 system.install
--- modules/system/system.install	16 May 2009 20:25:20 -0000	1.327
+++ modules/system/system.install	21 May 2009 10:53:44 -0000
@@ -3347,7 +3347,7 @@ function system_update_7020() {
 }
 
 /**
- * Add help block to the help region, migrate custom variables to blocks.
+ * Add new blocks to new regions, migrate custom variables to blocks.
  */
 function system_update_7021() {
   $ret = array();
@@ -3359,6 +3359,8 @@ function system_update_7021() {
     $themes_with_blocks[] = $theme->name;
     // Add new system generated help block.
     $ret[] = update_sql("INSERT INTO {block} (module, delta, theme, status, weight, region, pages, cache) VALUES ('system', 'help', '" . $theme->name . "', 1, 0, 'help', '', 1)");
+    // Add new system generated main page content block.
+    $ret[] = update_sql("INSERT INTO {block} (module, delta, theme, status, weight, region, pages, cache) VALUES ('system', 'main', '" . $theme->name . "', 1, 0, 'content', '', -1)");
   }
 
   // Migrate contact form information.
Index: modules/system/system.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/system/system.module,v
retrieving revision 1.694
diff -u -p -r1.694 system.module
--- modules/system/system.module	16 May 2009 18:34:23 -0000	1.694
+++ modules/system/system.module	21 May 2009 10:53:45 -0000
@@ -878,6 +878,11 @@ function system_user_timezone(&$edit, &$
  * Implementation of hook_block_list().
  */
 function system_block_list() {
+  $blocks['main'] = array(
+    'info' => t('Main page content'),
+     // Cached elsewhere.
+    'cache' => BLOCK_NO_CACHE,
+  );
   $blocks['powered-by'] = array(
     'info' => t('Powered by Drupal'),
     'weight' => '10',
@@ -946,6 +951,10 @@ function system_block_save($delta = '', 
 function system_block_view($delta = '') {
   $block = array();
   switch ($delta) {
+    case 'main':
+      $block['subject'] = NULL;
+      $block['content'] = drupal_set_content();
+      return $block;
     case 'powered-by':
       $image_path = 'misc/' . variable_get('drupal_badge_color', 'powered-blue') . '-' . variable_get('drupal_badge_size', '80x15') . '.png';
       $block['subject'] = NULL;
Index: modules/taxonomy/taxonomy.pages.inc
===================================================================
RCS file: /cvs/drupal/drupal/modules/taxonomy/taxonomy.pages.inc,v
retrieving revision 1.26
diff -u -p -r1.26 taxonomy.pages.inc
--- modules/taxonomy/taxonomy.pages.inc	26 Apr 2009 19:44:40 -0000	1.26
+++ modules/taxonomy/taxonomy.pages.inc	21 May 2009 10:53:45 -0000
@@ -79,7 +79,7 @@ function taxonomy_term_page($terms, $dep
             );
           }
 
-          return drupal_get_page($build);
+          return $build;
 
         case 'feed':
           $channel['link'] = url('taxonomy/term/' . $str_tids . '/' . $depth, array('absolute' => TRUE));
Index: modules/user/user.pages.inc
===================================================================
RCS file: /cvs/drupal/drupal/modules/user/user.pages.inc,v
retrieving revision 1.35
diff -u -p -r1.35 user.pages.inc
--- modules/user/user.pages.inc	6 May 2009 11:31:44 -0000	1.35
+++ modules/user/user.pages.inc	21 May 2009 10:53:45 -0000
@@ -176,7 +176,7 @@ function user_view($account) {
     '#account' => $account,
   );
 
-  return drupal_get_page($build);
+  return $build;
 }
 
 /**
Index: profiles/default/default.profile
===================================================================
RCS file: /cvs/drupal/drupal/profiles/default/default.profile,v
retrieving revision 1.41
diff -u -p -r1.41 default.profile
--- profiles/default/default.profile	30 Apr 2009 21:44:20 -0000	1.41
+++ profiles/default/default.profile	21 May 2009 10:53:45 -0000
@@ -91,9 +91,19 @@ function default_profile_task_list() {
  */
 function default_profile_tasks(&$task, $url) {
   
-  // Enable 5 standard blocks.
+  // Enable some standard blocks.
   $values = array(
     array(
+      'module' => 'system',
+      'delta' => 'main',
+      'theme' => 'garland',
+      'status' => 1,
+      'weight' => 0,
+      'region' => 'content',
+      'pages' => '',
+      'cache' => -1,
+    ),
+    array(
       'module' => 'user',
       'delta' => 'login',
       'theme' => 'garland',
Index: profiles/expert/expert.profile
===================================================================
RCS file: /cvs/drupal/drupal/profiles/expert/expert.profile,v
retrieving revision 1.7
diff -u -p -r1.7 expert.profile
--- profiles/expert/expert.profile	30 Apr 2009 21:44:20 -0000	1.7
+++ profiles/expert/expert.profile	21 May 2009 10:53:45 -0000
@@ -42,9 +42,20 @@ function expert_profile_task_list() {
  * Perform any final installation tasks for this profile.
  */
 function expert_profile_tasks(&$task, $url) {
-  // Enable 4 standard blocks.
+
+  // Enable some standard blocks.
   $values = array(
     array(
+      'module' => 'system',
+      'delta' => 'main',
+      'theme' => 'garland',
+      'status' => 1,
+      'weight' => 0,
+      'region' => 'content',
+      'pages' => '',
+      'cache' => -1,
+    ),
+    array(
       'module' => 'user',
       'delta' => 'login',
       'theme' => 'garland',
