? .git
Index: includes/plugins.inc
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/views/includes/plugins.inc,v
retrieving revision 1.152.2.9
diff -u -p -r1.152.2.9 plugins.inc
--- includes/plugins.inc	3 Dec 2009 01:47:31 -0000	1.152.2.9
+++ includes/plugins.inc	8 Dec 2009 23:34:50 -0000
@@ -326,6 +326,27 @@ function views_views_plugins() {
         'parent' => 'full',
       ),
     ),
+    'area' => array(
+      'parent' => array(
+        'no ui' => TRUE,
+        'handler' => 'views_plugin_area',
+        'parent' => '',
+        'uses options' => TRUE,
+      ),
+      'none' => array(
+        'title' => t('None'),
+        'help' => t('No text area'),
+        'handler' => 'views_plugin_area_none',
+        'help topic' => 'area-none',
+      ),
+      'text' => array(
+        'title' => t('Markup Textarea'),
+        'help' => t('Basic html textarea'),
+        'handler' => 'views_plugin_area_text',
+        'help topic' => 'area-text',
+        'uses options' => TRUE,
+      ),
+    ),
   );
 }
 
Index: plugins/views_plugin_area.inc
===================================================================
RCS file: plugins/views_plugin_area.inc
diff -N plugins/views_plugin_area.inc
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ plugins/views_plugin_area.inc	8 Dec 2009 23:34:52 -0000
@@ -0,0 +1,72 @@
+<?php
+// $Id: views_plugin_area.inc,v 1.1.2.2 2009/12/03 23:28:53 merlinofchaos Exp $
+
+/**
+ * The base plugin to handle area.
+ *
+ * @ingroup views_area_plugins
+ */
+class views_plugin_area extends views_plugin {
+  var $instance;
+  /**
+   * Initialize the plugin.
+   *
+   * @param $view
+   *   The view object.
+   * @param $display
+   *   The display handler.
+   */
+  function init(&$view, &$display, $options = array()) {
+    $this->view = &$view;
+    $this->display = &$display;
+    $this->instance = $options['instance'];
+
+    $this->unpack_options($this->options, $options);
+  }
+
+  function option_definition() {
+    $options = parent::option_definition();
+    return $options;
+  }
+
+  /**
+   * Provide the default form form for validating options
+   */
+  function options_validate(&$form, &$form_state) { }
+
+  /**
+   * Provide the default form form for submitting options
+   */
+  function options_submit(&$form, &$form_state) { }
+
+  /**
+   * Return a string to display as the clickable title for the
+   * area plugin.
+   */
+  function summary_title() {
+    return t('Unknown');
+  }
+
+  /**
+   * Render the area.
+   *
+   * Called during the view render process, this will render the
+   * area.
+   */
+  function render() { }
+
+  /**
+   * Determine if user can edit or view this area.
+   * 
+   * @param $operation
+   *  'edit' or 'view'
+   * 
+   * @return
+   *   TRUE if user can perform the define $operation.
+   */ 
+  function access($operation) {
+    // Other plugins can override this
+    return TRUE;
+  }
+
+}
Index: plugins/views_plugin_area_none.inc
===================================================================
RCS file: plugins/views_plugin_area_none.inc
diff -N plugins/views_plugin_area_none.inc
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ plugins/views_plugin_area_none.inc	8 Dec 2009 23:34:52 -0000
@@ -0,0 +1,15 @@
+<?php
+// $Id$
+/**
+ * The base plugin to handle area.
+ */
+class views_plugin_area_none extends views_plugin_area {
+
+  function render($empty = FALSE) {
+    return '';
+  }
+
+  function summary_title() {
+    return t('None');
+  }
+}
Index: plugins/views_plugin_area_text.inc
===================================================================
RCS file: plugins/views_plugin_area_text.inc
diff -N plugins/views_plugin_area_text.inc
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ plugins/views_plugin_area_text.inc	8 Dec 2009 23:34:53 -0000
@@ -0,0 +1,100 @@
+<?php
+// $Id$
+
+/**
+ * @file
+ *   Block plugin for textarea content.
+ */
+class views_plugin_area_text extends views_plugin_area {
+
+  function option_definition() {
+    $options = parent::option_definition();
+    $options['content'] = array('default' => '', 'translatable' => TRUE);
+    $options['format'] = array('default' => variable_get('filter_default_format', 1));
+    $options['empty'] = array('default' => 0);
+
+    return $options;
+  }
+
+  function options_form(&$form, &$form_state) {
+    switch ($this->instance) {
+      case 'header':
+        $description = t('Text to display at the top of the view. May contain an explanation or links or whatever you like. Optional. ');
+      break;
+      case 'empty':
+        $description = t('Text to display if the view has no results. Optional. ');
+      break;
+      case 'footer':
+        $description = t('Text to display at the bottom of the view. May contain an explanation or links or whatever you like. Optional. ');          
+        break;
+    }     
+
+    if ($this->instance != 'empty') {
+      $form['empty'] = array(
+        '#type' => 'checkbox',
+        '#title' => t('Display even if view has no result'),
+        '#default_value' => $this->options['empty'],
+      );
+    }
+    
+    $form['content'] = array(
+      '#type' => 'textarea',
+      '#default_value' => $this->options['content'],
+      '#rows' => 6,
+      '#description' => $description,
+    );
+
+    $form['format'] = filter_form($this->options['format']);
+  }
+
+  function options_submit(&$form, &$form_state) {
+    $form_state['values'][$this->instance .'_options']['format'] = $form_state['values']['format'];
+    parent::options_submit($form, $form_state);
+  }
+
+  function render($empty = FALSE) {
+    if ($this->access('view')) {
+      if ($this->instance == 'empty') {
+        if ($empty) {
+          return $this->render_textarea($this->options['content'], $this->options['format']);
+        }
+        else {
+          return '';
+        }
+      }
+      if (!$empty || !empty($this->options['empty'])) {
+        return $this->render_textarea($this->options['content'], $this->options['format']);
+      }
+    }
+    return '';
+  }
+
+  /**
+   * Render a text area, using the proper format.
+   */
+  function render_textarea($value, $format) {
+    static $formats = array();
+
+    // Check to make sure the filter format exists; if not, we don't
+    // display anything.
+    $format = filter_resolve_format($format);
+
+    if (!array_key_exists($format, $formats)) {
+      $formats[$format] = db_result(db_query("SELECT name FROM {filter_formats} WHERE format = %d", $format));
+    }
+
+    if (!$formats[$format]) {
+      return;
+    }
+
+    if ($value) {
+      return check_markup($value, $format, FALSE);
+    }
+  }
+
+  function summary_title() {
+    $formats = filter_formats();
+    return t('Text @format', array('@format' => $formats[$this->options['format']]->name));
+  }
+
+}
Index: plugins/views_plugin_display.inc
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/views/plugins/views_plugin_display.inc,v
retrieving revision 1.20.2.24
diff -u -p -r1.20.2.24 views_plugin_display.inc
--- plugins/views_plugin_display.inc	4 Dec 2009 19:05:18 -0000	1.20.2.24
+++ plugins/views_plugin_display.inc	8 Dec 2009 23:34:58 -0000
@@ -70,6 +70,37 @@ class views_plugin_display extends views
 
       $this->set_option('pager', $pager);
     }
