Release 940815

Tue Aug  9 23:58:29 MET DST 1994	<erik@hacktic.nl>

	* [misc/file.c]
	OpenFile(): Completly rewritten.

	* [miscemu/int21.c]
	CreateFile(): Fixed wrong mode in call to open.
	OpenExistingFile(): Implemented file sharing.
	FindNext(): Fixed.
	CreateNewFile(): Fixed wrong mode in call to open.
	fLock(): Added to handle record locking.
	GetFileAttribute(): Added.
	As a result, AH = 0x5c, 0x09, and 0x0b were changed.

	* [miscemu/int2f.c]
	AH = 0x10: SHARE installation check
 
	* [loader/resource.c]
	AccessResource(): Fixed. A new file descriptor will be returned by
	every call to AccessResource().

	* [windows/utility.c]
	wvsprintf(): Fixed.

	* [controls/menu.c]
	FindMenuItem(): Fixed (handling for nPos == -1 added).	

	* [windows/win.c]
	CreateWindowEx(): Added call to WINPOS_GetMinMaxInfo.

	* [Configure]
	Added two options for a processor emulator that might be
	plugged in later..

	* [loader/task.c] [include/toolhelp.h] [if1632/toolhelp.spec]
	CreateNewTask() stores real modulename instead of 'TASKxxxx'.
	Added TaskFirst(), TaskNext(), TaskFindHandle().

	* [memory/global.c]
	Added stub for MemManInfo().

	* [objects/text.c]
	Added stub for GetTabbedTextExt().

	* [miscemu/*]
	Changed all references to registers. Please don't access
 	the context structure.
	fix for GetSystemTime() by <jspeter@birch.ee.vt.edu> added.

	* [misc/lstr.c]
	Fixed bug in AnsiUpper() & AnsiLower().

	* [misc/winsocket.c]
	bugfix in getsockopt()/setsockopt(): winsock uses different values
	than unix.

	* [objects/dib.c]
	Added DIB_SetImageBits_RLE[48] to support compressed bitmaps.

Mon Aug  8 21:12:33 1994  David Metcalfe <david@prism.demon.co.uk>

	* [controls/edit.c]
	Added support for WM_COPY, WM_CUT and WM_PASTE messages.

	* [windows/dialog.c] [windows/defdlg.c] [include/dialog.h]
	Modified dialog code to create new heap for edit controls
	unless DS_LOCALEDIT style is set.

Thu Aug  4 18:50:56 1994  Alexandre Julliard  (julliard@lamisun.epfl.ch)

	* [controls/button.c] [controls/edit.c] [controls/static.c]
	Removed unneeded GlobalUnlock() calls.

	* [controls/menu.c] [include/menu.h]
	Lots of changes, fixed a lot of old bugs and introduced a lot of
	new ones :-)
	- Changed message loop to use MSG_GetInternalMessage().
	- Fixed a bug that caused the main window to lose activation when
	  displaying a menu.
	- Correctly send initialisation messages (WM_INITMENUPOPUP).
	- Implemented EndMenu() and LookupMenuHandle().
	- Changed internal structures to be as compatible as possible with
	  MS-Windows.
	- Allocated everything on the USER heap instead of the global heap.
	- Prefixed all internal function names with MENU_ and declared
	  them static.
	- Moved "About Wine..." handling to NC_HandleSysCommand().
	- Multi-line menus should now work correctly.

	* [loader/resource.c] [objects/bitmap.c]
	Added the possibility to create OEM bitmaps directly as X bitmaps.

	* [objects/dcvalues.c] [windows/dc.c]
	Fixed GetDCOrg() to return screen coordinates.

	* [windows/message.c]
	Fixed double-click checks when the message is not removed from the
	queue.
	Fixed MSG_GetInternalMessage() to send WM_ENTERIDLE messages.

	* [windows/nonclient.c]
	Bug fix in system menu hit-test calculation.
	A few changes for new menu functions.

Thu Aug 11 17:51:02 1994  Thomas Sandford <t.d.g.sandford@bradford.ac.uk>

        * [controls/edit.c]
        Bug fix in Edit_NCCreateMessage
        es->textlen was being used before being set

        * [controls/menu.c]
        Bug fix in MENU_DrawMenuItem
        don't try to write text if NULL pointer passed
diff --git a/controls/menu.c b/controls/menu.c
index 18ca832..0f791c7 100644
--- a/controls/menu.c
+++ b/controls/menu.c
@@ -3,71 +3,238 @@
  */
 static char RCSId[] = "$Id$";
 static char Copyright[] = "Copyright  Martin Ayotte, 1993";
+static char Copyright2[] = "Copyright  Alexandre Julliard, 1994";
+
+/*
+ * Note: the style MF_MOUSESELECT is used to mark popup items that
+ * have been selected, i.e. their popup menu is currently displayed.
+ * This is probably not the meaning this style has in MS-Windows.
+ */
 
 /*
 #define DEBUG_MENU
 */
 
+#include <ctype.h>
 #include <stdlib.h>
 #include <stdio.h>
+#include <string.h>
 #include "windows.h"
 #include "syscolor.h"
 #include "sysmetrics.h"
 #include "prototypes.h"
 #include "menu.h"
 #include "user.h"
-#include "heap.h"
 #include "win.h"
-
-#define SC_ABOUTWINE    	SC_SCREENSAVE+1
-#define SC_SYSMENU			SC_SCREENSAVE+2
-#define SC_ABOUTWINEDLG		SC_SCREENSAVE+3
+#include "message.h"
 
   /* Dimension of the menu bitmaps */
 static WORD check_bitmap_width = 0, check_bitmap_height = 0;
 static WORD arrow_bitmap_width = 0, arrow_bitmap_height = 0;
 
+  /* Flag set by EndMenu() to force an exit from menu tracking */
+static BOOL fEndMenuCalled = FALSE;
+
   /* Space between 2 menu bar items */
 #define MENU_BAR_ITEMS_SPACE  16
 
   /* Height of a separator item */
 #define SEPARATOR_HEIGHT      5
 
-extern HINSTANCE hSysRes;
-HMENU	hSysMenu = 0;
-HBITMAP hStdCheck = 0;
-HBITMAP hStdMnArrow = 0;
-static BOOL	MenuHasFocus = FALSE;
+  /* Values for menu->FocusedItem */
+  /* (other values give the position of the focused item) */
+#define NO_SELECTED_ITEM  0xffff
+#define SYSMENU_SELECTED  0xfffe  /* Only valid on menu-bars */
 
-LPPOPUPMENU PopupMenuGetStorageHeader(HWND hwnd);
-LPPOPUPMENU PopupMenuGetWindowAndStorage(HWND hwnd, WND **wndPtr);
-void StdDrawMenuBar(HDC hDC, LPRECT lprect, LPPOPUPMENU lppop, 
-		    BOOL suppress_draw);
-BOOL MenuButtonDown(HWND hWnd, LPPOPUPMENU lppop, int x, int y);
-void MenuButtonUp(HWND hWnd, LPPOPUPMENU lppop, int x, int y);
-void MenuMouseMove(HWND hWnd, LPPOPUPMENU lppop, WORD wParam, int x, int y);
-void StdDrawPopupMenu(HWND hwnd);
-void ResetHiliteFlags(LPPOPUPMENU lppop);
-void SelectPrevItem(LPPOPUPMENU lppop);
-void SelectNextItem(LPPOPUPMENU lppop);
-BOOL ExecFocusedMenuItem(HWND hWnd, LPPOPUPMENU lppop);
-void MenuItemSelect(HWND hWnd, LPPOPUPMENU lppop, WORD wIndex);
-LPMENUITEM MenuFindItem(LPPOPUPMENU lppop, int x, int y, WORD *lpRet);
-LPMENUITEM MenuFindItemBySelKey(LPPOPUPMENU lppop, WORD key, WORD *lpRet);
-BOOL ActivateMenuBarFocus(HWND hWnd);
-BOOL MenuFocusLoop(HWND hWnd, LPPOPUPMENU lpmenu);
-LPMENUITEM FindMenuItem(HMENU hMenu, WORD nPos, WORD wFlags);
-LPMENUITEM GetMenuItemPtr(LPPOPUPMENU menu, WORD nPos);
+#define IS_STRING_ITEM(flags) (!((flags) & (MF_BITMAP | MF_OWNERDRAW | \
+			     MF_MENUBARBREAK | MF_MENUBREAK | MF_SEPARATOR)))
+
+
+extern void NC_DrawSysButton(HWND hwnd, HDC hdc, BOOL down);  /* nonclient.c */
+extern void CURSOR_SetWinCursor( HWND hwnd, HCURSOR hcursor );   /* cursor.c */
+
+extern HINSTANCE hSysRes;
+
+static HMENU hSysMenu = 0;
+static HBITMAP hStdCheck = 0;
+static HBITMAP hStdMnArrow = 0;
+
 WORD GetSelectionKey(LPSTR str);
 LPSTR GetShortCutString(LPSTR str);
 int GetShortCutPos(LPSTR str);
-BOOL HideAllSubPopupMenu(LPPOPUPMENU menu);
-void InitStdBitmaps();
 HMENU CopySysMenu();
 WORD * ParseMenuResource(WORD *first_item, int level, HMENU hMenu);
-void SetMenuLogicalParent(HMENU hMenu, HWND hWnd);
 
-BOOL FAR PASCAL AboutWine_Proc(HWND hDlg, WORD msg, WORD wParam, LONG lParam);
+
+/***********************************************************************
+ *           MENU_Init
+ *
+ * Menus initialisation.
+ */
+BOOL MENU_Init()
+{
+    BITMAP bm;
+
+      /* Load bitmaps */
+
+    if (!(hStdCheck = LoadBitmap( 0, MAKEINTRESOURCE(OBM_CHECK) )))
+	return FALSE;
+    GetObject( hStdCheck, sizeof(BITMAP), (LPSTR)&bm );
+    check_bitmap_width = bm.bmWidth;
+    check_bitmap_height = bm.bmHeight;
+    if (!(hStdMnArrow = LoadBitmap( 0, MAKEINTRESOURCE(OBM_MNARROW) )))
+	return FALSE;
+    GetObject( hStdMnArrow, sizeof(BITMAP), (LPSTR)&bm );
+    arrow_bitmap_width = bm.bmWidth;
+    arrow_bitmap_height = bm.bmHeight;
+
+      /* Load system menu */
+
+    if (!(hSysMenu = LoadMenu( hSysRes, "SYSMENU" )))
+    {
+	printf("SysMenu not found in system resources !\n");
+	return FALSE;
+    }
+
+    return TRUE;
+}
+
+
+/***********************************************************************
+ *           MENU_HasSysMenu
+ *
+ * Check whether the window owning the menu bar has a system menu.
+ */
+static BOOL MENU_HasSysMenu( POPUPMENU *menu )
+{
+    WND *wndPtr;
+
+    if (menu->wFlags & MF_POPUP) return FALSE;
+    if (!(wndPtr = WIN_FindWndPtr( menu->hWnd ))) return FALSE;
+    return (wndPtr->dwStyle & WS_SYSMENU) != 0;
+}
+
+
+/***********************************************************************
+ *           MENU_IsInSysMenu
+ *
+ * Check whether the point (in screen coords) is in the system menu
+ * of the window owning the given menu.
+ */
+static BOOL MENU_IsInSysMenu( POPUPMENU *menu, POINT pt )
+{
+    WND *wndPtr;
+
+    if (menu->wFlags & MF_POPUP) return FALSE;
+    if (!(wndPtr = WIN_FindWndPtr( menu->hWnd ))) return FALSE;
+    if (!(wndPtr->dwStyle & WS_SYSMENU)) return FALSE;
+    if ((pt.x < wndPtr->rectClient.left) ||
+	(pt.x >= wndPtr->rectClient.left+SYSMETRICS_CXSIZE+SYSMETRICS_CXBORDER))
+	return FALSE;
+    if ((pt.y >= wndPtr->rectClient.top - menu->Height) ||
+	(pt.y < wndPtr->rectClient.top - menu->Height -
+	              SYSMETRICS_CYSIZE - SYSMETRICS_CYBORDER)) return FALSE;
+    return TRUE;
+}
+
+
+/***********************************************************************
+ *           MENU_FindItem
+ *
+ * Find a menu item. Return a pointer on the item, and modifies *hmenu
+ * in case the item was in a sub-menu.
+ */
+static MENUITEM *MENU_FindItem( HMENU *hmenu, WORD *nPos, WORD wFlags )
+{
+    POPUPMENU *menu;
+    MENUITEM *item;
+    int i;
+
+    if (!(menu = (POPUPMENU *) USER_HEAP_ADDR(*hmenu))) return NULL;
+    item = (MENUITEM *) USER_HEAP_ADDR( menu->hItems );
+    if (wFlags & MF_BYPOSITION)
+    {
+	if (*nPos >= menu->nItems) return NULL;
+	return &item[*nPos];
+    }
+    else
+    {
+	for (i = 0; i < menu->nItems; i++, item++)
+	{
+	    if (item->item_id == *nPos)
+	    {
+		*nPos = i;
+		return item;
+	    }
+	    else if (item->item_flags & MF_POPUP)
+	    {
+		HMENU hsubmenu = (HMENU)item->item_id;
+		MENUITEM *subitem = MENU_FindItem( &hsubmenu, nPos, wFlags );
+		if (subitem)
+		{
+		    *hmenu = hsubmenu;
+		    return subitem;
+		}
+	    }
+	}
+    }
+    return NULL;
+}
+
+
+/***********************************************************************
+ *           MENU_FindItemByCoords
+ *
+ * Find the item at the specified coordinates (screen coords).
+ */
+static MENUITEM *MENU_FindItemByCoords( POPUPMENU *menu, int x, int y, WORD *pos )
+{
+    MENUITEM *item;
+    WND *wndPtr;
+    int i;
+
+    if (!(wndPtr = WIN_FindWndPtr( menu->hWnd ))) return NULL;
+    x -= wndPtr->rectWindow.left;
+    y -= wndPtr->rectWindow.top;
+    item = (MENUITEM *) USER_HEAP_ADDR( menu->hItems );
+    for (i = 0; i < menu->nItems; i++, item++)
+    {
+	if ((x >= item->rect.left) && (x < item->rect.right) &&
+	    (y >= item->rect.top) && (y < item->rect.bottom))
+	{
+	    if (pos) *pos = i;
+	    return item;
+	}
+    }
+    return NULL;
+}
+
+
+/***********************************************************************
+ *           MENU_FindItemByKey
+ *
+ * Find the menu item selected by a key press.
+ * Return item id, -1 if none, -2 if we should close the menu.
+ */
+static WORD MENU_FindItemByKey( HWND hwndOwner, HMENU hmenu, WORD key )
+{
+    POPUPMENU *menu;
+    LPMENUITEM lpitem;
+    int i;
+    LONG menuchar;
+
+    menu = (POPUPMENU *) USER_HEAP_ADDR( hmenu );
+    lpitem = (MENUITEM *) USER_HEAP_ADDR( menu->hItems );
+    for (i = 0; i < menu->nItems; i++, lpitem++)
+    {
+	if (toupper(key) == lpitem->sel_key) return i;
+    }
+    menuchar = SendMessage( hwndOwner, WM_MENUCHAR, key,
+			    MAKELONG( menu->wFlags, hmenu ) );
+    if (HIWORD(menuchar) == 2) return LOWORD(menuchar);
+    if (HIWORD(menuchar) == 1) return -2;
+    return -1;
+}
 
 
 /***********************************************************************
@@ -87,7 +254,12 @@
 	return;
     }
 
-    if (!menuBar) lpitem->rect.right += check_bitmap_width+arrow_bitmap_width;
+    if (!menuBar)
+    {
+	lpitem->rect.right += 2 * check_bitmap_width;
+	if (lpitem->item_flags & MF_POPUP)
+	    lpitem->rect.right += arrow_bitmap_width;
+    }
 
     if (lpitem->item_flags & MF_BITMAP)
     {
@@ -113,30 +285,27 @@
  *
  * Calculate the size of a popup menu.
  */
