diff --git a/contrib/current_search/current_search.api.php b/contrib/current_search/current_search.api.php
new file mode 100644
index 0000000..1d117d0
--- /dev/null
+++ b/contrib/current_search/current_search.api.php
@@ -0,0 +1,40 @@
+<?php
+
+/**
+ * @file
+ * Hooks provided by the Current Search Blocks module.
+ */
+
+/**
+ * @addtogroup hooks
+ * @{
+ */
+
+/**
+ * Define all current search item provided by the module.
+ *
+ * Current search items are elements that are added to the current search block
+ * such as a list of active facet items, custom text, etc.
+ *
+ * @return array
+ *   An associative array keyed by unique name of the current search item. Each
+ *   item item is an associative array keyed by "handler" containing:
+ *   - label: The human readable name of the plugin displayed in the admin UI.
+ *   - class: The name of the plugin class.
+ *
+ * @see CurrentSearchItem
+ */
+function hook_current_search_items() {
+  return array(
+    'text' => array(
+      'handler' => array(
+        'label' => t('Custom text'),
+        'class' => 'CurrentSearchItemText',
+      ),
+    ),
+  );
+}
+
+/**
+ * @} End of "addtogroup hooks".
+ */
diff --git a/contrib/current_search/current_search.block.inc b/contrib/current_search/current_search.block.inc
new file mode 100644
index 0000000..ce89346
--- /dev/null
+++ b/contrib/current_search/current_search.block.inc
@@ -0,0 +1,207 @@
+<?php
+
+/**
+ * @file
+ * Block hook implementations and block form alterations.
+ */
+
+/**
+ * Implements hook_form_FORM_ID_alter().
+ *
+ * Adds the searcher visibility settings to the block form.
+ */
+function current_search_form_block_admin_configure_alter(&$form, &$form_state) {
+  if ('current_search' == $form['module']['#value']) {
+
+    $form['visibility']['current_search'] = array(
+      '#type' => 'fieldset',
+      '#title' => t('Search page'),
+      '#collapsible' => TRUE,
+      '#collapsed' => TRUE,
+      '#group' => 'visibility',
+      '#weight' => -5,
+      '#attached' => array(
+        'js' => array(drupal_get_path('module', 'current_search') . '/current_search.js'),
+      ),
+    );
+
+    // Gets the default value for this block.
+    $searcher = db_query("SELECT searcher FROM {block_current_search} WHERE delta = :delta", array(
+      ':delta' => $form['delta']['#value'],
+    ))->fetchCol();
+
+    $form['visibility']['current_search']['searcher'] = array(
+      '#type' => 'radios',
+      '#title' => t('Search page'),
+      '#options' => current_search_get_searcher_options(),
+      '#description' => t('Select the search page this block is active on.'),
+      '#default_value' => ($searcher) ? $searcher : current_search_get_default_searcher(),
+    );
+
+    // Adds submit handler to save the searcher data.
+    $form['#submit'][] = 'current_search_form_block_admin_configure_submit';
+  }
+}
+
+/**
+ * Form submit handler for block configuration form.
+ *
+ * @see current_search_form_block_admin_configure_alter()
+ */
+function current_search_form_block_admin_configure_submit($form, &$form_state) {
+  $values = $form_state['values'];
+  current_search_set_block_searcher($values['delta'], $values['searcher']);
+}
+
+/**
+ * Implements hook_block_info().
+ */
+function current_search_block_info() {
+  $blocks = array();
+
+  // Loads settings for enabled facets.
+  ctools_include('export');
+  foreach (ctools_export_crud_load_all('current_search') as $config) {
+    if (empty($config->disabled)) {
+      $blocks[$config->name] = array(
+        'info' => 'Current search: ' . $config->label,
+        'cache' => DRUPAL_NO_CACHE,
+      );
+    }
+  }
+
+  // Returns available blocks.
+  return $blocks;
+}
+
+/**
+ * Implements hook_block_list_alter().
+ *
+ * Enforces visibility settings.
+ */
+function current_search_block_list_alter(&$blocks) {
+  foreach ($blocks as $bid => $block) {
+    if ('current_search' == $block->module) {
+      if (!current_search_check_visibility($block->delta)) {
+        unset($blocks[$bid]);
+      }
+    }
+  }
+}
+
+/**
+ * Returns the content for a facet based on the delta.
+ */
+function current_search_block_view($delta = '') {
+  // Test block visibility if not already tested. This is necessary when using
+  // modules such as Context that do not invoke hook_block_list_alter().
+  $map = &drupal_static('current_search_delta_map');
+  if (NULL === $map && !current_search_check_visibility($delta)) {
+    return;
+  }
+
+  // Gets searcher from delta map.
+  $searcher = $map[$delta];
+
+  // Makes sure the adapter and configuration can be loaded.
+  $adapter = facetapi_adapter_load($searcher);
+  if ($adapter && ($config = ctools_export_crud_load('current_search', $delta))) {
+    $build = array();
+
+    // Iterates over configs and executes the plugins.
+    foreach ($config->settings as $name => $settings) {
+      if ($class = ctools_plugin_load_class('current_search', 'items', $settings['id'], 'handler')) {
+        $plugin = new $class($name, $settings);
+        if ($return = $plugin->execute($adapter)) {
+          $build[$name] = $return;
+          $build[$name]['#theme_wrappers'][] = 'current_search_item_wrapper';
+          $build[$name]['#current_search_id'] = $settings['id'];
+        }
+      }
+    }
+
+    // Returns the block content.
+    if ($build) {
+      $build['#contextual_links'] = array(
+        'current_search' => array('admin/config/search/current_search/list', array($delta)),
+      );
+      return array(
+        'subject' => t('Current search'),
+        'content' => $build,
+      );
+    }
+  }
+}
+
+/**
+ * Sets the block searcher for a configuration.
+ *
+ * @param $name
+ *   A string containing the machine readable name of the configuration. The
+ *   name also doubles as the block delta.
+ * @param $searcher
+ *   The machine readable name of the searcher.
+ */
+function current_search_set_block_searcher($name, $searcher) {
+  // Deletes current search data.
+  db_delete('block_current_search')
+    ->condition('delta', $name)
+    ->execute();
+
+  // Inserts new data into database.
+  db_insert('block_current_search')
+    ->fields(array('delta', 'searcher'))
+    ->values(array(
+      'delta' => $name,
+      'searcher' => $searcher,
+    ))
+    ->execute();
+}
+
+/**
+ * Checks whether the block should be displayed.
+ *
+ * In cases where modules like Context are being used, hook_block_list_alter()
+ * is not invoked and we get fatal errors. We have to test whether or not the
+ * hook has been invoked and call this function manually otherwise.
+ *
+ * @param $delta
+ *   The block delta.
+ *
+ * @return
+ *   A boolean flagging whether to display this block or not.
+ */
+function current_search_check_visibility($delta) {
+
+  // Caches the delta map, defaults to NULL so we can test whether this function
+  // was called in hook_block_list_alter() or not.
+  $map = &drupal_static('current_search_delta_map');
+  if (NULL === $map) {
+    $map = array();
+    $result = db_query('SELECT delta, searcher FROM {block_current_search}');
+    foreach ($result as $record) {
+      $map[$record->delta] = $record->searcher;
+    }
+  }
+
+  // Apply default if necessary.
+  if (empty($map[$delta])) {
+    $map[$delta] = current_search_get_default_searcher();
+  }
+
+  // Show the block if facets are being processed by the searcher.
+  return facetapi_is_active_searcher($map[$delta]);
+}
+
+/**
+ * Gets the default searcher.
+ *
+ * @return
+ *   The default searcher.
+ *
+ * @todo Figure out a beter default system.
+ */
+function current_search_get_default_searcher() {
+  $options = current_search_get_searcher_options();
+  return key($options);
+}
diff --git a/contrib/current_search/current_search.css b/contrib/current_search/current_search.css
new file mode 100644
index 0000000..4d06920
--- /dev/null
+++ b/contrib/current_search/current_search.css
@@ -0,0 +1,53 @@
+
+.current-search-setting {
+  float: left;
+  display: inline;
+}
+
+.current-search-plugin {
+  margin-right: 2em;
+}
+
+.current-search-label {
+  margin-right: 3em;
+}
+
+.current-search-plugin label, .current-search-label label {
+  display: inline-block;
+}
+
+.current-search-button .form-actions {
+  margin-top: .4em;
+}
+
+a.current-search-remove-link {
+  display: block;
+  padding-top: 1.5em;
+  font-size: 120%;
+}
+
+.current-search-group-title {
+  display: inline;
+  font-weight: bold;
+}
+
+.current-search-item-group .item-list {
+  display: inline-block;
+}
+
+.region-content .current-search-item-group .item-list,
+.region-highlighted .current-search-item-group .item-list,
+.region-help .current-search-item-group .item-list {
+  margin-left: -1.5em;
+}
+
+.form-actions {
+  float: right;
+  margin-top: 0;
+  margin-bottom: 0;
+}
+
+.current-search-description {
+  margin-top: .5em;
+  margin-bottom: 1em;
+}
diff --git a/contrib/current_search/current_search.current_search.inc b/contrib/current_search/current_search.current_search.inc
new file mode 100644
index 0000000..a05182b
--- /dev/null
+++ b/contrib/current_search/current_search.current_search.inc
@@ -0,0 +1,58 @@
+<?php
+
+/**
+ * @file
+ * Current Search default hooks.
+ */
+
+/**
+ * Deletes object and block visibility information from the database.
+ *
+ * @param stdClass $object
+ *   The object being deleted.
+ */
+function current_search_export_crud_delete($object) {
+  db_delete('current_search')
+    ->condition('name', $object->name)
+    ->execute();
+  db_delete('block_current_search')
+    ->condition('delta', $object->name)
+    ->execute();
+}
+
+/**
+ * Implements hook_current_search_default_items().
+ */
+function current_search_current_search_default_items() {
+  $items = array();
+
+  $item = new stdClass;
+  $item->disabled = FALSE;
+  $item->api_version = 1;
+  $item->name = 'standard';
+  $item->label = 'Standard';
+  $item->settings = array(
+    'results' => array(
+      'id' => 'text',
+      'label' => 'Results',
+      'text' => 'Search found [facetapi_results:result-count] items',
+      'wrapper' => 1,
+      'element' => 'h3',
+      'css' => 0,
+      'classes' => '',
+      'weight' => '-50',
+    ),
+    'active_items' => array(
+      'id' => 'active',
+      'label' => 'Active items',
+      'pattern' => '[facetapi_active:active-value]',
+      'keys' => 1,
+      'css' => 0,
+      'classes' => '',
+      'weight' => '-49',
+    ),
+  );
+  $items[$item->name] = $item;
+
+  return $items;
+}
diff --git a/contrib/current_search/current_search.info b/contrib/current_search/current_search.info
new file mode 100644
index 0000000..24405ca
--- /dev/null
+++ b/contrib/current_search/current_search.info
@@ -0,0 +1,10 @@
+name = Current Search Blocks
+description = Provides an interface for creating blocks containing information about the current search.
+dependencies[] = facetapi
+package = Search Toolkit
+core = 7.x
+files[] = plugins/current_search/item.inc
+files[] = plugins/current_search/item_active.inc
+files[] = plugins/current_search/item_group.inc
+files[] = plugins/current_search/item_text.inc
+configure = admin/config/search/current_search
diff --git a/contrib/current_search/current_search.install b/contrib/current_search/current_search.install
new file mode 100644
index 0000000..3805424
--- /dev/null
+++ b/contrib/current_search/current_search.install
@@ -0,0 +1,75 @@
+<?php
+
+/**
+ * @file
+ * Installation functions for the Facet API module.
+ */
+
+/**
+ * Implements hook_schema().
+ */
+function current_search_schema() {
+  $schema = array();
+
+  $schema['current_search'] = array(
+    'description' => 'Current search block configurations.',
+    'export' => array(
+      'key' => 'name',
+      'identifier' => 'item',
+      'default hook' => 'current_search_default_items',
+      'delete callback' => 'current_search_export_crud_delete',
+      'api' => array(
+        'owner' => 'current_search',
+        'api' => 'current_search',
+        'minimum_version' => 1,
+        'current_version' => 1,
+      ),
+    ),
+    'fields' => array(
+      'name' => array(
+        'description' => 'The machine readable name of the configuration.',
+        'type' => 'varchar',
+        'length' => 255,
+        'not null' => TRUE,
+        'default' => '',
+      ),
+      'label' => array(
+        'description' => 'The human readable name of the configuration.',
+        'type' => 'varchar',
+        'length' => 255,
+        'not null' => TRUE,
+        'default' => '',
+      ),
+      'settings' => array(
+        'description' => 'Serialized storage of general settings.',
+        'type' => 'text',
+        'serialize' => TRUE,
+      ),
+    ),
+    'primary key' => array('name'),
+  );
+
+  $schema['block_current_search'] = array(
+    'description' => 'Sets up display criteria for blocks based on searcher',
+    'fields' => array(
+      'delta' => array(
+        'type' => 'varchar',
+        'length' => 32,
+        'not null' => TRUE,
+        'description' => "The block's unique delta within module, from {block}.delta.",
+      ),
+      'searcher' => array(
+        'type' => 'varchar',
+        'length' => 128,
+        'not null' => TRUE,
+        'description' => "The machine-readable name of the searcher.",
+      ),
+    ),
+    'primary key' => array('delta'),
+    'indexes' => array(
+      'searcher' => array('searcher'),
+    ),
+  );
+
+  return $schema;
+}
diff --git a/contrib/current_search/current_search.js b/contrib/current_search/current_search.js
new file mode 100644
index 0000000..cf32f3e
--- /dev/null
+++ b/contrib/current_search/current_search.js
@@ -0,0 +1,22 @@
+(function ($) {
+  
+/**
+ * Provide the summary information for the block settings vertical tabs.
+ */
+Drupal.behaviors.currentSearch = {
+  attach: function (context) {
+    // The drupalSetSummary method required for this behavior is not available
+    // on the Blocks administration page, so we need to make sure this
+    // behavior is processed only if drupalSetSummary is defined.
+    if (typeof jQuery.fn.drupalSetSummary == 'undefined') {
+      return;
+    }
+
+    $('fieldset#edit-current-search', context).drupalSetSummary(function (context) {
+      var $radio = $('input[name="searcher"]:checked', context);
+      return $radio.next('label').text();
+    });
+  }
+};
+
+})(jQuery);
diff --git a/contrib/current_search/current_search.module b/contrib/current_search/current_search.module
new file mode 100644
index 0000000..6ae6f47
--- /dev/null
+++ b/contrib/current_search/current_search.module
@@ -0,0 +1,156 @@
+<?php
+
+/**
+ * @file
+ * Provides an interface for creating blocks containing information about the
+ * current search.
+ */
+
+// Includes the Block hooks and form alterations.
+require_once dirname(__FILE__) . '/current_search.block.inc';
+
+/**
+ * Implements hook_menu_alter().
+ */
+function current_search_menu_alter(&$items) {
+  // Ensures that the edit link shows up in contextual links.
+  $item = &$items['admin/config/search/current_search/list/%ctools_export_ui/edit'];
+  $item['title'] = 'Configure current search items';
+  $item['type'] = MENU_LOCAL_ACTION;
+  $item['context'] = MENU_CONTEXT_INLINE;
+}
+
+/**
+ * Implements hook_theme().
+ */
+function current_search_theme() {
+  return array(
+    'current_search_group_title' => array(
+      'arguments' => array('title' => NULL),
+      'file' => 'current_search.theme.inc',
+    ),
+    'current_search_text' => array(
+      'arguments' => array('text' => NULL, 'wrapper' => NULL, 'element' => NULL, 'css' => NULL, 'class' => array()),
+      'file' => 'current_search.theme.inc',
+    ),
+    'current_search_link_active' => array(
+      'arguments' => array('text' => NULL, 'path' => NULL, 'options' => array()),
+      'file' => 'current_search.theme.inc',
+    ),
+    'current_search_deactivate_widget' => array(
+      'file' => 'current_search.theme.inc',
+    ),
+    'current_search_item_wrapper' => array(
+      'render element'  => 'element',
+      'file' => 'current_search.theme.inc',
+    ),
+    'current_search_group_wrapper' => array(
+      'render element'  => 'element',
+      'file' => 'current_search.theme.inc',
+    ),
+    'current_search_sort_settings_table' => array(
+      'render element' => 'element',
+      'file' => 'plugins/export_ui/current_search_export_ui.class.php',
+    ),
+  );
+}
+
+/**
+ * Implements hook_ctools_plugin_api().
+ */
+function current_search_ctools_plugin_api($owner, $api) {
+  if ('current_search' == $owner && 'current_search' == $api) {
+    return array('version' => 1);
+  }
+}
+
+/**
+ * Implements hook_ctools_plugin_directory().
+ */
+function current_search_ctools_plugin_directory($module, $type) {
+  if ('export_ui' == $type) {
+    return 'plugins/export_ui';
+  }
+}
+
+/**
+ * Implements hook_ctools_plugin_type().
+ */
+function current_search_ctools_plugin_type() {
+  return array(
+    'items' => array(
+      'use hooks' => TRUE,
+    ),
+  );
+}
+
+/**
+ * Returns an array of available current search plugins.
+ *
+ * @return array
+ *   An associative array keyed by plugin ID to human readable label.
+ */
+function current_search_get_plugins() {
+  $plugins = &drupal_static(__FUNCTION__, array());
+  if (!$plugins) {
+    foreach (ctools_get_plugins('current_search', 'items') as $id => $plugin) {
+      $plugins[$id] = $plugin['handler']['label'];
+    }
+  }
+  return $plugins;
+}
+
+/**
+ * Returns an array of searcher options.
+ *
+ * @return
+ *   An array of options.
+ */
+function current_search_get_searcher_options() {
+  $options = array();
+  foreach (facetapi_get_searcher_info() as $name => $info) {
+    $options[$name] = $info['label'];
+  }
+  return $options;
+}
+
+/**
+ * Returns the settings for a current search block configuration.
+ *
+ * @param $name
+ *   The machine readable name of the configuration.
+ *
+ * @return stdClass
+ *   An object containing the configuration, FALSE if not defined.
+ */
+function current_search_item_load($name) {
+  ctools_include('export');
+  $result = ctools_export_crud_load('current_search', $name);
+  return $result ? $result : FALSE;
+}
+
+/**
+ * Implements hook_current_search_items().
+ */
+function current_search_current_search_items() {
+  return array(
+    'text' => array(
+      'handler' => array(
+        'label' => t('Custom text'),
+        'class' => 'CurrentSearchItemText',
+      ),
+    ),
+    'active' => array(
+      'handler' => array(
+        'label' => t('Active items'),
+        'class' => 'CurrentSearchItemActive',
+      ),
+    ),
+    'group' => array(
+      'handler' => array(
+        'label' => t('Field group'),
+        'class' => 'CurrentSearchGroup',
+      ),
+    ),
+  );
+}
diff --git a/contrib/current_search/current_search.theme.inc b/contrib/current_search/current_search.theme.inc
new file mode 100644
index 0000000..9636494
--- /dev/null
+++ b/contrib/current_search/current_search.theme.inc
@@ -0,0 +1,131 @@
+<?php
+
+/**
+ * @file
+ * Theme functions for the Current Search Blocks module.
+ */
+
+/**
+ * Returns HTML for the inactive facet item's count.
+ *
+ * @param $variables
+ *   An associative array containing:
+ *   - text: The text being displayed.
+ *   - wrapper: A boolean flagging whether wrapper markup should be added.
+ *   - element: The HTML element the text is wrapped in.
+ *   - css: A boolean flagging whether a CSS class should be added to the
+ *     wrapper element.
+ *   - class: An array of CSS classes.
+ *   - options: An associative array of options containing:
+ *     - html: Whether or not "text" is rendered HTML, otherwise the string is
+ *       passed through check_plain(). Defaults to FALSE.
+ *
+ * @ingroup themeable
+ */
+function theme_current_search_text(array $variables) {
+  // Initializes output, sanitizes text if necessary.
+  $sanitize = $variables['options']['html'];
+  $output = ($sanitize) ? check_plain($variables['text']) : $variables['text'];
+
+  // Adds wrapper markup and CSS classes.
+  if ($variables['wrapper'] && $variables['element']) {
+    $attributes = array('class' => $variables['class']);
+    $element = check_plain($variables['element']);
+    $output = '<' . $element . drupal_attributes($attributes) . '>' . $output . '</' . $element . '>';
+  }
+
+  return $output;
+}
+
+/**
+ * Returns HTML for the group list title.
+ *
+ * @param $variables
+ *   An associative array containing:
+ *   - title: The title of the group list.
+ *
+ * @ingroup themeable
+ */
+function theme_current_search_group_title(array $variables) {
+  return '<h4 class="current-search-group-title">' . $variables['title'] . '</h4>';
+}
+
+/**
+ * Adds wrapper markup around the current search item.
+ *
+ * @param $variables
+ *   An associative array containing:
+ *   - element: The render array for the current search item.
+ *
+ * @ingroup themeable
+ */
+function theme_current_search_item_wrapper(array $variables) {
+  $element = $variables['element'];
+  $attributes = array(
+    'class' => array(
+      'current-search-item',
+      drupal_html_class('current-search-item-' . $element['#current_search_id']),
+    ),
+  );
+  return '<div' . drupal_attributes($attributes) . '>' . $element['#children'] . '</div>';
+}
+
+/**
+ * Adds wrapper markup around the group.
+ *
+ * @param $variables
+ *   An associative array containing:
+ *   - element: The render array for the current search group.
+ *
+ * @ingroup themeable
+ */
+function theme_current_search_group_wrapper(array $variables) {
+  $element = $variables['element'];
+  $attributes = array('class' => array('current-search-group'));
+  return '<div' . drupal_attributes($attributes) . '>' . $element['#children'] . '</div>';
+}
+
+/**
+ * Returns HTML for a grouped active facet item.
+ *
+ * @param $variables
+ *   An associative array containing the keys 'text', 'path', 'options', and
+ *   'count'.
+ *
+ * @ingroup themeable
+ */
+function theme_current_search_link_active($variables) {
+  // Builds accessible markup.
+  // @see http://drupal.org/node/1316580
+  $accessible_vars = array(
+    'text' => $variables['text'],
+    'active' => TRUE,
+  );
+  $accessible_markup = theme('facetapi_accessible_markup', $accessible_vars);
+
+  // Sanitizes the link text if necessary.
+  $sanitize = empty($variables['options']['html']);
+  $variables['text'] = ($sanitize) ? check_plain($variables['text']) : $variables['text'];
+
+  // Adds the deactivation widget.
+  $variables['text'] .= theme('current_search_deactivate_widget');
+
+  // Resets link text, sets to options to HTML since we already sanitized the
+  // link text and are providing additional markup for accessibility.
+  $variables['text'] .= ' ' . $accessible_markup;
+  $variables['options']['html'] = TRUE;
+  return theme_link($variables);
+}
+
+/**
+ * Returns HTML for the deactivation widget.
+ *
+ * @param $variables
+ *   An associative array containing the keys 'text', 'path', 'options', and
+ *   'count'.
+ *
+ * @ingroup themeable
+ */
+function theme_current_search_deactivate_widget($variables) {
+  return ' [X]';
+}
diff --git a/contrib/current_search/plugins/current_search/item.inc b/contrib/current_search/plugins/current_search/item.inc
new file mode 100644
index 0000000..934f964
--- /dev/null
+++ b/contrib/current_search/plugins/current_search/item.inc
@@ -0,0 +1,216 @@
+<?php
+
+/**
+ * @file
+ * Current search plugin base class.
+ */
+
+/**
+ * Base class for current search item plugins.
+ */
+abstract class CurrentSearchItem {
+
+  /**
+   * The machine readable name of the item this instance is associated with.
+   *
+   * @var string
+   */
+  protected $name;
+
+  /**
+   * An array of facet settings.
+   *
+   * @var array
+   */
+  protected $settings;
+
+  /**
+   * Constructs a CurrentSearchItem object.
+   *
+   * @param string $name
+   *   The machine readable name of the item this instance is associated with.
+   * @param stdClass $settings
+   *   An array containing the settings for the instance of the class.
+   */
+  public function __construct($name, array $settings = array()) {
+    $this->name = $name;
+    $this->settings = $settings + $this->getDefaultSettings();
+  }
+
+  /**
+   * Executes the abstract class behavior.
+   *
+   * @param FacetapiAdapter $adapter
+   *   The adapter object of the current search.
+   *
+   * @return array
+   *   The element's render array.
+   */
+  abstract public function execute(FacetapiAdapter $adapter);
+
+  /**
+   * Allows for backend specific overrides to the settings form.
+   */
+  public function settingsForm(&$form, &$form_state) {
+    // Nothing to do...
+  }
+
+  /**
+   * Returns an array of default settings.
+   */
+  public function getDefaultSettings() {
+    return array();
+  }
+
+  /**
+   * Returns "wrapper HTML" form elements.
+   */
+  public function wrapperForm(&$form, &$form_state) {
+
+    $form['wrapper'] = array(
+      '#type' => 'checkbox',
+      '#title' => t('Customize wrapper HTML'),
+      '#default_value' => $this->settings['wrapper'],
+    );
+
+    $form['element'] = array(
+      '#type' => 'select',
+      '#title' => t('HTML element'),
+      '#default_value' => $this->settings['element'],
+      '#description' => t('Choose the HTML element to wrap around this item, e.g. H1, H2, etc.'),
+      '#states' => array(
+        'visible' => array(
+          ':input[name="plugin_settings[' . $this->name . '][wrapper]"]' => array('checked' => TRUE),
+        ),
+      ),
+      '#options' => array(
+        '0' => t('<None>'),
+        'div' => 'DIV',
+        'span' => 'SPAN',
+        'h1' => 'H1',
+        'h2' => 'H2',
+        'h3' => 'H3',
+        'h4' => 'H4',
+        'h5' => 'H5',
+        'h6' => 'H6',
+        'p' => 'P',
+        'strong' => 'STRONG',
+        'em' => 'EM',
+      ),
+    );
+
+    $form['css'] = array(
+      '#type' => 'checkbox',
+      '#title' => t('Add CSS classes to wrapper element'),
+      '#default_value' => $this->settings['css'],
+      '#states' => array(
+        'visible' => array(
+          ':input[name="plugin_settings[' . $this->name . '][wrapper]"]' => array('checked' => TRUE),
+        ),
+      ),
+    );
+
+    $form['classes'] = array(
+      '#type' => 'textfield',
+      '#title' => t('CSS classes'),
+      '#default_value' => $this->settings['classes'],
+      '#description' => t('A comma separated list of CSS classes. Token replacement patterns are allowed.'),
+      '#maxlength' => 128,
+      '#states' => array(
+        'visible' => array(
+          ':input[name="plugin_settings[' . $this->name . '][wrapper]"]' => array('checked' => TRUE),
+          ':input[name="plugin_settings[' . $this->name . '][css]"]' => array('checked' => TRUE),
+        ),
+      ),
+    );
+  }
+
+  /**
+   * Returns defaults for "wrapper HTML" elements.
+   *
+   * @return array
+   *   An array of default values.
+   */
+  public function wrapperDefaults() {
+    return array(
+      'wrapper' => FALSE,
+      'element' => '0',
+      'css' => FALSE,
+      'classes' => '',
+    );
+  }
+
+  /**
+   * Returns the token tree element.
+   *
+   * @return array
+   *   The token FAPI element.
+   */
+  public function getTokenTree(array $types = array()) {
+    if (module_exists('token')) {
+      return array(
+        '#theme' => 'token_tree',
+        '#token_types' => $types,
+      );
+    }
+    else {
+      return array(
+        '#markup' => '<p>' . t('Install the <a href="http://drupal.org/project/token" target="_blank" title="Token module project page">Token</a> module to view available replacement patterns.') . '</p>'
+      );
+    }
+  }
+
+  /**
+   * Helper function that returns a facet's query string.
+   *
+   * Ensures that all active child values are deactivated along with the parent.
+   *
+   * @param array $item
+   *   The item as returned by FacetapiAdapter::getAllActiveItems().
+   * @param FacetapiAdapter $adapter
+   *   The adapter object of the current search.
+   *
+   * @return array
+   *   An array of the facet value plus all children.
+   */
+  public function getQueryString(array $item, FacetapiAdapter $adapter) {
+    $values = array();
+
+    // Gets all children so they are deactivated as well.
+    foreach ($item['facets'] as $facet_name) {
+      $active_children = $adapter->getProcessor($facet_name)->getActiveChildren($item['value']);
+      $values = array_merge($values, $active_children);
+    }
+
+    // Handle the case of a URL value that matches no actual facet values.
+    // Otherwise, it can't be unclicked.
+    if (!in_array($item['value'], $values)) {
+      $values[] = $item['value'];
+    }
+
+    // Returns the query string for the active facet item.
+    return $adapter->getProcessor($item['facets'][0])->getQueryString($values, 1);
+  }
+}
+
+/**
+ * Parses the classes setting into an array of sanitized classes.
+ *
+ * @param $setting
+ *   The classes setting passed by the user.
+ * @param array $data
+ *   An optional array of data to pass to token_replace().
+ *
+ * @return array
+ *   An array of sanitized classes.
+ */
+function current_search_get_classes($setting, array $data = array()) {
+  $classes = array();
+  foreach (drupal_explode_tags($setting) as $class) {
+    if ($data) {
+      $class = token_replace($class, $data);
+    }
+    $classes[] = drupal_html_class($class);
+  }
+  return $classes;
+}
diff --git a/contrib/current_search/plugins/current_search/item_active.inc b/contrib/current_search/plugins/current_search/item_active.inc
new file mode 100644
index 0000000..f083265
--- /dev/null
+++ b/contrib/current_search/plugins/current_search/item_active.inc
@@ -0,0 +1,111 @@
+<?php
+
+/**
+ * @file
+ * Displays all active items.
+ */
+
+/**
+ * Extension of CurrentSearchItem that displays all active items.
+ */
+class CurrentSearchItemActive extends CurrentSearchItem {
+
+  /**
+   * Implements CurrentSearchItem::execute().
+   */
+  public function execute(FacetapiAdapter $adapter) {
+    $items = array();
+
+    // Makes sure facet builds are initialized.
+    $adapter->processFacets();
+
+    // Adds search keys.
+    if ($this->settings['keys']) {
+      $items[] = check_plain($adapter->getSearchKeys());
+    }
+
+    // Adds active facets to the current search block.
+    foreach ($adapter->getAllActiveItems() as $item) {
+      // Adds adapter to the active item for token replacement.
+      $item['adapter'] = $adapter;
+
+      // Builds variables to pass to theme function.
+      $variables = array(
+        'text' => token_replace($this->settings['pattern'], array('facetapi_active_item' => $item)),
+        'path' => current_path(),
+        'options' => array(
+          'attributes' => array('class' => array()),
+          'html' => TRUE,
+          'query' => $this->getQueryString($item, $adapter),
+        ),
+      );
+
+      // Renders the active link.
+      $items[] = theme('facetapi_link_active', $variables);
+    }
+
+    // If there are items, return the render array.
+    if ($items) {
+      $classes = ($this->settings['css']) ? current_search_get_classes($this->settings['classes']) : array();
+      return array(
+        '#theme' => 'item_list',
+        '#items' => $items,
+        '#attributes' => array('class' => $classes),
+      );
+    }
+  }
+
+  /**
+   * Implements CurrentSearchItem::settingsForm().
+   */
+  public function settingsForm(&$form, &$form_state) {
+
+    $form['pattern'] = array(
+      '#type' => 'textfield',
+      '#title' => t('Pattern'),
+      '#default_value' => $this->settings['pattern'],
+      '#description' => t('The pattern used to render active items in the list. Token replacement patterns are allowed.'),
+      '#maxlength' => 255,
+    );
+
+    $form['keys'] = array(
+      '#type' => 'checkbox',
+      '#title' => t('Append the keywords passed by the user to the list'),
+      '#default_value' => $this->settings['keys'],
+    );
+
+    $form['css'] = array(
+      '#type' => 'checkbox',
+      '#title' => t('Add CSS classes to wrapper element'),
+      '#default_value' => $this->settings['css'],
+    );
+
+    $form['classes'] = array(
+      '#type' => 'textfield',
+      '#title' => t('CSS classes'),
+      '#default_value' => $this->settings['classes'],
+      '#description' => t('A comma separated list of CSS classes.'),
+      '#maxlength' => 128,
+      '#states' => array(
+        'visible' => array(
+          ':input[name="plugin_settings[' . $this->name . '][css]"]' => array('checked' => TRUE),
+        ),
+      ),
+    );
+
+    // Adds token tree.
+    $form['tokens'] = $this->getTokenTree(array('facetapi_active'));
+  }
+
+  /**
+   * Implements CurrentSearchItem::getDefaultSettings().
+   */
+  public function getDefaultSettings() {
+    return array(
+      'pattern' => '[facetapi_active:active-value]',
+      'keys' => FALSE,
+      'css' => FALSE,
+      'classes' => '',
+    );
+  }
+}
diff --git a/contrib/current_search/plugins/current_search/item_group.inc b/contrib/current_search/plugins/current_search/item_group.inc
new file mode 100644
index 0000000..8147877
--- /dev/null
+++ b/contrib/current_search/plugins/current_search/item_group.inc
@@ -0,0 +1,101 @@
+<?php
+
+/**
+ * @file
+ * Displays field groups.
+ */
+
+/**
+ * Extension of CurrentSearchItem that displays field groups.
+ */
+class CurrentSearchGroup extends CurrentSearchItem {
+
+  /**
+   * Implements CurrentSearchItem::execute().
+   */
+  public function execute(FacetapiAdapter $adapter) {
+    $groups = array();
+
+    // Makes sure facet builds are initialized.
+    $adapter->processFacets();
+
+    // Adds other current search module's CSS.
+    $path = drupal_get_path('module', 'current_search');
+    drupal_add_css($path . '/current_search.css');
+
+    // Adds active facets to the current search block.
+    $searcher = $adapter->getSearcher();
+    foreach ($adapter->getAllActiveItems() as $item) {
+      $facet_name = $item['facets'][0];
+      $facet_value = $item['value'];
+      $groups[$facet_name][$facet_value] = $item;
+    }
+
+    // Iterates over groups, builds list.
+    $build = array();
+    foreach ($groups as $facet_name => $group) {
+      $items = array();
+
+      // Builds list items.
+      foreach ($group as $item) {
+        $markup = $adapter->getMappedValue($item['facets'][0], $item['value']);
+        $text = ($markup['#html']) ? $markup['#markup'] : check_plain($markup['#markup']);
+        $variables = array(
+          'text' => $text,
+          'path' => current_path(),
+          'options' => array(
+            'attributes' => array('class' => array()),
+            'html' => TRUE,
+            'query' => $this->getQueryString($item, $adapter),
+          ),
+        );
+        $items[] = theme('current_search_link_active', $variables);
+      }
+
+      // If there are items, add the render array.
+      if ($items) {
+        $build[$facet_name]['#theme_wrappers'] = array('current_search_group_wrapper');
+
+        // Performs token replacemenets and themes the group title.
+        $facet = facetapi_facet_load($facet_name, $searcher);
+        $title = filter_xss(token_replace($this->settings['field_pattern'], array('facetapi_facet' => $facet)));
+        $build[$facet_name]['title']['#markup'] = theme('current_search_group_title', array('title' => $title));
+
+        // Builds the list.
+        $build[$facet_name]['list'] = array(
+          '#theme' => 'item_list',
+          '#items' => $items,
+          '#attributes' => array('class' => array('inline')),
+        );
+      }
+    }
+
+    return $build;
+  }
+
+  /**
+   * Implements CurrentSearchItem::settingsForm().
+   */
+  public function settingsForm(&$form, &$form_state) {
+
+    $form['field_pattern'] = array(
+      '#type' => 'textfield',
+      '#title' => t('Field pattern'),
+      '#default_value' => $this->settings['field_pattern'],
+      '#maxlength' => 255,
+      '#description' => t('The pattern of the field label preceeding the links. Token replacement patterns are allowed.'),
+    );
+
+    // Adds token tree.
+    $form['tokens'] = $this->getTokenTree(array('facetapi_facet'));
+  }
+
+  /**
+   * Implements CurrentSearchItem::getDefaultSettings().
+   */
+  public function getDefaultSettings() {
+    return array(
+      'field_pattern' => '[facetapi_facet:facet-label]:',
+    );
+  }
+}
diff --git a/contrib/current_search/plugins/current_search/item_text.inc b/contrib/current_search/plugins/current_search/item_text.inc
new file mode 100644
index 0000000..b652ee4
--- /dev/null
+++ b/contrib/current_search/plugins/current_search/item_text.inc
@@ -0,0 +1,55 @@
+<?php
+
+/**
+ * @file
+ * Plugin that adds custom text to the current search block.
+ */
+
+/**
+ * Extension of CurrentSearchItem that displays all active items.
+ */
+class CurrentSearchItemText extends CurrentSearchItem {
+
+  /**
+   * Implements CurrentSearchItem::execute().
+   */
+  public function execute(FacetapiAdapter $adapter) {
+    $data = array('facetapi_adapter' => $adapter);
+    $variables = array(
+      'text' => filter_xss(token_replace($this->settings['text'], $data)),
+      'wrapper' => $this->settings['wrapper'],
+      'element' => $this->settings['element'],
+      'css' => $this->settings['css'],
+      'class' => current_search_get_classes($this->settings['classes'], $data),
+      'options' => array('html' => TRUE),
+    );
+    return array('#markup' => theme('current_search_text', $variables));
+  }
+
+  /**
+   * Implements CurrentSearchItem::settingsForm().
+   */
+  public function settingsForm(&$form, &$form_state) {
+
+    $form['text'] = array(
+      '#type' => 'textfield',
+      '#title' => t('Text'),
+      '#default_value' => $this->settings['text'],
+      '#maxlength' => 255,
+      '#description' => t('Custom text displayed in the text box. Token replacement patterns are allowed.'),
+    );
+
+    // Adds HTML wrapper elements.
+    $this->wrapperForm($form, $form_state);
+
+    // Adds token tree.
+    $form['tokens'] = $this->getTokenTree(array('facetapi_results'));
+  }
+
+  /**
+   * Implements CurrentSearchItem::getDefaultSettings().
+   */
+  public function getDefaultSettings() {
+    return array('text' => '') + $this->wrapperDefaults();
+  }
+}
diff --git a/contrib/current_search/plugins/export_ui/current_search_ctools_export_ui.inc b/contrib/current_search/plugins/export_ui/current_search_ctools_export_ui.inc
new file mode 100644
index 0000000..b1bbeb7
--- /dev/null
+++ b/contrib/current_search/plugins/export_ui/current_search_ctools_export_ui.inc
@@ -0,0 +1,31 @@
+<?php
+
+/**
+ * CTools Export UI plugin for current search block configurations.
+ */
+$plugin = array(
+  'schema' => 'current_search',
+  'access' => 'administer search',
+
+  'menu' => array(
+    'menu prefix' => 'admin/config/search',
+    'menu item' => 'current_search',
+    'menu title' => 'Current search blocks',
+    'menu description' => 'Configure current search blocks.',
+  ),
+
+  'title singular' => t('item'),
+  'title plural' => t('items'),
+  'title singular proper' => t('Current search item'),
+  'title plural proper' => t('Current search items'),
+
+  'form' => array(
+    'settings' => 'current_search_settings_form',
+    'submit' => 'current_search_settings_form_submit',
+  ),
+
+  'handler' => array(
+    'class' => 'current_search_export_ui',
+    'parent' => 'ctools_export_ui',
+  ),
+);
diff --git a/contrib/current_search/plugins/export_ui/current_search_export_ui.class.php b/contrib/current_search/plugins/export_ui/current_search_export_ui.class.php
new file mode 100644
index 0000000..70541c4
--- /dev/null
+++ b/contrib/current_search/plugins/export_ui/current_search_export_ui.class.php
@@ -0,0 +1,569 @@
+<?php
+
+/**
+ * @file
+ * Export UI display customizations.
+ */
+
+/**
+ * CTools export UI extending class. Slightly customized for Context.
+ */
+class current_search_export_ui extends ctools_export_ui {
+
+  /**
+   * Implements ctools_export_ui::list_form().
+   *
+   * Simplifies the form similar to how the Context module does it.
+   */
+  function list_form(&$form, &$form_state) {
+    parent::list_form($form, $form_state);
+    $form['top row']['submit'] = $form['bottom row']['submit'];
+    $form['top row']['reset'] = $form['bottom row']['reset'];
+    $form['bottom row']['#access'] = FALSE;
+    return;
+  }
+
+  /**
+   * Implements ctools_export_ui::list_build_row().
+   */
+  function list_build_row($item, &$form_state, $operations) {
+    parent::list_build_row($item, $form_state, $operations);
+  }
+
+  /**
+   * Implements ctools_export_ui::edit_execute_form().
+   *
+   * This is hacky, but since CTools Export UI uses drupal_goto() we have to
+   * effectively change the plugin to modify the redirect path dynamically.
+   */
+  function edit_execute_form(&$form_state) {
+    $output = parent::edit_execute_form($form_state);
+    if (!empty($form_state['executed'])) {
+      $clicked = $form_state['clicked_button']['#value'];
+      if (t('Add item') == $clicked || t('Save and edit') == $clicked) {
+        // We always want to redirect back to this page when adding an item,
+        // but we want to preserve the destination so we can be redirected back
+        // to where we came from after clicking "Save".
+        $options = array();
+        if (!empty($_GET['destination'])) {
+          $options['query']['destination'] = $_GET['destination'];
+          unset($_GET['destination']);
+        }
+
+        // Sets redirect path and options.
+        $op = $form_state['op'];
+        $name = $form_state['values']['name'];
+        $path = ('add' != $op) ? current_path() : 'admin/config/search/current_search/list/' . $name . '/edit';
+        $this->plugin['redirect'][$op] = array($path, $options);
+      }
+    }
+    return $output;
+  }
+
+  /**
+   * Implements ctools_export_ui::edit_page().
+   *
+   * Allows passing of options to drupal_goto() as opposed to just a path.
+   *
+   * @see http://drupal.org/node/1373048
+   */
+  function edit_page($js, $input, $item, $step = NULL) {
+    drupal_set_title($this->get_page_title('edit', $item));
+
+    // Check to see if there is a cached item to get if we're using the wizard.
+    if (!empty($this->plugin['use wizard'])) {
+      $cached = $this->edit_cache_get($item, 'edit');
+      if (!empty($cached)) {
+        $item = $cached;
+      }
+    }
+
+    $form_state = array(
+      'plugin' => $this->plugin,
+      'object' => &$this,
+      'ajax' => $js,
+      'item' => $item,
+      'op' => 'edit',
+      'form type' => 'edit',
+      'rerender' => TRUE,
+      'no_redirect' => TRUE,
+      'step' => $step,
+      // Store these in case additional args are needed.
+      'function args' => func_get_args(),
+    );
+
+    $output = $this->edit_execute_form($form_state);
+    if (!empty($form_state['executed'])) {
+      // @see @see http://drupal.org/node/1373048
+      $export_key = $this->plugin['export']['key'];
+      $args = (array) $this->plugin['redirect']['edit'];
+      $args[0] = str_replace('%ctools_export_ui', $form_state['item']->{$export_key}, $args[0]);
+      call_user_func_array('drupal_goto', $args);
+    }
+
+    return $output;
+  }
+
+   /**
+   * Implements ctools_export_ui::add_page().
+   *
+   * Allows passing of options to drupal_goto() as opposed to just a path.
+   *
+   * @see http://drupal.org/node/1373048
+   */
+  function add_page($js, $input, $step = NULL) {
+    drupal_set_title($this->get_page_title('add'));
+
+    // If a step not set, they are trying to create a new item. If a step
+    // is set, they're in the process of creating an item.
+    if (!empty($this->plugin['use wizard']) && !empty($step)) {
+      $item = $this->edit_cache_get(NULL, 'add');
+    }
+    if (empty($item)) {
+      $item = ctools_export_crud_new($this->plugin['schema']);
+    }
+
+    $form_state = array(
+      'plugin' => $this->plugin,
+      'object' => &$this,
+      'ajax' => $js,
+      'item' => $item,
+      'op' => 'add',
+      'form type' => 'add',
+      'rerender' => TRUE,
+      'no_redirect' => TRUE,
+      'step' => $step,
+      // Store these in case additional args are needed.
+      'function args' => func_get_args(),
+    );
+
+    $output = $this->edit_execute_form($form_state);
+    if (!empty($form_state['executed'])) {
+      // @see @see http://drupal.org/node/1373048
+      $export_key = $this->plugin['export']['key'];
+      $args = (array) $this->plugin['redirect']['add'];
+      $args[0] = str_replace('%ctools_export_ui', $form_state['item']->{$export_key}, $args[0]);
+      call_user_func_array('drupal_goto', $args);
+    }
+
+    return $output;
+  }
+}
+
+/**
+ * Define the preset add/edit form.
+ *
+ * @see current_search_add_item_submit()
+ * @see current_search_settings_form_submit()
+ * @ingroup forms
+ */
+function current_search_settings_form(&$form, &$form_state) {
+  $item = &$form_state['item'];
+  $form['info']['#weight'] = -30;
+
+  // Initializes the items.
+  if (empty($item->settings)) {
+    $item->settings = array();
+  }
+
+  // Handles removing items.
+  // @todo This is the wrong place for this. Find a better solution.
+  if (!empty($_GET['remove']) && is_string($_GET['remove'])) {
+    if (isset($item->settings[$_GET['remove']])) {
+      $label = $item->settings[$_GET['remove']]['label'];
+      drupal_set_message(t('@label has been removed.', array('@label' => $label)));
+      unset($item->settings[$_GET['remove']]);
+      ctools_export_crud_save('current_search', $item);
+    }
+  }
+
+  // NOTE: We need to add the #id in order for the machine_name to work.
+  $form['info']['label'] = array(
+    '#id' => 'edit-label',
+    '#title' => t('Name'),
+    '#type' => 'textfield',
+    '#default_value' => $item->label,
+    '#description' => t('The human-readable name of the current search block configuration.'),
+    '#required' => TRUE,
+    '#maxlength' => 255,
+    '#size' => 30,
+  );
+
+  $form['info']['name'] = array(
+    '#type' => 'machine_name',
+    '#default_value' => $item->name,
+    '#maxlength' => 32,
+    '#machine_name' => array(
+      'exists' => 'current_search_config_exists',
+      'source' => array('info', 'label'),
+    ),
+    '#disabled' => !empty($item->name),
+    '#description' => t('The machine readable name of the current search block configuration. This value can only contain letters, numbers, and underscores.'),
+  );
+
+  $form['info']['searcher'] = array(
+    '#type' => 'select',
+    '#title' => t('Search page'),
+    '#options' => current_search_get_searcher_options(),
+    '#description' => t('The search page this configuration will be active on.'),
+    '#default_value' => current_search_get_default_searcher(),
+    '#access' => empty($item->name),
+  );
+
+  // Hide the standard buttons.
+  $form['buttons']['#access'] = FALSE;
+
+  // Add our custom buttons.
+  $form['actions'] = array(
+    '#type' => 'actions',
+    '#weight' => -100,
+  );
+
+  // Gets destination from query string which is set when the page is navigated
+  // to via a contextual link. Builds messages based on where user came from.
+  if (isset($_GET['destination']) && !url_is_external($_GET['destination'])) {
+    $submit_text = t('Save and go back to search page');
+    $cancel_title = t('Return to the search page without saving configuration changes.');
+    $url = drupal_parse_url($_GET['destination']);
+  }
+  else {
+    $submit_text = t('Save and go back to list');
+    $cancel_title = t('Return to the list without saving configuration changes.');
+    $url = array();
+  }
+
+  $form['actions']['submit'] = array(
+    '#type' => 'submit',
+    '#value' => t('Save and edit'),
+  );
+
+  // Do not show the button if the page was navigated to via a contextual link
+  // because it would redirect the user back to the search page.
+  $form['actions']['submit_list'] = array(
+    '#type' => 'submit',
+    '#value' => $submit_text,
+  );
+
+  $form['actions']['cancel'] = array(
+    '#type' => 'link',
+    '#title' => t('Cancel'),
+    '#href' => (!$url) ? 'admin/config/search/current_search' : $url['path'],
+    '#options' => (!$url) ? array() : array('query' => $url['query']),
+    '#attributes' => array('title' => $cancel_title),
+  );
+
+  if (empty($item->name)) {
+    $description = t('Add a new current search block configuration.');
+  }
+  else {
+    $description = t('Add new items to the current search block or configure existing ones.');
+  }
+  $form['description'] = array(
+    '#prefix' => '<div class="current-search-description">',
+    '#suffix' => '</div>',
+    '#markup' => $description,
+    '#weight' => -90,
+  );
+
+  drupal_add_css(drupal_get_path('module', 'current_search') . '/current_search.css');
+
+  // If we are creating the configuration, only display the basic config items.
+  // Otherwise set the breadcrumb due to possible bug in CTools Export UI.
+  if (empty($form['info']['name']['#default_value'])) {
+    return;
+  }
+
+  // Gets list of plugins, sanitizes label for output.
+  $plugins = array_map('check_plain', current_search_get_plugins());
+
+  ////
+  ////
+  //// Add plugin section
+  ////
+  ////
+
+  $form['plugins_title'] = array(
+    '#type' => 'item',
+    '#title' => t('Add item to block'),
+  );
+
+  $form['plugins'] = array(
+    '#tree' => TRUE,
+    '#prefix' => '<div class="clearfix">',
+    '#suffix' => '</div>',
+  );
+
+  $form['plugins']['plugin'] = array(
+    '#type' => 'select',
+    '#title' => t('Type'),
+    '#options' => $plugins,
+    '#prefix' => '<div class="current-search-setting current-search-plugin">',
+    '#suffix' => '</div>',
+  );
+
+  $form['plugins']['item_label'] = array(
+    '#title' => t('Name'),
+    '#type' => 'textfield',
+    '#default_value' => '',
+    '#required' => FALSE,
+    '#size' => 30,
+    '#prefix' => '<div class="current-search-setting current-search-label">',
+    '#suffix' => '</div>',
+  );
+
+  $form['plugins']['item_name'] = array(
+    '#type' => 'machine_name',
+    '#default_value' => '',
+    '#maxlength' => 32,
+    '#machine_name' => array(
+      'exists' => 'current_search_item_exists',
+      'source' => array('plugins', 'item_label'),
+    ),
+    '#required' => FALSE,
+    '#description' => t('The machine readable name of the item being added to the current search block. This value can only contain letters, numbers, and underscores.'),
+  );
+
+  $form['plugins']['actions'] = array(
+    '#type' => 'actions',
+    '#prefix' => '<div class="current-search-setting current-search-button">',
+    '#suffix' => '</div>',
+  );
+
+  $form['plugins']['actions']['add_item'] = array(
+    '#type' => 'submit',
+    '#value' => t('Add item'),
+    '#submit' => array('current_search_add_item_submit'),
+    '#validate' => array('current_search_add_item_validate'),
+  );
+
+  ////
+  ////
+  //// Sort settings
+  ////
+  ////
+
+  $form['plugin_sort'] = array(
+    '#type' => 'item',
+    '#access' => !empty($item->settings),
+    '#title' => t('Item display order'),
+    '#theme' => 'current_search_sort_settings_table',
+    '#current_search' => $item->settings,
+    '#tree' => TRUE,
+  );
+
+  // Builds checkbox options and weight dropboxes.
+  foreach ($item->settings as $name => $settings) {
+    $form['plugin_sort'][$name]['item'] = array(
+      '#markup' => check_plain($settings['label']),
+    );
+    $form['plugin_sort'][$name]['weight'] = array(
+      '#type' => 'weight',
+      '#title' => t('Weight for @title', array('@title' => $settings['label'])),
+      '#title_display' => 'invisible',
+      '#delta' => 50,
+      '#default_value' => isset($settings['weight']) ? $settings['weight'] : 0,
+      '#attributes' => array('class' => array('current-search-sort-weight')),
+    );
+  }
+
+  ////
+  ////
+  //// Filter settings
+  ////
+  ////
+
+  $form['plugin_settings_title'] = array(
+    '#type' => 'item',
+    '#access' => !empty($item->settings),
+    '#title' => t('Item settings'),
+  );
+
+  $form['plugin_settings'] = array(
+    '#type' => 'vertical_tabs',
+    '#tree' => TRUE,
+  );
+
+  // Builds table, adds settings to vertical tabs.
+  $has_settings = FALSE;
+  foreach ($item->settings as $name => $settings) {
+    if ($class = ctools_plugin_load_class('current_search', 'items', $settings['id'], 'handler')) {
+      $plugin = new $class($name, $settings);
+
+      // Initializes vertical tab for the item's settings.
+      $form['plugin_settings'][$name] = array(
+        '#type' => 'fieldset',
+        '#title' => check_plain($settings['label']),
+        '#group' => 'settings',
+        '#tree' => TRUE,
+      );
+
+      $form['plugin_settings'][$name]['id'] = array(
+        '#type' => 'value',
+        '#value' => $settings['id'],
+      );
+
+      $form['plugin_settings'][$name]['label'] = array(
+        '#type' => 'value',
+        '#value' => $settings['label'],
+      );
+
+      // Gets settings from plugin.
+      $plugin->settingsForm($form['plugin_settings'][$name], $form_state);
+      $has_settings = TRUE;
+
+      $link_options = array('query' => array('remove' => $name));
+      if (!empty($_GET['destination'])) {
+        $link_options['query']['destination'] = $_GET['destination'];
+      }
+
+      // Adds "remove" link.
+      $form['plugin_settings'][$name]['remove'] = array(
+        '#type' => 'link',
+        '#title' => t('Remove item'),
+        '#href' => current_path(),
+        '#attributes' => array('class' => array('current-search-remove-link')),
+        '#options' => $link_options,
+      );
+    }
+  }
+
+  // Removes fieldset if there aren't any settings.
+  if (!$has_settings) {
+    unset($form['plugin_settings']);
+  }
+}
+
+/**
+ * Returns the sort table.
+ *
+ * @param $variables
+ *   An associative array containing:
+ *   - element: A render element representing the form.
+ *
+ * @ingroup themeable
+ */
+function theme_current_search_sort_settings_table($variables) {
+  $output = '';
+
+  // Builds table rows.
+  $rows = array();
+  foreach ($variables['element']['#current_search'] as $name => $settings) {
+    $rows[$name] = array(
+      'class' => array('draggable'),
+      'data' => array(
+        drupal_render($variables['element'][$name]['item']),
+        drupal_render($variables['element'][$name]['weight']),
+      ),
+    );
+  }
+
+  // Builds table with drabble rows, returns output.
+  $table_id = 'current-search-sort-settings';
+  drupal_add_tabledrag($table_id, 'order', 'sibling', 'current-search-sort-weight');
+  $output .= drupal_render_children($variables['element']);
+  $output .= theme('table', array('rows' => $rows, 'attributes' => array('id' => $table_id)));
+  return $output;
+}
+
+/**
+ * Form validation handler for current_search_settings_form().
+ * Processed when the "Add item" button is selected.
+ */
+function current_search_add_item_validate($form, &$form_state) {
+  // NOTE: The form items are only required with the "Add item" button is
+  // submitted, so we cannot use the #required property. Otherwise we could
+  // not click the save or delete buttons without the form failing validation.
+  if (empty($form_state['values']['plugins']['item_name'])) {
+    $vars = array('!name' => 'Item name');
+    form_set_error('item_name', t('!name field is required', $vars));
+  }
+  if (empty($form_state['values']['plugins']['item_label'])) {
+    $vars = array('!name' => 'Machine-readable name');
+    form_set_error('item_label', t('!name field is required', $vars));
+  }
+}
+
+/**
+ * Form submission handler for current_search_settings_form().
+ *
+ * Processed when the "Add item" button is selected.
+ */
+function current_search_add_item_submit($form, &$form_state) {
+  $item = &$form_state['item'];
+  if (empty($item->settings)) {
+    $item->settings = array();
+  }
+
+  // Gets variables for code readability.
+  $id = $form_state['values']['plugins']['plugin'];
+  $name = $form_state['values']['plugins']['item_name'];
+  $label = $form_state['values']['plugins']['item_label'];
+
+  // Adds settings to the array.
+  if ($class = ctools_plugin_load_class('current_search', 'items', $id, 'handler')) {
+    $plugin = new $class($name);
+    $item->settings[$name] = $plugin->getDefaultSettings() + array(
+      'id' => $id,
+      'label' => $label,
+    );
+  }
+}
+
+/**
+ * Form submission handler for current_search_settings_form().
+ */
+function current_search_settings_form_submit($form, &$form_state) {
+  $item = &$form_state['item'];
+  if (empty($item->settings)) {
+    $item->settings = array();
+  }
+
+  // If there are plugin settings, we are updating an existing config.
+  if (!empty($form_state['values']['plugin_settings'])) {
+    $item->label = $form_state['values']['label'];
+    if (!empty($form_state['values']['plugin_settings'])) {
+
+      // Gathers settings, stores in $items->settings.
+      foreach ($form_state['values']['plugin_settings'] as $name => $settings) {
+        if (is_array($settings)) {
+          $item->settings[$name] = $settings + array(
+            'weight' => $form_state['values']['plugin_sort'][$name]['weight'],
+          );
+        }
+      }
+
+      // Sorts settings by weight.
+      uasort($item->settings, 'drupal_sort_weight');
+    }
+  }
+  else {
+    // Saves the block visibility settings if searcher was passed.
+    if (!empty($form_state['values']['searcher'])) {
+      $name = $form_state['values']['name'];
+      $searcher = $form_state['values']['searcher'];
+      current_search_set_block_searcher($name, $searcher);
+    }
+  }
+}
+
+/**
+ * Tests if the configuration name already exists.
+ *
+ * @return
+ *   A boolean flagging whether the item exists.
+ */
+function current_search_config_exists($name) {
+  $configs = ctools_export_crud_load_all('current_search');
+  return isset($configs[$name]);
+}
+
+/**
+ * Tests if the item name already exists.
+ *
+ * @return
+ *   A boolean flagging whether the item exists.
+ */
+function current_search_item_exists($name, &$element, &$form_state) {
+  $item = &$form_state['item'];
+  return isset($item->settings[$name]);
+}
diff --git a/facetapi.block.inc b/facetapi.block.inc
index 2bfedad..dedaed3 100644
--- a/facetapi.block.inc
+++ b/facetapi.block.inc
@@ -6,29 +6,23 @@
  */
 
 /**
- * Returns block information.
+ * Implements hook_block_info().
  */
