diff --git a/README b/README
index 0cd4247..9d1e4f6 100644
--- a/README
+++ b/README
@@ -11,10 +11,15 @@
     * Go to the footermap settings page (admin/structure/footermap)
 
     * Recurse Limit
-       * The recurse limit is the menu depth for every menu.
+       * The recurse limit is the menu depth for every menu item.
        * By default footermap will crawl through each enabled menu, and display each menu 
          item in the footer.
 
+    * Enable Menu Heading
+       * This will provide the menu name as a header above each menu item list.
+       * You can override footermap's theme functions in order to change, which part of
+         the array is considered a header by changing #theme to "footermap_header".
+
     * Drupal Root Menu
        * Input which mlid you would like to start grabbing menus from.  This is useful if
          you only want to grab from one unique menu tree other than Primary Links, 
@@ -55,6 +60,7 @@
        * NOTE: This means that there has been a php error. Please consult your apache/iis
          error logs. I cannot help with this issue without error logs.
        * This could be a memory issue.
+
     * Views
        * You can turn on views menu items with the "Enable System Menu Items" option,
          but this will enable all system menu items. There is no finer grain control than
diff --git a/footermap.css b/footermap.css
index 1fafeac..c5a72d5 100644
--- a/footermap.css
+++ b/footermap.css
@@ -4,24 +4,21 @@ div.footermap
   height: 100%;
   display: inline;
   margin: 0 auto;
-  width: 600px;
+  text-align: center;
 }
 
 div.footermap-col
 {
   float: left;
   margin: 0 0 0 20px;
-  text-align: left;
 }
 
-ul.footermap-item {
-  margin: 0;
-  padding: 0;
-}
-
-ul.footermap-item li {
+li.footermap-item {
+  float: none;
+  display: block;
   list-style-type: none;
+  list-style-position: inside;
+  list-style-image: none;
   margin: 0 0 5px;
   padding: 0px;
-  display: block;
 }
diff --git a/footermap.module b/footermap.module
index 84c4030..4061e4e 100644
--- a/footermap.module
+++ b/footermap.module
@@ -45,6 +45,27 @@ function footermap_menu()
   return $items;
 }
 
