diff --git a/category_menu/category_menu.module b/category_menu/category_menu.module
index 131e22bc970631507c5b2efbd0af96aae33c2d52..076ba88efbc51ba47eb5e3a515a4532ef7d7fec7 100644
--- a/category_menu/category_menu.module
+++ b/category_menu/category_menu.module
@@ -60,6 +60,15 @@ function category_menu_nodeapi(&$node, $op, $teaser, $page) {
 
       return $output;
 
+    case 'view':
+      if (!$teaser && $page) {
+        if (!empty($node->category_menu_map['mlid']) && $node->build_mode == NODE_BUILD_NORMAL) {
+          menu_set_active_trail(category_menu_build_active_trail($node->category_menu_map));
+          menu_set_active_menu_name($node->category_menu_map['menu_name']);
+        }
+      }
+      break;
+
     case 'prepare':
       $behavior = variable_get('category_behavior_'. $node->type, 0);
       if (!empty($behavior)) {
@@ -701,7 +710,16 @@ function _category_menu_map_save_category($nid) {
   $parent = reset($parents);
 
   if (empty($parent->cid)) {
-    return 0;
+    // Special edge case of a category with one or more hidden containers as
+    // its ancestors, and with the top hidden container having a custom menu
+    // parent. In such cases, the category gets the custom menu parent as its
+    // menu parent.
+    if (($container = category_get_container($nid)) && $container->hidden_cont && ($container_menu = category_menu_get_container($nid)) && !empty($container_menu->plid_for_container) && ($parent_link = menu_link_load($container_menu->plid_for_container))) {
+      return $container_menu->plid_for_container;
+    }
+    else {
+      return 0;
+    }
   }
 
   $parent_category = category_get_category($parent->cid);
@@ -738,6 +756,119 @@ function category_menu_menu_name($cnid) {
   return 'category-menu-toc-'. $cnid;
 }
 
+/**
+ * Build an active trail to show in the breadcrumb.
+ */
+function category_menu_build_active_trail($menu_link) {
+  static $trail;
+
+  if (!isset($trail)) {
+    $trail = array();
+    $trail[] = array('title' => t('Home'), 'href' => '<front>', 'localized_options' => array());
+
+    $tree = category_menu_tree_all_data($menu_link['menu_name'], $menu_link);
+    $curr = array_shift($tree);
+
+    while ($curr) {
+      if ($curr['link']['href'] == $menu_link['href']) {
+        $trail[] = $curr['link'];
+        $curr = FALSE;
+      }
+      else {
+        if ($curr['below'] && $curr['link']['in_active_trail']) {
+          $trail[] = $curr['link'];
+          $tree = $curr['below'];
+        }
+        $curr = array_shift($tree);
+      }
+    }
+  }
+  return $trail;
+}
+
+/**
+ * Creates a tree that is able to recognise distant-parent menu items.
+ * This is done by finding top-level menu items with a parent defined (which
+ * technically should never exist in Drupal), and by extending the tree based
+ * on these items. The tree is also extended down, by searching for distant
+ * children of bottom-level menu items.
+ */
+function category_menu_tree_all_data($menu_name, &$item) {
+  // Start with a regular tree, based on the specified item, containing
+  // items local to the $menu_name menu.
+  $tree = menu_tree_all_data($menu_name, $item);
+
+  // Next, find top-level items with defined parents, and extend the tree
+  // to include such parents and their ancestors.
+  $parent_link = reset($tree);
+  $parent_link_key = key($tree);
+  while ($parent_link['link']['plid']) {
+    $ancestor_link = menu_link_load($parent_link['link']['plid']);
+    if ($ancestor_link['menu_name'] != $menu_name) {
+      $tree = menu_tree_all_data($ancestor_link['menu_name'], $ancestor_link);
+      _category_menu_tree_above($tree, array(
+        'key' => $parent_link_key,
+        'value' => $parent_link,
+      ));
+
+      $parent_link = reset($tree);
+      $parent_link_key = key($tree);
+    }
+    else {
+      $parent_link['link']['plid'] = 0;
+    }
+  };
+
+  // Finally, find distant children with the specified item as their parent,
+  // and extend the tree to include such children and their descendants.
+  $children = db_query("SELECT m.*, ml.* FROM {menu_links} ml LEFT JOIN {menu_router} m ON m.path = ml.router_path WHERE ml.plid = %d AND ml.menu_name != '%s'", $item['mlid'], $menu_name);
+  $child_tree_prev = array();
+
+  while ($child_link = db_fetch_array($children)) {
+    _menu_link_translate($child_link);
+    $child_tree = menu_tree_all_data($child_link['menu_name'], $child_link);
+    if (!empty($child_tree) && $child_tree != $child_tree_prev) {
+      $item['has_children'] = 1;
+      _category_menu_tree_below($tree, $child_tree, $item);
+      $child_tree_prev = $child_tree;
+    }
+  }
+
+  return $tree;
+}
+
+/**
+ * Helper function for category_menu_tree_all_data(). Recursively searches the tree for
+ * the specified menu item, and appends the child tree below it.
+ */
+function _category_menu_tree_below(&$tree, $child_tree, $item) {
+  foreach (array_keys($tree) as $key) {
+    if ($tree[$key]['link']['mlid'] != $item['mlid']) {
+      if (!empty($tree[$key]['below'])) {
+        _category_menu_tree_below($tree[$key]['below'], $child_tree, $item);
+      }
+    }
+    else {
+      $tree[$key]['below'] = $child_tree;
+    }
+  }
+}
+
+/**
+ * Helper function for category_menu_tree_all_data(). Recursively searches the tree for
+ * the specified parent item, and appends the rest of the tree below it.
+ */
+function _category_menu_tree_above(&$tree, $parent_link) {
+  foreach (array_keys($tree) as $key) {
+    if (!empty($tree[$key]['below'])) {
+      _category_menu_tree_above($tree[$key]['below'], $parent_link);
+    }
+    else {
+      $tree[$key]['below'] = array($parent_link['key'] => $parent_link['value']);
+    }
+  }
+}
+
 /**
  * Helper function to flatten the $node->category['menu'] array.
  */