-function facetapi_get_block_info($realm_name = 'block') {
+function facetapi_block_info() {
   $blocks = array();
 
   // Gets delta map, iterates over all enabled facets.
   $map = facetapi_get_delta_map();
   foreach (facetapi_get_searcher_info() as $searcher => $info) {
+
     // Gets cache settings for the searcher.
     $cache = variable_get('facetapi:block_cache:' . $searcher, DRUPAL_NO_CACHE);
 
-    // Adds "Current Search" blocks.
-    $delta = array_search($searcher . ':current_search', $map);
-    $blocks[$delta] = array(
-      'info' => 'Facet API: ' . $info['label'] . ' : ' . t('Current Search'),
-      'cache' => $cache,
-    );
-
     // Adds blocks for facets that are enabled or whose delta mapping is forced.
-    foreach (facetapi_get_delta_map_queue($searcher, $realm_name) as $facet_name) {
+    foreach (facetapi_get_delta_map_queue($searcher, 'block') as $facet_name) {
       if ($facet = facetapi_facet_load($facet_name, $searcher)) {
         // Gets the delta from the delta map.
-        $string = facetapi_build_delta($searcher, $realm_name, $facet_name);
+        $string = facetapi_build_delta($searcher, 'block', $facet_name);
         $delta = array_search($string, $map);
 
         // Defines the block.
@@ -45,57 +39,35 @@ function facetapi_get_block_info($realm_name = 'block') {
 }
 
 /**
- * Returns the content for a facet based on the delta.
+ * Implements hook_block_list_alter().
+ *
+ * Parses delta information, checks whether to display block.
  */
-function facetapi_get_block($delta) {
-  $builds = &drupal_static(__FUNCTION__, array());
-
-  // Bails if delta is not mapped.
-  $map = facetapi_get_delta_map();
-  if (!isset($map[$delta])) {
-    return;
-  }
-
-  // Extracts the searcher, realm name, and facet name from $delta.
-  // Process the parts from the end in case the searcher includes a ':'.
-  $parts = explode(':', $map[$delta]);
-  $facet_name = array_pop($parts);
-  $facet_name = rawurldecode($facet_name);
-  $realm_name = array_pop($parts);
-  $searcher = implode(':', $parts);
-
-  // If we are viewing the current search block, set variable names accordingly.
-  if (!$searcher && 'current_search' == $facet_name) {
-    $searcher = $realm_name;
-    $realm_name = $facet_name = FALSE;
-  }
-
-  // Bails if adapter can't be loaded.
-  if (!$adapter = facetapi_adapter_load($searcher)) {
-    return;
-  }
-
-  // If there is no realm, we are rendering the curent search block.
-  if (FALSE === $realm_name) {
-    if (!$adapter->searchExecuted()) {
-      return;
+function facetapi_block_list_alter(&$blocks) {
+  foreach ($blocks as $bid => $block) {
+    if ('facetapi' == $block->module) {
+      if (!facetapi_check_block_visibility($block->delta)) {
+        unset($blocks[$bid]);
+      }
     }
-    return array(
-      'subject' => t('Current search'),
-      'content' => $adapter->buildCurrentSearch(),
-    );
   }
+}
 
-  // Bails if the output should be suppressed.
-  if ($adapter->suppressOutput($realm_name)) {
-    return;
-  }
+/**
+ * Implements hook_block_view().
+ */
+function facetapi_block_view($delta = '') {
+  $builds = &drupal_static(__FUNCTION__, array());
+  $parsed = &drupal_static('facetapi_parsed_deltas', array());
 
-  // Bails if the facet isn't enabled.
-  if (!facetapi_facet_enabled($searcher, $realm_name, $facet_name)) {
+  // Test block visibility if not already tested. This is necessary when using
+  // modules such as Context that do not invoke hook_block_list_alter().
+  if (!isset($parsed[$delta]) && !facetapi_check_block_visibility($delta)) {
     return;
   }
 
+  list($searcher, $realm_name, $facet_name) = $parsed[$delta];
+
   // Builds and caches the entire realm per searcher / realm combination.
   $group = $searcher . ':' . $realm_name;
   if (!isset($builds[$group])) {
@@ -120,6 +92,54 @@ function facetapi_get_block($delta) {
 }
 
 /**
+ * Checks whether the block should be displayed.
+ *
+ * In cases where modules like Context are being used, hook_block_list_alter()
+ * is not invoked and we get fatal errors. We have to test whether or not the
+ * hook has been invoked and call this function manually otherwise.
+ *
+ * @param $delta
+ *   The block delta.
+ *
+ * @return
+ *   A boolean flagging whether to display this block or not.
+ */
+function facetapi_check_block_visibility($delta) {
+  $map = facetapi_get_delta_map();
+
+  // Store parsed deltas so we only calculate once. This also lets us know
+  // whether hook_block_list_alter() was called or not.
+  $parsed = &drupal_static('facetapi_parsed_deltas', array());
+
+  // Ensures the delta is mapped.
+  if (!isset($map[$delta])) {
+    $parsed[$delta] = FALSE;
+    return FALSE;
+  }
+
+  // Parses the raw delta, extracts variables for code readability.
+  $parsed[$delta] = facetapi_parse_delta($map[$delta]);
+  list($searcher, $realm_name, $facet_name) = $parsed[$delta];
+
+  // Checks whether block should be displayed.
+  if (!facetapi_is_active_searcher($searcher)) {
+    return FALSE;
+  }
+  if (!facetapi_facet_enabled($searcher, $realm_name, $facet_name)) {
+    return FALSE;
+  }
+  if (!$adapter = facetapi_adapter_load($searcher)) {
+    return FALSE;
+  }
+  if ($adapter->suppressOutput($realm_name)) {
+    return FALSE;
+  }
+
+  // We have facets!
+  return TRUE;
+}
+
+/**
  * Returns a cached delta map of hashes to names.
  *
  * Sometimes our deltas are longer than 32 chars and need to be passed to hash().
@@ -137,21 +157,13 @@ function facetapi_get_delta_map() {
       $map = $data->data;
     }
     else {
-
       $map = array();
-      foreach (facetapi_get_searcher_info() as $searcher => $info) {
 
-        // Maps current search block.
-        $delta = $searcher . ':current_search';
-        $map[facetapi_hash_delta($delta)] = $delta;
-
-        // Maps facet deltas.
-        // @todo - some other way to define realms that are block-like.
-        foreach (array('block') as $realm_name) {
-          foreach (facetapi_get_delta_map_queue($searcher, $realm_name) as $facet_name) {
-            $delta = facetapi_build_delta($searcher, $realm_name, $facet_name);
-            $map[facetapi_hash_delta($delta)] = $delta;
-          }
+      // Maps facet deltas.
+      foreach (facetapi_get_searcher_info() as $searcher => $info) {
+        foreach (facetapi_get_delta_map_queue($searcher, 'block') as $facet_name) {
+          $delta = facetapi_build_delta($searcher, 'block', $facet_name);
+          $map[facetapi_hash_delta($delta)] = $delta;
         }
       }
 
@@ -181,6 +193,29 @@ function facetapi_build_delta($searcher, $realm_name, $facet_name) {
 }
 
 /**
+ * Parses a raw delta into parts.
+ *
+ * @param $raw_delta
+ *   A string containing the raw delta prior to being hashed.
+ *
+ * @return
+ *   An array containing the searcher, realm_name, and facet name in that order.
+ */
+function facetapi_parse_delta($raw_delta) {
+  $parsed = array();
+
+  // Splits by ":", finds each part.
+  $parts = explode(':', $raw_delta);
+  $facet_name = array_pop($parts);
+  $facet_name = rawurldecode($facet_name);
+  $realm_name = array_pop($parts);
+  $searcher = implode(':', $parts);
+
+  // Returns array with parsed info.
+  return array($searcher, $realm_name, $facet_name);
+}
+
+/**
  * Hashing code for deltas.
  *
  * @param $delta
diff --git a/facetapi.module b/facetapi.module
index 441de41..e8d19b0 100644
--- a/facetapi.module
+++ b/facetapi.module
@@ -65,6 +65,9 @@ define('FACETAPI_REGEX_DATE', '/^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})
  */
 define('FACETAPI_REGEX_DATE_RANGE', '/^\[(' . trim(FACETAPI_REGEX_DATE, '/^$') . ') TO (' . trim(FACETAPI_REGEX_DATE, '/^$') . ')\]$/');
 
+// Calls block specific hooks and overrides.
+require_once dirname(__FILE__) . '/facetapi.block.inc';
+
 /**
  * Implements hook_menu().
  */
@@ -78,6 +81,7 @@ function facetapi_menu() {
       continue;
     }
 
+    // Builds realm settings.
     $first = TRUE;
     foreach (facetapi_get_realm_info() as $realm_name => $realm) {
       if ($first) {
@@ -235,22 +239,6 @@ function facetapi_theme() {
 }
 
 /**
- * Implements hook_block_info().
- */
-function facetapi_block_info() {
-  module_load_include('inc', 'facetapi', 'facetapi.block');
-  return facetapi_get_block_info();
-}
-
-/**
- * Implements hook_block_view().
- */
-function facetapi_block_view($delta = '') {
-  module_load_include('inc', 'facetapi', 'facetapi.block');
-  return facetapi_get_block($delta);
-}
-
-/**
  * Custom access callback. Checks if the user has either the "administer search"
  * OR "administer facets" permissions.
  *
@@ -495,6 +483,21 @@ function facetapi_get_searcher_info() {
 }
 
 /**
+ * Returns a list of active searchers.
+ *
+ * An active searcher means that facet data is parsed and processed by the
+ * backend. Any searcher's adapter who's FacetapiAdapter::addActiveFilters() was
+ * called is automatically added to this list.
+ *
+ * @return array
+ *   An associative array of active adapters
+ */
+function facetapi_get_active_searchers() {
+  $searchers = &drupal_static('facetapi_active_searchers', array());
+  return $searchers;
+}
+
+/**
  * Returns all defined realm definitions.
  *
  * @return array
@@ -987,6 +990,33 @@ function facetapi_facetapi_url_processors() {
 ////
 
 /**
+ * Tests whether a searcher is active or not.
+ *
+ * @param $searcher
+ *   The machine readable name of the searcher.
+ *
+ * @return FacetapiAdapter
+ *   The adapter object, FALSE if the object can't be loaded.
+ */
+function facetapi_is_active_searcher($searcher) {
+  $searchers = facetapi_get_active_searchers();
+  return (isset($searchers[$searcher]));
+}
+
+/**
+ * Adds an active searcher to the list.
+ *
+ * @param $searcher
+ *   The machine readable name of the searcher.
+ *
+ * @see facetapi_get_active_searchers();
+ */
+function facetapi_add_active_searcher($searcher) {
+  $searchers = &drupal_static('facetapi_active_searchers', array());
+  $searchers[$searcher] = $searcher;
+}
+
+/**
  * Tests whether a single facet is enabled in a given realm.
  *
  * @param $searcher
diff --git a/facetapi.tokens.inc b/facetapi.tokens.inc
new file mode 100644
index 0000000..27e3b80
--- /dev/null
+++ b/facetapi.tokens.inc
@@ -0,0 +1,221 @@
+<?php
+
+/**
+ * @file
+ * Builds placeholder replacement tokens for searches.
+ */
+
+/**
+ * Implements hook_token_info().
+ */
+function facetapi_token_info() {
+  $types = $results = $active = $facet = array();
+
+  // The types of tokens.
+  $types['facetapi_results'] = array(
+    'name' => t('Search results'),
+    'description' => t('Tokens related to the search query and response.'),
+    'needs-data' => 'facetapi_adapter',
+  );
+
+  $types['facetapi_active'] = array(
+    'name' => t('Active facet items'),
+    'description' => t('Tokens related to active facet items.'),
+    'needs-data' => 'facetapi_active_item',
+  );
+
+  $types['facetapi_facet'] = array(
+    'name' => t('Facet field'),
+    'description' => t('Tokens related to a facet field.'),
+    'needs-data' => 'facetapi_facet',
+  );
+
+  // Tokens related to search results and response.
+  $results['keys'] = array(
+    'name' => t('Search keywords'),
+    'description' => t('The search keywords entered by the user.'),
+  );
+
+  $results['page-number'] = array(
+    'name' => t('Page number'),
+    'description' => t('The page number of the result set.'),
+  );
+
+  $results['page-limit'] = array(
+    'name' => t('Page limit'),
+    'description' => t('The number of results displayed per page.'),
+  );
+
+  $results['page-total'] = array(
+    'name' => t('Page total'),
+    'description' => t('The total number of pages in the result set.'),
+  );
+
+  $results['offset'] = array(
+    'name' => t('Offset'),
+    'description' => t('The zero-based offset of the first element on the search page.'),
+  );
+
+  $results['start-count'] = array(
+    'name' => t('Start count'),
+    'description' => t('The number of the first item on the page.'),
+  );
+
+  $results['end-count'] = array(
+    'name' => t('End count'),
+    'description' => t('The number of the last item on the page.'),
+  );
+
+  $results['result-count'] = array(
+    'name' => t('Result count'),
+    'description' => t('The total number of results matched by the search query.'),
+  );
+
+  // Tokens related to active facet items.
+  $active['active-value'] = array(
+    'name' => t('Mapped value'),
+    'description' => t('The mapped value of the active item.'),
+  );
+
+  $active['active-value-raw'] = array(
+    'name' => t('Raw value'),
+    'description' => t('The raw value of the active item as stored in the index.'),
+  );
+
+  $active['active-pos'] = array(
+    'name' => t('Position'),
+    'description' => t('The zero-based position of the active item.'),
+  );
+
+  $active['facet-label'] = array(
+    'name' => t('Facet label'),
+    'description' => t('The human readable label of the active item\'s facet.'),
+  );
+
+  $active['facet-name'] = array(
+    'name' => t('Facet name'),
+    'description' => t('The machine readable name of the active item\'s facet.'),
+  );
+
+  // Tokens related to a facet.
+  $facet['facet-label'] = array(
+    'name' => t('Facet label'),
+    'description' => t('The human readable label of the active item\'s facet.'),
+  );
+
+  $facet['facet-name'] = array(
+    'name' => t('Facet name'),
+    'description' => t('The machine readable name of the active item\'s facet.'),
+  );
+
+  return array(
+    'types' => $types,
+    'tokens' => array(
+      'facetapi_results' => $results,
+      'facetapi_active' => $active,
+      'facetapi_facet' => $facet,
+    ),
+  );
+}
+
+/**
+ * Implements hook_tokens().
+ */
+function facetapi_tokens($type, $tokens, array $data = array(), array $options = array()) {
+  $replacements = array();
+
+  if ('facetapi_results' == $type && !empty($data['facetapi_adapter'])) {
+
+    $adapter = $data['facetapi_adapter'];
+    foreach ($tokens as $name => $original) {
+      switch ($name) {
+
+        case 'keys':
+          $replacements[$original] = check_plain($adapter->getSearchKeys());
+          break;
+
+        case 'result-count':
+          $replacements[$original] = (int) $adapter->getResultCount();
+          break;
+
+        case 'page-number':
+          $replacements[$original] = (int) $adapter->getPageNumber();
+          break;
+
+        case 'page-limit':
+          $replacements[$original] = (int) $adapter->getPageLimit();
+          break;
+
+        case 'page-total':
+          $replacements[$original] = (int) $adapter->getPageTotal();
+          break;
+
+        case 'offset':
+          $offset = ($adapter->getPageNumber() - 1) * $adapter->getPageLimit;
+          $replacements[$original] = $offset;
+          break;
+
+        case 'start-count':
+          $offset = (($adapter->getPageNumber() - 1) * $adapter->getPageLimit) + 1;
+          $replacements[$original] = $offset;
+          break;
+
+        case 'end-count':
+          $offset = ($adapter->getPageNumber()) * $adapter->getPageLimit;
+          $replacements[$original] = $offset;
+          break;
+      }
+    }
+  }
+  elseif ('facetapi_active' == $type && !empty($data['facetapi_active_item'])) {
+
+    $item = $data['facetapi_active_item'];
+    $adapter = $item['adapter'];
+    foreach ($tokens as $name => $original) {
+      switch ($name) {
+
+        case 'active-value':
+          $markup = $adapter->getMappedValue($item['facets'][0], $item['value']);
+          $text = ($markup['#html']) ? $markup['#markup'] : check_plain($markup['#markup']);
+          $replacements[$original] = $text;
+          break;
+
+        case 'active-value-raw':
+          $replacements[$original] = check_plain($item['value']);
+          break;
+
+        case 'active-pos':
+          $replacements[$original] = $item['pos'];
+          break;
+
+        case 'facet-label':
+          if ($facet = facetapi_facet_load($item['facets'][0], $adapter->getSearcher())) {
+            $replacements[$original] = check_plain($facet['label']);
+          }
+          break;
+
+        case 'facet-name':
+          $replacements[$original] = check_plain($item['facets'][0]);
+          break;
+      }
+    }
+  }
+  elseif ('facetapi_facet' == $type && !empty($data['facetapi_facet'])) {
+
+    $facet = $data['facetapi_facet'];
+    foreach ($tokens as $name => $original) {
+      switch ($name) {
+
+        case 'facet-label':
+          $replacements[$original] = check_plain($facet['label']);
+          break;
+
+        case 'facet-name':
+          $replacements[$original] = check_plain($facet['name']);
+          break;
+      }
+    }
+  }
+
+  return $replacements;
+}
diff --git a/plugins/facetapi/adapter.inc b/plugins/facetapi/adapter.inc
index 00dddda..51ed274 100644
--- a/plugins/facetapi/adapter.inc
+++ b/plugins/facetapi/adapter.inc
@@ -366,7 +366,40 @@ abstract class FacetapiAdapter {
    *   An integer containing the number of results.
    */
   public function getResultCount() {
-    return;
+    global $pager_total;
+    return isset($pager_total[0]) ? $pager_total[0] : 0;
+  }
+
+  /**
+   * Returns the number of results per page.
+   *
+   * @return int
+   *   The number of results per page, or the limit.
+   */
+  public function getPageLimit() {
+    global $pager_limits;
+    return isset($pager_limits[0]) ? $pager_limits[0] : 10;
+  }
+
+  /**
+   * Returns the page number of the search result set.
+   *
+   * @return int
+   *   The current page of the result set.
+   */
+  public function getPageNumber() {
+    return pager_find_page() + 1;
+  }
+
+  /**
+   * Returns the total number of pages in the result set.
+   *
+   * @return int
+   *   The total number of pages.
+   */
+  public function getPageTotal() {
+    global $pager_total;
+    return isset($pager_total[0]) ? $pager_total[0] : 0;
   }
 
   /**
@@ -415,6 +448,7 @@ abstract class FacetapiAdapter {
    */
   function addActiveFilters($query) {
     module_load_include('inc', 'facetapi', 'facetapi.callbacks');
+    facetapi_add_active_searcher($this->info['name']);
 
     // Runs initActiveFilters hook, finds active facets.
     $this->initActiveFilters($query);
@@ -674,6 +708,23 @@ abstract class FacetapiAdapter {
   }
 
   /**
+   * Returns the processor associates with the facet.
+   *
+   * @param string $facet_name
+   *   The machine readable name of the facet.
+   *
+   * @return FacetapiFacetProcessor
+   */
+  public function getProcessor($facet_name) {
+    if (isset($this->processors[$facet_name])) {
+      return $this->processors[$facet_name];
+    }
+    else {
+      return FALSE;
+    }
+  }
+
+  /**
    * Helper function that returns the query string variables for a facet item.
    *
    * @param array $facet
@@ -692,78 +743,9 @@ abstract class FacetapiAdapter {
   }
 
   /**
-   * Builds the content for the current search block.
-   *
-   * @return array
-   *   The block's render array.
-   */
-  public function buildCurrentSearch() {
-    $items = array();
-
-    // Makes sure facet builds are initialized.
-    $this->processFacets();
-
-    // Adds search keys.
-    // @todo Need a getBaseQuery() method or something.
-    if ($keys = $this->getSearchKeys()) {
-      $items[] = check_plain($keys);
-    }
-
-    // Adds active facets to the current search block.
-    foreach ($this->getAllActiveItems() as $item) {
-
-      // Gets all children so they can be deactivated as well.
-      $values = array();
-      foreach ($item['facets'] as $facet_name) {
-        $values = array_merge($values, $this->processors[$facet_name]->getActiveChildren($item['value']));
-      }
-      // Handle the case of a URL value that matches no actual
-      // facet values. Otherwise, it can't be unclicked.
-      if (!in_array($item['value'], $values)) {
-        $values[] = $item['value'];
-      }
-
-      // Builds variables for active link theme.
-      $mapped = $this->getMappedValue($item['facets'][0], $item['value']);
-
-      $variables = array(
-        'text' => $mapped['#markup'],
-        'path' => current_path(),
-        'options' => array(
-          'attributes' => array('class' => array()),
-          'html' => !empty($mapped['#html']),
-          'query' => $this->processors[$item['facets'][0]]->getQueryString($values, 1),
-        ),
-      );
-
-      // Renders the active link.
-      $items[] = theme('facetapi_link_active', $variables);
-    }
-
-    // If there are items, return the render array.
-    if ($items) {
-      $content = array(
-        '#title' => t('Current search'),
-        'block' => array(
-          '#theme' => 'item_list',
-          '#items' => $items,
-        ),
-      );
-
-      // Set message as title if list if result count was returned.
-      if (NULL !== ($count = $this->getResultCount())) {
-        $content['block']['#title'] = format_plural($count, 'Search found 1 item', 'Search found @count items');
-      }
-
-      // Returns the render array for the block.
-      return $content;
-    }
-  }
-
-  /**
    * Initializes facet builds, adds breadcrumb trail.
    */
-  protected function processFacets() {
+  public function processFacets() {
     if (!$this->processed) {
       $this->processed = TRUE;
 
