[Win32k|User32]
[reactos.git] / reactos / dll / win32 / user32 / windows / menu.c
index c90dbd6..ade437c 100644 (file)
@@ -1,5 +1,4 @@
-/* $Id$
- *
+/*
  * COPYRIGHT:       See COPYING in the top level directory
  * PROJECT:         ReactOS user32.dll
  * FILE:            user32/windows/menu.c
@@ -34,7 +33,6 @@ WINE_DEFAULT_DEBUG_CHANNEL(menu);
 
 /* Internal MenuTrackMenu() flags */
 #define TPM_INTERNAL           0xF0000000
-#define TPM_ENTERIDLEEX                0x80000000              /* set owner window for WM_ENTERIDLE */
 #define TPM_BUTTONDOWN         0x40000000              /* menu was clicked before tracking */
 #define TPM_POPUPMENU           0x20000000              /* menu is a popup menu */
 
@@ -58,6 +56,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(menu);
 /* Use global popup window because there's no way 2 menus can
  * be tracked at the same time.  */
 static HWND top_popup;
+static HMENU top_popup_hmenu;
 
 /* Flag set by EndMenu() to force an exit from menu tracking */
 static BOOL fEndMenu = FALSE;
@@ -268,6 +267,157 @@ MenuCleanupAllRosMenuItemInfo(PROSMENUITEMINFO ItemInfo)
   HeapFree(GetProcessHeap(), 0, ItemInfo);
 }
 
+/***********************************************************************
+ *           MenuInitSysMenuPopup
+ *
+ * Grey the appropriate items in System menu.
+ */
+void FASTCALL MenuInitSysMenuPopup(HMENU hmenu, DWORD style, DWORD clsStyle, LONG HitTest )
+{
+    BOOL gray;
+    UINT DefItem;
+    #if 0
+    MENUITEMINFOW mii;
+    #endif
+
+    gray = !(style & WS_THICKFRAME) || (style & (WS_MAXIMIZE | WS_MINIMIZE));
+    EnableMenuItem( hmenu, SC_SIZE, (gray ? MF_GRAYED : MF_ENABLED) );
+    gray = ((style & WS_MAXIMIZE) != 0);
+    EnableMenuItem( hmenu, SC_MOVE, (gray ? MF_GRAYED : MF_ENABLED) );
+    gray = !(style & WS_MINIMIZEBOX) || (style & WS_MINIMIZE);
+    EnableMenuItem( hmenu, SC_MINIMIZE, (gray ? MF_GRAYED : MF_ENABLED) );
+    gray = !(style & WS_MAXIMIZEBOX) || (style & WS_MAXIMIZE);
+    EnableMenuItem( hmenu, SC_MAXIMIZE, (gray ? MF_GRAYED : MF_ENABLED) );
+    gray = !(style & (WS_MAXIMIZE | WS_MINIMIZE));
+    EnableMenuItem( hmenu, SC_RESTORE, (gray ? MF_GRAYED : MF_ENABLED) );
+    gray = (clsStyle & CS_NOCLOSE) != 0;
+
+    /* The menu item must keep its state if it's disabled */
+    if(gray)
+        EnableMenuItem( hmenu, SC_CLOSE, MF_GRAYED);
+
+    /* Set default menu item */
+    if(style & WS_MINIMIZE) DefItem = SC_RESTORE;
+    else if(HitTest == HTCAPTION) DefItem = ((style & (WS_MAXIMIZE | WS_MINIMIZE)) ? SC_RESTORE : SC_MAXIMIZE);
+    else DefItem = SC_CLOSE;
+#if 0
+    mii.cbSize = sizeof(MENUITEMINFOW);
+    mii.fMask |= MIIM_STATE;
+    if((DefItem != SC_CLOSE) && GetMenuItemInfoW(hmenu, DefItem, FALSE, &mii) &&
+       (mii.fState & (MFS_GRAYED | MFS_DISABLED))) DefItem = SC_CLOSE;
+#endif
+    SetMenuDefaultItem(hmenu, DefItem, MF_BYCOMMAND);
+}
+
+/******************************************************************************
+ *
+ *   UINT MenuGetStartOfNextColumn(
+ *     PROSMENUINFO MenuInfo)
+ *
+ *****************************************************************************/
+static UINT MenuGetStartOfNextColumn(
+    PROSMENUINFO MenuInfo)
+{
+    PROSMENUITEMINFO MenuItems;
+    UINT i;
+
+    i = MenuInfo->FocusedItem;
+    if ( i == NO_SELECTED_ITEM )
+        return i;
+
+    if (MenuGetAllRosMenuItemInfo(MenuInfo->Self, &MenuItems) <= 0)
+        return NO_SELECTED_ITEM;
+
+    for (i++ ; i < MenuInfo->MenuItemCount; i++)
+        if (0 != (MenuItems[i].fType & (MF_MENUBREAK | MF_MENUBARBREAK)))
+            return i;
+
+    return NO_SELECTED_ITEM;
+}
+
+/******************************************************************************
+ *
+ *   UINT MenuGetStartOfPrevColumn(
+ *     PROSMENUINFO MenuInfo)
+ *
+ *****************************************************************************/
+
+static UINT FASTCALL MenuGetStartOfPrevColumn(
+    PROSMENUINFO MenuInfo)
+{
+    PROSMENUITEMINFO MenuItems;
+    UINT i;
+
+    if (!MenuInfo->FocusedItem || MenuInfo->FocusedItem == NO_SELECTED_ITEM)
+        return NO_SELECTED_ITEM;
+
+    if (MenuGetAllRosMenuItemInfo(MenuInfo->Self, &MenuItems) <= 0)
+        return NO_SELECTED_ITEM;
+
+    /* Find the start of the column */
+    for (i = MenuInfo->FocusedItem;
+         0 != i && 0 == (MenuItems[i].fType & (MF_MENUBREAK | MF_MENUBARBREAK));
+         --i)
+    {
+        ; /* empty */
+    }
+
+    if (i == 0)
+    {
+        MenuCleanupAllRosMenuItemInfo(MenuItems);
+        return NO_SELECTED_ITEM;
+    }
+
+    for (--i; 0 != i; --i)
+        if (MenuItems[i].fType & (MF_MENUBREAK | MF_MENUBARBREAK))
+            break;
+
+    MenuCleanupAllRosMenuItemInfo(MenuItems);
+    TRACE("ret %d.\n", i );
+
+    return i;
+}
+
+/***********************************************************************
+ *           MenuFindSubMenu
+ *
+ * Find a Sub menu. Return the position of the submenu, and modifies
+ * *hmenu in case it is found in another sub-menu.
+ * If the submenu cannot be found, NO_SELECTED_ITEM is returned.
+ */
+static UINT FASTCALL MenuFindSubMenu(HMENU *hmenu, HMENU hSubTarget )
+{
+    ROSMENUINFO menu;
+    UINT i;
+    ROSMENUITEMINFO item;
+    if (((*hmenu)==(HMENU)0xffff) ||
+          (!MenuGetRosMenuInfo(&menu, *hmenu)))
+        return NO_SELECTED_ITEM;
+
+    MenuInitRosMenuItemInfo(&item);
+    for (i = 0; i < menu.MenuItemCount; i++) {
+        if (! MenuGetRosMenuItemInfo(menu.Self, i, &item))
+        {
+            MenuCleanupRosMenuItemInfo(&item);
+            return NO_SELECTED_ITEM;
+        }
+        if (!(item.fType & MF_POPUP)) continue;
+        if (item.hSubMenu == hSubTarget) {
+            MenuCleanupRosMenuItemInfo(&item);
+            return i;
+        }
+        else  {
+            HMENU hsubmenu = item.hSubMenu;
+            UINT pos = MenuFindSubMenu(&hsubmenu, hSubTarget );
+            if (pos != NO_SELECTED_ITEM) {
+                *hmenu = hsubmenu;
+                return pos;
+           }
+        }
+    }
+    MenuCleanupRosMenuItemInfo(&item);
+    return NO_SELECTED_ITEM;
+}
 
 /***********************************************************************
  *           MenuLoadBitmaps
@@ -349,49 +499,6 @@ MenuDrawPopupGlyph(HDC dc, LPRECT r, INT_PTR popupMagic, BOOL inactive, BOOL hil
   DeleteObject(hFont);
 }
 
-/***********************************************************************
- *           MenuFindSubMenu
- *
- * Find a Sub menu. Return the position of the submenu, and modifies
- * *hmenu in case it is found in another sub-menu.
- * If the submenu cannot be found, NO_SELECTED_ITEM is returned.
- */
-static UINT FASTCALL MenuFindSubMenu(HMENU *hmenu, HMENU hSubTarget )
-{
-    ROSMENUINFO menu;
-    UINT i;
-    ROSMENUITEMINFO item;
-
-    if (((*hmenu)==(HMENU)0xffff) ||
-          (!MenuGetRosMenuInfo(&menu, *hmenu)))
-        return NO_SELECTED_ITEM;
-
-    MenuInitRosMenuItemInfo(&item);
-    for (i = 0; i < menu.MenuItemCount; i++)
-    {
-        if (! MenuGetRosMenuItemInfo(menu.Self, i, &item))
-        {
-            MenuCleanupRosMenuItemInfo(&item);
-            return NO_SELECTED_ITEM;
-        }
-        if (!(item.fType & MF_POPUP)) continue;
-        if (item.hSubMenu == hSubTarget) {
-            MenuCleanupRosMenuItemInfo(&item);
-            return i;
-        }
-        else  {
-            HMENU hsubmenu = item.hSubMenu;
-            UINT pos = MenuFindSubMenu(&hsubmenu, hSubTarget );
-            if (pos != NO_SELECTED_ITEM) {
-                *hmenu = hsubmenu;
-                return pos;
-           }
-        }
-    }
-    MenuCleanupRosMenuItemInfo(&item);
-    return NO_SELECTED_ITEM;
-}
-
 /***********************************************************************
  *           MenuFindItemByKey
  *
@@ -432,7 +539,7 @@ static UINT FASTCALL MenuFindItemByKey(HWND WndOwner, PROSMENUINFO MenuInfo,
           ItemInfo = Items;
           for (i = 0; i < MenuInfo->MenuItemCount; i++, ItemInfo++)
             {
-              if ((ItemInfo->Text) && NULL != ItemInfo->dwTypeData)
+              if ((ItemInfo->lpstr) && NULL != ItemInfo->dwTypeData)
                 {
                   WCHAR *p = (WCHAR *) ItemInfo->dwTypeData - 2;
                   do
@@ -468,8 +575,7 @@ static UINT FASTCALL MenuFindItemByKey(HWND WndOwner, PROSMENUINFO MenuInfo,
  *
  * Get the size of a bitmap item.
  */
