Index: includes/menu.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/menu.inc,v
retrieving revision 1.431
diff -u -p -r1.431 menu.inc
--- includes/menu.inc	4 Jan 2011 06:20:30 -0000	1.431
+++ includes/menu.inc	12 Jan 2011 23:40:29 -0000
@@ -1191,23 +1191,23 @@ function menu_tree_page_data($menu_name,
         );
         // Parent mlids; used both as key and value to ensure uniqueness.
         // We always want all the top-level links with plid == 0.
-        $active_trail = array(0 => 0);
+        $active_trail = $parents = array(0 => 0);
 
         // If the item for the current page is accessible, build the tree
         // parameters accordingly.
         if ($item['access']) {
           // Find a menu link corresponding to the current path.
-          if ($active_link = menu_link_get_preferred()) {
+          if ($preferred_link = menu_link_get_preferred()) {
             // The active link may only be taken into account to build the
             // active trail, if it resides in the requested menu. Otherwise,
             // we'd needlessly re-run _menu_build_tree() queries for every menu
             // on every page.
-            if ($active_link['menu_name'] == $menu_name) {
+            if ($preferred_link['menu_name'] == $menu_name) {
               // Use all the coordinates, except the last one because there
               // can be no child beyond the last column.
               for ($i = 1; $i < MENU_MAX_DEPTH; $i++) {
-                if ($active_link['p' . $i]) {
-                  $active_trail[$active_link['p' . $i]] = $active_link['p' . $i];
+                if ($preferred_link['p' . $i]) {
+                  $active_trail[$preferred_link['p' . $i]] = $preferred_link['p' . $i];
                 }
               }
               // If we are asked to build links for the active trail only, skip
@@ -1217,7 +1217,19 @@ function menu_tree_page_data($menu_name,
               }
             }
           }
-          $parents = $active_trail;
+          
+          // Get all of the active links corresponding to the current path
+          if ($all_active_links = menu_link_get_active()) {
+            foreach ($all_active_links as $active_link) {
+              // Use all the coordinates, except the last one because there
+              // can be no child beyond the last column.
+              for ($i = 1; $i < MENU_MAX_DEPTH; $i++) {
+                if ($active_link['p' . $i]) {
+                  $parents[$active_link['p' . $i]] = $active_link['p' . $i];
+                }
+              }
+            }
+          }
 
           $expanded = variable_get('menu_expanded', array());
           // Check whether the current menu has any links set to be expanded.
@@ -2415,6 +2427,79 @@ function menu_link_get_preferred($path =
 }
 
 /**
++ * Lookup the active menu links for a given system path.
++ *
++ * @param $path
++ *   The path, for example 'node/5'. The function will find the corresponding
++ *   menu link ('node/5' if it exists, or fallback to 'node/%').
++ *
++ * @return
++ *   An array of fully translated menu links, or NULL if not matching menu link was
++ *   found. The most specific menu links ('node/5' preferred over 'node/%') is
++ *   returned.
++ */
+function menu_link_get_active($path = NULL) {
+  $menu_links = &drupal_static(__FUNCTION__);
+
+  if (!isset($path)) {
+    $path = $_GET['q'];
+  }
+
+  if (!isset($menu_links[$path])) {
+    $menu_links[$path] = FALSE;
+
+    // Look for the correct menu link by building a list of candidate paths,
+    // which are ordered by priority (translated hrefs are preferred over
+    // untranslated paths). Afterwards, the most relevant path is picked from
+    // the menus, ordered by menu preference.
+    $item = menu_get_item($path);
+    $path_candidates = array();
+    // 1. The current item href.
+    $path_candidates[$item['href']] = $item['href'];
+    // 2. The tab root href of the current item (if any).
+    if ($item['tab_parent'] && ($tab_root = menu_get_item($item['tab_root_href']))) {
+      $path_candidates[$tab_root['href']] = $tab_root['href'];
+    }
+    // 3. The current item path (with wildcards).+    $path_candidates[$item['path']] = $item['path'];
+    // 4. The tab root path of the current item (if any).
+    if (!empty($tab_root)) {
+      $path_candidates[$tab_root['path']] = $tab_root['path'];
+    }
+
+    $query = db_select('menu_links', 'ml', array('fetch' => PDO::FETCH_ASSOC));
+    $query->leftJoin('menu_router', 'm', 'm.path = ml.router_path');
+    $query->fields('ml');
+    // Weight must be taken from {menu_links}, not {menu_router}.
+    $query->addField('ml', 'weight', 'link_weight');
+    $query->fields('m');
+    $query->condition('ml.link_path', $path_candidates, 'IN');
+
+    // Sort candidates by link path and menu name.
+    $candidates = array();
+    foreach ($query->execute() as $candidate) {
+      $candidate['weight'] = $candidate['link_weight'];
+      $candidates[$candidate['link_path']][] = $candidate;
+    }
+
+    // Pick the most specific links.
+    foreach ($path_candidates as $link_path) {
+      if (!isset($candidates[$link_path])) {
+        continue;
+      }
+      foreach ($candidates[$link_path] as $candidate_item) {
+        $map = explode('/', $path);
+        _menu_translate($candidate_item, $map);
+        if ($candidate_item['access']) {
+          $menu_links[$path][] = $candidate_item;
+        }
+      }
+    }
+  }
+
+  return $menu_links[$path];
+}
+
+/**
  * Gets the active trail (path to root menu root) of the current page.
  *
  * See menu_set_active_trail() for details of return value.