+
+    // Plugable headers, footer and empty texts are
+    // not compatible with previous version of views
+    // This code converts old values into configured plugins instances
+    foreach (array('header', 'footer', 'empty') as $area) {
+      $area_plugin = array(
+        'type' => 'none',
+        'plugin' => 'area',
+        'options' => array(
+          'instance' => $area,
+        ),
+      );
+      $content = $this->get_option($area);
+      if (!empty($content) && !is_array($content)) {
+        $format = $this->get_option($area . '_format');
+        $area_plugin = array(
+          'type' => 'text',
+          'plugin' => 'area',
+          'options' => array(
+            'content' => $content,
+            'format' => !empty($format) ? $format : variable_get('filter_default_format', 1),
+            'instance' => $area,
+          ),
+        );
+        
+        if ($area != 'empty' && $empty = $this->get_option($area . '_empty')) {
+          $area_plugin['options']['empty'] = $empty;
+        }
+        $this->set_option($area, $area_plugin);
+      }
+    }
   }
 
   function destroy() {
@@ -206,9 +237,6 @@ class views_plugin_display extends views
       'access' => array('access'),
       'cache' => array('cache'),
       'title' => array('title'),
-      'header' => array('header', 'header_format', 'header_empty'),
-      'footer' => array('footer', 'footer_format', 'footer_empty'),
-      'empty' => array('empty', 'empty_format'),
       'use_ajax' => array('use_ajax'),
       'items_per_page' => array('items_per_page', 'offset', 'use_pager', 'pager_element'),
       'pager' => array('pager'),
@@ -231,6 +259,12 @@ class views_plugin_display extends views
       'arguments' => array('arguments'),
       'filters' => array('filters'),
     );