+/**
+ * Implementation of hook_theme
+ */
+function footermap_theme($existing, $type, $theme, $path) {
+  return array(
+    'footermap' => array(
+      'variables' => array('footermap' => NULL, 'title' => NULL),
+      'file' => 'footermap.theme.inc',
+      'template' => 'footermap',
+    ),
+    'footermap_item' => array(
+      'variables' => array('href' => NULL, 'title' => NULL, 'level' => NULL, 'children' => NULL, 'attributes' => NULL),
+      'file' => 'footermap.theme.inc',
+    ),
+    'footermap_header' => array(
+      'variables' => array('title' => NULL, 'items' => NULL, 'attributes' => NULL),
+      'file' => 'footermap.theme.inc',
+    ),
+  );
+}
+
 /*
  * Footermap settings
  * @return system_settings_callback form
@@ -137,7 +158,7 @@ function footermap_block_view($delta = '')
 
 /*
  * footermap_render
- * @return HTML output
+ * @return Render array
  */
 function footermap_render()
 {
@@ -145,22 +166,34 @@ function footermap_render()
   $base = variable_get('top_menu', 0);
   $menus = menu_get_menus(TRUE);
   $mapref = array();
-  $disp_heading = variable_get('footermap_heading', 0);
+  $avail_menus = variable_get('avail_menus', array());
   $o = '';
 
+  $i = 1;
+  foreach ($menus as $key => $menu) {
+    if (isset($avail_menus[$key]) && $avail_menus[$key] === $key) {
+      $mapref[$key] = array(
+        '#theme' => 'footermap_header',
+        '#title' => $menu, // Need to check_plain() or t() during render.
+        '#attributes' => array(
+          'class' => array('footermap-col', 'footermap-header'),
+          'id' => 'footermap-col-' . $i,
+        ),
+      );
+
+      $i++;
+    }
+  }
+
   footermap_get_menu($base, $mapref, $recurse, 0);
 
-  $n = 0;
-  foreach ($mapref as $key => $block)
-  {
-    $heading = ($disp_heading == 1) ? $menus[$key] : '';
-    $o .= '<div class="footermap-col" id="footermap-col-'.$n.'-footermap-col-'.$key.'">'.theme('links', array('links' => $block, 'heading' => array('text' => t($heading), 'level' => 'h3'), 'attributes' => array('class' => 'footermap-item links'))) . '</div>';
-    $n++;
-  }
-  
-  $o = '<div class="footermap">'.$o.'</div>';
+  $content = array(
+    '#theme' => 'footermap',
+    '#footermap' => $mapref,
+    '#title' => '',
+  );
 
-  return $o;
+  return $content;
 }
 
 /*
@@ -180,39 +213,48 @@ function footermap_get_menu($mlid, &$mapref, $recurse, $level)
 
   $avail_menus = variable_get('avail_menus', array());
 
-  if (variable_get('sys_menus', 0) == 0) 
-    $system_menu = " AND ml.module <> 'system' ";
-  else
-    $system_menu = ' ';
-
-  $sql = 'SELECT * FROM {menu_links} ml LEFT OUTER JOIN {menu_router} mr ON (ml.router_path = mr.path) WHERE ml.plid = :mlid AND ml.hidden = 0' . $system_menu . 'ORDER BY ml.plid, ml.weight, ml.link_title, mr.title';
-
-  $res = db_query($sql, array('mlid' => $mlid));
-
-  while ($h = $res->fetchObject())
+  $query = db_select('menu_links', 'ml');
+  $query
+    ->fields('ml')
+    ->condition('ml.plid', $mlid, '=')
+    ->condition('ml.hidden', 0, '=')
+    ->orderBy('ml.plid')
+    ->orderBy('ml.weight')
+    ->orderBy('ml.link_title');
+  $query->leftJoin('menu_router', 'mr', 'ml.router_path = mr.path');
+  $query
+    ->fields('mr')
+    ->orderBy('mr.title');
+
+  if (variable_get('sys_menus', 0) == 0)
+    $query->condition('ml.module', 'system', '<>');
+
+  $res = $query->execute();
+
+  foreach ($res as $item)
   {
     // available menus check 
-    if (!_footermap_check_menu_item($avail_menus, $h))
+    if (!_footermap_check_menu_item($avail_menus, $item))
       continue;
 
     // access check for menu router items
-    if (isset($h->path))
+    if (isset($item->path))
     {
-      if (empty($h->access_callback)) // automatic fail
+      if (empty($item->access_callback)) // automatic fail
         continue;
 
       $map = array();
       $args = array();
-      $map = explode('/', $h->link_path);
-      if (!empty($h->to_arg_functions))
-        _menu_link_map_translate($map, $h->to_arg_functions);
+      $map = explode('/', $item->link_path);
+      if (!empty($item->to_arg_functions))
+        _menu_link_map_translate($map, $item->to_arg_functions);
 
-      $args = menu_unserialize($h->access_arguments, $map);
+      $args = menu_unserialize($item->access_arguments, $map);
 
       // There's no way that I can do access callback stuff for every 
       // custom access callback with custom arguments under the sun. 
       // It's out of scope of this module, and a non-issue.
-      if ($h->access_callback == 'user_access')
+      if ($item->access_callback == 'user_access')
       {
         if (!empty($args[0])) {
           if (! user_access($args[0], $user)) {
@@ -220,7 +262,7 @@ function footermap_get_menu($mlid, &$mapref, $recurse, $level)
           }
         }
       }
-      else if ($h->access_callback == 'node_access')
+      else if ($item->access_callback == 'node_access')
       {
         if (is_numeric($args[1]))
         {
@@ -236,15 +278,27 @@ function footermap_get_menu($mlid, &$mapref, $recurse, $level)
       }
     }
 
-    $h->link_path = preg_replace("/\/%$/", '', $h->link_path);
-    $mapref[$h->menu_name]['menu-'.$h->mlid] = array(
-      'href' => $h->link_path,
-      'title' => $h->link_title,
+    // Mapref reference becomes child.
+    if (isset($mapref[$item->menu_name]))
+      $child = &$mapref[$item->menu_name]['#items'];
+    else
+      $child = &$mapref;
+
+    $item->link_path = preg_replace("/\/%$/", '', $item->link_path);
+    $child['menu-' . $item->mlid] = array(
+      '#theme' => 'footermap_item',
+      '#href' => $item->link_path,
+      '#title' => $item->link_title,
+      '#attributes' => array(
+        'class' => array('footermap-item', 'footermap-item-' . $level),
+        'id' => 'footermap-item-' . $item->mlid,
+      ),
+      '#level' => $level,
     );
 
-    if ($h->has_children == 1)
+    if ($item->has_children == 1)
     {
-      footermap_get_menu($h->mlid, $mapref, $recurse, $level+1);
+      footermap_get_menu($item->mlid, $child['menu-' . $item->mlid]['#children'], $recurse, $level+1);
     }
   }
 }
@@ -261,9 +315,17 @@ function footermap_get_primary_menus($top_menu)
   if (!is_numeric($top_menu))
     return $ret;
 
-  $res = db_query("SELECT * FROM {menu_links} ml INNER JOIN {menu_custom} mc ON (ml.menu_name = mc.menu_name) WHERE ml.plid = :top_menu AND ml.hidden = 0", array(':top_menu' => $top_menu));
+  $query = db_select('menu_links', 'ml');
+  $query
+    ->fields('ml')
+    ->condition('ml.plid', $top_menu, '=')
+    ->condition('ml.hidden', 0, '=');
+  $query->join('menu_custom', 'mc', 'ml.menu_name = mc.menu_name');
+  $query->fields('mc');
+
+  $res = $query->execute();
 
-  while ($menu = $res->fetchObject())
+  foreach ($res as $menu)
     $ret[$menu->menu_name] = t($menu->title);
 
   return $ret;
diff --git a/footermap.theme.inc b/footermap.theme.inc
new file mode 100644
index 0000000..344329a
--- /dev/null
+++ b/footermap.theme.inc
@@ -0,0 +1,58 @@
+<?php
+
+/**
+ * @file
+ */
+
+
+/**
+ * Footermap template preprocess function.
+ * @param &$variables
+ */
+function template_preprocess_footermap(&$variables) {
+  drupal_add_css(drupal_get_path('module', 'footermap') . '/footermap.css', array('type' => 'file', 'every_page' => TRUE, 'group' => CSS_DEFAULT));
+}
+
+/**
+ * Footermap Item theme function
+ * @param &$variables
+ * @return HTML output
+ */
+function theme_footermap_item($variables) {
+  $o = '<li ' . drupal_attributes($variables['attributes']) . '>';
+  $o .= l($variables['title'], $variables['href']);
+  $o .= '</li>';
+
+  if (isset($variables['children'])) {
+    foreach (element_children($variables['children']) as $child) {
+      $o .= theme('footermap_item', $variables['children'][$child]);
+    }
+  }
+
+  return $o;
+}
+
+/**
+ * Footermap Header theme function
+ * @param &$variables
+ * @return HTML output
+ */
+function theme_footermap_header($variables) {
+  $o = '';
+
+  if (variable_get('footermap_heading', 0)) {
+    $o .= '<h3>' . $variables['title'] . '</h3>';
+  }
+
+  $o .= '<ul ' . drupal_attributes($variables['attributes']) . '>';
+
+  if (isset($variables['items'])) {
+    foreach (element_children($variables['items']) as $child) {
+      $o .= theme('footermap_item', $variables['items'][$child]);
+    }
+  }
+
+  $o .= '</ul>';
+
+  return $o;
+}
diff --git a/footermap.tpl.php b/footermap.tpl.php
new file mode 100644
index 0000000..1e3a894
--- /dev/null
+++ b/footermap.tpl.php
@@ -0,0 +1,33 @@
+<?php
+/**
+ * variables:
+ *   $footermap: The render array containing all items to be rendered. The
+ *               top level is the "header" level. You can change this by
+ *               calling element_children() and changing the #theme to
+ *               footermap_header of the child element you wish.
+ *
+ *         e.g. <?php
+ *              foreach (element_children($footermap['main-menu']) as $child) {
+ *                $footermap['main-menu'][$child]['#theme'] = 'footermap_header';
+ *                $new[] = $child;
+ *              }
+ *              
+ *              print render($new);
+ *              ?>
+ *
+ *       $title: An optional title that will be printed out. This is
+ *               normally blank. You may also set a title via the block,
+ *               if rendering in a block.
+ */
+?>
+<div class="footermap">
+  <?php if (!empty($title)): ?>
+    <h2><?php print check_plain($title); ?></h2>
+  <?php endif; ?>
+
+  <?php foreach ($footermap as $key => $header) { ?>
+  <div id="<?php print 'footermap-col-' . $key; ?>" class="footermap-col">
+    <?php print render($header); ?>
+  </div>
+  <?php } ?>
+</div>