-static void FASTCALL MenuGetBitmapItemSize(PROSMENUITEMINFO lpitem, SIZE *size,
-                                                                                  HWND WndOwner)
+static void FASTCALL MenuGetBitmapItemSize(PROSMENUITEMINFO lpitem, SIZE *size, HWND WndOwner)
 {
     BITMAP bm;
     HBITMAP bmp = lpitem->hbmpItem;
@@ -700,7 +806,7 @@ static void FASTCALL MenuCalcItemSize( HDC hdc, PROSMENUITEMINFO lpitem, PROSMEN
         return;
     }
 
-    lpitem->XTab = 0;
+    lpitem->dxTab = 0;
 
     if (lpitem->hbmpItem)
     {
@@ -723,12 +829,12 @@ static void FASTCALL MenuCalcItemSize( HDC hdc, PROSMENUITEMINFO lpitem, PROSMEN
             if( !(MenuInfo->dwStyle & MNS_NOCHECK))
                 lpitem->Rect.right += 2 * check_bitmap_width;
             lpitem->Rect.right += 4 + MenuCharSize.cx;
-            lpitem->XTab = lpitem->Rect.right;
+            lpitem->dxTab = lpitem->Rect.right;
             lpitem->Rect.right += check_bitmap_width;
         } else /* hbmpItem & MenuBar */ {
             MenuGetBitmapItemSize(lpitem, &size, hwndOwner );
             lpitem->Rect.right  += size.cx;
-            if( lpitem->Text) lpitem->Rect.right  += 2;
+            if( lpitem->lpstr) lpitem->Rect.right  += 2;
             itemheight = size.cy;
 
             /* Special case: Minimize button doesn't have a space behind it. */
@@ -741,12 +847,12 @@ static void FASTCALL MenuCalcItemSize( HDC hdc, PROSMENUITEMINFO lpitem, PROSMEN
         if( !(MenuInfo->dwStyle & MNS_NOCHECK))
              lpitem->Rect.right += check_bitmap_width;
         lpitem->Rect.right += 4 + MenuCharSize.cx;
-        lpitem->XTab = lpitem->Rect.right;
+        lpitem->dxTab = lpitem->Rect.right;
         lpitem->Rect.right += check_bitmap_width;
     }
 
     /* it must be a text item - unless it's the system menu */
-    if (!(lpitem->fType & MF_SYSMENU) && lpitem->Text) {
+    if (!(lpitem->fType & MF_SYSMENU) && lpitem->lpstr) {
         HFONT hfontOld = NULL;
         RECT rc = lpitem->Rect;
         LONG txtheight, txtwidth;
@@ -775,7 +881,7 @@ static void FASTCALL MenuCalcItemSize( HDC hdc, PROSMENUITEMINFO lpitem, PROSMEN
                 /* get text size after the tab */
                 tmpheight = DrawTextW( hdc, p, -1, &tmprc,
                         DT_SINGLELINE|DT_CALCRECT);
-                lpitem->XTab += txtwidth;
+                lpitem->dxTab += txtwidth;
                 txtheight = max( txtheight, tmpheight);
                 txtwidth += MenuCharSize.cx + /* space for the tab */
                     tmprc.right - tmprc.left; /* space for the short cut */
@@ -783,7 +889,7 @@ static void FASTCALL MenuCalcItemSize( HDC hdc, PROSMENUITEMINFO lpitem, PROSMEN
                 txtheight = DrawTextW( hdc, lpitem->dwTypeData, -1, &rc,
                         DT_SINGLELINE|DT_CALCRECT);
                 txtwidth = rc.right - rc.left;
-                lpitem->XTab += txtwidth;
+                lpitem->dxTab += txtwidth;
             }
             lpitem->Rect.right  += 2 + txtwidth;
             itemheight = max( itemheight,
@@ -859,10 +965,10 @@ static void FASTCALL MenuPopupMenuCalcSize(PROSMENUINFO MenuInfo, HWND WndOwner)
 //        }
           maxX = max(maxX, lpitem.Rect.right);
           orgY = lpitem.Rect.bottom;
-          if ((lpitem.Text) && lpitem.XTab )
+          if ((lpitem.lpstr) && lpitem.dxTab )
              {
-              maxTab = max( maxTab, lpitem.XTab );
-              maxTabWidth = max(maxTabWidth, lpitem.Rect.right - lpitem.XTab);
+              maxTab = max( maxTab, lpitem.dxTab );
+              maxTabWidth = max(maxTabWidth, lpitem.Rect.right - lpitem.dxTab);
           }
         }
 
@@ -873,9 +979,9 @@ static void FASTCALL MenuPopupMenuCalcSize(PROSMENUINFO MenuInfo, HWND WndOwner)
             if (MenuGetRosMenuItemInfo(MenuInfo->Self, start, &lpitem))
             {
                 lpitem.Rect.right = maxX;
-                if ((lpitem.Text) && 0 != lpitem.XTab)
+                if ((lpitem.lpstr) && 0 != lpitem.dxTab)
                 {
-                    lpitem.XTab = maxTab;
+                    lpitem.dxTab = maxTab;
                 }
                 MenuSetRosMenuItemInfo(MenuInfo->Self, start, &lpitem);
             }
@@ -1273,7 +1379,7 @@ static void FASTCALL MenuDrawMenuItem(HWND hWnd, PROSMENUINFO MenuInfo, HWND Wnd
     }
 
     /* process text if present */
-    if (lpitem->Text)
+    if (lpitem->lpstr)
     {
         register int i = 0;
         HFONT hfontOld = 0;
@@ -1323,12 +1429,12 @@ static void FASTCALL MenuDrawMenuItem(HWND hWnd, PROSMENUINFO MenuInfo, HWND Wnd
         {
             if (L'\t' == Text[i])
             {
-                rect.left = lpitem->XTab;
+                rect.left = lpitem->dxTab;
                 uFormat = DT_LEFT | DT_VCENTER | DT_SINGLELINE;
             }
             else
             {
-                rect.right = lpitem->XTab;
+                rect.right = lpitem->dxTab;
                 uFormat = DT_RIGHT | DT_VCENTER | DT_SINGLELINE;
             }
 
@@ -1527,6 +1633,7 @@ static BOOL FASTCALL MenuShowPopup(HWND hwndOwner, HMENU hmenu, UINT id, UINT fl
     if ( !MenuInfo.Wnd || ! MenuSetRosMenuInfo(&MenuInfo)) return FALSE;
     if (!top_popup) {
         top_popup = MenuInfo.Wnd;
+        top_popup_hmenu = hmenu;
     }
 
     /* Display the window */
@@ -1537,6 +1644,7 @@ static BOOL FASTCALL MenuShowPopup(HWND hwndOwner, HMENU hmenu, UINT id, UINT fl
     return TRUE;
 }
 
+
 /***********************************************************************
  *           MenuSelectItem
  */
@@ -1555,6 +1663,7 @@ static void FASTCALL MenuSelectItem(HWND hwndOwner, PROSMENUINFO hmenu, UINT wIn
     else hdc = GetDCEx(hmenu->Wnd, 0, DCX_CACHE | DCX_WINDOW);
     if (!top_popup) {
         top_popup = hmenu->Wnd;
+        top_popup_hmenu = hmenu->Self;
     }
 
     SelectObject( hdc, hMenuFont );
@@ -1726,6 +1835,7 @@ LRESULT WINAPI PopupMenuWndProcA(HWND Wnd, UINT Message, WPARAM wParam, LPARAM l
       if (Wnd == top_popup)
         {
           top_popup = NULL;
+          top_popup_hmenu = NULL;
         }
       break;
 
@@ -1798,6 +1908,7 @@ PopupMenuWndProcW(HWND Wnd, UINT Message, WPARAM wParam, LPARAM lParam)
       if (Wnd == top_popup)
         {
           top_popup = NULL;
+          top_popup_hmenu = NULL;
         }
       break;
 
@@ -2120,66 +2231,6 @@ DrawMenuBarTemp(HWND Wnd, HDC DC, LPRECT Rect, HMENU Menu, HFONT Font)
   return MenuInfo.Height;
 }
 
-/***********************************************************************
- *           MenuInitSysMenuPopup
- *
- * Grey the appropriate items in System menu.
- */
-void FASTCALL
-MenuInitSysMenuPopup(HMENU Menu, DWORD Style, DWORD ClsStyle, LONG HitTest )
-{
-  BOOL Gray;
-  UINT DefItem;
-  #if 0
-  MENUITEMINFOW mii;
-  #endif
-
-  Gray = 0 == (Style & WS_THICKFRAME) || 0 != (Style & (WS_MAXIMIZE | WS_MINIMIZE));
-  EnableMenuItem(Menu, SC_SIZE, (Gray ? MF_GRAYED : MF_ENABLED));
-  Gray = 0 != (Style & WS_MAXIMIZE);
-  EnableMenuItem(Menu, SC_MOVE, (Gray ? MF_GRAYED : MF_ENABLED));
-  Gray = 0 == (Style & WS_MINIMIZEBOX) || 0 != (Style & WS_MINIMIZE);
-  EnableMenuItem(Menu, SC_MINIMIZE, (Gray ? MF_GRAYED : MF_ENABLED));
-  Gray = 0 == (Style & WS_MAXIMIZEBOX) || 0 != (Style & WS_MAXIMIZE);
-  EnableMenuItem(Menu, SC_MAXIMIZE, (Gray ? MF_GRAYED : MF_ENABLED));
-  Gray = 0 == (Style & (WS_MAXIMIZE | WS_MINIMIZE));
-  EnableMenuItem(Menu, SC_RESTORE, (Gray ? MF_GRAYED : MF_ENABLED));
-  Gray = 0 != (ClsStyle & CS_NOCLOSE);
-
-  /* The menu item must keep its state if it's disabled */
-  if (Gray)
-    {
-      EnableMenuItem(Menu, SC_CLOSE, MF_GRAYED);
-    }
-
-  /* Set default menu item */
-  if(Style & WS_MINIMIZE)
-  {
-    DefItem = SC_RESTORE;
-  }
-  else
-  {
-    if(HitTest == HTCAPTION)
-    {
-      DefItem = ((Style & (WS_MAXIMIZE | WS_MINIMIZE)) ? SC_RESTORE : SC_MAXIMIZE);
-    }
-    else
-    {
-      DefItem = SC_CLOSE;
-    }
-  }
-  #if 0
-  mii.cbSize = sizeof(MENUITEMINFOW);
-  mii.fMask |= MIIM_STATE;
-  if((DefItem != SC_CLOSE) && GetMenuItemInfoW(Menu, DefItem, FALSE, &mii) &&
-     (mii.fState & (MFS_GRAYED | MFS_DISABLED)))
-  {
-    DefItem = SC_CLOSE;
-  }
-  #endif
-  SetMenuDefaultItem(Menu, DefItem, MF_BYCOMMAND);
-}
-
 /***********************************************************************
  *           MenuShowSubPopup
  *
@@ -2306,13 +2357,30 @@ MenuShowSubPopup(HWND WndOwner, PROSMENUINFO MenuInfo, BOOL SelectFirst, UINT Fl
   return Ret;
 }
 
+/**********************************************************************
+ *         MENU_EndMenu
+ *
+ * Calls EndMenu() if the hwnd parameter belongs to the menu owner
+ *
+ * Does the (menu stuff) of the default window handling of WM_CANCELMODE
+ */
+void MENU_EndMenu( HWND hwnd )
+{
+    ROSMENUINFO MenuInfo;
+    BOOL Ret = FALSE;
+    if (top_popup_hmenu)
+       Ret = MenuGetRosMenuInfo(&MenuInfo, top_popup_hmenu);
+    if (Ret && hwnd == MenuInfo.WndOwner) EndMenu();
+}
+
 /***********************************************************************
  *           MenuHideSubPopups
  *
  * Hide the sub-popup menus of this menu.
  */
 static void FASTCALL
-MenuHideSubPopups(HWND WndOwner, PROSMENUINFO MenuInfo, BOOL SendMenuSelect)
+MenuHideSubPopups(HWND WndOwner, PROSMENUINFO MenuInfo,
+                               BOOL SendMenuSelect, UINT wFlags)
 {
   ROSMENUINFO SubMenuInfo;
   ROSMENUITEMINFO ItemInfo;
@@ -2320,28 +2388,32 @@ MenuHideSubPopups(HWND WndOwner, PROSMENUINFO MenuInfo, BOOL SendMenuSelect)
   TRACE("owner=%x menu=%x 0x%04x\n", WndOwner, MenuInfo, SendMenuSelect);
 
   if (NULL != MenuInfo && NULL != top_popup && NO_SELECTED_ITEM != MenuInfo->FocusedItem)
-    {
+  {
       MenuInitRosMenuItemInfo(&ItemInfo);
       ItemInfo.fMask |= MIIM_FTYPE | MIIM_STATE;
       if (! MenuGetRosMenuItemInfo(MenuInfo->Self, MenuInfo->FocusedItem, &ItemInfo)
           || 0 == (ItemInfo.fType & MF_POPUP)
           || 0 == (ItemInfo.fState & MF_MOUSESELECT))
-        {
+      {
           MenuCleanupRosMenuItemInfo(&ItemInfo);
           return;
-        }
+      }
       ItemInfo.fState &= ~MF_MOUSESELECT;
       ItemInfo.fMask |= MIIM_STATE;
       MenuSetRosMenuItemInfo(MenuInfo->Self, MenuInfo->FocusedItem, &ItemInfo);
       if (MenuGetRosMenuInfo(&SubMenuInfo, ItemInfo.hSubMenu))
-        {
-          MenuHideSubPopups(WndOwner, &SubMenuInfo, FALSE);
+      {
+          MenuHideSubPopups(WndOwner, &SubMenuInfo, FALSE, wFlags);
           MenuSelectItem(WndOwner, &SubMenuInfo, NO_SELECTED_ITEM, SendMenuSelect, NULL);
           DestroyWindow(SubMenuInfo.Wnd);
           SubMenuInfo.Wnd = NULL;
           MenuSetRosMenuInfo(&SubMenuInfo);
-        }
-    }
+
+          if (!(wFlags & TPM_NONOTIFY))
+             SendMessageW( WndOwner, WM_UNINITMENUPOPUP, (WPARAM)ItemInfo.hSubMenu,
+                                 MAKELPARAM(0, IS_SYSTEM_MENU(&SubMenuInfo)) );
+      }
+  }
 }
 
 /***********************************************************************
@@ -2350,7 +2422,7 @@ MenuHideSubPopups(HWND WndOwner, PROSMENUINFO MenuInfo, BOOL SendMenuSelect)
  * Helper function for menu navigation routines.
  */
 static void FASTCALL
-MenuSwitchTracking(MTRACKER* Mt, PROSMENUINFO PtMenuInfo, UINT Index)
+MenuSwitchTracking(MTRACKER* Mt, PROSMENUINFO PtMenuInfo, UINT Index, UINT wFlags)
 {
   ROSMENUINFO TopMenuInfo;
 
@@ -2361,13 +2433,13 @@ MenuSwitchTracking(MTRACKER* Mt, PROSMENUINFO PtMenuInfo, UINT Index)
       0 == ((PtMenuInfo->Flags | TopMenuInfo.Flags) & MF_POPUP))
     {
       /* both are top level menus (system and menu-bar) */
-      MenuHideSubPopups(Mt->OwnerWnd, &TopMenuInfo, FALSE);
+      MenuHideSubPopups(Mt->OwnerWnd, &TopMenuInfo, FALSE, wFlags);
       MenuSelectItem(Mt->OwnerWnd, &TopMenuInfo, NO_SELECTED_ITEM, FALSE, NULL);
       Mt->TopMenu = PtMenuInfo->Self;
     }
   else
     {
-      MenuHideSubPopups(Mt->OwnerWnd, PtMenuInfo, FALSE);
+      MenuHideSubPopups(Mt->OwnerWnd, PtMenuInfo, FALSE, wFlags);
     }
 
   MenuSelectItem(Mt->OwnerWnd, PtMenuInfo, Index, TRUE, NULL);
@@ -2483,7 +2555,7 @@ MenuButtonDown(MTRACKER* Mt, HMENU PtMenu, UINT Flags)
        {
           if (MenuInfo.FocusedItem != Index)
             {
-              MenuSwitchTracking(Mt, &MenuInfo, Index);
+              MenuSwitchTracking(Mt, &MenuInfo, Index, Flags);
             }
 
           /* If the popup menu is not already "popped" */
@@ -2666,7 +2738,7 @@ MenuMouseMove(MTRACKER *Mt, HMENU PtMenu, UINT Flags)
        if (MenuGetRosMenuItemInfo(MenuInfo.Self, Index, &ItemInfo) &&
            !(ItemInfo.fType & MF_SEPARATOR))
        {
-           MenuSwitchTracking(Mt, &MenuInfo, Index);
+           MenuSwitchTracking(Mt, &MenuInfo, Index, Flags);
         if (!(ItemInfo.fState & (MFS_DISABLED | MFS_GRAYED)))
                Mt->CurrentMenu = MenuShowSubPopup(Mt->OwnerWnd, &MenuInfo, FALSE, Flags);
        }
@@ -2676,86 +2748,6 @@ MenuMouseMove(MTRACKER *Mt, HMENU PtMenu, UINT Flags)
   return TRUE;
 }
 
-/******************************************************************************
- *
- *   UINT MenuGetStartOfNextColumn(PROSMENUINFO MenuInfo)
- */
-static UINT MenuGetStartOfNextColumn(PROSMENUINFO MenuInfo)
-{
-  UINT i;
-  PROSMENUITEMINFO MenuItems;
-
-  i = MenuInfo->FocusedItem;
-  if (NO_SELECTED_ITEM == i)
-    {
-      return i;
-    }
-
-  if (MenuGetAllRosMenuItemInfo(MenuInfo->Self, &MenuItems) <= 0)
-    {
-      return NO_SELECTED_ITEM;
-    }
-
-  for (i++ ; i < MenuInfo->MenuItemCount; i++)
-    {
-      if (0 != (MenuItems[i].fType & (MF_MENUBREAK | MF_MENUBARBREAK)))
-        {
-          return i;
-        }
-    }
-
-  return NO_SELECTED_ITEM;
-}
-
-/******************************************************************************
- *
- *   UINT MenuGetStartOfPrevColumn(PROSMENUINFO MenuInfo)
- */
-static UINT FASTCALL
-MenuGetStartOfPrevColumn(PROSMENUINFO MenuInfo)
-{
-  UINT i;
-  PROSMENUITEMINFO MenuItems;
-
-  if (0 == MenuInfo->FocusedItem || NO_SELECTED_ITEM == MenuInfo->FocusedItem)
-    {
-      return NO_SELECTED_ITEM;
-    }
-
-  if (MenuGetAllRosMenuItemInfo(MenuInfo->Self, &MenuItems) <= 0)
-    {
-      return NO_SELECTED_ITEM;
-    }
-
-  /* Find the start of the column */
-
-  for (i = MenuInfo->FocusedItem;
-       0 != i && 0 == (MenuItems[i].fType & (MF_MENUBREAK | MF_MENUBARBREAK));
-       --i)
-    {
-      ; /* empty */
-    }
-
-  if (0 == i)
-    {
-      MenuCleanupAllRosMenuItemInfo(MenuItems);
-      return NO_SELECTED_ITEM;
-    }
-
-  for (--i; 0 != i; --i)
-    {
-      if (MenuItems[i].fType & (MF_MENUBREAK | MF_MENUBARBREAK))
-        {
-          break;
-        }
-    }
-
-  MenuCleanupAllRosMenuItemInfo(MenuItems);
-  TRACE("ret %d.\n", i );
-
-  return i;
-}
-
 /***********************************************************************
  *           MenuGetSubPopup
  *
@@ -2795,7 +2787,7 @@ MenuGetSubPopup(HMENU Menu)
  * NOTE: WM_NEXTMENU documented in Win32 is a bit different.
  */
 static LRESULT FASTCALL
-MenuDoNextMenu(MTRACKER* Mt, UINT Vk)
+MenuDoNextMenu(MTRACKER* Mt, UINT Vk, UINT wFlags)
 {
   ROSMENUINFO TopMenuInfo;
   ROSMENUINFO MenuInfo;
@@ -2890,7 +2882,7 @@ MenuDoNextMenu(MTRACKER* Mt, UINT Vk)
                          FALSE, 0 );
           if (Mt->CurrentMenu != Mt->TopMenu)
             {
-              MenuHideSubPopups(Mt->OwnerWnd, &TopMenuInfo, FALSE);
+              MenuHideSubPopups(Mt->OwnerWnd, &TopMenuInfo, FALSE, wFlags);
             }
         }
 
@@ -2981,7 +2973,7 @@ MenuKeyEscape(MTRACKER *Mt, UINT Flags)
 
           if (MenuGetRosMenuInfo(&MenuInfo, MenuPrev))
             {
-              MenuHideSubPopups(Mt->OwnerWnd, &MenuInfo, TRUE);
+              MenuHideSubPopups(Mt->OwnerWnd, &MenuInfo, TRUE, Flags);
             }
           Mt->CurrentMenu = MenuPrev;
           EndMenu = FALSE;
@@ -3033,7 +3025,7 @@ MenuKeyLeft(MTRACKER* Mt, UINT Flags)
     {
       return;
     }
-  MenuHideSubPopups(Mt->OwnerWnd, &PrevMenuInfo, TRUE);
+  MenuHideSubPopups(Mt->OwnerWnd, &PrevMenuInfo, TRUE, Flags);
   Mt->CurrentMenu = MenuPrev;
 
   if (! MenuGetRosMenuInfo(&TopMenuInfo, Mt->TopMenu))
@@ -3044,7 +3036,7 @@ MenuKeyLeft(MTRACKER* Mt, UINT Flags)
     {
       /* move menu bar selection if no more popups are left */
 
-      if (! MenuDoNextMenu(Mt, VK_LEFT))
+      if (! MenuDoNextMenu(Mt, VK_LEFT, Flags))
         {
           MenuMoveSelection(Mt->OwnerWnd, &TopMenuInfo, ITEM_PREV);
         }
@@ -3114,7 +3106,7 @@ static void FASTCALL MenuKeyRight(MTRACKER *Mt, UINT Flags)
     {
       if (Mt->CurrentMenu != Mt->TopMenu)
         {
-          MenuHideSubPopups(Mt->OwnerWnd, &MenuInfo, FALSE );
+          MenuHideSubPopups(Mt->OwnerWnd, &MenuInfo, FALSE, Flags);
           hmenutmp = Mt->CurrentMenu = Mt->TopMenu;
         }
       else
@@ -3123,7 +3115,7 @@ static void FASTCALL MenuKeyRight(MTRACKER *Mt, UINT Flags)
         }
 
       /* try to move to the next item */
-      if ( !MenuDoNextMenu(Mt, VK_RIGHT))
+      if ( !MenuDoNextMenu(Mt, VK_RIGHT, Flags))
           MenuMoveSelection(Mt->OwnerWnd, &MenuInfo, ITEM_NEXT);
 
       if ( hmenutmp || Mt->TrackFlags & TF_SUSPENDPOPUP )
@@ -3167,6 +3159,7 @@ static INT FASTCALL MenuTrackMenu(HMENU hmenu, UINT wFlags, INT x, INT y,
 
     if (!IsMenu(hmenu))
     {
+        WARN("Invalid menu handle %p\n", hmenu);
         SetLastError( ERROR_INVALID_MENU_HANDLE );
         return FALSE;
     }
@@ -3209,7 +3202,7 @@ static INT FASTCALL MenuTrackMenu(HMENU hmenu, UINT wFlags, INT x, INT y,
             {
                 if (!enterIdleSent)
                 {
-                  HWND win = (wFlags & TPM_ENTERIDLEEX) && (MenuInfo.Flags & MF_POPUP) ? MenuInfo.Wnd : NULL;
+                  HWND win = MenuInfo.Flags & MF_POPUP ? MenuInfo.Wnd : NULL;
                   enterIdleSent = TRUE;
                   SendMessageW( mt.OwnerWnd, WM_ENTERIDLE, MSGF_MENU, (LPARAM) win);
                 }
@@ -3252,138 +3245,138 @@ static INT FASTCALL MenuTrackMenu(HMENU hmenu, UINT wFlags, INT x, INT y,
 
             switch(msg.message)
             {
-            /* no WM_NC... messages in captured state */
-
-            case WM_RBUTTONDBLCLK:
-            case WM_RBUTTONDOWN:
-                 if (!(wFlags & TPM_RIGHTBUTTON)) break;
-                /* fall through */
-            case WM_LBUTTONDBLCLK:
-            case WM_LBUTTONDOWN:
-                /* If the message belongs to the menu, removes it from the queue */
-                /* Else, end menu tracking */
-                fRemove = MenuButtonDown(&mt, hmenu, wFlags);
-                fEndMenu = !fRemove;
-                break;
+                /* no WM_NC... messages in captured state */
+
+                case WM_RBUTTONDBLCLK:
+                case WM_RBUTTONDOWN:
+                     if (!(wFlags & TPM_RIGHTBUTTON)) break;
+                    /* fall through */
+                case WM_LBUTTONDBLCLK:
+                case WM_LBUTTONDOWN:
+                    /* If the message belongs to the menu, removes it from the queue */
+                    /* Else, end menu tracking */
+                    fRemove = MenuButtonDown(&mt, hmenu, wFlags);
+                    fEndMenu = !fRemove;
+                    break;
 
-            case WM_RBUTTONUP:
-                if (!(wFlags & TPM_RIGHTBUTTON)) break;
-                /* fall through */
-            case WM_LBUTTONUP:
-                /* Check if a menu was selected by the mouse */
-                if (hmenu)
-                {
-                    executedMenuId = MenuButtonUp( &mt, hmenu, wFlags);
+                case WM_RBUTTONUP:
+                    if (!(wFlags & TPM_RIGHTBUTTON)) break;
+                    /* fall through */
+                case WM_LBUTTONUP:
+                    /* Check if a menu was selected by the mouse */
+                    if (hmenu)
+                    {
+                        executedMenuId = MenuButtonUp( &mt, hmenu, wFlags);
+                        TRACE("executedMenuId %d\n", executedMenuId);
 
                     /* End the loop if executedMenuId is an item ID */
                     /* or if the job was done (executedMenuId = 0). */
-                    fEndMenu = fRemove = (executedMenuId != -1);
-                }
-                else
-                {
+                        fEndMenu = fRemove = (executedMenuId != -1);
+                    }
                     /* No menu was selected by the mouse */
                     /* if the function was called by TrackPopupMenu, continue
                        with the menu tracking. If not, stop it */
-                    fEndMenu = ((wFlags & TPM_POPUPMENU) ? FALSE : TRUE);
-                }
-                break;
+                    else
+                        fEndMenu = ((wFlags & TPM_POPUPMENU) ? FALSE : TRUE);
 
-            case WM_MOUSEMOVE:
-                if (hmenu)
-                    fEndMenu |= !MenuMouseMove(&mt, hmenu, wFlags);
-                break;
+                    break;
 
-               } /* switch(Msg.message) - mouse */
-         }
-      else if ((msg.message >= WM_KEYFIRST) && (msg.message <= WM_KEYLAST))
-       {
-          fRemove = TRUE;  /* Keyboard messages are always removed */
-          switch(msg.message)
+                case WM_MOUSEMOVE:
+                    /* the selected menu item must be changed every time */
+                    /* the mouse moves. */
+
+                    if (hmenu)
+                        fEndMenu |= !MenuMouseMove( &mt, hmenu, wFlags );
+
+               } /* switch(msg.message) - mouse */
+           }
+        else if ((msg.message >= WM_KEYFIRST) && (msg.message <= WM_KEYLAST))
+        {
+            fRemove = TRUE;  /* Keyboard messages are always removed */
+            switch(msg.message)
             {
-              case WM_SYSKEYDOWN:
-              case WM_KEYDOWN:
+                case WM_KEYDOWN:
+                case WM_SYSKEYDOWN:
                 switch(msg.wParam)
-                  {
+                {
                     case VK_MENU:
-                      fEndMenu = TRUE;
-                      break;
+                    case VK_F10:
+                        fEndMenu = TRUE;
+                         break;
+
                     case VK_HOME:
                     case VK_END:
-                      if (MenuGetRosMenuInfo(&MenuInfo, mt.CurrentMenu))
+                        if (MenuGetRosMenuInfo(&MenuInfo, mt.CurrentMenu))
                         {
-                          MenuSelectItem(mt.OwnerWnd, &MenuInfo, NO_SELECTED_ITEM,
-                                         FALSE, 0 );
-                          MenuMoveSelection(mt.OwnerWnd, &MenuInfo,
-                                            VK_HOME == msg.wParam ? ITEM_NEXT : ITEM_PREV);
+                            MenuSelectItem(mt.OwnerWnd, &MenuInfo,
+                                    NO_SELECTED_ITEM, FALSE, 0 );
+                            MenuMoveSelection(mt.OwnerWnd, &MenuInfo,
+                                              VK_HOME == msg.wParam ? ITEM_NEXT : ITEM_PREV);
                         }
-                      break;
+                        break;
 
                     case VK_UP:
                     case VK_DOWN: /* If on menu bar, pull-down the menu */
-                      if (MenuGetRosMenuInfo(&MenuInfo, mt.CurrentMenu))
+                        if (MenuGetRosMenuInfo(&MenuInfo, mt.CurrentMenu))
                         {
-                          if (!(MenuInfo.Flags & MF_POPUP))
+                            if (!(MenuInfo.Flags & MF_POPUP))
                             {
-                              if (MenuGetRosMenuInfo(&MenuInfo, mt.TopMenu))
-                                {
-                                  mt.CurrentMenu = MenuShowSubPopup(mt.OwnerWnd, &MenuInfo,
-                                                                    TRUE, wFlags);
-                                }
-                            }
-                          else      /* otherwise try to move selection */
-                            {
-                              MenuMoveSelection(mt.OwnerWnd, &MenuInfo,
-                                            VK_DOWN == msg.wParam ? ITEM_NEXT : ITEM_PREV);
+                                if (MenuGetRosMenuInfo(&MenuInfo, mt.TopMenu))
+                                    mt.CurrentMenu = MenuShowSubPopup(mt.OwnerWnd, &MenuInfo, TRUE, wFlags);
                             }
+                            else      /* otherwise try to move selection */
+                                MenuMoveSelection(mt.OwnerWnd, &MenuInfo,
+                                       (msg.wParam == VK_UP)? ITEM_PREV : ITEM_NEXT );
                         }
-                      break;
+                        break;
 
                     case VK_LEFT:
-                      MenuKeyLeft(&mt, wFlags);
-                      break;
+                        MenuKeyLeft( &mt, wFlags );
+                        break;
 
                     case VK_RIGHT:
-                      MenuKeyRight(&mt, wFlags);
-                      break;
+                        MenuKeyRight( &mt, wFlags );
+                        break;
 
                     case VK_ESCAPE:
-                      fEndMenu = MenuKeyEscape(&mt, wFlags);
-                      break;
+                        fEndMenu = MenuKeyEscape(&mt, wFlags);
+                        break;
 
                     case VK_F1:
-                      {
+                    {
                         HELPINFO hi;
                         hi.cbSize = sizeof(HELPINFO);
                         hi.iContextType = HELPINFO_MENUITEM;
                         if (MenuGetRosMenuInfo(&MenuInfo, mt.CurrentMenu))
-                          {
-                            if (MenuInfo.FocusedItem == NO_SELECTED_ITEM) hi.iCtrlId = 0;
+                        {
+                            if (MenuInfo.FocusedItem == NO_SELECTED_ITEM)
+                                hi.iCtrlId = 0;
                             else
-                              {
+                            {
                                 MenuInitRosMenuItemInfo(&ItemInfo);
                                 if (MenuGetRosMenuItemInfo(MenuInfo.Self,
                                                            MenuInfo.FocusedItem,
                                                            &ItemInfo))
-                                  {
+                                {
                                     hi.iCtrlId = ItemInfo.wID;
-                                  }
+                                }
                                 else
-                                  {
+                                {
                                     hi.iCtrlId = 0;
-                                  }
+                                }
                                 MenuCleanupRosMenuItemInfo(&ItemInfo);
-                              }
-                          }
+                            }
+                        }
                         hi.hItemHandle = hmenu;
                         hi.dwContextId = MenuInfo.dwContextHelpID;
                         hi.MousePos = msg.pt;
-                        SendMessageW(hwnd, WM_HELP, 0, (LPARAM) &hi);
+                        SendMessageW(hwnd, WM_HELP, 0, (LPARAM)&hi);
                         break;
-                      }
+                    }
 
                     default:
-                      break;
-                  }
+                        break;
+                }
                 break;  /* WM_KEYDOWN */
 
                 case WM_CHAR:
@@ -3433,6 +3426,7 @@ static INT FASTCALL MenuTrackMenu(HMENU hmenu, UINT wFlags, INT x, INT y,
             PeekMessageW( &msg, 0, msg.message, msg.message, PM_REMOVE );
         else mt.TrackFlags &= ~TF_SKIPREMOVE;
     }
+    ERR("MenuTrackMenu 2\n");
 
     (void)NtUserSetGUIThreadHandle(MSQ_STATE_MENUOWNER, NULL);
     SetCapture(NULL);  /* release the capture */
@@ -3447,7 +3441,7 @@ static INT FASTCALL MenuTrackMenu(HMENU hmenu, UINT wFlags, INT x, INT y,
         {
             if (MenuGetRosMenuInfo(&MenuInfo, mt.TopMenu))
             {
-                MenuHideSubPopups(mt.OwnerWnd, &MenuInfo, FALSE);
+                MenuHideSubPopups(mt.OwnerWnd, &MenuInfo, FALSE, wFlags);
 
                 if (MenuInfo.Flags & MF_POPUP)
                 {
@@ -3496,31 +3490,35 @@ static BOOL FASTCALL MenuInitTracking(HWND hWnd, HMENU hMenu, BOOL bPopup, UINT
 
     SendMessageW( hWnd, WM_SETCURSOR, (WPARAM)hWnd, HTCAPTION );
 
+    MenuGetRosMenuInfo(&MenuInfo, hMenu);
+
     if (!(wFlags & TPM_NONOTIFY))
     {
        SendMessageW( hWnd, WM_INITMENU, (WPARAM)hMenu, 0 );
+       /* If an app changed/recreated menu bar entries in WM_INITMENU
+        * menu sizes will be recalculated once the menu created/shown.
+        */
 
-       MenuGetRosMenuInfo(&MenuInfo, hMenu);
-
-        if (!MenuInfo.Height)
-        {
-            /* app changed/recreated menu bar entries in WM_INITMENU
-               Recalculate menu sizes else clicks will not work */
-            SetWindowPos(hWnd, 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE |
+       if (!MenuInfo.Height)
+       {
+          /* app changed/recreated menu bar entries in WM_INITMENU
+             Recalculate menu sizes else clicks will not work */
+             SetWindowPos(hWnd, 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE |
                        SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED );
 
-        }
-        /* This makes the menus of applications built with Delphi work.
-         * It also enables menus to be displayed in more than one window,
-         * but there are some bugs left that need to be fixed in this case.
-         */
-        if(MenuInfo.Self == hMenu)
-        {
-            MenuInfo.Wnd = hWnd;
-            MenuSetRosMenuInfo(&MenuInfo);
-        }
+       }
     }
 
+    /* This makes the menus of applications built with Delphi work.
+     * It also enables menus to be displayed in more than one window,
+     * but there are some bugs left that need to be fixed in this case.
+     */
+    if(MenuInfo.Self == hMenu)
+    {
+        MenuInfo.Wnd = hWnd;
+        MenuSetRosMenuInfo(&MenuInfo);
+    }
     return TRUE;
 }
 /***********************************************************************
@@ -3533,6 +3531,7 @@ static BOOL FASTCALL MenuExitTracking(HWND hWnd)
     SendMessageW( hWnd, WM_EXITMENULOOP, 0, 0 );
     ShowCaret(0);
     top_popup = 0;
+    top_popup_hmenu = NULL;
     return TRUE;
 }
 
@@ -3544,7 +3543,7 @@ static BOOL FASTCALL MenuExitTracking(HWND hWnd)
 VOID MenuTrackMouseMenuBar( HWND hWnd, ULONG ht, POINT pt)
 {
     HMENU hMenu = (ht == HTSYSMENU) ? NtUserGetSystemMenu( hWnd, FALSE) : GetMenu(hWnd);
-    UINT wFlags = TPM_ENTERIDLEEX | TPM_BUTTONDOWN | TPM_LEFTALIGN | TPM_LEFTBUTTON;
+    UINT wFlags = TPM_BUTTONDOWN | TPM_LEFTALIGN | TPM_LEFTBUTTON;
 
     TRACE("wnd=%p ht=0x%04x (%ld,%ld)\n", hWnd, ht, pt.x, pt.y);
 
@@ -3574,7 +3573,7 @@ VOID MenuTrackKbdMenuBar(HWND hwnd, UINT wParam, WCHAR wChar)
     UINT uItem = NO_SELECTED_ITEM;
     HMENU hTrackMenu;
     ROSMENUINFO MenuInfo;
-    UINT wFlags = TPM_ENTERIDLEEX | TPM_LEFTALIGN | TPM_LEFTBUTTON;
+    UINT wFlags = TPM_LEFTALIGN | TPM_LEFTBUTTON;
 
     TRACE("hwnd %p wParam 0x%04x wChar 0x%04x\n", hwnd, wParam, wChar);
 
@@ -3638,6 +3637,42 @@ track_menu:
 
 }
 
+/**********************************************************************
+ *           TrackPopupMenuEx   (USER32.@)
+ */
+BOOL WINAPI TrackPopupMenuEx( HMENU Menu, UINT Flags, int x, int y,
+                              HWND Wnd, LPTPMPARAMS Tpm)
+{
+    BOOL ret = FALSE;
+
+    if (!IsMenu(Menu))
+    {
+      SetLastError( ERROR_INVALID_MENU_HANDLE );
+      return FALSE;
+    }
+
+    MenuInitTracking(Wnd, Menu, TRUE, Flags);
+
+    /* Send WM_INITMENUPOPUP message only if TPM_NONOTIFY flag is not specified */
+    if (!(Flags & TPM_NONOTIFY))
+        SendMessageW(Wnd, WM_INITMENUPOPUP, (WPARAM) Menu, 0);
+
+    if (MenuShowPopup(Wnd, Menu, 0, Flags, x, y, 0, 0 ))
+       ret = MenuTrackMenu(Menu, Flags | TPM_POPUPMENU, 0, 0, Wnd,
+                           Tpm ? &Tpm->rcExclude : NULL);
+    MenuExitTracking(Wnd);
+    return ret;
+}
+
+/**********************************************************************
+ *           TrackPopupMenu     (USER32.@)
+ */
+BOOL WINAPI TrackPopupMenu( HMENU Menu, UINT Flags, int x, int y,
+                            int Reserved, HWND Wnd, CONST RECT *Rect)
+{
+    return TrackPopupMenuEx( Menu, Flags, x, y, Wnd, NULL);
+}
+
 /*
  *  From MSDN:
  *  The MFT_BITMAP, MFT_SEPARATOR, and MFT_STRING values cannot be combined
@@ -4030,7 +4065,6 @@ DrawMenuBar(HWND hWnd)
   return TRUE;
 }
 
-
 /*
  * @implemented
  */
@@ -4052,11 +4086,48 @@ EndMenu(VOID)
   guii.cbSize = sizeof(GUITHREADINFO);
   if(GetGUIThreadInfo(GetCurrentThreadId(), &guii) && guii.hwndMenuOwner)
   {
-    PostMessageW(guii.hwndMenuOwner, WM_CANCELMODE, 0, 0);
+    if (!fEndMenu &&
+         top_popup &&
+         guii.hwndMenuOwner != top_popup )
+    {
+       ERR("Capture GUI pti hWnd does not match top_popup!\n");
+    }
+  }
+
+  /* if we are in the menu code, and it is active */
+  if (!fEndMenu && top_popup)
+  {
+      /* terminate the menu handling code */
+      fEndMenu = TRUE;
+
+      /* needs to be posted to wakeup the internal menu handler */
+      /* which will now terminate the menu, in the event that */
+      /* the main window was minimized, or lost focus, so we */
+      /* don't end up with an orphaned menu */
+      PostMessageW( top_popup, WM_CANCELMODE, 0, 0);
   }
   return TRUE;
 }
 
+// So this one maybe one day it will be a callback!
+BOOL WINAPI HiliteMenuItem( HWND hWnd, HMENU hMenu, UINT wItemID,
+                                UINT wHilite )
+{
+    ROSMENUINFO MenuInfo;
+    ROSMENUITEMINFO mii;
+    TRACE("(%p, %p, %04x, %04x);\n", hWnd, hMenu, wItemID, wHilite);
+    if (!hWnd)
+    {
+       SetLastError(ERROR_INVALID_WINDOW_HANDLE);
+       return FALSE;
+    }
+    if (!NtUserMenuItemInfo(hMenu, wItemID, wHilite, &mii, FALSE)) return FALSE;
+    if (!NtUserMenuInfo(hMenu, &MenuInfo, FALSE)) return FALSE;
+    if (MenuInfo.FocusedItem == wItemID) return TRUE;
+    MenuHideSubPopups( hWnd, &MenuInfo, FALSE, 0 );
+    MenuSelectItem( hWnd, &MenuInfo, wItemID, TRUE, 0 );
+    return TRUE;
+}
 
 /*
  * @implemented
@@ -4992,64 +5063,6 @@ SetSystemMenu (
   return NtUserSetSystemMenu(hwnd, hMenu);
 }
 
-
-/*
- * @implemented
- */
-BOOL
-WINAPI
-TrackPopupMenu(
-  HMENU Menu,
-  UINT Flags,
-  int x,
-  int y,
-  int Reserved,
-  HWND Wnd,
-  CONST RECT *Rect)
-{
-  BOOL ret = FALSE;
-
-  if (!IsMenu(Menu))
-  {
-    SetLastError( ERROR_INVALID_MENU_HANDLE );
-    return FALSE;
-  }
-
-  MenuInitTracking(Wnd, Menu, TRUE, Flags);
-
-  /* Send WM_INITMENUPOPUP message only if TPM_NONOTIFY flag is not specified */
-  if (0 == (Flags & TPM_NONOTIFY))
-    {
-      SendMessageW(Wnd, WM_INITMENUPOPUP, (WPARAM) Menu, 0);
-    }
-
-  if (MenuShowPopup(Wnd, Menu, 0, Flags, x, y, 0, 0 ))
-    {
-      ret = MenuTrackMenu(Menu, Flags | TPM_POPUPMENU, 0, 0, Wnd, Rect);
-    }
-  MenuExitTracking(Wnd);
-  return ret;
-}
-
-
-/*
- * @unimplemented
- */
-BOOL
-WINAPI
-TrackPopupMenuEx(
-  HMENU Menu,
-  UINT Flags,
-  int x,
-  int y,
-  HWND Wnd,
-  LPTPMPARAMS Tpm)
-{
-  /* Not fully implemented */
-  return TrackPopupMenu(Menu, Flags, x, y, 0, Wnd,
-                        NULL != Tpm ? &Tpm->rcExclude : NULL);
-}
-
 //
 // Example for the Win32/User32 rewrite.
 // Def = TrackPopupMenuEx@24=NtUserTrackPopupMenuEx@24