+    
+    $areas = array_keys($this->display_areas());
+    foreach ($areas as $area) {
+      $sections[$area] = array($area);
+    }
+
     if ($section) {
       if (!empty($sections[$section])) {
         return $sections[$section];
@@ -272,14 +306,6 @@ class views_plugin_display extends views
           'access' => TRUE,
           'cache' => TRUE,
           'title' => TRUE,
-          'header' => TRUE,
-          'header_format' => TRUE,
-          'header_empty' => TRUE,
-          'footer' => TRUE,
-          'footer_format' => TRUE,
-          'footer_empty' => TRUE,
-          'empty' => TRUE,
-          'empty_format' => TRUE,
 
           'use_ajax' => TRUE,
           'items_per_page' => TRUE,
@@ -313,33 +339,6 @@ class views_plugin_display extends views
         'default' => '',
         'translatable' => TRUE,
       ),
-      'header' => array(
-        'default' => '',
-        'translatable' => TRUE,
-      ),
-      'header_format' => array(
-        'default' => FILTER_FORMAT_DEFAULT,
-      ),
-      'header_empty' => array(
-        'default' => FALSE,
-      ),
-      'footer' => array(
-        'default' => '',
-        'translatable' => TRUE,
-      ),
-      'footer_format' => array(
-        'default' => FILTER_FORMAT_DEFAULT,
-      ),
-      'footer_empty' => array(
-        'default' => FALSE,
-      ),
-      'empty' => array(
-        'default' => '',
-        'translatable' => TRUE,
-      ),
-      'empty_format' => array(
-        'default' => FILTER_FORMAT_DEFAULT,
-      ),
       'use_ajax' => array(
         'default' => FALSE,
         'bool' => TRUE,
@@ -455,6 +454,20 @@ class views_plugin_display extends views
 
     );
 
+    // Plugins with diferent instances includes a 'plugin' value 
+    // since we cannot use the key of the array to get the kind of plugin
+    $areas = array_keys($this->display_areas());
+    foreach ($areas as $area) {
+      $options['defaults']['default'][$area] = TRUE; 
+      $options[$area] = array(
+        'contains' => array(
+          'plugin' => array('default' => 'area', 'export' => 'export_plugin'),
+          'type' => array('default' => 'none', 'export' => 'export_plugin'),
+          'options' => array('default' => array('instance' => $area), 'export' => FALSE),
+         ),
+      );
+    }
+
     if ($this->is_default_display()) {
       unset($options['defaults']);
     }
@@ -563,9 +576,9 @@ class views_plugin_display extends views
   /**
    * Get the display or row plugin, if it exists.
    */
-  function get_plugin($type = 'style', $name = NULL) {
+  function get_plugin($type = 'style', $name = NULL, $instance = NULL) {
     static $cache = array();
-    if (!isset($cache[$type][$name])) {
+    if (!isset($cache[$type][$name]) || $instance) {
       switch ($type) {
         case 'style':
         case 'row':
@@ -577,8 +590,20 @@ class views_plugin_display extends views
 
           break;
         default:
-          $option_name = $type;
-          $options = $this->get_option($type);
+          // Some plugins like area plugins can be used with more than
+          // one instance, i.e. header, footer, empty are different 
+          // instances of the same plugin.
+          // When $instance is provided, we load the options 
+          // for the specified instance
+          if ($instance) {
+            $options = $this->get_option($instance);
+            $type = $options['plugin'];
+            $name = $options['type'];
+            $options['options']['instance'] = $instance;
+          }
+          else {
+            $options = $this->get_option($type);
+          }
           if (!$name) {
             $name = $options['type'];
           }
@@ -596,9 +621,13 @@ class views_plugin_display extends views
       }
 
       $plugin->init($this->view, $this->display, $options);
-      $cache[$type][$name] = $plugin;
+      if (!$instance) {
+        $cache[$type][$name] = $plugin;
+      }
+      else {
+        return $plugin;
+      }
     }
-
     return $cache[$type][$name];
   }
 
@@ -921,32 +950,26 @@ class views_plugin_display extends views
       $options['exposed_form']['links']['exposed_form_options'] = t('Exposed form settings for this exposed form style.');
     }
 
-    foreach (array('header' => t('Header'), 'footer' => t('Footer'), 'empty' => t('Empty text')) as $type => $name) {
-      if (!$this->get_option($type)) {
-        $field = t('None');
-      }
-      else {
-        // A lot of code to get the name of the filter format.
-        $fmt_string = $this->get_option($type . '_format');
-        if (empty($fmt_string)) {
-          $fmt_string = FILTER_FORMAT_DEFAULT;
-        }
-        $format_val = filter_resolve_format($fmt_string);
-        $format = filter_formats($format_val);
-        if ($format) {
-          $field = check_plain($format->name);
-        }
-        else {
-          $field = t('Unknown/missing format');
+    foreach ($this->display_areas() as $type => $name) {
+      $area_plugin = $this->get_plugin('area', NULL, $type);
+      if (!$area_plugin) {
+        // default to the no area plugin.
+        $area_plugin = views_get_plugin('area', 'none');
+      }
+      
+      if ($area_plugin->access('edit')) {
+        $area_str = $area_plugin->summary_title();
+        $options[$type] = array(
+          'category' => 'style',
+          'title' => $name,
+          'value' => $area_str,
+          'desc' => t("Change this display's !name.", array('!name' => strtolower($name))),
+        );
+        
+        if (!empty($area_plugin->definition['uses options'])) {
+          $options[$type]['links'][$type . '_options'] = t('Change settings for this area type.');
         }
       }
-
-      $options[$type] = array(
-        'category' => 'style',
-        'title' => $name,
-        'value' => $field,
-        'desc' => t("Change this display's !name.", array('!name' => strtolower($name))),
-      );
     }
 
     $options['analyze-theme'] = array(
@@ -1132,49 +1155,6 @@ class views_plugin_display extends views
           $plugin->options_form($form['cache_options'], $form_state);
         }
         break;
-      case 'header':
-        $form['#title'] .= t('Header');
-        $form['header_empty'] = array(
-          '#type' => 'checkbox',
-          '#title' => t('Display even if view has no result'),
-          '#default_value' => $this->get_option('header_empty'),
-        );
-        $form['header'] = array(
-          '#type' => 'textarea',
-          '#default_value' => $this->get_option('header'),
-          '#rows' => 6,
-          '#description' => t('Text to display at the top of the view. May contain an explanation or links or whatever you like. Optional.'),
-        );
-
-        $form['header_format'] = filter_form($this->get_option('header_format'), NULL, array('header_format'));
-        break;
-      case 'footer':
-        $form['#title'] .= t('Footer');
-        $form['footer_empty'] = array(
-          '#type' => 'checkbox',
-          '#title' => t('Display even if view has no result'),
-          '#default_value' => $this->get_option('footer_empty'),
-        );
-        $form['footer'] = array(
-          '#type' => 'textarea',
-          '#default_value' => $this->get_option('footer'),
-          '#rows' => 6,
-          '#description' => t('Text to display beneath the view. May contain an explanation or links or whatever you like. Optional.'),
-        );
-
-        $form['footer_format'] = filter_form($this->get_option('footer_format'), NULL, array('footer_format'));
-        break;
-      case 'empty':
-        $form['#title'] .= t('Empty text');
-        $form['empty'] = array(
-          '#type' => 'textarea',
-          '#default_value' => $this->get_option('empty'),
-          '#rows' => 6,
-          '#description' => t('Text to display if the view has no results. Optional.'),
-        );
-
-        $form['empty_format'] = filter_form($this->get_option('empty_format'), NULL, array('empty_format'));
-        break;
       case 'style_plugin':
         $form['#title'] .= t('How should this view be styled');
         $form['#help_topic'] = 'style';
@@ -1553,7 +1533,55 @@ class views_plugin_display extends views
         }
         break;
     }
+    
+    $display_areas = $this->display_areas();
+    if (in_array($form_state['section'], array_keys($display_areas))) {
+      $instance = $form_state['section'];
+      $plugin = $this->get_plugin('area', NULL, $instance);
+      if (!$plugin) {
+        $plugin = views_get_plugin('area', 'none');
+      }
+      if ($plugin->access('edit')) {
+        $form['#title'] .= $display_areas[$instance];
+        $form[$instance] = array(
+          '#prefix' => '<div class="clear-block">',
+          '#suffix' => '</div>',
+          '#tree' => TRUE,
+        );
+        $area = $this->get_option($instance);
+        $form[$instance]['type'] =  array(
+          '#type' => 'radios',
+          '#options' => views_fetch_plugin_names('area'),
+          '#default_value' => $area['type'],
+        );
+
+        $area_plugin = views_fetch_plugin_data('area', $area['type']);
+        if (!empty($area_plugin['uses options'])) {
+          $form['markup'] = array(
+            '#prefix' => '<div class="form-item description">',
+            '#suffix' => '</div>',
+            '#value' => t('You may also adjust the !settings for the currently selected area-plugin by clicking on the icon.', array('!settings' => $this->option_link(t('settings'), $instance . '_options'))),
+          );
+        }
+      }
+    }
+    
+    $display_areas_options = $this->display_areas(TRUE);
+    if (in_array($form_state['section'], array_keys($display_areas_options))) {
+      $instance = str_replace('_options', '', $form_state['section']);
+      $plugin = $this->get_plugin('area', NULL, $instance);
+      if ($plugin->access('edit')) {
+        $form['#title'] .= $display_areas_options[$instance];
+        if ($plugin) {
+          $form['#help_topic'] = $plugin->definition['help topic'];
 
+          $form[$instance . '_options'] = array(
+            '#tree' => TRUE,
+          );
+          $plugin->options_form($form[$instance . '_options'], $form_state);
+        }
+      }
+    }
   }
 
   /**
@@ -1632,6 +1660,13 @@ class views_plugin_display extends views
         }
         break;
     }
+    if (in_array($form_state['section'], array_keys($this->display_areas()))) {
+      $instance = $form_state['section'];
+      $plugin = $this->get_plugin('area', NULL, $instance);
+      if ($plugin) {
+        $plugin->options_validate($form[$instance . '_options'], $form_state);
+      }
+    }
   }
 
   /**
@@ -1751,15 +1786,6 @@ class views_plugin_display extends views
         }
         $this->set_option($section, $form_state['values'][$section]);
         break;
-      case 'header':
-      case 'footer':
-      case 'empty':
-        $this->set_option($section, $form_state['values'][$section]);
-        $this->set_option($section . '_format', $form_state['values'][$section . '_format']);
-        if ($section != 'empty') {
-          $this->set_option($section . '_empty', $form_state['values'][$section . '_empty']);
-        }
-        break;
       case 'exposed_block':
         $this->set_option($section, (bool) $form_state['values'][$section]);
         break;
@@ -1814,6 +1840,39 @@ class views_plugin_display extends views
         }
         break;
     }
+    
+    $display_areas = $this->display_areas();
+    if (in_array($section, array_keys($display_areas))) {
+      $area = $this->get_option($section);
+      if ($area['type'] != $form_state['values'][$section]['type']) {
+        $plugin = views_get_plugin('area', $form_state['values'][$section]['type']);
+        if ($plugin) {
+          $plugin->options['instance'] = $section;
+          $area = array(
+            'type' => $form_state['values'][$section]['type'], 
+            'plugin' => 'area',
+            'options' => $plugin->options
+          );
+
+          $this->set_option($section, $area);
+          if (!empty($plugin->definition['uses options'])) {
+            views_ui_add_form_to_stack('display', $this->view, $this->display->id, array($section . '_options'));
+          }
+        }
+      }
+    }
+    
+    $display_areas_options = $this->display_areas(TRUE);
+    if (in_array($section, array_keys($display_areas_options))) {
+      $instance = str_replace('_options', '', $section); 
+      $plugin = $this->get_plugin('area', NULL, $instance);
+      if ($plugin) {
+        $area = $this->get_option($instance);
+        $plugin->options_submit($form[$instance . '_options'], $form_state);
+        $area['options'] = $form_state['values'][$instance . '_options'];
+        $this->set_option($instance, $area);
+      }
+    }
   }
 
   /**
@@ -1932,52 +1991,6 @@ class views_plugin_display extends views
   }
 
   /**
-   * Render a text area, using the proper format.
-   */
-  function render_textarea($area) {
-    static $formats = array();
-
-    $value = $this->get_option($area);
-    // Check to make sure the filter format exists; if not, we don't
-    // display anything.
-    $format = filter_resolve_format($this->get_option($area . '_format'));
-
-    if (!array_key_exists($format, $formats)) {
-      $formats[$format] = db_result(db_query("SELECT name FROM {filter_formats} WHERE format = %d", $format));
-    }
-
-    if (!$formats[$format]) {
-      return;
-    }
-
-    if ($value) {
-      return check_markup($value, $format, FALSE);
-    }
-  }
-
-  /**
-   * Render the header of the view.
-   */
-  function render_header() {
-    if (!empty($this->view->result) || $this->get_option('header_empty')) {
-      return $this->render_textarea('header');
-    }
-  }
-
-  /**
-   * Render the footer of the view.
-   */
-  function render_footer() {
-    if (!empty($this->view->result) || $this->get_option('footer_empty')) {
-      return $this->render_textarea('footer');
-    }
-  }
-
-  /**
-   * Render the empty text of the view.
-   */
-  function render_empty() { return $this->render_textarea('empty'); }
-  /**
    * If this display creates a block, implement one of these.
    */
   function hook_block($op = 'list', $delta = 0, $edit = array()) { return array(); }
@@ -2155,6 +2168,29 @@ class views_plugin_display extends views
   }
 
   /**
+   * Define areas for this plugin.
+   * 
+   * Other display plugins can override 
+   * this function to provide views with more areas.
+   */
+  function display_areas($area_options = FALSE) {
+    if ($area_options) {
+      return array(
+        'header_options' => t('Header options'),
+        'footer_options' => t('Footer options'), 
+        'empty_options' => t('Empty text options'),
+      );
+    }
+    else {
+      return array(
+        'header' => t('Header'),
+        'footer' => t('Footer'), 
+        'empty' => t('Empty text'),
+      );
+    }
+  }
+  
+  /**
    * Override of export_option()
    *
    * Because displays do not want to export options that are NOT overridden from the
@@ -2256,11 +2292,20 @@ class views_plugin_display extends views
    * to the plugin. For modern plugins, the options are stored in the 'options'
    * array, but for legacy plugins (access and cache) options are stored as
    * siblings to the type.
+   * 
+   * For plugins with multiple instances the plugin type is storage in
+   * $storage['plugin'] since key of the plugin doesn't reflect the kind
+   * of pllugin. 
    */
   function export_plugin($indent, $prefix, $storage, $option, $definition, $parents) {
     $output = '';
     $plugin_type = end($parents);
-    $plugin = $this->get_plugin($plugin_type);
+    if (isset($storage['plugin'])) {
+      $plugin = $this->get_plugin($storage['plugin'], NULL, $plugin_type);
+    }
+    else {
+      $plugin = $this->get_plugin($plugin_type);
+    }
     if ($plugin) {
       // Write which plugin to use.
       $value = $storage[$option];
Index: theme/theme.inc
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/views/theme/theme.inc,v
retrieving revision 1.73.2.16
diff -u -p -r1.73.2.16 theme.inc
--- theme/theme.inc	3 Dec 2009 23:28:53 -0000	1.73.2.16
+++ theme/theme.inc	8 Dec 2009 23:35:00 -0000
@@ -49,27 +49,21 @@ function template_preprocess_views_view(
   $vars['name']       = $view->name;
   $vars['display_id'] = $view->current_display;
 
-  if (!$vars['rows']) {
-    $vars['empty']    = $view->display_handler->render_empty();
-    if (!$view->display_handler->get_option('header_empty')) {
-      $vars['header'] = '';
+  $header = $view->display_handler->get_plugin('area', NULL, 'header');
+  $footer = $view->display_handler->get_plugin('area', NULL, 'footer');
+  
+  $empty = empty($vars['rows']);
+  
+  $areas = array_keys($view->display_handler->display_areas());
+  foreach ($areas as $area) {
+    $plugin_area = $view->display_handler->get_plugin('area', NULL, $area);
+    if (!$plugin_area) {
+      $plugin_area = $view->display_handler->get_plugin('area', 'none');
     }
-    if (!$view->display_handler->get_option('footer_empty')) {
-      $vars['footer'] = '';
-    }
-  }
-  else {
-    $vars['empty']    = '';
-    $header = TRUE;
+    $vars[$area]  = $plugin_area->render($empty);
   }
 
   $vars['exposed']    = !empty($view->exposed_widgets) ? $view->exposed_widgets : '';
-  if (!isset($vars['header'])) {
-    $vars['header']   = $view->display_handler->render_header();
-  }
-  if (!isset($vars['footer'])) {
-    $vars['footer']   = $view->display_handler->render_footer();
-  }
   $vars['more']       = $view->display_handler->render_more_link();
   $vars['feed_icon']  = !empty($view->feed_icon) ? $view->feed_icon : '';
   $vars['pager']      = $view->query->render_pager();