-static void MENU_PopupMenuCalcSize( HWND hwnd )
+static void MENU_PopupMenuCalcSize( LPPOPUPMENU lppop )
 {
-    LPPOPUPMENU lppop;
-    LPMENUITEM  lpitem, lpitemStart, lptmp;
-    WND *wndPtr;
+    LPMENUITEM  items, lpitem;
     HDC hdc;
-    int orgX, orgY, maxX;
+    int start, i, orgX, orgY, maxX;
 
-    if (!(lppop = PopupMenuGetWindowAndStorage(hwnd, &wndPtr))) return;
-    SetRect( &lppop->rect, 0, 0, 0, 0 );
     lppop->Width = lppop->Height = 0;
     if (lppop->nItems == 0) return;
-    hdc = GetDC( hwnd );
-    maxX = 0;
-    lpitemStart = lppop->firstItem;
-    while (lpitemStart != NULL)
+    items = (MENUITEM *)USER_HEAP_ADDR( lppop->hItems );
+    hdc = GetDC( 0 );
+    maxX = start = 0;
+    while (start < lppop->nItems)
     {
+	lpitem = &items[start];
 	orgX = maxX;
 	orgY = 0;
 
 	  /* Parse items until column break or end of menu */
-	for (lpitem = lpitemStart; lpitem != NULL; lpitem = lpitem->next)
+	for (i = start; i < lppop->nItems; i++, lpitem++)
 	{
-	    if ((lpitem != lpitemStart) &&
+	    if ((i != start) &&
 		(lpitem->item_flags & (MF_MENUBREAK | MF_MENUBARBREAK))) break;
 	    MENU_CalcItemSize( hdc, lpitem, orgX, orgY, FALSE );
 	    maxX = max( maxX, lpitem->rect.right );
@@ -144,19 +313,12 @@
 	}
 
 	  /* Finish the column (set all items to the largest width found) */
-	for (lptmp = lpitemStart; lptmp != lpitem; lptmp = lptmp->next)
-	{
-	    lptmp->rect.right = maxX;
-	}
-
-	  /* And go to the next column */
+	while (start < i) items[start++].rect.right = maxX;
 	lppop->Height = max( lppop->Height, orgY );
-	lpitemStart = lpitem;
     }
 
     lppop->Width  = maxX;
-    SetRect( &lppop->rect, 0, 0, lppop->Width, lppop->Height );
-    ReleaseDC( hwnd, hdc );
+    ReleaseDC( 0, hdc );
 }
 
 
@@ -167,8 +329,8 @@
  */
 static void MENU_MenuBarCalcSize( HDC hdc, LPRECT lprect, LPPOPUPMENU lppop )
 {
-    LPMENUITEM lpitem, lpitemStart, lptmp;
-    int orgX, orgY, maxY;
+    LPMENUITEM lpitem, items;
+    int start, i, orgX, orgY, maxY;
 
     if ((lprect == NULL) || (lppop == NULL)) return;
     if (lppop->nItems == 0) return;
@@ -176,25 +338,26 @@
 	printf("MenuBarCalcSize left=%d top=%d right=%d bottom=%d !\n", 
 		lprect->left, lprect->top, lprect->right, lprect->bottom);
 #endif
+    items = (MENUITEM *)USER_HEAP_ADDR( lppop->hItems );
     lppop->Width  = lprect->right - lprect->left;
     lppop->Height = 0;
     maxY = lprect->top;
-
-    lpitemStart = lppop->firstItem;
-    while (lpitemStart != NULL)
+    start = 0;
+    while (start < lppop->nItems)
     {
+	lpitem = &items[start];
 	orgX = lprect->left;
 	orgY = maxY;
 
 	  /* Parse items until line break or end of menu */
-	for (lpitem = lpitemStart; lpitem != NULL; lpitem = lpitem->next)
+	for (i = start; i < lppop->nItems; i++, lpitem++)
 	{
-	    if ((lpitem != lpitemStart) &&
+	    if ((i != start) &&
 		(lpitem->item_flags & (MF_MENUBREAK | MF_MENUBARBREAK))) break;
 	    MENU_CalcItemSize( hdc, lpitem, orgX, orgY, TRUE );
 	    if (lpitem->rect.right > lprect->right)
 	    {
-		if (lpitem != lpitemStart) break;
+		if (i != start) break;
 		else lpitem->rect.right = lprect->right;
 	    }
 	    maxY = max( maxY, lpitem->rect.bottom );
@@ -202,18 +365,11 @@
 	}
 
 	  /* Finish the line (set all items to the largest height found) */
-	for (lptmp = lpitemStart; lptmp != lpitem; lptmp = lptmp->next)
-	{
-	    lptmp->rect.bottom = maxY;
-	}
-
-	  /* And go to the next line */
-	lpitemStart = lpitem;
+	while (start < i) items[start++].rect.bottom = maxY;
     }
 
     lprect->bottom = maxY;
     lppop->Height = lprect->bottom - lprect->top;
-    CopyRect( &lppop->rect, lprect );
 }
 
 
@@ -223,7 +379,7 @@
  * Draw a single menu item.
  */
 static void MENU_DrawMenuItem( HDC hdc, LPMENUITEM lpitem,
-			       LPRECT menuRect, BOOL menuBar )
+			       WORD height, BOOL menuBar )
 {
     RECT rect;
 
@@ -242,8 +398,8 @@
     if (!menuBar && (lpitem->item_flags & MF_MENUBARBREAK))
     {
 	SelectObject( hdc, sysColorObjects.hpenWindowFrame );
-	MoveTo( hdc, rect.left, menuRect->top );
-	LineTo( hdc, rect.left, menuRect->bottom );
+	MoveTo( hdc, rect.left, 0 );
+	LineTo( hdc, rect.left, height );
     }
     if (lpitem->item_flags & MF_SEPARATOR)
     {
@@ -252,6 +408,25 @@
 	LineTo( hdc, rect.right, rect.top + SEPARATOR_HEIGHT/2 );
     }
 
+      /* Setup colors */
+
+    if (lpitem->item_flags & MF_HILITE)
+    {
+	if (lpitem->item_flags & MF_GRAYED)
+	    SetTextColor( hdc, GetSysColor( COLOR_GRAYTEXT ) );
+	else
+	    SetTextColor( hdc, GetSysColor( COLOR_HIGHLIGHTTEXT ) );
+	SetBkColor( hdc, GetSysColor( COLOR_HIGHLIGHT ) );
+    }
+    else
+    {
+	if (lpitem->item_flags & MF_GRAYED)
+	    SetTextColor( hdc, GetSysColor( COLOR_GRAYTEXT ) );
+	else
+	    SetTextColor( hdc, GetSysColor( COLOR_MENUTEXT ) );
+	SetBkColor( hdc, GetSysColor( COLOR_MENU ) );
+    }
+
     if (!menuBar)
     {
 	  /* Draw the check mark */
@@ -287,7 +462,7 @@
 	{
 	    HDC hMemDC = CreateCompatibleDC( hdc );
 	    SelectObject(hMemDC, hStdMnArrow);
-	    BitBlt( hdc, rect.right-arrow_bitmap_width,
+	    BitBlt( hdc, rect.right-arrow_bitmap_width-1,
 		    (rect.top + rect.bottom - arrow_bitmap_height) / 2,
 		    arrow_bitmap_width, arrow_bitmap_height,
 		    hMemDC, 0, 0, SRCCOPY );
@@ -298,22 +473,6 @@
 	rect.right -= arrow_bitmap_width;
     }
 
-      /* Setup colors */
-
-    if (lpitem->item_flags & MF_HILITE)
-    {
-	SetTextColor( hdc, GetSysColor( COLOR_HIGHLIGHTTEXT ) );
-	SetBkColor( hdc, GetSysColor( COLOR_HIGHLIGHT ) );
-    }
-    else
-    {
-	if (lpitem->item_flags & MF_GRAYED)
-	    SetTextColor( hdc, GetSysColor( COLOR_GRAYTEXT ) );
-	else
-	    SetTextColor( hdc, GetSysColor( COLOR_MENUTEXT ) );
-	SetBkColor( hdc, GetSysColor( COLOR_MENU ) );
-    }
-
       /* Draw the item text or bitmap */
 
     if (lpitem->item_flags & MF_BITMAP)
@@ -327,7 +486,8 @@
 	DeleteDC( hMemDC );
 	return;
     }
-    else  /* No bitmap */
+    /* No bitmap - process text if present */
+    else if ((lpitem->item_text) != ((char *) NULL)) 
     {
 	int x = GetShortCutPos(lpitem->item_text);
 	if (menuBar)
@@ -349,735 +509,869 @@
 
 
 /***********************************************************************
- *           PopupMenuWndProc
+ *           MENU_DrawPopupMenu
+ *
+ * Paint a popup menu.
  */
-LONG PopupMenuWndProc( HWND hwnd, WORD message, WORD wParam, LONG lParam )
-{    
-	CREATESTRUCT *createStruct;
-	WORD	wRet;
-	short	x, y;
-	WND  	*wndPtr;
-	LPPOPUPMENU lppop, lppop2;
-	LPMENUITEM	lpitem, lpitem2;
-	HMENU	hSubMenu;
-	RECT	rect;
-	HDC		hDC;
-	PAINTSTRUCT ps;
-	switch(message) {
-	case WM_CREATE:
-#ifdef DEBUG_MENU
-		printf("PopupMenu WM_CREATE lParam=%08X !\n", lParam);
-#endif
-		createStruct = (CREATESTRUCT *)lParam;
-		lppop = (LPPOPUPMENU)createStruct->lpCreateParams;
-		if (lppop == NULL) break;
-		wndPtr = WIN_FindWndPtr(hwnd);
-		*((LPPOPUPMENU *)&wndPtr->wExtra[1]) = lppop;
-#ifdef DEBUG_MENU
-		printf("PopupMenu WM_CREATE lppop=%08X !\n", lppop);
-#endif
-		InitStdBitmaps();
-#ifdef DEBUG_MENU
-		printf("PopupMenu End of WM_CREATE !\n");
-#endif
-		ResetHiliteFlags(lppop);
-		return 0;
-	case WM_DESTROY:
-		lppop = PopupMenuGetWindowAndStorage(hwnd, &wndPtr);
-#ifdef DEBUG_MENU
-		printf("PopupMenu WM_DESTROY %lX !\n", lppop);
-#endif
-		return 0;
-	case WM_COMMAND:
-#ifdef DEBUG_MENU
-		printf("PopupMenuWndProc // WM_COMMAND received !\n");
-#endif
-		lppop = PopupMenuGetWindowAndStorage(hwnd, &wndPtr);
-		if (lppop == NULL) break;
-		if (lppop->SysFlag) {
-			MenuHasFocus = FALSE;
-			if (wParam == SC_ABOUTWINE) {
-				printf("SysMenu // Show 'About Wine ...' !\n");
-/*				DialogBox(hSysRes, MAKEINTRESOURCE(SC_ABOUTWINEDLG), */
-				DialogBox(hSysRes, MAKEINTRESOURCE(2), 
-					GetParent(hwnd), (FARPROC)AboutWine_Proc);
-				}
-			else {
-#ifdef DEBUG_MENU
-				printf("PopupMenuWndProc // push to Owner WM_SYSCOMMAND !\n");
-#endif
-				PostMessage(lppop->ownerWnd, WM_SYSCOMMAND, wParam, lParam);
-				}
-			break;
-			}
-#ifdef DEBUG_MENU
-		printf("PopupMenuWndProc // push to Owner WM_COMMAND !\n");
-#endif
-		MenuHasFocus = FALSE;
-		PostMessage(lppop->hWndParent, WM_COMMAND, wParam, lParam);
-		break;
-	case WM_SHOWWINDOW:
-#ifdef DEBUG_MENU
-		printf("PopupMenuWndProc // WM_SHOWWINDOW received !\n");
-#endif
-		lppop = PopupMenuGetWindowAndStorage(hwnd, &wndPtr);
-		if (lppop == NULL) break;
-		if (wParam == 0 && lParam == 0L) {
-			ResetHiliteFlags(lppop);
-			HideAllSubPopupMenu(lppop);
-#ifdef DEBUG_MENU
-			printf("PopupMenuWndProc hWnd=%04X WM_SHOWWINDOW -> HIDE!\n", hwnd);
-#endif
-			if (lppop->SysFlag) MenuHasFocus = FALSE;
-			SetFocus(lppop->hWndPrev);
-			if (GetCapture() != 0) ReleaseCapture(); 
-			break;
-			}
-		lppop->FocusedItem = (WORD)-1;
-    	break;
-	case WM_LBUTTONDOWN:
-		lppop = PopupMenuGetWindowAndStorage(hwnd, &wndPtr);
-		if (lppop == NULL) break;
-		SetCapture(hwnd); 
-		MenuButtonDown(hwnd, lppop, LOWORD(lParam), HIWORD(lParam));
-		break;
-	case WM_LBUTTONUP:
-		lppop = PopupMenuGetStorageHeader(hwnd);
-		if (lppop == NULL) break;
-		ReleaseCapture(); 
-		MenuButtonUp(hwnd, lppop, LOWORD(lParam), HIWORD(lParam));
-		break;
-	case WM_MOUSEMOVE:
-		lppop = PopupMenuGetStorageHeader(hwnd);
-		if (lppop == NULL) break;
-		MenuMouseMove(hwnd, lppop, wParam, LOWORD(lParam), HIWORD(lParam));
-		break;
+static void MENU_DrawPopupMenu( HWND hwnd, HDC hdc, HMENU hmenu )
+{
+    POPUPMENU *menu;
+    MENUITEM *item;
+    RECT rect;
+    int i;
 
-	case WM_KEYUP:
-#ifdef DEBUG_MENU
-		printf("PopupMenuWndProc hWnd=%04X WM_KEYUP w=%04X l=%08X !\n", 
-												hwnd, wParam, lParam);
-#endif
-		break;
-	case WM_KEYDOWN:
-#ifdef DEBUG_MENU
-		printf("PopupMenuWndProc hWnd=%04X WM_KEYDOWN w=%04X l=%08X !\n", 
-												hwnd, wParam, lParam);
-#endif
-		if (lParam < 0L) break;
-		lppop = PopupMenuGetWindowAndStorage(hwnd, &wndPtr);
-		if (lppop == NULL) break;
-		switch(wParam) {
-			case VK_HOME:
-				if (lppop->FocusedItem == 0) break;
-				MenuItemSelect(hwnd, lppop, 0);
-				break;
-			case VK_UP:
-				if (lppop->BarFlag) break;
-				SelectPrevItem(lppop);
-				break;
-			case VK_DOWN:
-				if (lppop->BarFlag) goto ProceedSPACE;
-				SelectNextItem(lppop);
-				break;
-			case VK_LEFT:
-				if (lppop->SysFlag != 0) {
-					ShowWindow(hwnd, SW_HIDE);
-					hwnd = lppop->hWndParent;
-					lppop = PopupMenuGetWindowAndStorage(hwnd, &wndPtr);
-					printf("VK_LEFT // try to put focus on MenuBar %08X !\n", lppop);
-					if (lppop == NULL) break;
-					MenuItemSelect(hwnd, lppop, lppop->nItems - 1);
-				    break;
-					}
-				if (lppop->BarFlag) {
-					if (lppop->FocusedItem < 1) {
-						MenuItemSelect(hwnd, lppop, -1);
-						NC_TrackSysMenu(hwnd);
-						break;
-						}
-					if (HideAllSubPopupMenu(lppop)) {
-						MenuItemSelect(hwnd, lppop, lppop->FocusedItem - 1);
-						goto ProceedSPACE;
-						}
-					}
-			    if (lppop->hWndParent != 0) {
-					PostMessage(lppop->hWndParent, WM_KEYDOWN, wParam, lParam);
-				    break;
-				    }
-				MenuItemSelect(hwnd, lppop, lppop->FocusedItem - 1);
-				break;
-			case VK_RIGHT:
-				if (lppop->SysFlag != 0) {
-					ShowWindow(hwnd, SW_HIDE);
-					hwnd = lppop->hWndParent;
-					lppop = PopupMenuGetWindowAndStorage(hwnd, &wndPtr);
-					printf("VK_RIGHT // try to put focus on MenuBar %08X !\n", lppop);
-					if (lppop == NULL) break;
-					MenuItemSelect(hwnd, lppop, 0);
-				    break;
-					}
-				if (lppop->BarFlag) {
-					if (lppop->FocusedItem >= lppop->nItems - 1) {
-						MenuItemSelect(hwnd, lppop, -1);
-						NC_TrackSysMenu(hwnd);
-						break;
-						}
-					if (HideAllSubPopupMenu(lppop)) {
-						MenuItemSelect(hwnd, lppop, lppop->FocusedItem + 1);
-						goto ProceedSPACE;
-						}
-					}
-			    if (lppop->hWndParent != 0) {
-					PostMessage(lppop->hWndParent, WM_KEYDOWN, wParam, lParam);
-				    break;
-				    }
-				MenuItemSelect(hwnd, lppop, lppop->FocusedItem + 1);
-				break;
-			default:
-				break;
-			}
-			break;
-	case WM_CHAR:
-#ifdef DEBUG_MENU
-		printf("PopupMenuWndProc hWnd=%04X WM_CHAR wParam=%04X !\n", hwnd, wParam);
-#endif
-		if (lParam < 0L) break;
-		hwnd = GetFocus();
-		lppop = PopupMenuGetWindowAndStorage(hwnd, &wndPtr);
-		if (lppop == NULL) break;
-		switch(wParam) {
-			case VK_RETURN:
-			case VK_SPACE:
-ProceedSPACE:	lppop = PopupMenuGetWindowAndStorage(hwnd, &wndPtr);
-				ExecFocusedMenuItem(hwnd, lppop);
-				break;
-			case VK_ESCAPE:
-				if (lppop->BarFlag) {
-#ifdef DEBUG_MENU
-					printf("VK_ESCAPE // Unselect all MenuBar's Items !\n");
-#endif
-					if (lppop->FocusedItem != (WORD)-1)
-						MenuItemSelect(hwnd, lppop, -1);
-					}
-				if (lppop->SysFlag) {
-#ifdef DEBUG_MENU
-					printf("VK_ESCAPE // SysMenu !\n");
-#endif
-					ShowWindow(hwnd, SW_HIDE);
-					break;
-					}
-				if (lppop->hWndParent != 0) {
-#ifdef DEBUG_MENU
-					printf("VK_ESCAPE // Hide only SubPopup !\n");
-#endif
-					lppop2 = PopupMenuGetWindowAndStorage(lppop->hWndParent, &wndPtr);
-					if (lppop2 == NULL) break;
-					HideAllSubPopupMenu(lppop2);
-					break;
-					}
-				else {
-#ifdef DEBUG_MENU
-					printf("VK_ESCAPE // Hide Root Popup !\n");
-#endif
-					ShowWindow(hwnd, SW_HIDE);
-					MenuHasFocus = FALSE;
-					}
-				break;
-			default:
-				if (wParam >= 'a' && wParam <= 'z') wParam -= 'a' - 'A';
-				lpitem = MenuFindItemBySelKey(lppop, wParam, &wRet);
-				if (lpitem != NULL) {
-				    printf("ShortKey Found  wRet=%d !\n", wRet);
-					MenuItemSelect(hwnd, lppop, wRet);
-					lppop->FocusedItem = wRet;
-					goto ProceedSPACE;
-					}
-			    printf("ShortKey Not Found wParam=%04X wRet=%d lpitem=%08X !\n",
-					wParam, wRet, lpitem);
-				if (lppop->hWndParent != (HWND)NULL)
-					SendMessage(lppop->hWndParent, WM_MENUCHAR, wParam, 
-						MAKELONG(0, 0));
-				else 
-					SendMessage(lppop->ownerWnd, WM_MENUCHAR, wParam, 
-						MAKELONG(0, 0));
-				break;
-			}
-		break;
-	case WM_PAINT:
-#ifdef DEBUG_MENU
-		printf("PopupMenuWndProc // WM_PAINT received !\n");
-#endif
-		StdDrawPopupMenu(hwnd);
-		break;
-	default:
-		return DefWindowProc(hwnd, message, wParam, lParam);
-    }
-return 0;
+    GetClientRect( hwnd, &rect );
+    FillRect( hdc, &rect, sysColorObjects.hbrushMenu );
+    menu = (POPUPMENU *) USER_HEAP_ADDR( hmenu );
+    if (!menu || !menu->nItems) return;
+    item = (MENUITEM *) USER_HEAP_ADDR( menu->hItems );
+    for (i = menu->nItems; i > 0; i--, item++)
+	MENU_DrawMenuItem( hdc, item, menu->Height, FALSE );
 }
 
 
-BOOL ExecFocusedMenuItem(HWND hWnd, LPPOPUPMENU lppop)
+/***********************************************************************
+ *           MENU_DrawMenuBar
+ *
+ * Paint a menu bar. Returns the height of the menu bar.
+ */
+WORD MENU_DrawMenuBar(HDC hDC, LPRECT lprect, HMENU hmenu, BOOL suppress_draw)
 {
-	short	x, y;
-	LPPOPUPMENU lppop2;
-	LPMENUITEM	lpitem;
-	HMENU	hSubMenu;
-	RECT	rect;
-	lpitem = GetMenuItemPtr(lppop, lppop->FocusedItem);
-	if ((lpitem->item_flags & MF_POPUP) == MF_POPUP) {
-		hSubMenu = (HMENU)lpitem->item_id;
-		lppop2 = (LPPOPUPMENU) GlobalLock(hSubMenu);
-		if (lppop2 == NULL) return FALSE;
-		lppop2->hWndParent = hWnd;
-		GetClientRect(hWnd, &rect);
-		if (lppop->BarFlag) {
-			GetWindowRect(hWnd, &rect);
-			y = rect.top + lpitem->rect.bottom;
-			TrackPopupMenu(hSubMenu, TPM_LEFTBUTTON, 
-				rect.left + lpitem->rect.left, 
-				y, 0, lppop->ownerWnd, (LPRECT)NULL);
-			}
-		else {
-			x = lppop->rect.right;
-			GetWindowRect(hWnd, &rect);
-			x += rect.left;
-			TrackPopupMenu(hSubMenu, TPM_LEFTBUTTON, 
-				x, rect.top + lpitem->rect.top,
-				0, lppop->ownerWnd, (LPRECT)NULL);
-			}
-		GlobalUnlock(hSubMenu);
-		return TRUE;
-		}
-	if (((lpitem->item_flags & MF_SEPARATOR) != MF_SEPARATOR) &&
-		((lpitem->item_flags & MF_POPUP) != MF_POPUP)) {
-		MenuHasFocus = FALSE;
-		if (lppop->BarFlag) {
-			PostMessage(lppop->ownerWnd, WM_COMMAND, lpitem->item_id, 0L);
-			}
-		else {
-			ShowWindow(lppop->hWnd, SW_HIDE);
-			SendMessage(lppop->hWnd, WM_COMMAND, lpitem->item_id, 0L);
-			}
-		}
-	return TRUE;
-}
-
-
-
-BOOL MenuButtonDown(HWND hWnd, LPPOPUPMENU lppop, int x, int y)
-{
-	HDC		hDC;
-	LPMENUITEM	lpitem, lpitem2;
-	RECT	rect;
-	HMENU	hSubMenu;
-	WORD	wRet;
-	LPPOPUPMENU lppop2;
-	if (lppop == NULL) return;
-	lpitem = MenuFindItem(lppop, x, y, &wRet);
-#ifdef DEBUG_MENU
-	printf("MenuButtonDown hWnd=%04X x=%d y=%d // wRet=%d lpitem=%08X !\n", 
-											hWnd, x, y, wRet, lpitem);
-#endif
-	if (lpitem != NULL) {
-		if (lppop->FocusedItem != (WORD)-1 && wRet == lppop->FocusedItem) {
-			lpitem2 = GetMenuItemPtr(lppop, lppop->FocusedItem);
-			if ((lpitem2->item_flags & MF_POPUP) == MF_POPUP) {
-				hSubMenu = (HMENU)lpitem2->item_id;
-				lppop2 = (LPPOPUPMENU) GlobalLock(hSubMenu);
-				if (lppop2 == NULL) return FALSE;
-				if (IsWindowVisible(lppop2->hWnd)) {
-					ShowWindow(lppop2->hWnd, SW_HIDE);
-					return TRUE;
-					}
-				}
-			}
-		MenuItemSelect(hWnd, lppop, wRet);
-		if ((lpitem->item_flags & MF_POPUP) == MF_POPUP) {
-			hSubMenu = (HMENU)lpitem->item_id;
-			lppop2 = (LPPOPUPMENU) GlobalLock(hSubMenu);
-			if (lppop2 == NULL) return FALSE;
-			lppop2->hWndParent = hWnd;
-			if (lppop->BarFlag) {
-				GetWindowRect(hWnd, &rect);
-				y = rect.top + lpitem->rect.bottom;
-				ReleaseCapture(); 
-				if (MenuHasFocus) {
-					TrackPopupMenu(hSubMenu, TPM_LEFTBUTTON, 
-						rect.left + lpitem->rect.left, 
-						y, 0, lppop->ownerWnd, (LPRECT)NULL);
-					}
-				else {
-					MenuHasFocus = TRUE;
-					TrackPopupMenu(hSubMenu, TPM_LEFTBUTTON, 
-						rect.left + lpitem->rect.left, 
-						y, 0, lppop->ownerWnd, (LPRECT)NULL);
-					MenuHasFocus = FALSE;
-					MenuFocusLoop(hWnd, lppop);
-					return TRUE;
-					}
-				}
-			else {
-				x = lppop->rect.right;
-				GetWindowRect(hWnd, &rect);
-				x += rect.left;
-				TrackPopupMenu(hSubMenu, TPM_LEFTBUTTON,
-					x, rect.top + lpitem->rect.top,
-					0, lppop->ownerWnd, (LPRECT)NULL);
-				}
-			GlobalUnlock(hSubMenu);
-			return TRUE;
-			}
-		if (lppop->BarFlag && !MenuHasFocus) {
-			MenuFocusLoop(hWnd, lppop);
-			}
-		return TRUE;
-		}
-	printf("MenuButtonDown // x=%d y=%d // Not Found !\n", x, y);
-	if (GetCapture() != 0) ReleaseCapture(); 
-	MenuHasFocus = FALSE;
-	ShowWindow(lppop->hWnd, SW_HIDE);
-	return FALSE;
-}
-
-
-
-void MenuButtonUp(HWND hWnd, LPPOPUPMENU lppop, int x, int y)
-{
-	HDC		hDC;
-	LPMENUITEM	lpitem, lpitem2;
-	RECT	rect;
-	HMENU	hSubMenu;
-	WORD	wRet;
-	LPPOPUPMENU lppop2;
-	if (lppop == NULL) return;
-	lpitem = MenuFindItem(lppop, x, y, &wRet);
-#ifdef DEBUG_MENU
-	printf("MenuButtonUp // x=%d y=%d // wRet=%d lpitem=%08X !\n", 
-											x, y, wRet, lpitem);
-#endif
-	if (lpitem != NULL) {
-		if ((lpitem->item_flags & MF_POPUP) == MF_POPUP) {
-			return;
-			}
-		if (((lpitem->item_flags & MF_SEPARATOR) != MF_SEPARATOR) &&
-			((lpitem->item_flags & MF_POPUP) != MF_POPUP)) {
-			MenuHasFocus = FALSE;
-			if (lppop->BarFlag) {
-				PostMessage(lppop->ownerWnd, WM_COMMAND, lpitem->item_id, 0L);
-				}
-			else {
-				ShowWindow(lppop->hWnd, SW_HIDE);
-				SendMessage(lppop->hWnd, WM_COMMAND, lpitem->item_id, 0L);
-				}
-			return;
-			}
-		}
-	if (lppop->FocusedItem != (WORD)-1) {
-		MenuItemSelect(hWnd, lppop, lppop->FocusedItem);
-		}
-}
-
-
-
-void MenuMouseMove(HWND hWnd, LPPOPUPMENU lppop, WORD wParam, int x, int y)
-{
-    HDC		hDC;
-    RECT	rect;
-    HMENU	hSubMenu;
-    LPMENUITEM	lpitem, lpitem2;
-    LPPOPUPMENU lppop2;
-    WORD	wRet;
-
-    if (GetKeyState(VK_LBUTTON)	!= 0) 
-    {
-	lpitem = MenuFindItem(lppop, x, y, &wRet);
-#ifdef DEBUG_MENU
-	printf("MenuMouseMove // x=%d y=%d // wRet=%d lpitem=%08X !\n", 
-	       x, y, wRet, lpitem);
-#endif
-	if ((lpitem != NULL) && (lppop->FocusedItem != wRet)) 
-	{
-	    lpitem2 = GetMenuItemPtr(lppop, lppop->FocusedItem);
-	    hDC = GetWindowDC(hWnd);
-	    if ((lpitem2 != NULL ) &&
-		(lpitem2->item_flags & MF_POPUP) == MF_POPUP) 
-	    {
-		HideAllSubPopupMenu(lppop);
-	    }
-	    MenuItemSelect(hWnd, lppop, wRet);
-	    if ((lpitem->item_flags & MF_POPUP) == MF_POPUP) 
-	    {
-		hSubMenu = (HMENU)lpitem->item_id;
-		lppop2 = (LPPOPUPMENU) GlobalLock(hSubMenu);
-		if (lppop2 == NULL) 
-		{
-		    ReleaseDC(hWnd, hDC);
-		    return;
-		}
-		if (lppop->BarFlag) 
-		{
-		    lppop2->hWndParent = hWnd;
-		    GetWindowRect(hWnd, &rect);
-		    rect.top += lpitem->rect.bottom;
-		    TrackPopupMenu(hSubMenu, TPM_LEFTBUTTON, 
-				   rect.left + lpitem->rect.left, rect.top, 
-				   0, lppop->ownerWnd, (LPRECT)NULL);
-		}
-		GlobalUnlock(hSubMenu);
-	    }
-	    ReleaseDC(hWnd, hDC);
-	}
-    }
-}
-
-
-void SelectPrevItem(LPPOPUPMENU lppop)
-{
-	int		nIndex;
-	LPMENUITEM lpitem;
-	if (lppop == NULL) return;
-	nIndex = lppop->FocusedItem;
-	if (nIndex < 1) {
-		if (nIndex == -1)
-			nIndex = 0;
-		else
-			nIndex = lppop->nItems - 1;
-		lpitem = GetMenuItemPtr(lppop, nIndex);
-		}
-	else {
-		nIndex--;
-		lpitem = GetMenuItemPtr(lppop, nIndex);
-		}
-	while (lpitem != NULL && lpitem->item_flags & MF_SEPARATOR) {
-		nIndex--;
-		lpitem = GetMenuItemPtr(lppop, nIndex);
-		}
-	MenuItemSelect(lppop->hWnd, lppop, nIndex);
-}
-
-
-void SelectNextItem(LPPOPUPMENU lppop)
-{
-	int		nIndex;
-	LPMENUITEM lpitem;
-	if (lppop == NULL) return;
-	nIndex = lppop->FocusedItem;
-	if ((nIndex == -1) || (nIndex >= lppop->nItems - 1)) {
-		nIndex = 0;
-		lpitem = GetMenuItemPtr(lppop, nIndex);
-		}
-	else {
-		nIndex++;
-		lpitem = GetMenuItemPtr(lppop, nIndex);
-		}
-	while (lpitem != NULL && (lpitem->item_flags & MF_SEPARATOR)) {
-		nIndex++;
-		lpitem = GetMenuItemPtr(lppop, nIndex);
-		}
-	MenuItemSelect(lppop->hWnd, lppop, nIndex);
-}
-
-
-void ResetHiliteFlags(LPPOPUPMENU lppop)
-{
-	LPMENUITEM lpitem;
-	int		i;
-#ifdef DEBUG_MENU
-	printf("ResetHiliteFlags lppop=%08X\n", lppop);
-#endif
-	if (lppop == NULL) return;
-	lpitem = lppop->firstItem;
-	for(i = 0; i < lppop->nItems; i++) {
-		if (lpitem == NULL) return;
-		lpitem->item_flags &= ~MF_HILITE;
-		lpitem = (LPMENUITEM)lpitem->next;
-		}
-}
-
-
-void MenuItemSelect(HWND hWnd, LPPOPUPMENU lppop, WORD wIndex)
-{
+    LPPOPUPMENU lppop;
     LPMENUITEM lpitem;
+    int i;
+
+    lppop = (LPPOPUPMENU) USER_HEAP_ADDR( hmenu );
+    if (lppop == NULL || lprect == NULL) return SYSMETRICS_CYMENU;
+#ifdef DEBUG_MENU
+    printf("MENU_DrawMenuBar(%04X, %08X, %08X); !\n", hDC, lprect, lppop);
+#endif
+    if (lppop->Height == 0) MENU_MenuBarCalcSize(hDC, lprect, lppop);
+    if (suppress_draw) return lppop->Height;
+    
+    FillRect(hDC, lprect, sysColorObjects.hbrushMenu );
+    SelectObject( hDC, sysColorObjects.hpenWindowFrame );
+    MoveTo( hDC, lprect->left, lprect->bottom );
+    LineTo( hDC, lprect->right, lprect->bottom );
+
+    if (lppop->nItems == 0) return SYSMETRICS_CYMENU;
+    lpitem = (MENUITEM *) USER_HEAP_ADDR( lppop->hItems );
+    for (i = 0; i < lppop->nItems; i++, lpitem++)
+    {
+	MENU_DrawMenuItem( hDC, lpitem, lppop->Height, TRUE );
+    }
+    return lppop->Height;
+} 
+
+
+/***********************************************************************
+ *           MENU_ShowPopup
+ *
+ * Display a popup menu.
+ */
+static BOOL MENU_ShowPopup(HWND hwndOwner, HMENU hmenu, WORD id, int x, int y)
+{
+    POPUPMENU *menu;
+
+    if (!(menu = (POPUPMENU *) USER_HEAP_ADDR( hmenu ))) return FALSE;
+    if (menu->FocusedItem != NO_SELECTED_ITEM)
+    {
+	MENUITEM *item = (MENUITEM *) USER_HEAP_ADDR( menu->hItems );
+	item[menu->FocusedItem].item_flags &= ~(MF_HILITE | MF_MOUSESELECT);
+	menu->FocusedItem = NO_SELECTED_ITEM;
+    }
+    SendMessage( hwndOwner, WM_INITMENUPOPUP, hmenu,
+		 MAKELONG( id, (menu->wFlags & MF_POPUP) ? 1 : 0 ));
+    MENU_PopupMenuCalcSize( menu );
+    if (!menu->hWnd)
+    {
+	WND *wndPtr = WIN_FindWndPtr( hwndOwner );
+	if (!wndPtr) return FALSE;
+	menu->hWnd = CreateWindow( POPUPMENU_CLASS_NAME, "",
+				   WS_POPUP | WS_BORDER, x, y, 
+				   menu->Width + 2*SYSMETRICS_CXBORDER,
+				   menu->Height + 2*SYSMETRICS_CYBORDER,
+				   0, 0, wndPtr->hInstance,
+				   (LPSTR)(DWORD)hmenu );
+	if (!menu->hWnd) return FALSE;
+    }
+    else SetWindowPos( menu->hWnd, 0, x, y,
+		       menu->Width + 2*SYSMETRICS_CXBORDER,
+		       menu->Height + 2*SYSMETRICS_CYBORDER,
+		       SWP_NOACTIVATE | SWP_NOZORDER );
+
+      /* Display the window */
+
+    SetWindowPos( menu->hWnd, HWND_TOP, 0, 0, 0, 0,
+		  SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE );
+    UpdateWindow( menu->hWnd );
+    return TRUE;
+}
+
+
+/***********************************************************************
+ *           MENU_SelectItem
+ */
+static void MENU_SelectItem( HMENU hmenu, WORD wIndex )
+{
+    MENUITEM *items;
+    LPPOPUPMENU lppop;
     HDC hdc;
 
-    if (lppop == NULL) return;
-    if (lppop->BarFlag) hdc = GetDCEx( hWnd, 0, DCX_CACHE | DCX_WINDOW );
-    else hdc = GetDC( hWnd );
+    lppop = (POPUPMENU *) USER_HEAP_ADDR( hmenu );
+    if (!lppop->nItems) return;
+    items = (MENUITEM *) USER_HEAP_ADDR( lppop->hItems );
+    if ((wIndex != NO_SELECTED_ITEM) && 
+	(wIndex != SYSMENU_SELECTED) &&
+	(items[wIndex].item_flags & MF_SEPARATOR))
+	wIndex = NO_SELECTED_ITEM;
+    if (lppop->FocusedItem == wIndex) return;
+    if (lppop->wFlags & MF_POPUP) hdc = GetDC( lppop->hWnd );
+    else hdc = GetDCEx( lppop->hWnd, 0, DCX_CACHE | DCX_WINDOW);
 
       /* Clear previous highlighted item */
-    if (lppop->FocusedItem != (WORD)-1) 
+    if (lppop->FocusedItem != NO_SELECTED_ITEM) 
     {
-	if ((lpitem = GetMenuItemPtr(lppop, lppop->FocusedItem)) != NULL)
+	if (lppop->FocusedItem == SYSMENU_SELECTED)
+	    NC_DrawSysButton( lppop->hWnd, hdc, FALSE );
+	else
 	{
-	    lpitem->item_flags &= ~MF_HILITE;
-	    if ((lpitem->item_flags & MF_POPUP) == MF_POPUP)
-		HideAllSubPopupMenu(lppop);
-	    MENU_DrawMenuItem( hdc, lpitem, &lppop->rect, lppop->BarFlag );
+	    items[lppop->FocusedItem].item_flags &=~(MF_HILITE|MF_MOUSESELECT);
+	    MENU_DrawMenuItem( hdc, &items[lppop->FocusedItem], lppop->Height,
+			       !(lppop->wFlags & MF_POPUP) );
 	}
     }
 
       /* Highlight new item (if any) */
     lppop->FocusedItem = wIndex;
-    if (lppop->FocusedItem != (WORD)-1) 
+    if (lppop->FocusedItem != NO_SELECTED_ITEM) 
     {
-	if ((lpitem = GetMenuItemPtr(lppop, lppop->FocusedItem)) != NULL)
+	if (lppop->FocusedItem == SYSMENU_SELECTED)
+	    NC_DrawSysButton( lppop->hWnd, hdc, TRUE );
+	else
 	{
-	    lpitem->item_flags |= MF_HILITE;
-	    MENU_DrawMenuItem( hdc, lpitem, &lppop->rect, lppop->BarFlag );
-	    SendMessage(hWnd, WM_MENUSELECT, lpitem->item_id, 
-			MAKELONG(0, lpitem->item_flags));
+	    items[lppop->FocusedItem].item_flags |= MF_HILITE;
+	    MENU_DrawMenuItem( hdc, &items[lppop->FocusedItem], lppop->Height,
+			       !(lppop->wFlags & MF_POPUP) );
+	    SendMessage(lppop->hWnd, WM_MENUSELECT,
+			items[lppop->FocusedItem].item_id, 
+		       MAKELONG( hmenu, items[lppop->FocusedItem].item_flags));
 	}
     }
-    ReleaseDC( hWnd, hdc );
+    ReleaseDC( lppop->hWnd, hdc );
 }
 
 
-LPPOPUPMENU PopupMenuGetWindowAndStorage(HWND hwnd, WND **wndPtr)
+/***********************************************************************
+ *           MENU_SelectNextItem
+ */
+static void MENU_SelectNextItem( HMENU hmenu )
 {
-    WND  *Ptr;
-    LPPOPUPMENU lppop;
-    *(wndPtr) = Ptr = WIN_FindWndPtr(hwnd);
-    if (Ptr == 0) {
-    	printf("PopupMenuGetWindowAndStorage // Bad Window handle !\n");
-    	return NULL;
-    	}
-    lppop = *((LPPOPUPMENU *)&Ptr->wExtra[1]);
-	if (lppop == NULL) {
-		lppop = (LPPOPUPMENU) GlobalLock(Ptr->wIDmenu);
-		if (lppop == NULL) {
-			printf("PopupMenuGetWindowAndStorage // Bad Menu Handle !\n");
-	    	return NULL;
-			}
-		}
-    return lppop;
-}
+    int i;
+    MENUITEM *items;
+    POPUPMENU *menu;
 
-
-LPPOPUPMENU PopupMenuGetStorageHeader(HWND hwnd)
-{
-    WND  *Ptr;
-    LPPOPUPMENU lppop;
-    Ptr = WIN_FindWndPtr(hwnd);
-    if (Ptr == 0) {
-    	printf("Bad Window handle on PopupMenu !\n");
-    	return 0;
-    	}
-    lppop = *((LPPOPUPMENU *)&Ptr->wExtra[1]);
-    return lppop;
-}
-
-
-void SetMenuLogicalParent(HMENU hMenu, HWND hWnd)
-{
-    LPPOPUPMENU lppop;
-    lppop = (LPPOPUPMENU)GlobalLock(hMenu);
-    lppop->hWndParent = hWnd;
-    GlobalUnlock(hMenu);
-}
-
-
-void StdDrawPopupMenu(HWND hwnd)
-{
-	WND *wndPtr;
-	LPPOPUPMENU lppop;
-	LPMENUITEM  lpitem;
-	PAINTSTRUCT ps;
-	RECT rect;
-	HDC hDC;
-
-	hDC = BeginPaint(hwnd, &ps);
-	GetClientRect(hwnd, &rect);
-	FillRect(hDC, &rect, sysColorObjects.hbrushMenu );
-
-	lppop = PopupMenuGetWindowAndStorage(hwnd, &wndPtr);
-	for (lpitem = lppop->firstItem; lpitem != NULL; lpitem = lpitem->next )
+    menu = (POPUPMENU *) USER_HEAP_ADDR( hmenu );
+    if (!menu->nItems) return;
+    items = (MENUITEM *) USER_HEAP_ADDR( menu->hItems );
+    if ((menu->FocusedItem != NO_SELECTED_ITEM) &&
+	(menu->FocusedItem != SYSMENU_SELECTED))
+    {
+	for (i = menu->FocusedItem+1; i < menu->nItems; i++)
 	{
-	    MENU_DrawMenuItem( hDC, lpitem, &rect, FALSE );
+	    if (!(items[i].item_flags & MF_SEPARATOR))
+	    {
+		MENU_SelectItem( hmenu, i );
+		return;
+	    }
 	}
-	EndPaint( hwnd, &ps );
+	if (MENU_HasSysMenu( menu ))
+	{
+	    MENU_SelectItem( hmenu, SYSMENU_SELECTED );
+	    return;
+	}
+    }
+    for (i = 0; i < menu->nItems; i++)
+    {
+	if (!(items[i].item_flags & MF_SEPARATOR))
+	{
+	    MENU_SelectItem( hmenu, i );
+	    return;
+	}
+    }
+    if (MENU_HasSysMenu( menu )) MENU_SelectItem( hmenu, SYSMENU_SELECTED );
 }
 
 
-void StdDrawMenuBar(HDC hDC, LPRECT lprect, LPPOPUPMENU lppop, 
-		    BOOL suppress_draw)
+/***********************************************************************
+ *           MENU_SelectPrevItem
+ */
+static void MENU_SelectPrevItem( HMENU hmenu )
 {
-	LPMENUITEM 	lpitem;
-	if (lppop == NULL || lprect == NULL) return;
+    int i;
+    MENUITEM *items;
+    POPUPMENU *menu;
+
+    menu = (POPUPMENU *) USER_HEAP_ADDR( hmenu );
+    if (!menu->nItems) return;
+    items = (MENUITEM *) USER_HEAP_ADDR( menu->hItems );
+    if ((menu->FocusedItem != NO_SELECTED_ITEM) &&
+	(menu->FocusedItem != SYSMENU_SELECTED))
+    {
+	for (i = menu->FocusedItem - 1; i >= 0; i--)
+	{
+	    if (!(items[i].item_flags & MF_SEPARATOR))
+	    {
+		MENU_SelectItem( hmenu, i );
+		return;
+	    }
+	}
+	if (MENU_HasSysMenu( menu ))
+	{
+	    MENU_SelectItem( hmenu, SYSMENU_SELECTED );
+	    return;
+	}
+    }
+    for (i = menu->nItems - 1; i > 0; i--)
+    {
+	if (!(items[i].item_flags & MF_SEPARATOR))
+	{
+	    MENU_SelectItem( hmenu, i );
+	    return;
+	}
+    }
+    if (MENU_HasSysMenu( menu )) MENU_SelectItem( hmenu, SYSMENU_SELECTED );
+}
+
+
+/***********************************************************************
+ *           MENU_GetSubPopup
+ *
+ * Return the handle of the selected sub-popup menu (if any).
+ */
+static HMENU MENU_GetSubPopup( HMENU hmenu )
+{
+    POPUPMENU *menu;
+    MENUITEM *item;
+
+    menu = (POPUPMENU *) USER_HEAP_ADDR( hmenu );
+    if (menu->FocusedItem == NO_SELECTED_ITEM) return 0;
+    else if (menu->FocusedItem == SYSMENU_SELECTED)
+	return GetSystemMenu( menu->hWnd, FALSE );
+
+    item = ((MENUITEM *)USER_HEAP_ADDR( menu->hItems )) + menu->FocusedItem;
+    if (!(item->item_flags & MF_POPUP) || !(item->item_flags & MF_MOUSESELECT))
+	return 0;
+    return item->item_id;
+}
+
+
+/***********************************************************************
+ *           MENU_HideSubPopups
+ *
+ * Hide the sub-popup menus of this menu.
+ */
+static void MENU_HideSubPopups( HMENU hmenu )
+{
+    MENUITEM *item;
+    POPUPMENU *menu, *submenu;
+    HMENU hsubmenu;
+
+    if (!(menu = (POPUPMENU *) USER_HEAP_ADDR( hmenu ))) return;
+    if (menu->FocusedItem == NO_SELECTED_ITEM) return;
+    if (menu->FocusedItem == SYSMENU_SELECTED)
+    {
+	hsubmenu = GetSystemMenu( menu->hWnd, FALSE );
+    }
+    else
+    {
+	item = ((MENUITEM *)USER_HEAP_ADDR(menu->hItems)) + menu->FocusedItem;
+	if (!(item->item_flags & MF_POPUP) ||
+	    !(item->item_flags & MF_MOUSESELECT)) return;
+	item->item_flags &= ~MF_MOUSESELECT;
+	hsubmenu = item->item_id;
+    }
+    submenu = (POPUPMENU *) USER_HEAP_ADDR( hsubmenu );
+    MENU_HideSubPopups( hsubmenu );
+    if (submenu->hWnd) ShowWindow( submenu->hWnd, SW_HIDE );
+    MENU_SelectItem( hsubmenu, NO_SELECTED_ITEM );
+}
+
+
+/***********************************************************************
+ *           MENU_ShowSubPopup
+ *
+ * Display the sub-menu of the selected item of this menu.
+ * Return the handle of the submenu, or hmenu if no submenu to display.
+ */
+static HMENU MENU_ShowSubPopup( HWND hwndOwner, HMENU hmenu, BOOL selectFirst )
+{
+    POPUPMENU *menu;
+    MENUITEM *item;
+    WND *wndPtr;
+
+    if (!(menu = (POPUPMENU *) USER_HEAP_ADDR( hmenu ))) return hmenu;
+    if (!(wndPtr = WIN_FindWndPtr( menu->hWnd ))) return hmenu;
+    if (menu->FocusedItem == NO_SELECTED_ITEM) return hmenu;
+    if (menu->FocusedItem == SYSMENU_SELECTED)
+    {
+	MENU_ShowPopup(hwndOwner, wndPtr->hSysMenu, 0, wndPtr->rectClient.left,
+		wndPtr->rectClient.top - menu->Height - 2*SYSMETRICS_CYBORDER);
+	if (selectFirst) MENU_SelectNextItem( wndPtr->hSysMenu );
+	return wndPtr->hSysMenu;
+    }
+    item = ((MENUITEM *)USER_HEAP_ADDR( menu->hItems )) + menu->FocusedItem;
+    if (!(item->item_flags & MF_POPUP) ||
+	(item->item_flags & (MF_GRAYED | MF_DISABLED))) return hmenu;
+    item->item_flags |= MF_MOUSESELECT;
+    if (menu->wFlags & MF_POPUP)
+    {
+	MENU_ShowPopup( hwndOwner, (HMENU)item->item_id, menu->FocusedItem,
+		 wndPtr->rectWindow.left + item->rect.right-arrow_bitmap_width,
+		 wndPtr->rectWindow.top + item->rect.top );
+    }
+    else
+    {
+	MENU_ShowPopup( hwndOwner, (HMENU)item->item_id, menu->FocusedItem,
+		        wndPtr->rectWindow.left + item->rect.left,
+		        wndPtr->rectWindow.top + item->rect.bottom );
+    }
+    if (selectFirst) MENU_SelectNextItem( (HMENU)item->item_id );
+    return (HMENU)item->item_id;
+}
+
+
+/***********************************************************************
+ *           MENU_FindMenuByCoords
+ *
+ * Find the menu containing a given point (in screen coords).
+ */
+static HMENU MENU_FindMenuByCoords( HMENU hmenu, POINT pt )
+{
+    POPUPMENU *menu;
+    HWND hwnd;
+
+    if (!(hwnd = WindowFromPoint( pt ))) return 0;
+    while (hmenu)
+    {
+	menu = (POPUPMENU *) USER_HEAP_ADDR( hmenu );
+	if (menu->hWnd == hwnd)
+	{
+	    if (!(menu->wFlags & MF_POPUP))
+	    {
+		  /* Make sure it's in the menu bar (or in system menu) */
+		WND *wndPtr = WIN_FindWndPtr( menu->hWnd );
+		if ((pt.x < wndPtr->rectClient.left) ||
+		    (pt.x >= wndPtr->rectClient.right) ||
+		    (pt.y >= wndPtr->rectClient.top)) return 0;
+		if (pt.y < wndPtr->rectClient.top - menu->Height)
+		{
+		    if (!MENU_IsInSysMenu( menu, pt )) return 0;
+		}
+		/* else it's in the menu bar */
+	    }
+	    return hmenu;
+	}
+	hmenu = MENU_GetSubPopup( hmenu );
+    }
+    return 0;
+}
+
+
+/***********************************************************************
+ *           MENU_ExecFocusedItem
+ *
+ * Execute a menu item (for instance when user pressed Enter).
+ * Return TRUE if we can go on with menu tracking.
+ */
+static BOOL MENU_ExecFocusedItem( HWND hwndOwner, HMENU hmenu,
+				  HMENU *hmenuCurrent )
+{
+    MENUITEM *item;
+    POPUPMENU *menu = (POPUPMENU *) USER_HEAP_ADDR( hmenu );
+    if (!menu || !menu->nItems || (menu->FocusedItem == NO_SELECTED_ITEM) ||
+	(menu->FocusedItem == SYSMENU_SELECTED)) return TRUE;
+    item = ((MENUITEM *)USER_HEAP_ADDR( menu->hItems )) + menu->FocusedItem;
+    if (!(item->item_flags & MF_POPUP))
+    {
+	if (!(item->item_flags & (MF_GRAYED | MF_DISABLED)))
+	{
+	    PostMessage( hwndOwner, (menu->wFlags & MF_SYSMENU) ? 
+			WM_SYSCOMMAND : WM_COMMAND, item->item_id, 0 );
+	    return FALSE;
+	}
+	else return TRUE;
+    }
+    else
+    {
+	*hmenuCurrent = MENU_ShowSubPopup( hwndOwner, hmenu, TRUE );
+	return TRUE;
+    }
+}
+
+
+/***********************************************************************
+ *           MENU_ButtonDown
+ *
+ * Handle a button-down event in a menu. Point is in screen coords.
+ * hmenuCurrent is the top-most visible popup.
+ * Return TRUE if we can go on with menu tracking.
+ */
+static BOOL MENU_ButtonDown( HWND hwndOwner, HMENU hmenu, HMENU *hmenuCurrent,
+			     POINT pt )
+{
+    POPUPMENU *menu;
+    MENUITEM *item;
+    WORD id;
+
+    if (!hmenu) return FALSE;  /* Outside all menus */
+    menu = (POPUPMENU *) USER_HEAP_ADDR( hmenu );
+    item = MENU_FindItemByCoords( menu, pt.x, pt.y, &id );
+    if (!item)  /* Maybe in system menu */
+    {
+	if (!MENU_IsInSysMenu( menu, pt )) return FALSE;
+	id = SYSMENU_SELECTED;
+    }	
+
+    if (menu->FocusedItem == id)
+    {
+	if (id == SYSMENU_SELECTED) return FALSE;
+	if (item->item_flags & MF_POPUP)
+	{
+	    if (item->item_flags & MF_MOUSESELECT)
+	    {
+		if (menu->wFlags & MF_POPUP)
+		{
+		    MENU_HideSubPopups( hmenu );
+		    *hmenuCurrent = hmenu;
+		}
+		else return FALSE;
+	    }
+	    else *hmenuCurrent = MENU_ShowSubPopup( hwndOwner, hmenu, FALSE );
+	}
+    }
+    else
+    {
+	MENU_HideSubPopups( hmenu );
+	MENU_SelectItem( hmenu, id );
+	*hmenuCurrent = MENU_ShowSubPopup( hwndOwner, hmenu, FALSE );
+    }
+    return TRUE;
+}
+
+
+/***********************************************************************
+ *           MENU_ButtonUp
+ *
+ * Handle a button-up event in a menu. Point is in screen coords.
+ * hmenuCurrent is the top-most visible popup.
+ * Return TRUE if we can go on with menu tracking.
+ */
+static BOOL MENU_ButtonUp( HWND hwndOwner, HMENU hmenu, HMENU *hmenuCurrent,
+			   POINT pt )
+{
+    POPUPMENU *menu;
+    MENUITEM *item;
+    HMENU hsubmenu;
+    WORD id;
+
+    if (!hmenu) return FALSE;  /* Outside all menus */
+    menu = (POPUPMENU *) USER_HEAP_ADDR( hmenu );
+    item = MENU_FindItemByCoords( menu, pt.x, pt.y, &id );
+    if (!item)  /* Maybe in system menu */
+    {
+	if (!MENU_IsInSysMenu( menu, pt )) return FALSE;
+	id = SYSMENU_SELECTED;
+	hsubmenu = GetSystemMenu( menu->hWnd, FALSE );
+    }	
+
+    if (menu->FocusedItem != id) return FALSE;
+
+    if (id != SYSMENU_SELECTED)
+    {
+	if (!(item->item_flags & MF_POPUP))
+	{
+	    return MENU_ExecFocusedItem( hwndOwner, hmenu, hmenuCurrent );
+	}
+	hsubmenu = item->item_id;
+    }
+      /* Select first item of sub-popup */
+    MENU_SelectItem( hsubmenu, NO_SELECTED_ITEM );
+    MENU_SelectNextItem( hsubmenu );
+    return TRUE;
+}
+
+
+/***********************************************************************
+ *           MENU_MouseMove
+ *
+ * Handle a motion event in a menu. Point is in screen coords.
+ * hmenuCurrent is the top-most visible popup.
+ * Return TRUE if we can go on with menu tracking.
+ */
+static BOOL MENU_MouseMove( HWND hwndOwner, HMENU hmenu, HMENU *hmenuCurrent,
+			    POINT pt )
+{
+    POPUPMENU *menu;
+    MENUITEM *item;
+    WORD id = NO_SELECTED_ITEM;
+
+    if (hmenu)
+    {
+	menu = (POPUPMENU *) USER_HEAP_ADDR( hmenu );
+	item = MENU_FindItemByCoords( menu, pt.x, pt.y, &id );
+	if (!item)  /* Maybe in system menu */
+	{
+	    if (!MENU_IsInSysMenu( menu, pt ))
+		id = NO_SELECTED_ITEM;  /* Outside all items */
+	    else id = SYSMENU_SELECTED;
+	}
+    }	
+    if (id == NO_SELECTED_ITEM)
+    {
+	MENU_SelectItem( *hmenuCurrent, NO_SELECTED_ITEM );
+    }
+    else if (menu->FocusedItem != id)
+    {
+	MENU_HideSubPopups( hmenu );
+	MENU_SelectItem( hmenu, id );
+	*hmenuCurrent = MENU_ShowSubPopup( hwndOwner, hmenu, FALSE );
+    }
+    return TRUE;
+}
+
+
+/***********************************************************************
+ *           MENU_KeyLeft
+ *
+ * Handle a VK_LEFT key event in a menu.
+ * hmenuCurrent is the top-most visible popup.
+ */
+static void MENU_KeyLeft( HWND hwndOwner, HMENU hmenu, HMENU *hmenuCurrent )
+{
+    POPUPMENU *menu;
+    HMENU hmenutmp, hmenuprev;
+
+    menu = (POPUPMENU *) USER_HEAP_ADDR( hmenu );
+    hmenuprev = hmenutmp = hmenu;
+    while (hmenutmp != *hmenuCurrent)
+    {
+	hmenutmp = MENU_GetSubPopup( hmenuprev );
+	if (hmenutmp != *hmenuCurrent) hmenuprev = hmenutmp;
+    }
+    MENU_HideSubPopups( hmenuprev );
+
+    if ((hmenuprev == hmenu) && !(menu->wFlags & MF_POPUP))
+    {
+	  /* Select previous item on the menu bar */
+	MENU_SelectPrevItem( hmenu );
+	if (*hmenuCurrent != hmenu)
+	{
+	      /* A popup menu was displayed -> display the next one */
+	    *hmenuCurrent = MENU_ShowSubPopup( hwndOwner, hmenu, TRUE );
+	}
+    }
+    else *hmenuCurrent = hmenuprev;
+}
+
+
+/***********************************************************************
+ *           MENU_KeyRight
+ *
+ * Handle a VK_RIGHT key event in a menu.
+ * hmenuCurrent is the top-most visible popup.
+ */
+static void MENU_KeyRight( HWND hwndOwner, HMENU hmenu, HMENU *hmenuCurrent )
+{
+    POPUPMENU *menu;
+    HMENU hmenutmp;
+
+    menu = (POPUPMENU *) USER_HEAP_ADDR( hmenu );
+
+    if ((menu->wFlags & MF_POPUP) || (*hmenuCurrent != hmenu))
+    {
+	  /* If already displaying a popup, try to display sub-popup */
+	hmenutmp = MENU_ShowSubPopup( hwndOwner, *hmenuCurrent, TRUE );
+	if (hmenutmp != *hmenuCurrent)  /* Sub-popup displayed */
+	{
+	    *hmenuCurrent = hmenutmp;
+	    return;
+	}
+    }
+
+      /* If on menu-bar, go to next item */
+    if (!(menu->wFlags & MF_POPUP))
+    {
+	MENU_HideSubPopups( hmenu );
+	MENU_SelectNextItem( hmenu );
+	if (*hmenuCurrent != hmenu)
+	{
+	      /* A popup menu was displayed -> display the next one */
+	    *hmenuCurrent = MENU_ShowSubPopup( hwndOwner, hmenu, TRUE );
+	}
+    }
+    else if (*hmenuCurrent != hmenu)  /* Hide last level popup */
+    {
+	HMENU hmenuprev;
+	hmenuprev = hmenutmp = hmenu;
+	while (hmenutmp != *hmenuCurrent)
+	{
+	    hmenutmp = MENU_GetSubPopup( hmenuprev );
+	    if (hmenutmp != *hmenuCurrent) hmenuprev = hmenutmp;
+	}
+	MENU_HideSubPopups( hmenuprev );
+	*hmenuCurrent = hmenuprev;
+    }
+}
+
+
+/***********************************************************************
+ *           MENU_TrackMenu
+ *
+ * Menu tracking code.
+ * If 'x' and 'y' are not 0, we simulate a button-down event at (x,y)
+ * before beginning tracking. This is to help menu-bar tracking.
+ */
+static BOOL MENU_TrackMenu( HMENU hmenu, WORD wFlags, int x, int y,
+			    HWND hwnd, LPRECT lprect )
+{
+    MSG msg;
+    POPUPMENU *menu;
+    HMENU hmenuCurrent = hmenu;
+    BOOL fClosed = FALSE;
+    WORD pos;
+
+    fEndMenuCalled = FALSE;
+    if (!(menu = (POPUPMENU *) USER_HEAP_ADDR( hmenu ))) return FALSE;
+    if (x && y)
+    {
+	POINT pt = { x, y };
+	MENU_ButtonDown( hwnd, hmenu, &hmenuCurrent, pt );
+    }
+    SetCapture( hwnd );
+
+    while (!fClosed)
+    {
+	if (!MSG_InternalGetMessage( &msg, 0, hwnd, MSGF_MENU, 0, TRUE ))
+	    break;
+
+	if ((msg.message >= WM_MOUSEFIRST) && (msg.message <= WM_MOUSELAST))
+	{
+	      /* Find the sub-popup for this mouse event (if any) */
+	    HMENU hsubmenu = MENU_FindMenuByCoords( hmenu, msg.pt );
+
+	    switch(msg.message)
+	    {
+	    case WM_RBUTTONDOWN:
+	    case WM_NCRBUTTONDOWN:
+		if (!(wFlags & TPM_RIGHTBUTTON)) break;
+		/* fall through */
+	    case WM_LBUTTONDOWN:
+	    case WM_NCLBUTTONDOWN:
+		fClosed = !MENU_ButtonDown( hwnd, hsubmenu,
+					    &hmenuCurrent, msg.pt );
+		break;
+		
+	    case WM_RBUTTONUP:
+	    case WM_NCRBUTTONUP:
+		if (!(wFlags & TPM_RIGHTBUTTON)) break;
+		/* fall through */
+	    case WM_LBUTTONUP:
+	    case WM_NCLBUTTONUP:
+		  /* If outside all menus but inside lprect, ignore it */
+		if (!hsubmenu && lprect && PtInRect( lprect, msg.pt )) break;
+		fClosed = !MENU_ButtonUp( hwnd, hsubmenu,
+					  &hmenuCurrent, msg.pt );
+		break;
+		
+	    case WM_MOUSEMOVE:
+	    case WM_NCMOUSEMOVE:
+		if ((msg.wParam & MK_LBUTTON) ||
+		    ((wFlags & TPM_RIGHTBUTTON) && (msg.wParam & MK_RBUTTON)))
+		{
+		    fClosed = !MENU_MouseMove( hwnd, hsubmenu,
+					       &hmenuCurrent, msg.pt );
+		}
+		break;
+	    }
+	}
+	else if ((msg.message >= WM_KEYFIRST) && (msg.message <= WM_KEYLAST))
+	{
+	    switch(msg.message)
+	    {
+	    case WM_KEYDOWN:
+		switch(msg.wParam)
+		{
+		case VK_HOME:
+		    MENU_SelectItem( hmenuCurrent, NO_SELECTED_ITEM );
+		    MENU_SelectNextItem( hmenuCurrent );
+		    break;
+
+		case VK_END:
+		    MENU_SelectItem( hmenuCurrent, NO_SELECTED_ITEM );
+		    MENU_SelectPrevItem( hmenuCurrent );
+		    break;
+
+		case VK_UP:
+		    MENU_SelectPrevItem( hmenuCurrent );
+		    break;
+
+		case VK_DOWN:
+		      /* If on menu bar, pull-down the menu */
+		    if (!(menu->wFlags & MF_POPUP) && (hmenuCurrent == hmenu))
+			hmenuCurrent = MENU_ShowSubPopup( hwnd, hmenu, TRUE );
+		    else
+			MENU_SelectNextItem( hmenuCurrent );
+		    break;
+
+		case VK_LEFT:
+		    MENU_KeyLeft( hwnd, hmenu, &hmenuCurrent );
+		    break;
+		    
+		case VK_RIGHT:
+		    MENU_KeyRight( hwnd, hmenu, &hmenuCurrent );
+		    break;
+		    
+		case VK_SPACE:
+		case VK_RETURN:
+		    fClosed = !MENU_ExecFocusedItem( hwnd, hmenuCurrent,
+						     &hmenuCurrent );
+		    break;
+
+		case VK_ESCAPE:
+		    fClosed = TRUE;
+		    break;
+
+		default:
+		    break;
+		}
+		break;  /* WM_KEYDOWN */
+
+	    case WM_SYSKEYDOWN:
+		switch(msg.wParam)
+		{
+		case VK_MENU:
+		    fClosed = TRUE;
+		    break;
+		    
+		}
+		break;  /* WM_SYSKEYDOWN */
+
+	    case WM_CHAR:
+		{
+		      /* Hack to avoid control chars. */
+		      /* We will find a better way real soon... */
+		    if ((msg.wParam <= 32) || (msg.wParam >= 127)) break;
+		    pos = MENU_FindItemByKey( hwnd, hmenuCurrent, msg.wParam );
+		    if (pos == (WORD)-2) fClosed = TRUE;
+		    else if (pos == (WORD)-1) MessageBeep(0);
+		    else
+		    {
+			MENU_SelectItem( hmenuCurrent, pos );
+			fClosed = !MENU_ExecFocusedItem( hwnd, hmenuCurrent,
+							 &hmenuCurrent );
+			
+		    }
+		}		    
+		break;  /* WM_CHAR */
+	    }  /* switch(msg.message) */
+	}
+	else
+	{
+	    DispatchMessage( &msg );
+	}
+	if (fEndMenuCalled) fClosed = TRUE;
+
+	if (!fClosed)  /* Remove the message from the queue */
+	    PeekMessage( &msg, 0, 0, 0, PM_REMOVE );
+    }
+    ReleaseCapture();
+    MENU_HideSubPopups( hmenu );
+    if (menu->wFlags & MF_POPUP) ShowWindow( menu->hWnd, SW_HIDE );
+    MENU_SelectItem( hmenu, NO_SELECTED_ITEM );
+    fEndMenuCalled = FALSE;
+    return TRUE;
+}
+
+
+/***********************************************************************
+ *           MENU_TrackMouseMenuBar
+ *
+ * Menu-bar tracking upon a mouse event. Called from NC_HandleSysCommand().
+ */
+void MENU_TrackMouseMenuBar( HWND hwnd, POINT pt )
+{
+    WND *wndPtr = WIN_FindWndPtr( hwnd );
+    MENU_TrackMenu( (HMENU)wndPtr->wIDmenu, TPM_LEFTALIGN | TPM_LEFTBUTTON,
+		    pt.x, pt.y, hwnd, NULL );
+}
+
+
+/***********************************************************************
+ *           MENU_TrackKbdMenuBar
+ *
+ * Menu-bar tracking upon a keyboard event. Called from NC_HandleSysCommand().
+ */
+void MENU_TrackKbdMenuBar( HWND hwnd, WORD wParam )
+{
+    WND *wndPtr = WIN_FindWndPtr( hwnd );
+      /* Select first selectable item */
+    MENU_SelectItem( wndPtr->wIDmenu, NO_SELECTED_ITEM );
+    MENU_SelectNextItem( (HMENU)wndPtr->wIDmenu );
+    MENU_TrackMenu( (HMENU)wndPtr->wIDmenu, TPM_LEFTALIGN | TPM_LEFTBUTTON,
+		    0, 0, hwnd, NULL );
+}
+
+
+/**********************************************************************
+ *			TrackPopupMenu		[USER.416]
+ */
+BOOL TrackPopupMenu( HMENU hMenu, WORD wFlags, short x, short y,
+		     short nReserved, HWND hWnd, LPRECT lpRect )
+{
+    if (!MENU_ShowPopup( hWnd, hMenu, 0, x, y )) return FALSE;
+    return MENU_TrackMenu( hMenu, wFlags, 0, 0, hWnd, lpRect );
+}
+
+
+/***********************************************************************
+ *           PopupMenuWndProc
+ */
+LONG PopupMenuWndProc( HWND hwnd, WORD message, WORD wParam, LONG lParam )
+{    
+    switch(message)
+    {
+    case WM_CREATE:
+	{
 #ifdef DEBUG_MENU
-	printf("StdDrawMenuBar(%04X, %08X, %08X); !\n", hDC, lprect, lppop);
+	    printf("PopupMenu WM_CREATE lParam=%08X !\n", lParam);
 #endif
-	if (lppop->Height == 0) MENU_MenuBarCalcSize(hDC, lprect, lppop);
-	if (suppress_draw) return;
-
-	FillRect(hDC, lprect, sysColorObjects.hbrushMenu );
-	SelectObject( hDC, sysColorObjects.hpenWindowFrame );
-	MoveTo( hDC, lprect->left, lprect->bottom );
-	LineTo( hDC, lprect->right, lprect->bottom );
-
-	if (lppop->nItems == 0) return;
-	for (lpitem = lppop->firstItem; lpitem != NULL; lpitem = lpitem->next )
-	{
-	    MENU_DrawMenuItem( hDC, lpitem, lprect, TRUE );
+	    CREATESTRUCT *createStruct = (CREATESTRUCT *)lParam;
+	    HMENU hmenu = (HMENU) ((int)createStruct->lpCreateParams & 0xffff);
+	    SetWindowWord( hwnd, 0, hmenu );
+	    return 0;
 	}
-} 
 
+    case WM_MOUSEACTIVATE:  /* We don't want to be activated */
+	return MA_NOACTIVATE;
 
+    case WM_PAINT:
+	{
+	    PAINTSTRUCT ps;
+	    BeginPaint( hwnd, &ps );
+	    MENU_DrawPopupMenu( hwnd, ps.hdc,
+			        (HMENU)GetWindowWord( hwnd, 0 ) );
+	    EndPaint( hwnd, &ps );
+	    return 0;
+	}
 
-LPMENUITEM MenuFindItem(LPPOPUPMENU lppop, int x, int y, WORD *lpRet)
-{
-	LPMENUITEM 	lpitem;
-	UINT  	i;
-	if (lpRet != NULL) *lpRet = 0;
-	if (lppop == NULL) return NULL;
-	if (lppop->nItems == 0) return NULL;
-	lpitem = lppop->firstItem;
-	for(i = 0; i < lppop->nItems; i++) {
-		if (lpitem == NULL) return NULL;
-#ifdef DEBUG_MENUFINDITEM
-		printf("FindItem // left=%d top=%d right=%d bottom=%d\n",
-		lpitem->rect.left, lpitem->rect.top, 
-		lpitem->rect.right, lpitem->rect.bottom);
-#endif
-		if (x > lpitem->rect.left && x < lpitem->rect.right && 
-			y > lpitem->rect.top && y < lpitem->rect.bottom) {
-			if (lpRet != NULL) *lpRet = i;
-			return lpitem;
-			}
-		lpitem = (LPMENUITEM)lpitem->next;
-		}
-	return NULL;
+    default:
+	return DefWindowProc(hwnd, message, wParam, lParam);
+    }
+    return 0;
 }
 
 
-LPMENUITEM MenuFindItemBySelKey(LPPOPUPMENU lppop, WORD key, WORD *lpRet)
-{
-	LPMENUITEM 	lpitem;
-	UINT  	i;
-	if (lppop == NULL) return NULL;
-
-	if (lppop->nItems == 0) return NULL;
-	lpitem = lppop->firstItem;
-	for(i = 0; i < lppop->nItems; i++) {
-		if (lpitem == NULL) return NULL;
-#ifdef DEBUG_MENUFINDITEM
-		printf("FindItemBySelKey // key=%04X lpitem->sel_key=%04X\n",
-										key, lpitem->sel_key);
-#endif
-		if (key == lpitem->sel_key) {
-			if (lpRet != NULL) *lpRet = i;
-			return lpitem;
-			}
-		lpitem = (LPMENUITEM)lpitem->next;
-		}
-	return NULL;
-}
-
-
-
-
-
-
 /***********************************************************************
  *           MENU_GetMenuBarHeight
  *
@@ -1090,60 +1384,18 @@
     WND *wndPtr;
     LPPOPUPMENU lppop;
 
-    if (!(lppop = PopupMenuGetWindowAndStorage( hwnd, &wndPtr ))) return 0;
-    if (!wndPtr) return 0;
+    if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return 0;
+    if (!(lppop = (LPPOPUPMENU)USER_HEAP_ADDR( wndPtr->wIDmenu ))) return 0;
     hdc = GetDC( hwnd );
     SetRect( &rectBar, orgX, orgY, orgX+menubarWidth, orgY+SYSMETRICS_CYMENU );
     MENU_MenuBarCalcSize( hdc, &rectBar, lppop );
     ReleaseDC( hwnd, hdc );
-    printf( "MENU_GetMenuBarHeight: returning %d\n", lppop->Height );
     return lppop->Height;
 }
 
 
-/***********************************************************************
- *           FindMenuItem
- */
-LPMENUITEM FindMenuItem(HMENU hMenu, WORD nPos, WORD wFlags)
-{
-	LPPOPUPMENU	menu;
-	LPMENUITEM 	lpitem;
-	int		i;
-	menu = (LPPOPUPMENU) GlobalLock(hMenu);
-	if (menu == NULL) {
-		GlobalUnlock(hMenu);
-		return FALSE;
-		}
-	lpitem = menu->firstItem;
-	if (wFlags & MF_BYPOSITION) {
-		for (i = 0; i < nPos; i++, lpitem = lpitem->next) 
-			if (lpitem == NULL)	return NULL;
-		}
-	else {
-		for (i = 0; i < menu->nItems && lpitem != NULL; i++) {
-			if (lpitem->item_id == nPos) return lpitem;
-			lpitem = lpitem->next;
-			}
-		return NULL;
-		}
-    return lpitem;
-}
 
 
-LPMENUITEM GetMenuItemPtr(LPPOPUPMENU menu, WORD nPos)
-{
-    LPMENUITEM 	lpitem;
-    int		i;
-    if (menu == NULL) return NULL;
-    lpitem = menu->firstItem;
-    for (i = 0; i < menu->nItems; i++) {
-    	if (lpitem == NULL) return NULL;
-    	if (i == nPos) return(lpitem);
-    	lpitem = (LPMENUITEM)lpitem->next;
-    	}
-    return NULL;
-}
-
 
 WORD GetSelectionKey(LPSTR str)
 {
@@ -1206,35 +1458,6 @@
 }
 
 
-
-BOOL HideAllSubPopupMenu(LPPOPUPMENU menu)
-{
-	LPPOPUPMENU submenu;
-	LPMENUITEM 	lpitem;
-	BOOL	someClosed = FALSE;
-	int		i;
-	if (menu == NULL) return;
-	lpitem = menu->firstItem;
-	for (i = 0; i < menu->nItems; i++) {
-		if (lpitem == NULL) return;
-		if (lpitem->item_flags & MF_POPUP) {
-			submenu = (LPPOPUPMENU) GlobalLock((HMENU)lpitem->item_id);
-			if (submenu != NULL) {
-				if (IsWindowVisible(submenu->hWnd)) {
-					ShowWindow(submenu->hWnd, SW_HIDE);
-					someClosed = TRUE;
-					}
-				GlobalUnlock((HMENU)lpitem->item_id);
-		    	}
-	   	    }
-	   	lpitem = (LPMENUITEM)lpitem->next;
-	   	}
-	return someClosed;
-}
-
-
-
-
 /**********************************************************************
  *			ChangeMenu		[USER.153]
  */
@@ -1264,18 +1487,10 @@
 #ifdef DEBUG_MENU
 	printf("CheckMenuItem (%04X, %04X, %04X) !\n", hMenu, wItemID, wFlags);
 #endif
-	lpitem = FindMenuItem(hMenu, wItemID, wFlags);
-	if (lpitem != NULL) {
-		if ((wFlags & MF_CHECKED) == MF_CHECKED)
-			lpitem->item_flags |= MF_CHECKED;
-		else
-			lpitem->item_flags &= ((WORD)-1 ^ MF_CHECKED);
-#ifdef DEBUG_MENU
-		printf("CheckMenuItem // Found !\n");
-#endif
-		return(TRUE);
-		}
-	return FALSE;
+	if (!(lpitem = MENU_FindItem(&hMenu, &wItemID, wFlags))) return FALSE;
+	if (wFlags & MF_CHECKED) lpitem->item_flags |= MF_CHECKED;
+	else lpitem->item_flags &= ~MF_CHECKED;
+	return TRUE;
 }
 
 
@@ -1288,7 +1503,7 @@
 #ifdef DEBUG_MENU
     printf("EnableMenuItem (%04X, %04X, %04X) !\n", hMenu, wItemID, wFlags);
 #endif
-    if (!(lpitem = FindMenuItem(hMenu, wItemID, wFlags))) return FALSE;
+    if (!(lpitem = MENU_FindItem( &hMenu, &wItemID, wFlags ))) return FALSE;
 
       /* We can't have MF_GRAYED and MF_DISABLED together */
     if (wFlags & MF_GRAYED)
@@ -1311,7 +1526,7 @@
  *			GetMenuString		[USER.161]
  */
 int GetMenuString(HMENU hMenu, WORD wItemID, 
-	LPSTR str, short nMaxSiz, WORD wFlags)
+		  LPSTR str, short nMaxSiz, WORD wFlags)
 {
 	LPMENUITEM 	lpitem;
 	int		maxsiz;
@@ -1320,7 +1535,7 @@
 					hMenu, wItemID, str, nMaxSiz, wFlags);
 #endif
 	if (str == NULL) return FALSE;
-	lpitem = FindMenuItem(hMenu, wItemID, wFlags);
+	lpitem = MENU_FindItem( &hMenu, &wItemID, wFlags );
 	if (lpitem != NULL) {
 		if (lpitem->item_text != NULL) {
 			maxsiz = min(nMaxSiz - 1, strlen(lpitem->item_text));
@@ -1342,17 +1557,18 @@
  */
 BOOL HiliteMenuItem(HWND hWnd, HMENU hMenu, WORD wItemID, WORD wHilite)
 {
-	LPPOPUPMENU	menu;
-	LPMENUITEM 	lpitem;
+    LPPOPUPMENU menu;
+    LPMENUITEM  lpitem;
 #ifdef DEBUG_MENU
 	printf("HiliteMenuItem(%04X, %04X, %04X, %04X);\n", 
 						hWnd, hMenu, wItemID, wHilite);
 #endif
-	menu = (LPPOPUPMENU) GlobalLock(hMenu);
-	if (menu == NULL) return FALSE;
-	lpitem = FindMenuItem(hMenu, wItemID, wHilite);
-	if (lpitem == NULL) return FALSE;
-	return FALSE;
+    if (!(lpitem = MENU_FindItem( &hMenu, &wItemID, wHilite ))) return FALSE;
+    if (!(menu = (LPPOPUPMENU) USER_HEAP_ADDR(hMenu))) return FALSE;
+    if (menu->FocusedItem == wItemID) return TRUE;
+    MENU_HideSubPopups( hMenu );
+    MENU_SelectItem( hMenu, wItemID );
+    return TRUE;
 }
 
 
@@ -1361,16 +1577,18 @@
  */
 WORD GetMenuState(HMENU hMenu, WORD wItemID, WORD wFlags)
 {
-	LPPOPUPMENU	menu;
-	LPMENUITEM 	lpitem;
+    LPMENUITEM lpitem;
 #ifdef DEBUG_MENU
-	printf("GetMenuState(%04X, %04X, %04X);\n", hMenu, wItemID, wFlags);
+    printf("GetMenuState(%04X, %04X, %04X);\n", hMenu, wItemID, wFlags);
 #endif
-	menu = (LPPOPUPMENU) GlobalLock(hMenu);
-	if (menu == NULL) return -1;
-	lpitem = FindMenuItem(hMenu, wItemID, wFlags);
-	if (lpitem == NULL) return -1;
-	return lpitem->item_flags;
+    if (!(lpitem = MENU_FindItem( &hMenu, &wItemID, wFlags ))) return -1;
+    if (lpitem->item_flags & MF_POPUP)
+    {
+	POPUPMENU *menu = (POPUPMENU *) USER_HEAP_ADDR( lpitem->item_id );
+	if (!menu) return -1;
+	else return (menu->nItems << 8) | (menu->wFlags & 0xff);
+    }
+    else return lpitem->item_flags;
 }
 
 
@@ -1383,7 +1601,7 @@
 #ifdef DEBUG_MENU
 	printf("GetMenuItemCount(%04X);\n", hMenu);
 #endif
-	menu = (LPPOPUPMENU) GlobalLock(hMenu);
+	menu = (LPPOPUPMENU) USER_HEAP_ADDR(hMenu);
 	if (menu == NULL) return (WORD)-1;
 #ifdef DEBUG_MENU
 	printf("GetMenuItemCount(%04X) return %d \n", hMenu, menu->nItems);
@@ -1397,24 +1615,17 @@
  */
 WORD GetMenuItemID(HMENU hMenu, int nPos)
 {
-	WORD		i;
-	LPPOPUPMENU	menu;
-	LPMENUITEM 	lpitem;
-	printf("GetMenuItemID(%04X, %d);\n", hMenu, nPos);
-	menu = (LPPOPUPMENU) GlobalLock(hMenu);
-	if (menu == NULL) return -1;
-	lpitem = menu->firstItem;
-	for (i = 0; i < menu->nItems; i++) {
-		if (lpitem == NULL) break;
-		if (i == nPos) {
+    LPPOPUPMENU	menu;
+    MENUITEM *item;
+
 #ifdef DEBUG_MENU
-			printf("GetMenuItemID // Found !\n");
+    printf("GetMenuItemID(%04X, %d);\n", hMenu, nPos);
 #endif
-			return lpitem->item_id;
-			}
-		lpitem = (LPMENUITEM)lpitem->next;
-		}
-	return -1;
+    if (!(menu = (LPPOPUPMENU) USER_HEAP_ADDR(hMenu))) return -1;
+    if ((nPos < 0) || (nPos >= menu->nItems)) return -1;
+    item = (MENUITEM *) USER_HEAP_ADDR( menu->hItems );
+    if (item[nPos].item_flags & MF_POPUP) return -1;
+    return item[nPos].item_id;
 }
 
 
@@ -1423,64 +1634,70 @@
  */
 BOOL InsertMenu(HMENU hMenu, WORD nPos, WORD wFlags, WORD wItemID, LPSTR lpNewItem)
 {
-	LPPOPUPMENU	menu;
-	HANDLE	hNewItem;
-	LPMENUITEM 	lpitem, lpitem2;
+    HANDLE hNewItems;
+    MENUITEM *lpitem, *newItems;
+    LPPOPUPMENU	menu;
+    
 #ifdef DEBUG_MENU
-	if ((wFlags & (MF_BITMAP | MF_SEPARATOR | MF_MENUBREAK | MF_OWNERDRAW)) == 0)
+    if (IS_STRING_ITEM(wFlags))
 		printf("InsertMenu (%04X, %04X, %04X, '%s') !\n",
 					hMenu, wFlags, wItemID, lpNewItem);
-	else
+    else
 		printf("InsertMenu (%04X, %04X, %04X, %04X, %08X) !\n",
-					hMenu, nPos, wFlags, wItemID, lpNewItem);
+		                  hMenu, nPos, wFlags, wItemID, lpNewItem);
 #endif
-	menu = (LPPOPUPMENU) GlobalLock(hMenu);
-	if (menu == NULL) return FALSE;
-	lpitem = FindMenuItem(hMenu, nPos, wFlags);
-	if (lpitem == NULL) lpitem = menu->firstItem;
-	hNewItem = GlobalAlloc(GMEM_MOVEABLE, sizeof(MENUITEM));
-	if (hNewItem == 0) {
-		GlobalUnlock(hMenu);
-		return FALSE;
-		}
-	lpitem2 = (LPMENUITEM)GlobalLock(hNewItem);
-	if (lpitem2 == NULL) {
-		GlobalFree(hNewItem);
-		GlobalUnlock(hMenu);
-		return FALSE;
-		}
-	lpitem2->hItem = hNewItem;
-	lpitem2->item_flags = wFlags;
-	lpitem2->item_id = wItemID;
-	if (!(wFlags & (MF_BITMAP | MF_OWNERDRAW | MF_MENUBARBREAK | 
-		MF_MENUBREAK | MF_SEPARATOR))) {
-		lpitem2->hText = GlobalAlloc(GMEM_MOVEABLE, strlen(lpNewItem) + 1);
-		lpitem2->item_text = GlobalLock(lpitem2->hText);
-		if (lpitem2->item_text != NULL)
-			strcpy(lpitem2->item_text, lpNewItem);
-		else {
-			printf("InsertMenu // Bad Alloc !\n");
-			return FALSE;
-			}
-		lpitem2->sel_key = GetSelectionKey(lpitem2->item_text);
-		}
-	else {
-		lpitem2->item_text = lpNewItem;
-		}
-	if (lpitem == NULL) {
-		menu->firstItem = lpitem2;
-		lpitem2->prev = NULL;
-		lpitem2->next = NULL;
-		}
-	else {
-		lpitem2->prev = lpitem;
-		lpitem2->next = lpitem->next;
-		if (lpitem2->next != NULL) lpitem2->next->prev = lpitem2;
-		lpitem->next = lpitem2;
-		}
-	menu->nItems++;
-	GlobalUnlock(hMenu);
-	return TRUE;
+
+      /* Find where to insert new item */
+
+    if ((wFlags & MF_BYPOSITION) && (nPos == (WORD)-1))
+    {
+	  /* Special case: append to menu */
+	if (!(menu = (LPPOPUPMENU) USER_HEAP_ADDR(hMenu))) return FALSE;
+	nPos = menu->nItems;
+    }
+    else
+    {
+	if (!MENU_FindItem( &hMenu, &nPos, wFlags )) return FALSE;
+	if (!(menu = (LPPOPUPMENU) USER_HEAP_ADDR(hMenu))) return FALSE;
+    }
+
+      /* Create new items array */
+
+    hNewItems = USER_HEAP_ALLOC( GMEM_MOVEABLE,
+				 sizeof(MENUITEM) * (menu->nItems+1) );
+    if (!hNewItems) return FALSE;
+    newItems = (MENUITEM *) USER_HEAP_ADDR( hNewItems );
+    if (menu->nItems > 0)
+    {
+	  /* Copy the old array into the new */
+	MENUITEM *oldItems = (MENUITEM *) USER_HEAP_ADDR( menu->hItems );
+	if (nPos > 0) memcpy( newItems, oldItems, nPos * sizeof(MENUITEM) );
+	if (nPos < menu->nItems) memcpy( &newItems[nPos+1], &oldItems[nPos],
+					(menu->nItems-nPos)*sizeof(MENUITEM) );
+
+	USER_HEAP_FREE( menu->hItems );
+    }
+    menu->hItems = hNewItems;
+    menu->nItems++;
+
+      /* Store the new item data */
+
+    lpitem = &newItems[nPos];
+    lpitem->item_flags = wFlags & ~(MF_HILITE | MF_MOUSESELECT);
+    lpitem->item_id    = wItemID;
+
+    if (IS_STRING_ITEM(wFlags))
+    {
+	lpitem->hText = USER_HEAP_ALLOC( GMEM_MOVEABLE, strlen(lpNewItem)+1 );
+	lpitem->item_text = (char *)USER_HEAP_ADDR( lpitem->hText );
+	strcpy( lpitem->item_text, lpNewItem );
+	lpitem->sel_key = GetSelectionKey( lpitem->item_text );
+    }
+    else lpitem->item_text = lpNewItem;
+    SetRectEmpty( &lpitem->rect );
+    lpitem->hCheckBit   = hStdCheck;
+    lpitem->hUnCheckBit = 0;
+    return TRUE;
 }
 
 
@@ -1489,65 +1706,7 @@
  */
 BOOL AppendMenu(HMENU hMenu, WORD wFlags, WORD wItemID, LPSTR lpNewItem)
 {
-	LPPOPUPMENU	menu;
-	HANDLE	hNewItem;
-	LPMENUITEM 	lpitem, lpitem2;
-#ifdef DEBUG_MENU
-	if ((wFlags & (MF_BITMAP | MF_SEPARATOR | MF_MENUBREAK | MF_OWNERDRAW)) == 0)
-		printf("AppendMenu (%04X, %04X, %04X, '%s') !\n",
-					hMenu, wFlags, wItemID, lpNewItem);
-	else
-		printf("AppendMenu (%04X, %04X, %04X, %08X) !\n",
-					hMenu, wFlags, wItemID, lpNewItem);
-#endif
-	menu = (LPPOPUPMENU) GlobalLock(hMenu);
-	if (menu == NULL) return FALSE;
-	lpitem = menu->firstItem;
-	if (lpitem != NULL) {
-		while (lpitem->next != NULL) {
-			lpitem = (LPMENUITEM)lpitem->next;
-			}
-		}
-	hNewItem = GlobalAlloc(GMEM_MOVEABLE, sizeof(MENUITEM));
-	if (hNewItem == 0) {
-		GlobalUnlock(hMenu);
-		return FALSE;
-		}
-	lpitem2 = (LPMENUITEM)GlobalLock(hNewItem);
-	lpitem2->hItem = hNewItem;
-	if (lpitem2 == NULL) {
-		GlobalFree(hNewItem);
-		GlobalUnlock(hMenu);
-		return FALSE;
-		}
-	lpitem2->item_flags = wFlags;
-	lpitem2->item_id = wItemID;
-	if (!(wFlags & (MF_BITMAP | MF_OWNERDRAW | MF_MENUBARBREAK | 
-		MF_MENUBREAK | MF_SEPARATOR))) {
-		lpitem2->hText = GlobalAlloc(GMEM_MOVEABLE, strlen(lpNewItem) + 1);
-		lpitem2->item_text = GlobalLock(lpitem2->hText);
-		if (lpitem2->item_text != NULL)
-			strcpy(lpitem2->item_text, lpNewItem);
-		else {
-			printf("AppendMenu // Bad Alloc !\n");
-			return FALSE;
-			}
-		lpitem2->sel_key = GetSelectionKey(lpitem2->item_text);
-		}
-	else {
-		lpitem2->item_text = lpNewItem;
-		}
-	if (lpitem == NULL)
-		menu->firstItem = lpitem2;
-	else
-		lpitem->next = lpitem2;
-	lpitem2->prev = lpitem;
-	lpitem2->next = NULL;
-	lpitem2->hCheckBit = (HBITMAP)NULL;
-	lpitem2->hUnCheckBit = (HBITMAP)NULL;
-	menu->nItems++;
-	GlobalUnlock(hMenu);
-	return TRUE;
+    return InsertMenu( hMenu, -1, wFlags | MF_BYPOSITION, wItemID, lpNewItem );
 }
 
 
@@ -1556,36 +1715,35 @@
  */
 BOOL RemoveMenu(HMENU hMenu, WORD nPos, WORD wFlags)
 {
-	LPPOPUPMENU	menu;
-	LPMENUITEM 	lpitem;
-	int		i;
+    LPPOPUPMENU	menu;
+    LPMENUITEM 	lpitem;
 #ifdef DEBUG_MENU
 	printf("RemoveMenu (%04X, %04X, %04X) !\n", hMenu, nPos, wFlags);
 #endif
-	menu = (LPPOPUPMENU) GlobalLock(hMenu);
-	if (menu == NULL) return FALSE;
-	lpitem = menu->firstItem;
-	for (i = 0; i < menu->nItems; i++) {
-		if (lpitem == NULL) break;
-		if (i == nPos) {
-			lpitem->prev->next = lpitem->next;
-			lpitem->next->prev = lpitem->prev;
-			if (!(lpitem->item_flags & 
-				(MF_BITMAP | MF_OWNERDRAW | MF_MENUBARBREAK | 
-				MF_MENUBREAK | MF_SEPARATOR))) {
-				GlobalUnlock(lpitem->hText);
-				GlobalFree(lpitem->hText);
-				}
-			GlobalFree(lpitem->hItem);
-			GlobalUnlock(hMenu);
-			return TRUE;
-			}
-		lpitem = (LPMENUITEM)lpitem->next;
-		printf("RemoveMenu // during loop items !\n");
-		}
-	printf("RemoveMenu // after loop items !\n");
-	GlobalUnlock(hMenu);
-	return FALSE;
+    if (!(lpitem = MENU_FindItem( &hMenu, &nPos, wFlags ))) return FALSE;
+    if (!(menu = (LPPOPUPMENU) USER_HEAP_ADDR(hMenu))) return FALSE;
+    
+      /* Remove item */
+
+    if (IS_STRING_ITEM(lpitem->item_flags)) USER_HEAP_FREE( lpitem->hText );
+    if (--menu->nItems == 0)
+    {
+	USER_HEAP_FREE( menu->hItems );
+	menu->hItems = 0;
+    }
+    else
+    {
+	while(nPos < menu->nItems)
+	{
+	    *lpitem = *(lpitem+1);
+	    lpitem++;
+	    nPos++;
+	}
+	menu->hItems = USER_HEAP_REALLOC( menu->hItems,
+					  menu->nItems * sizeof(MENUITEM),
+					  GMEM_MOVEABLE );
+    }
+    return TRUE;
 }
 
 
@@ -1594,35 +1752,12 @@
  */
 BOOL DeleteMenu(HMENU hMenu, WORD nPos, WORD wFlags)
 {
-	LPPOPUPMENU	menu;
-	LPMENUITEM 	lpitem;
-	int		i;
-#ifdef DEBUG_MENU
-	printf("DeleteMenu (%04X, %04X, %04X) !\n", hMenu, nPos, wFlags);
-#endif
-	menu = (LPPOPUPMENU) GlobalLock(hMenu);
-	if (menu == NULL) {
-		GlobalUnlock(hMenu);
-		return FALSE;
-		}
-	lpitem = FindMenuItem(hMenu, nPos, wFlags);
-	if (lpitem != NULL) {
-		if ((lpitem->item_flags & MF_POPUP) == MF_POPUP) 
-			DestroyMenu((HMENU)lpitem->item_id);
-		if (!(lpitem->item_flags & 
-			(MF_BITMAP | MF_OWNERDRAW | MF_MENUBARBREAK | 
-			MF_MENUBREAK | MF_SEPARATOR))) {
-			GlobalUnlock(lpitem->hText);
-			GlobalFree(lpitem->hText);
-			}
-		if (lpitem->prev) lpitem->prev->next = lpitem->next;
-		if (lpitem->next) lpitem->next->prev = lpitem->prev;
-		GlobalFree(lpitem->hItem);
-		GlobalUnlock(hMenu);
-		return TRUE;
-		}
-	GlobalUnlock(hMenu);
-	return FALSE;
+    MENUITEM *item = MENU_FindItem( &hMenu, &nPos, wFlags );
+    if (!item) return FALSE;
+    if (item->item_flags & MF_POPUP) DestroyMenu( item->item_id );
+      /* nPos is now the position of the item */
+    RemoveMenu( hMenu, nPos, wFlags | MF_BYPOSITION );
+    return TRUE;
 }
 
 
@@ -1631,48 +1766,31 @@
  */
 BOOL ModifyMenu(HMENU hMenu, WORD nPos, WORD wFlags, WORD wItemID, LPSTR lpNewItem)
 {
-	LPPOPUPMENU	menu;
-	LPMENUITEM 	lpitem;
-	int		i;
+    LPMENUITEM 	lpitem;
 #ifdef DEBUG_MENU
-	if ((wFlags & (MF_BITMAP | MF_SEPARATOR | MF_MENUBREAK | MF_OWNERDRAW)) == 0)
-		printf("ModifyMenu (%04X, %04X, %04X, %04X, '%s') !\n",
-					hMenu, nPos, wFlags, wItemID, lpNewItem);
-	else
-		printf("ModifyMenu (%04X, %04X, %04X, %04X, %08X) !\n",
-					hMenu, nPos, wFlags, wItemID, lpNewItem);
+    if (IS_STRING_ITEM(wFlags))
+	printf("ModifyMenu (%04X, %04X, %04X, %04X, '%s') !\n",
+	       hMenu, nPos, wFlags, wItemID, lpNewItem);
+    else
+	printf("ModifyMenu (%04X, %04X, %04X, %04X, %08X) !\n",
+	       hMenu, nPos, wFlags, wItemID, lpNewItem);
 #endif
-	menu = (LPPOPUPMENU) GlobalLock(hMenu);
-	if (menu == NULL) return FALSE;
-	lpitem = menu->firstItem;
-	for (i = 0; i < menu->nItems; i++) {
-		if (lpitem == NULL) break;
-		if (i == nPos) {
-			lpitem->item_flags = wFlags;
-			lpitem->item_id    = wItemID;
-			if (!(lpitem->item_flags & 
-				(MF_BITMAP | MF_OWNERDRAW | MF_MENUBARBREAK | 
-				MF_MENUBREAK | MF_SEPARATOR))) {
-				GlobalUnlock(lpitem->hText);
-				GlobalFree(lpitem->hText);
-				lpitem->hText = GlobalAlloc(GMEM_MOVEABLE, strlen(lpNewItem) + 1);
-				lpitem->item_text = GlobalLock(lpitem->hText);
-				printf("ModifyMenu %08X %08X '%s') !\n",
-					lpitem->item_text, lpNewItem, lpNewItem);
-				if (lpitem->item_text != NULL)
-					strcpy(lpitem->item_text, lpNewItem);
-				else
-					printf("ModifyMenu // Bad Alloc !\n");
-				}
-			else
-				lpitem->item_text = lpNewItem;
-				GlobalUnlock(hMenu);
-				return(TRUE);
-				}
-		lpitem = (LPMENUITEM)lpitem->next;
-		}
-    GlobalUnlock(hMenu);
-    return FALSE;
+    if (!(lpitem = MENU_FindItem( &hMenu, &nPos, wFlags ))) return FALSE;
+    
+    if (IS_STRING_ITEM(lpitem->item_flags)) USER_HEAP_FREE( lpitem->hText );
+    lpitem->item_flags = wFlags & ~(MF_HILITE | MF_MOUSESELECT);
+    lpitem->item_id    = wItemID;
+
+    if (IS_STRING_ITEM(wFlags))
+    {
+	lpitem->hText = USER_HEAP_ALLOC( GMEM_MOVEABLE, strlen(lpNewItem)+1 );
+	lpitem->item_text = (char *)USER_HEAP_ADDR( lpitem->hText );
+	strcpy( lpitem->item_text, lpNewItem );
+	lpitem->sel_key = GetSelectionKey( lpitem->item_text );
+    }
+    else lpitem->item_text = lpNewItem;
+    SetRectEmpty( &lpitem->rect );
+    return TRUE;
 }
 
 
@@ -1681,238 +1799,13 @@
  */
 HMENU CreatePopupMenu()
 {
-	HANDLE	hItem;
-	HMENU	hMenu;
-	LPPOPUPMENU menu;
-#ifdef DEBUG_MENU
-	printf("CreatePopupMenu !\n");
-#endif
-	hMenu = GlobalAlloc(GMEM_MOVEABLE, sizeof(POPUPMENU));
-	menu = (LPPOPUPMENU) GlobalLock(hMenu);
-	if (menu == NULL) {
-		GlobalFree(hMenu);
-		return 0;
-		}
-	menu->nItems 		= 0;
-	menu->firstItem 	= NULL;
-	menu->ownerWnd		= 0;
-	menu->hWndPrev		= 0;
-	menu->hWnd			= 0;
-	menu->hWndParent	= 0;
-	menu->MouseFlags	= 0;
-	menu->BarFlag		= FALSE;
-	menu->SysFlag		= FALSE;
-	menu->ChildFlag		= TRUE;
-	menu->Width 		= 100;
-	menu->Height 		= 0;
-	GlobalUnlock(hMenu);
-#ifdef DEBUG_MENU
-	printf("CreatePopupMenu // return %04X\n", hMenu);
-#endif
-	return hMenu;
-}
+    HMENU hmenu;
+    POPUPMENU *menu;
 
-
-/**********************************************************************
- *			TrackPopupMenu		[USER.416]
- */
-BOOL TrackPopupMenu(HMENU hMenu, WORD wFlags, short x, short y,
-	short nReserved, HWND hWnd, LPRECT lpRect)
-{
-	WND		*wndPtr;
-	LPPOPUPMENU	lppop;
-	RECT	rect;
-#ifdef DEBUG_MENU
-	printf("TrackPopupMenu (%04X, %04X, %d, %d, %04X, %04X, %08X) !\n",
-		hMenu, wFlags, x, y, nReserved, hWnd, lpRect);
-#endif
-	lppop = (LPPOPUPMENU) GlobalLock(hMenu);
-	if (lppop == NULL) {
-		printf("TrackPopupMenu // Bad menu handle %04X !\n", hMenu);
-		return FALSE;
-		}
-	wndPtr = WIN_FindWndPtr(hWnd);
-	if (wndPtr == NULL) {
-		printf("TrackPopupMenu // Bad window handle %04X !\n", hWnd);
-		return FALSE;
-		}
-	lppop->ownerWnd = hWnd;
-	lppop->hWndPrev = GetFocus();
-	if (lppop->hWnd == (HWND)NULL) {
-		lppop->hWnd = CreateWindow(POPUPMENU_CLASS_NAME, "",
-					   WS_POPUP | WS_BORDER,
-			x, y, lppop->Width, lppop->Height, (HWND)NULL, 0, 
-			wndPtr->hInstance, (LPSTR)lppop);
-		if (lppop->hWnd == 0) {
-			printf("TrackPopupMenu // Can't create PopupMenu window !\n");
-			return FALSE;
-			}
-		}
-	if (!lppop->BarFlag) {
-	    MENU_PopupMenuCalcSize(lppop->hWnd);
-#ifdef DEBUG_MENU
-		printf("TrackPopupMenu // x=%d y=%d Width=%d Height=%d\n", 
-			x, y, lppop->Width, lppop->Height); 
-#endif
-		SetWindowPos(lppop->hWnd, 0, x, y, lppop->Width + 2, lppop->Height + 2, 
-			SWP_NOACTIVATE | SWP_NOZORDER);
-		}
-	ShowWindow(lppop->hWnd, SW_SHOWNOACTIVATE);
-	SetFocus(lppop->hWnd);
-	if (!MenuHasFocus) {
-#ifdef DEBUG_MENU
-		printf("TrackPopupMenu // before MenuFocusLoop !\n");
-#endif
-		MenuFocusLoop(hWnd, NULL);
-#ifdef DEBUG_MENU
-		printf("TrackPopupMenu // after MenuFocusLoop !\n");
-#endif
-		}
-	GlobalUnlock(hMenu);
-	return TRUE;
-}
-
-
-BOOL ActivateMenuBarFocus(HWND hWnd)
-{
-	WND		*wndPtr;
-	LPPOPUPMENU	lpmenu;
-	BOOL	bRet;
-	MSG		msg;
-	if (MenuHasFocus) return FALSE;
-	wndPtr = WIN_FindWndPtr(hWnd);
-	if (wndPtr == NULL) return FALSE;
-#ifdef DEBUG_MENU
-	printf("ActivateMenuBarFocus (%04X) !\n", hWnd);
-#endif
-	while((wndPtr->dwStyle & WS_CHILD) == WS_CHILD) {
-		hWnd = GetParent(hWnd);
-		printf("ActivateMenuBarFocus // next Parent=%04X !\n", hWnd);
-		wndPtr = WIN_FindWndPtr(hWnd);
-		if (wndPtr == NULL) return FALSE;
-		}
-	if ((wndPtr->dwStyle & WS_CHILD) == 0 && wndPtr->wIDmenu != 0) {
-		lpmenu = (LPPOPUPMENU) GlobalLock(wndPtr->wIDmenu);
-		if (lpmenu == NULL) return FALSE;
-		lpmenu->hWndPrev = GetFocus();
-		SetFocus(hWnd);
-		MenuItemSelect(hWnd, lpmenu, 0);
-		bRet = MenuFocusLoop(hWnd, lpmenu);
-		GlobalUnlock(wndPtr->wIDmenu);
-		return bRet;
-		}
-	return FALSE;
-}
-
-
-BOOL MenuFocusLoop(HWND hWnd, LPPOPUPMENU lpmenu)
-{
-	MSG		msg;
-#ifdef DEBUG_MENU
-	printf("Enter in Menu Focus Loop !\n");
-#endif
-	MenuHasFocus = TRUE;
-	while(TRUE) {
-		if (!MenuHasFocus) break;
-		if (!GetMessage(&msg, (HWND)NULL, 0, 0)) break;
-		TranslateMessage(&msg);
-		if (hWnd == msg.hwnd && lpmenu != NULL) {
-			if ((msg.message == WM_SYSKEYDOWN && msg.wParam == VK_MENU) ||
-				(msg.message == WM_CHAR && msg.wParam == VK_ESCAPE)) {
-				HideAllSubPopupMenu(lpmenu);
-				break;
-				}
-			ScreenToClient(hWnd, &msg.pt);
-			msg.pt.y += lpmenu->rect.bottom;
-			switch(msg.message) {
-				case WM_LBUTTONDOWN:
-				case WM_NCLBUTTONDOWN:
-				    SetCapture(hWnd);
-				    MenuButtonDown(hWnd, lpmenu, msg.pt.x, msg.pt.y);
-				    break;
-				case WM_LBUTTONUP:
-				case WM_NCLBUTTONUP:
-				    MenuButtonUp(hWnd, lpmenu, msg.pt.x, msg.pt.y);
-				    ReleaseCapture();
-				    break;
-				case WM_MOUSEMOVE:
-				case WM_NCMOUSEMOVE:
-				    MenuMouseMove(hWnd, lpmenu, msg.wParam, msg.pt.x, msg.pt.y);
-				    break;
-				case WM_KEYDOWN:
-				case WM_KEYUP:
-				case WM_CHAR:
-					PopupMenuWndProc(hWnd, msg.message, msg.wParam, msg.lParam);
-				default:
-					DispatchMessage(&msg);
-				}
-			}
-		else
-			DispatchMessage(&msg);
-		}
-EndOfFocus:
-	MenuHasFocus = FALSE;
-	if (lpmenu != NULL) MenuItemSelect(hWnd, lpmenu, -1);
-#ifdef DEBUG_MENU
-	printf("End of Menu Focus Loop !\n");
-#endif
-	return TRUE;
-}
-
-
-/**********************************************************************
- *			NC_TrackSysMenu		[Internal]
- */
-void NC_TrackSysMenu(HWND hWnd)
-{
-	RECT	rect;
-	LPPOPUPMENU	lpsys;
-	WND *wndPtr = WIN_FindWndPtr(hWnd);    
-#ifdef DEBUG_MENU
-	printf("NC_TrackSysMenu hWnd=%04X !\n", hWnd);
-#endif
-	if (!wndPtr) return;
-	lpsys = (LPPOPUPMENU)GlobalLock(wndPtr->hSysMenu);
-#ifdef DEBUG_MENU
-	printf("NC_TrackSysMenu wndPtr->hSysMenu=%04X !\n", wndPtr->hSysMenu);
-#endif
-	if (lpsys == NULL) return;
-#ifdef DEBUG_MENU
-	printf("NC_TrackSysMenu wndPtr->hSysMenu=%04X !\n", wndPtr->hSysMenu);
-#endif
-	lpsys->BarFlag = FALSE;
-	lpsys->SysFlag = TRUE;
-	lpsys->ChildFlag = FALSE;
-	lpsys->hWndParent = hWnd;
-	if (!IsWindowVisible(lpsys->hWnd)) {
-		GetWindowRect(hWnd, &rect);
-#ifdef DEBUG_MENU
-		printf("NC_TrackSysMenu lpsys->hWnd=%04X !\n", lpsys->hWnd);
-#endif
-		if (MenuHasFocus) {
-			TrackPopupMenu(wndPtr->hSysMenu, TPM_LEFTBUTTON, 
-				rect.left, rect.top + SYSMETRICS_CYSIZE, 
-				0, hWnd, (LPRECT)NULL);
-			}
-		else {
-			MenuHasFocus = TRUE;
-			TrackPopupMenu(wndPtr->hSysMenu, TPM_LEFTBUTTON, 
-				rect.left, rect.top + SYSMETRICS_CYSIZE, 
-				0, hWnd, (LPRECT)NULL);
-			MenuHasFocus = FALSE;
-#ifdef DEBUG_MENU
-			printf("NC_TrackSysMenu // before MenuFocusLoop !\n");
-#endif
-			MenuFocusLoop(hWnd, NULL);
-#ifdef DEBUG_MENU
-			printf("NC_TrackSysMenu // after MenuFocusLoop !\n");
-#endif
-			}
-		}
-	else {
-		ShowWindow(lpsys->hWnd, SW_HIDE);
-		}
-	GlobalUnlock(wndPtr->hSysMenu);
+    if (!(hmenu = CreateMenu())) return 0;
+    menu = (POPUPMENU *) USER_HEAP_ADDR( hmenu );
+    menu->wFlags |= MF_POPUP;
+    return hmenu;
 }
 
 
@@ -1921,7 +1814,6 @@
  */
 DWORD GetMenuCheckMarkDimensions()
 {
-    InitStdBitmaps();
     return MAKELONG( check_bitmap_width, check_bitmap_height );
 }
 
@@ -1932,28 +1824,27 @@
 BOOL SetMenuItemBitmaps(HMENU hMenu, WORD nPos, WORD wFlags,
 		HBITMAP hNewCheck, HBITMAP hNewUnCheck)
 {
-	LPPOPUPMENU	menu;
-	LPMENUITEM 	lpitem;
-	int		i;
+    LPMENUITEM lpitem;
 #ifdef DEBUG_MENU
-	printf("SetMenuItemBitmaps (%04X, %04X, %04X, %04X, %08X) !\n",
-					hMenu, nPos, wFlags, hNewCheck, hNewUnCheck);
+    printf("SetMenuItemBitmaps (%04X, %04X, %04X, %04X, %08X) !\n",
+	    hMenu, nPos, wFlags, hNewCheck, hNewUnCheck);
 #endif
-	menu = (LPPOPUPMENU) GlobalLock(hMenu);
-	if (menu == NULL) return FALSE;
-	lpitem = menu->firstItem;
-	for (i = 0; i < menu->nItems; i++) {
-		if (lpitem == NULL) break;
-		if (i == nPos) {
-			lpitem->hCheckBit   = hNewCheck;
-			lpitem->hUnCheckBit = hNewUnCheck;
-			GlobalUnlock(hMenu);
-			return TRUE;
-			}
-		lpitem = (LPMENUITEM)lpitem->next;
-		}
-	GlobalUnlock(hMenu);
-	return FALSE;
+    if (!(lpitem = MENU_FindItem( &hMenu, &nPos, wFlags ))) return FALSE;
+
+    if (!hNewCheck && !hNewUnCheck)
+    {
+	  /* If both are NULL, restore default bitmaps */
+	lpitem->hCheckBit   = hStdCheck;
+	lpitem->hUnCheckBit = 0;
+	lpitem->item_flags &= ~MF_USECHECKBITMAPS;
+    }
+    else  /* Install new bitmaps */
+    {
+	lpitem->hCheckBit   = hNewCheck;
+	lpitem->hUnCheckBit = hNewUnCheck;
+	lpitem->item_flags |= MF_USECHECKBITMAPS;
+    }
+    return TRUE;
 }
 
 
@@ -1962,35 +1853,28 @@
  */
 HMENU CreateMenu()
 {
-	HANDLE	hItem;
-	HMENU	hMenu;
-	LPPOPUPMENU menu;
+    HMENU hMenu;
+    LPPOPUPMENU menu;
 #ifdef DEBUG_MENU
 	printf("CreateMenu !\n");
 #endif
-	hMenu = GlobalAlloc(GMEM_MOVEABLE, sizeof(POPUPMENU));
-	menu = (LPPOPUPMENU) GlobalLock(hMenu);
-	if (menu == NULL) {
-		GlobalFree(hMenu);
-		return 0;
-		}
-	menu->nItems 		= 0;
-	menu->firstItem 	= NULL;
-	menu->hWndPrev		= 0;
-	menu->ownerWnd		= 0;
-	menu->hWnd			= 0;
-	menu->hWndParent	= 0;
-	menu->MouseFlags	= 0;
-	menu->BarFlag		= TRUE;
-	menu->SysFlag		= FALSE;
-	menu->ChildFlag 	= TRUE;
-	menu->Width 		= 100;
-	menu->Height 		= 0;
-	GlobalUnlock(hMenu);
+    if (!(hMenu = USER_HEAP_ALLOC( GMEM_MOVEABLE, sizeof(POPUPMENU) )))
+	return 0;
+    menu = (LPPOPUPMENU) USER_HEAP_ADDR(hMenu);
+    menu->hNext  = 0;
+    menu->wFlags = 0;
+    menu->wMagic = MENU_MAGIC;
+    menu->hTaskQ = 0;
+    menu->Width  = 0;
+    menu->Height = 0;
+    menu->nItems = 0;
+    menu->hWnd   = 0;
+    menu->hItems = 0;
+    menu->FocusedItem = NO_SELECTED_ITEM;
 #ifdef DEBUG_MENU
-	printf("CreateMenu // return %04X\n", hMenu);
+    printf("CreateMenu // return %04X\n", hMenu);
 #endif
-	return hMenu;
+    return hMenu;
 }
 
 
@@ -2000,26 +1884,26 @@
 BOOL DestroyMenu(HMENU hMenu)
 {
 	LPPOPUPMENU lppop;
-	LPMENUITEM 	lpitem, lpitem2;
 #ifdef DEBUG_MENU
 	printf("DestroyMenu (%04X) !\n", hMenu);
 #endif
 	if (hMenu == 0) return FALSE;
-	lppop = (LPPOPUPMENU) GlobalLock(hMenu);
+	lppop = (LPPOPUPMENU) USER_HEAP_ADDR(hMenu);
 	if (lppop == NULL) return FALSE;
 	if (lppop->hWnd) DestroyWindow (lppop->hWnd);
-	lpitem = lppop->firstItem;
-	while (lpitem != NULL) {
-#ifdef DEBUG_MENU
-		printf("DestroyMenu (%04X) // during loop items !\n", hMenu);
-#endif
-		if ((lpitem->item_flags & MF_POPUP) == MF_POPUP) {
-			DestroyMenu((HMENU)lpitem->item_id);
-			}
-		lpitem = (LPMENUITEM)lpitem->next;
-		}
-	GlobalUnlock(hMenu);
-	GlobalFree(hMenu);
+
+	if (lppop->hItems)
+	{
+	    int i;
+	    MENUITEM *item = (MENUITEM *) USER_HEAP_ADDR( lppop->hItems );
+	    for (i = lppop->nItems; i > 0; i--, item++)
+	    {
+		if (item->item_flags & MF_POPUP)
+		    DestroyMenu( item->item_flags & MF_POPUP );
+	    }
+	    USER_HEAP_FREE( lppop->hItems );
+	}
+	USER_HEAP_FREE( hMenu );
 #ifdef DEBUG_MENU
 	printf("DestroyMenu (%04X) // End !\n", hMenu);
 #endif
@@ -2048,6 +1932,7 @@
 		return 0;
 		}
 	hMenu = LoadMenuIndirect((LPSTR)menu_desc);
+	GlobalUnlock( hMenu_desc );
 	return hMenu;
 }
 
@@ -2091,14 +1976,13 @@
 	return wndPtr->wIDmenu;
 }
 
+
 /**********************************************************************
  * 			SetMenu 	[USER.158]
  */
 BOOL SetMenu(HWND hWnd, HMENU hMenu)
 {
-	RECT	rect;
 	LPPOPUPMENU lpmenu;
-	WORD	flags;
 	WND * wndPtr = WIN_FindWndPtr(hWnd);
 	if (wndPtr == NULL) {
 		printf("SetMenu(%04X, %04X) // Bad window handle !\n", hWnd, hMenu);
@@ -2111,15 +1995,14 @@
 	wndPtr->wIDmenu = hMenu;
 	if (hMenu != 0)
 	{
-	    lpmenu = (LPPOPUPMENU) GlobalLock(hMenu);
+	    lpmenu = (LPPOPUPMENU) USER_HEAP_ADDR(hMenu);
 	    if (lpmenu == NULL) {
 		printf("SetMenu(%04X, %04X) // Bad menu handle !\n", hWnd, hMenu);
 		return FALSE;
 		}
-	    lpmenu->ownerWnd = hWnd;
+	    lpmenu->hWnd = hWnd;
+	    lpmenu->wFlags &= ~MF_POPUP;  /* Can't be a popup */
 	    lpmenu->Height = 0;  /* Make sure we recalculate the size */
-	    ResetHiliteFlags(lpmenu);
-	    GlobalUnlock(hMenu);
 	}
 	SetWindowPos( hWnd, 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE |
 		      SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED );
@@ -2133,31 +2016,16 @@
  */
 HMENU GetSubMenu(HMENU hMenu, short nPos)
 {
-	HMENU	hSubMenu;
-	LPPOPUPMENU lppop;
-	LPMENUITEM 	lpitem;
-	int		i;
+    LPPOPUPMENU lppop;
+    LPMENUITEM 	lpitem;
 #ifdef DEBUG_MENU
-	printf("GetSubMenu (%04X, %04X) !\n", hMenu, nPos);
+    printf("GetSubMenu (%04X, %04X) !\n", hMenu, nPos);
 #endif
-	if (hMenu == 0) return 0;
-	lppop = (LPPOPUPMENU) GlobalLock(hMenu);
-	if (lppop == NULL) return 0;
-	lpitem = lppop->firstItem;
-	for (i = 0; i < lppop->nItems; i++) {
-		if (lpitem == NULL) break;
-		if (i == nPos) {
-#ifdef DEBUG_MENU
-			printf("    found %04x\n", lpitem->item_id);
-#endif	    
-			if (lpitem->item_flags & MF_POPUP)
-				return lpitem->item_id;
-			else
-				return 0;
-			}
-		lpitem = (LPMENUITEM)lpitem->next;
-		}
-	return 0;
+    if (!(lppop = (LPPOPUPMENU) USER_HEAP_ADDR(hMenu))) return 0;
+    if ((WORD)nPos >= lppop->nItems) return 0;
+    lpitem = (MENUITEM *) USER_HEAP_ADDR( lppop->hItems );
+    if (!(lpitem[nPos].item_flags & MF_POPUP)) return 0;
+    return lpitem[nPos].item_id;
 }
 
 
@@ -2177,17 +2045,36 @@
 #ifdef DEBUG_MENU
 		printf("DrawMenuBar wIDmenu=%04X \n", wndPtr->wIDmenu);
 #endif
-		lppop = (LPPOPUPMENU) GlobalLock(wndPtr->wIDmenu);
+		lppop = (LPPOPUPMENU) USER_HEAP_ADDR(wndPtr->wIDmenu);
 		if (lppop == NULL) return;
 
 		lppop->Height = 0; /* Make sure we call MENU_MenuBarCalcSize */
 		SetWindowPos( hWnd, 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE |
 			    SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED );
-		GlobalUnlock(wndPtr->wIDmenu);
 	    }
 }
 
 
+/***********************************************************************
+ *           EndMenu   (USER.187)
+ */
+void EndMenu(void)
+{
+      /* Note: this won't work when we have multiple tasks... */
+    fEndMenuCalled = TRUE;
+}
+
+
+/***********************************************************************
+ *           LookupMenuHandle   (USER.217)
+ */
+HMENU LookupMenuHandle( HMENU hmenu, INT id )
+{
+    if (!MENU_FindItem( &hmenu, &id, MF_BYCOMMAND )) return 0;
+    else return hmenu;
+}
+
+
 /**********************************************************************
  *			LoadMenuIndirect	[USER.220]
  */
@@ -2195,89 +2082,40 @@
 {
 	HMENU     		hMenu;
 	MENU_HEADER 	*menu_desc;
-	LPPOPUPMENU lppop;
 #ifdef DEBUG_MENU
 	printf("LoadMenuIndirect: menu_template '%08X'\n", menu_template);
 #endif
 	hMenu = CreateMenu();
 	menu_desc = (MENU_HEADER *)menu_template;
 	ParseMenuResource((WORD *)(menu_desc + 1), 0, hMenu); 
-	lppop = (LPPOPUPMENU) GlobalLock(hMenu);
-	ResetHiliteFlags(lppop);
-	GlobalUnlock(hMenu);
 	return hMenu;
 }
 
 
 /**********************************************************************
- *			InitStdBitmaps (Internal)
- */
-void InitStdBitmaps()
-{
-    BITMAP bm;
-    if (hStdCheck == (HBITMAP)NULL)
-    {
-	hStdCheck = LoadBitmap((HANDLE)NULL, (LPSTR)OBM_CHECK);
-	GetObject( hStdCheck, sizeof(BITMAP), (LPSTR)&bm );
-	check_bitmap_width = bm.bmWidth;
-	check_bitmap_height = bm.bmHeight;
-    }
-    if (hStdMnArrow == (HBITMAP)NULL) 
-    {
-	hStdMnArrow = LoadBitmap((HANDLE)NULL, (LPSTR)OBM_MNARROW);
-	GetObject( hStdMnArrow, sizeof(BITMAP), (LPSTR)&bm );
-	arrow_bitmap_width = bm.bmWidth;
-	arrow_bitmap_height = bm.bmHeight;
-    }
-}
-
-
-/**********************************************************************
  *			CopySysMenu (Internal)
  */
 HMENU CopySysMenu()
 {
-	HMENU     		hMenu;
-	LPPOPUPMENU 	menu;
-	LPPOPUPMENU 	sysmenu;
+    HMENU hMenu;
+    LPPOPUPMENU sysmenu, menu;
+    MENUITEM *item;
+    int i;
+
+    sysmenu = (LPPOPUPMENU) USER_HEAP_ADDR(hSysMenu);
+    if (!(hMenu = CreatePopupMenu())) return 0;
+    menu = (POPUPMENU *) USER_HEAP_ADDR( hMenu );
+    menu->wFlags |= MF_SYSMENU;
+    item = (MENUITEM *) USER_HEAP_ADDR( sysmenu->hItems );
+    for (i = 0; i < sysmenu->nItems; i++, item++)
+    {
+	AppendMenu( hMenu, item->item_flags, item->item_id, item->item_text );
+    }
+
 #ifdef DEBUG_MENU
-	printf("CopySysMenu entry !\n");
+    printf("CopySysMenu hMenu=%04X !\n", hMenu);
 #endif
-	if (hSysMenu == 0) {
-/*		hSysMenu = LoadMenu((HINSTANCE)NULL, MAKEINTRESOURCE(1)); */
-/*		hSysMenu = LoadMenu((HINSTANCE)NULL, MAKEINTRESOURCE(SC_SYSMENU));*/
-		hSysMenu = LoadMenu((HINSTANCE)NULL, "SYSMENU"); 
-		if (hSysMenu == 0) {
-			printf("SysMenu not found in system resources !\n");
-			return (HMENU)NULL;
-			}
-#ifdef DEBUG_MENU
-		else
-			printf("SysMenu loaded from system resources %04X !\n", hSysMenu);
-#endif
-		}
-	hMenu = GlobalAlloc(GMEM_MOVEABLE, sizeof(POPUPMENU));
-	menu = (LPPOPUPMENU) GlobalLock(hMenu);
-	sysmenu = (LPPOPUPMENU) GlobalLock(hSysMenu);
-	if (menu != NULL && sysmenu != NULL) {
-		sysmenu->BarFlag = FALSE;
-		sysmenu->SysFlag = TRUE;
-		memcpy(menu, sysmenu, sizeof(POPUPMENU));
-		}
-	else {
-		printf("CopySysMenu // Bad SysMenu pointers !\n");
-		if (menu != NULL) {
-			GlobalUnlock(hMenu);
-			GlobalFree(hMenu);
-			}
-		return (HMENU)NULL;
-		}
-	GlobalUnlock(hMenu);
-	GlobalUnlock(hSysMenu);
-#ifdef DEBUG_MENU
-	printf("CopySysMenu hMenu=%04X !\n", hMenu);
-#endif
-	return hMenu;
+    return hMenu;
 }
 
 
@@ -2320,17 +2158,13 @@
     return next_item;
 }
 
+
 /**********************************************************************
- *		IsMenu(USER.358)
+ *		IsMenu    (USER.358)
  */
-BOOL IsMenu(HMENU hMenu)
+BOOL IsMenu( HMENU hmenu )
 {
-	LPPOPUPMENU	menu;
-
-	menu = (LPPOPUPMENU) GlobalLock(hMenu);
-	if (menu == NULL) 
-		return FALSE;
-
-	GlobalUnlock(hMenu);
-	return TRUE;
+    LPPOPUPMENU menu;
+    if (!(menu = (LPPOPUPMENU) USER_HEAP_ADDR( hmenu ))) return FALSE;
+    return (menu->wMagic == MENU_MAGIC);
 }