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/ChangeLog b/ChangeLog
index 59d5518..e7dfebd 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,4 +1,119 @@
 ----------------------------------------------------------------------
+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
+
+----------------------------------------------------------------------
 Thu Aug  4 07:18:02 1994  Michael Patra  <micky@marie.physik.tu-berlin.de>
 
         * [windows/message.c]
diff --git a/Configure b/Configure
index 1cb4d5c..c2fee7d 100644
--- a/Configure
+++ b/Configure
@@ -11,8 +11,23 @@
     ALLDEFINES="$ALLDEFINES -DWINELIB"
 else
     WINELIB=''
+    echo -n 'Use processor emulator (*DOES*NOT*WORK*YET*) (Y/N) [N]? '
+    read input
+    if [ "$input" = 'y' -o "$input" = 'Y' ]
+    then
+	PROCEMU='#define PROCEMU'
+	echo -n 'bochs directory [/usr/src/bochs]? '
+	read input
+	if [ "$input" = '' ]
+	then
+		ALLDEFINES="$ALLDEFINES -DPROC_EMU_DIR=/usr/src/bochs"
+	else
+		ALLDEFINES="$ALLDEFINES -DPROC_EMU_DIR="$input
+	fi
+    fi
 fi
 
+echo
 echo -n 'Short filenames (Y/N) [N]? '
 read input
 if [ "$input" = 'y' -o "$input" = 'Y' ]
@@ -47,17 +62,13 @@
     NEWBUILD=''
 fi
 
+NEWLINUXLDT=''
 if [ -f /usr/include/linux/ldt.h ]
 then
-	if grep -q seg_not_present /usr/include/linux/ldt.h
+	if grep seg_not_present /usr/include/linux/ldt.h
 	then
-		NEWLINUXLDT='#define NewLinuxLdt -DNEW_LDT_STRUCT'
-		ALLDEFINES="$ALLDEFINES -DNEW_LDT_STRUCT"
-	else
-		NEWLINUXLDT=''
+		NEWLINUXLDT='#define NEW_LDT_STRUCT'
 	fi
-else
-	NEWLINUXLDT=''
 fi
 
 echo '/* autoconf.h generated automatically.  Run Configure. */' > autoconf.h
@@ -66,6 +77,9 @@
 echo $NEWBUILD >> autoconf.h
 echo $WINE_INI_GLOBAL >> autoconf.h
 echo $NEWLINUXLDT >> autoconf.h
+echo $ENDIAN >> autoconf.h
+echo $PROCEMU >> autoconf.h
+echo $PROCEMUDIR >> autoconf.h
 echo "#define AutoDefines  $ALLDEFINES" >> autoconf.h
 
 xmkmf -a
diff --git a/controls/button.c b/controls/button.c
index 67de0ab..a5d3946 100644
--- a/controls/button.c
+++ b/controls/button.c
@@ -254,7 +254,6 @@
 		break;
 	}
 
-	GlobalUnlock(hWnd);
 	return lResult;
 }
 
@@ -522,7 +521,6 @@
 
     SelectObject(hDC, hOldPen);
     USER_HEAP_FREE(hText);
-    GlobalUnlock(hWnd);
     EndPaint(hWnd, &ps);
 }
 
@@ -604,7 +602,6 @@
 	}
 	NOTIFY_PARENT(hWnd, BN_CLICKED);
     }
-    GlobalUnlock(hWnd);
     InvalidateRect(hWnd, NULL, FALSE);
     UpdateWindow(hWnd);
 }
@@ -644,7 +641,6 @@
 	InvalidateRect(hWnd, NULL, FALSE);
 	UpdateWindow(hWnd);
     }
-    GlobalUnlock(hWnd);
 }
 
 static LONG CB_GetCheck(HWND hWnd)
@@ -653,7 +649,6 @@
     WND *wndPtr = WIN_FindWndPtr(hWnd);
 
     wResult = (WORD)(*(wndPtr->wExtra));
-    GlobalUnlock(hWnd);
     return (LONG)wResult;
 }
 
@@ -723,7 +718,6 @@
 
     SelectObject(hDC, hOldPen );
     USER_HEAP_FREE(hText);
-    GlobalUnlock(hWnd);
     EndPaint(hWnd, &ps);
 }
 
@@ -777,7 +771,6 @@
 	    (WORD)(*(wndPtr->wExtra)) = 1;
 	NOTIFY_PARENT(hWnd, BN_CLICKED);
     }
-    GlobalUnlock(hWnd);
     InvalidateRect(hWnd, NULL, FALSE);
     UpdateWindow(hWnd);
 }
@@ -817,7 +810,6 @@
 	InvalidateRect(hWnd, NULL, FALSE);
 	UpdateWindow(hWnd);
     }
-    GlobalUnlock(hWnd);
 }
 
 static LONG RB_GetCheck(HWND hWnd)
@@ -826,7 +818,6 @@
     WND *wndPtr = WIN_FindWndPtr(hWnd);
 
     wResult = (WORD)(*(wndPtr->wExtra));
-    GlobalUnlock(hWnd);
     return (LONG)wResult;
 }
 
diff --git a/controls/edit.c b/controls/edit.c
index 7f00cb8..bcbe8f2 100644
--- a/controls/edit.c
+++ b/controls/edit.c
@@ -17,12 +17,6 @@
 #include "user.h"
 #include "scroll.h"
 
-#define EDIT_HEAP_ALLOC(size)          USER_HEAP_ALLOC(GMEM_MOVEABLE,size)
-#define EDIT_HEAP_REALLOC(handle,size) USER_HEAP_REALLOC(handle,size,\
-							 GMEM_MOVEABLE)
-#define EDIT_HEAP_ADDR(handle)         USER_HEAP_ADDR(handle)
-#define EDIT_HEAP_FREE(handle)         USER_HEAP_FREE(handle)
-
 /* #define DEBUG_EDIT /* */
 
 #define NOTIFY_PARENT(hWndCntrl, wNotifyCode) \
@@ -37,7 +31,6 @@
 #define HSCROLLDIM (ClientWidth(wndPtr) / 3)
                            /* "line" dimension for horizontal scroll */
 
-
 typedef struct
 {
     int wlines;              /* number of lines of text */
@@ -172,6 +165,8 @@
 unsigned int EDIT_HeapSize(HWND hwnd, unsigned int handle);
 void EDIT_SetHandleMsg(HWND hwnd, WORD wParam);
 LONG EDIT_SetTabStopsMsg(HWND hwnd, WORD wParam, LONG lParam);
+void EDIT_CopyToClipboard(HWND hwnd);
+void EDIT_PasteMsg(HWND hwnd);
 void swap(int *a, int *b);
 
 
@@ -326,10 +321,20 @@
 	EDIT_CharMsg(hwnd, wParam);
 	break;
 
+    case WM_COPY:
+	EDIT_CopyToClipboard(hwnd);
+	EDIT_ClearSel(hwnd);
+	break;
+
     case WM_CREATE:
 	lResult = EDIT_CreateMsg(hwnd, lParam);
 	break;
 
+    case WM_CUT:
+	EDIT_CopyToClipboard(hwnd);
+	EDIT_DeleteSel(hwnd);
+	break;
+
     case WM_DESTROY:
 	EDIT_HeapFree(hwnd, es->hTextPtrs);
 	EDIT_HeapFree(hwnd, es->hCharWidths);
@@ -403,6 +408,10 @@
 	EDIT_PaintMsg(hwnd);
 	break;
 
+    case WM_PASTE:
+	EDIT_PasteMsg(hwnd);
+	break;
+
     case WM_SETFOCUS:
 	CreateCaret(hwnd, 0, 2, es->txtht);
 	SetCaretPos(es->WndCol, es->WndRow * es->txtht);
@@ -435,7 +444,6 @@
 	break;
     }
 
-    GlobalUnlock(hwnd);
     return lResult;
 }
 
@@ -479,11 +487,11 @@
     {
 	if (strlen(createStruct->lpszName) < EditBufLen(wndPtr))
 	{
+	    es->textlen = EditBufLen(wndPtr) + 1;
 	    es->hText = EDIT_HeapAlloc(hwnd, EditBufLen(wndPtr) + 2);
 	    text = EDIT_HeapAddr(hwnd, es->hText);
 	    strcpy(text, createStruct->lpszName);
 	    *(text + es->textlen) = '\0';
-	    es->textlen = EditBufLen(wndPtr) + 1;
 	}
 	else
 	{
@@ -3146,6 +3154,65 @@
 
 
 /*********************************************************************
+ *  EDIT_CopyToClipboard
+ *
+ *  Copy the specified text to the clipboard.
+ */
+
+void EDIT_CopyToClipboard(HWND hwnd)
+{
+    HANDLE hMem;
+    char *lpMem;
+    int i, len;
+    char *bbl, *bel;
+    WND *wndPtr = WIN_FindWndPtr(hwnd);
+    EDITSTATE *es = 
+	(EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
+
+    bbl = EDIT_TextLine(hwnd, es->SelBegLine) + es->SelBegCol;
+    bel = EDIT_TextLine(hwnd, es->SelEndLine) + es->SelEndCol;
+    len = (int)(bel - bbl);
+
+    hMem = GlobalAlloc(GHND, (DWORD)(len + 1));
+    lpMem = GlobalLock(hMem);
+
+    for (i = 0; i < len; i++)
+	*lpMem++ = *bbl++;
+
+    GlobalUnlock(hMem);
+    OpenClipboard(hwnd);
+    EmptyClipboard();
+    SetClipboardData(CF_TEXT, hMem);
+    CloseClipboard();
+}
+
+
+/*********************************************************************
+ *  WM_PASTE message function
+ */
+
+void EDIT_PasteMsg(HWND hwnd)
+{
+    HANDLE hClipMem;
+    char *lpClipMem;
+
+    OpenClipboard(hwnd);
+    if (!(hClipMem = GetClipboardData(CF_TEXT)))
+    {
+	/* no text in clipboard */
+	CloseClipboard();
+	return;
+    }
+    lpClipMem = GlobalLock(hClipMem);
+    EDIT_InsertText(hwnd, lpClipMem, strlen(lpClipMem));
+    GlobalUnlock(hClipMem);
+    CloseClipboard();
+    InvalidateRect(hwnd, NULL, TRUE);
+    UpdateWindow(hwnd);
+}
+
+
+/*********************************************************************
  *  Utility functions
  */
 
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);
 }
diff --git a/controls/static.c b/controls/static.c
index 0f84195..409fd03 100644
--- a/controls/static.c
+++ b/controls/static.c
@@ -127,7 +127,6 @@
 		break;
 	}
 
-	GlobalUnlock(hWnd);
 	return lResult;
 }
 
@@ -187,7 +186,6 @@
     DrawText(hdc, text, textlen, &rc, wFormat);
 
     USER_HEAP_FREE(hText);
-    GlobalUnlock(hwnd);
     EndPaint(hwnd, &ps);
 }
 
@@ -231,7 +229,6 @@
     DeleteObject((HANDLE)hPen);
     DeleteObject((HANDLE)hBrush);
 
-    GlobalUnlock(hwnd);
     EndPaint(hwnd, &ps);
 }
 
@@ -273,7 +270,6 @@
     DeleteObject((HANDLE)hPen);
     DeleteObject((HANDLE)hBrush);
 
-    GlobalUnlock(hwnd);
     EndPaint(hwnd, &ps);
 }
 
@@ -304,7 +300,6 @@
     hIcon = LoadIcon(wndPtr->hInstance, textPtr);
     DrawIcon(hdc, rc.left, rc.top, hIcon);
     EndPaint(hwnd, &ps);
-    GlobalUnlock(hwnd);
 }
 
 
diff --git a/if1632/relay.c b/if1632/relay.c
index 070a58a..3122d8b 100644
--- a/if1632/relay.c
+++ b/if1632/relay.c
@@ -290,7 +290,7 @@
 			    used++;
 			    if (table[j].handler) implemented++;
 			    else 
-				    printf("%s.%d\n",
+				    printf("%s.%d not implemented\n",
 					   dll_builtin_table[i].dll_name,
 					   j);
 		    };
@@ -301,10 +301,11 @@
 		    perc = implemented * 100.00 / used;
 	    else
 		    perc = 0.0;
-	    printf("%s: %d of %d (%3.1f %%)\n", dll_builtin_table[i].dll_name, implemented, used, perc);
+	    if (used)
+		    printf("%s: %d of %d (%3.1f %%)\n", dll_builtin_table[i].dll_name, implemented, used, perc);
     };
 	perc = timplemented * 100.00 / tused;
-	printf("TOTAL: %d of %d implemented (%3.1f %%)\n",timplemented, tused, perc);
+	printf("TOTAL: %d of %d winapi functions implemented (%3.1f %%)\n",timplemented, tused, perc);
 }
 #endif /* WINESTAT */
 #endif /* !WINELIB */
diff --git a/if1632/toolhelp.spec b/if1632/toolhelp.spec
index 682dec5..4380277 100644
--- a/if1632/toolhelp.spec
+++ b/if1632/toolhelp.spec
@@ -15,16 +15,16 @@
 60 pascal ModuleNext(ptr) ModuleNext(1)
 61 pascal ModuleFindName(ptr ptr) ModuleFindName(1 2)
 62 pascal ModuleFindHandle(ptr word) ModuleFindHandle(1 2)
-# 63   1  0caa  TASKFIRST exported, shared data
-# 64   1  0ced  TASKNEXT exported, shared data
-# 65   1  0d2e  TASKFINDHANDLE exported, shared data
+63 pascal16 TaskFirst(ptr) TaskFirst(1)
+64 pascal16 TaskNext(ptr) TaskNext(1)
+65 pascal16 TaskFindHandle(ptr word) TaskFindHandle(1 2)
 # 66   1  0f1c  STACKTRACEFIRST exported, shared data
 # 67   1  0f67  STACKTRACECSIPFIRST exported, shared data
 # 68   1  0fca  STACKTRACENEXT exported, shared data
 # 69   1  28b0  CLASSFIRST exported, shared data
 # 70   1  2925  CLASSNEXT exported, shared data
 # 71   1  11ce  SYSTEMHEAPINFO exported, shared data
-# 72   1  13f4  MEMMANINFO exported, shared data
+72 pascal16 MemManInfo(ptr) MemManInfo(1)
 # 73   1  1b72  NOTIFYREGISTER exported, shared data
 # 74   1  1c29  NOTIFYUNREGISTER exported, shared data
 # 75   1  2060  INTERRUPTREGISTER exported, shared data
diff --git a/if1632/user.spec b/if1632/user.spec
index 88c5d9d..371b3d7 100644
--- a/if1632/user.spec
+++ b/if1632/user.spec
@@ -190,7 +190,7 @@
 185 pascal GrayString(word word ptr ptr word word word word word)
 	   GrayString(1 2 3 4 5 6 7 8 9)
 186 pascal SwapMouseButton(word) SwapMouseButton(1)
-#187 ENDMENU
+187 pascal EndMenu() EndMenu()
 188 pascal SetSysModalWindow(word) SetSysModalWindow(1)
 189 pascal GetSysModalWindow() GetSysModalWindow()
 190 pascal GetUpdateRect(word ptr word) GetUpdateRect(1 2 3)
@@ -201,7 +201,8 @@
 195 pascal DlgDirListComboBox(word ptr word word word) DlgDirListComboBox(1 2 3 4 5)
 196 pascal TabbedTextOut(word s_word s_word ptr s_word s_word ptr s_word)
 		TabbedTextOut(1 2 3 4 5 6 7 8)
-#197 GETTABBEDTEXTEXTENT
+197 pascal GETTABBEDTEXTEXTENT(word ptr word word ptr)
+	   GetTabbedTextExtent(1 2 3 4 5)
 #198 CASCADECHILDWINDOWS
 #199 TILECHILDWINDOWS
 200 pascal OpenComm(ptr word word) OpenComm(1 2 3)
@@ -221,7 +222,7 @@
 214 pascal EscapeCommFunction(word word) EscapeCommFunction(1 2)
 215 pascal FlushComm(word word) FlushComm(1 2)
 #216 USERSEEUSERDO
-#217 LOOKUPMENUHANDLE
+217 pascal LookupMenuHandle(word s_word) LookupMenuHandle(1 2)
 218 pascal DialogBoxIndirect(word word word ptr) DialogBoxIndirect(1 2 3 4)
 219 pascal CreateDialogIndirect(word ptr word ptr)
 	   CreateDialogIndirect(1 2 3 4)
diff --git a/include/bitmaps/check_bitmap b/include/bitmaps/check_bitmap
deleted file mode 100644
index bc76d9f..0000000
--- a/include/bitmaps/check_bitmap
+++ /dev/null
@@ -1,7 +0,0 @@
-#define check_bitmap_width 10
-#define check_bitmap_height 10
-#define check_bitmap_x_hot 0
-#define check_bitmap_y_hot 0
-static char check_bitmap_bits[] = {
-   0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x03, 0x80, 0x01, 0xc0, 0x00,
-   0x63, 0x00, 0x36, 0x00, 0x1c, 0x00, 0x08, 0x00};
diff --git a/include/bitmaps/check_mark b/include/bitmaps/check_mark
new file mode 100644
index 0000000..4c7adce
--- /dev/null
+++ b/include/bitmaps/check_mark
@@ -0,0 +1,6 @@
+#define check_mark_width 14
+#define check_mark_height 14
+static char check_mark_bits[] = {
+   0x00, 0x00, 0x00, 0x08, 0x00, 0x08, 0x00, 0x0c, 0x00, 0x04, 0x00, 0x06,
+   0x30, 0x02, 0x60, 0x03, 0x40, 0x01, 0xc0, 0x01, 0x80, 0x00, 0x00, 0x00,
+   0x00, 0x00, 0x00, 0x00};
diff --git a/include/bitmaps/menu_arrow b/include/bitmaps/menu_arrow
new file mode 100644
index 0000000..a38ff70
--- /dev/null
+++ b/include/bitmaps/menu_arrow
@@ -0,0 +1,4 @@
+#define menu_arrow_width 7
+#define menu_arrow_height 11
+static char menu_arrow_bits[] = {
+   0x00, 0x02, 0x06, 0x0e, 0x1e, 0x3e, 0x1e, 0x0e, 0x06, 0x02, 0x00};
diff --git a/include/bitmaps/nocheck_bitmap b/include/bitmaps/nocheck_bitmap
deleted file mode 100644
index a56ae35..0000000
--- a/include/bitmaps/nocheck_bitmap
+++ /dev/null
@@ -1,7 +0,0 @@
-#define nocheck_bitmap_width 10
-#define nocheck_bitmap_height 10
-#define nocheck_bitmap_x_hot 0
-#define nocheck_bitmap_y_hot 0
-static char nocheck_bitmap_bits[] = {
-   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
diff --git a/include/dialog.h b/include/dialog.h
index b6fe1b3..3b33347 100644
--- a/include/dialog.h
+++ b/include/dialog.h
@@ -25,6 +25,7 @@
     WORD      xBaseUnit;
     WORD      yBaseUnit;
     WORD      fEnd;
+    HANDLE    hDialogHeap;
 } DIALOGINFO;
 
 
diff --git a/include/menu.h b/include/menu.h
index c877618..2e0f7ca 100644
--- a/include/menu.h
+++ b/include/menu.h
@@ -6,42 +6,34 @@
 #ifndef MENU_H
 #define MENU_H
 
+#define MENU_MAGIC   0x554d  /* 'MU' */
 
 
 typedef struct tagMENUITEM
 {
-    struct tagMENUITEM *next;
-    struct tagMENUITEM *prev;
-	HANDLE	hItem;	
     WORD	item_flags;
     WORD	item_id;
-    WORD	sel_key;
-    char	*item_text;
-	HANDLE	hText;	
     RECT	rect;
+    WORD	sel_key;
     HBITMAP	hCheckBit;
     HBITMAP	hUnCheckBit;
+    char	*item_text;
+	HANDLE	hText;	
 } MENUITEM, *LPMENUITEM;
 
 
 typedef struct tagPOPUPMENU
 {
-    HWND	hWnd;			/* PopupMenu window handle	  		*/
-    HWND	hWndParent;		/* Parent PopupMenu window handle  	*/
-    HWND	ownerWnd;		/* Owner window			  			*/
-    HWND	hWndPrev;		/* Previous Window Focus Owner 		*/
-    WORD	nItems;    		/* Number of items on menu			*/
-    MENUITEM   *firstItem;
-    WORD	FocusedItem;
-    WORD	MouseFlags;
-    BOOL	BarFlag;		/* TRUE if menu is a MENUBAR		*/
-    BOOL	SysFlag; 		/* TRUE if menu is a SYSMENU		*/
-    BOOL	ChildFlag;		/* TRUE if child of other menu		*/
-    WORD	Width;
-    WORD	Height;
-    WORD	CheckWidth;
-    WORD	PopWidth;
-    RECT	rect;
+    HMENU       hNext;        /* Next menu (compatibility only, always 0) */
+    WORD        wFlags;       /* Menu flags (MF_POPUP, MF_SYSMENU) */
+    WORD        wMagic;       /* Magic number */
+    HANDLE      hTaskQ;       /* Task queue for this menu */
+    WORD	Width;        /* Width of the whole menu */
+    WORD	Height;       /* Height of the whole menu */
+    WORD	nItems;       /* Number of items in the menu */
+    HWND	hWnd;	      /* Window containing the menu */
+    HANDLE      hItems;       /* Handle to the items array */
+    WORD	FocusedItem;  /* Currently focused item */
 } POPUPMENU, *LPPOPUPMENU;
 
 typedef struct
@@ -63,11 +55,4 @@
     char	item_text[1];		/* Text for menu item		  */
 } MENUITEMTEMPLATE;
 
-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);
-extern void NC_TrackSysMenu(HWND hwnd);
-
 #endif /* MENU_H */
diff --git a/include/message.h b/include/message.h
index 5e6e9e8..66d7926 100644
--- a/include/message.h
+++ b/include/message.h
@@ -53,7 +53,7 @@
 extern void hardware_event( WORD message, WORD wParam, LONG lParam,
 			    int xPos, int yPos, DWORD time, DWORD extraInfo );
 extern BOOL MSG_GetHardwareMessage( LPMSG msg );
-extern BOOL MSG_InternalGetMessage( LPMSG msg, HWND hwnd,
-				    short code, BOOL sendIdle );
+extern BOOL MSG_InternalGetMessage( LPMSG msg, HWND hwnd, HWND hwndOwner,
+				    short code, WORD flags, BOOL sendIdle );
 
 #endif  /* MESSAGE_H */
diff --git a/include/msdos.h b/include/msdos.h
index 99eccef..e5443f1 100644
--- a/include/msdos.h
+++ b/include/msdos.h
@@ -17,29 +17,6 @@
 #define DOSVERSION 0x0330;
 #define MAX_DOS_DRIVES	26
 
-#define EAX context->sc_eax
-#define EBX context->sc_ebx
-#define ECX context->sc_ecx
-#define EDX context->sc_edx
-
-#define AX (context->sc_eax & 0x0000ffffL)
-#define BX (context->sc_ebx & 0x0000ffffL)
-#define CX (context->sc_ecx & 0x0000ffffL)
-#define DX (context->sc_edx & 0x0000ffffL)
-
-#define CS context->sc_cs
-#define DS context->sc_ds
-#define ES context->sc_es
-#define SS context->sc_ss
-
-#define DI context->sc_edi
-#define SI context->sc_esi
-#define SP context->sc_esp
-#define EFL context->sc_efl
-
-#define SetCflag	(EFL |= 0x00000001L)
-#define ResetCflag	(EFL &= 0xfffffffeL)
-
 #define pointer(a,b) 	(BYTE*)(((WORD) a << 16) | b)
 #define segment(a) 	((DWORD)a >> 16)
 #define offset(a)	((DWORD)a & 0xffff)
diff --git a/include/registers.h b/include/registers.h
new file mode 100644
index 0000000..0284abf
--- /dev/null
+++ b/include/registers.h
@@ -0,0 +1,50 @@
+#ifndef __WINE_REGISTERS_H
+#define __WINE_REGISTERS_H
+
+#include <windows.h>
+#include "autoconf.h"
+
+#ifndef PROCEMU
+
+#define EAX context->sc_eax
+#define EBX context->sc_ebx
+#define ECX context->sc_ecx
+#define EDX context->sc_edx
+
+#define AX *(WORD*)&context->sc_eax
+#define BX *(WORD*)&context->sc_ebx
+#define CX *(WORD*)&context->sc_ecx
+#define DX *(WORD*)&context->sc_edx
+
+#define AL *(BYTE*)&context->sc_eax
+#define AH *(((BYTE*)&context->sc_eax)+1)
+#define BL *(BYTE*)&context->sc_ebx
+#define BH *(((BYTE*)&context->sc_ebx)+1)
+#define CL *(BYTE*)&context->sc_ecx
+#define CH *(((BYTE*)&context->sc_ecx)+1)
+#define DL *(BYTE*)&context->sc_edx
+#define DH *(((BYTE*)&context->sc_edx)+1)
+
+#define CS context->sc_cs
+#define DS context->sc_ds
+#define ES context->sc_es
+#define SS context->sc_ss
+
+#define DI context->sc_edi
+#define SI context->sc_esi
+#define SP context->sc_esp
+#define EFL context->sc_efl
+#define EIP context->sc_eip
+
+#define SetCflag	(EFL |= 0x00000001)
+#define ResetCflag	(EFL &= 0xfffffffe)
+
+#else
+
+#include "bx_bochs.h"
+
+#define SetCflag	bx_STC()
+#define ResetCflag	bx_CLC()
+
+#endif /* PROCEMU */
+#endif /* __WINE_REGISTERS_H */
diff --git a/include/task.h b/include/task.h
index 1c05265..8be9787 100644
--- a/include/task.h
+++ b/include/task.h
@@ -7,30 +7,9 @@
 
 #include "toolhelp.h"
 
-typedef HANDLE HGLOBAL;
-
-typedef struct {
-	DWORD		dwSize;
-	HTASK		hTask;
-	HTASK		hTaskParent;
-	HINSTANCE	hInst;
-	HMODULE		hModule;
-	WORD		wSS;
-	WORD		wSP;
-	WORD		wStackTop;
-	WORD		wStackMinimum;
-	WORD		wStackBottom;
-	WORD		wcEvents;
-	HGLOBAL		hQueue;
-	char		szModule[MAX_MODULE_NAME + 1];
-	WORD		wPSPOffset;
-	HANDLE		hNext;
-} TASKENTRY;
-typedef TASKENTRY *LPTASKENTRY;
-
 typedef struct {
 	TASKENTRY	te;
-	int			unix_pid;
+	int		unix_pid;
 	HICON		hIcon;
 	HWND		*lpWndList;
 	void		*lpPrevTask;
diff --git a/include/toolhelp.h b/include/toolhelp.h
index 6941d1b..40d7d9b 100644
--- a/include/toolhelp.h
+++ b/include/toolhelp.h
@@ -4,9 +4,14 @@
 #include "windows.h"
 
 DECLARE_HANDLE(HMODULE);
+DECLARE_HANDLE(HGLOBAL);
 
-#define MAX_MODULE_NAME 9
-#define MAX_PATH 255
+#define MAX_DATA	11
+#define MAX_MODULE_NAME	9
+#define MAX_PATH	255
+#define MAX_CLASSNAME	255
+
+/* modules */
 
 typedef struct {
     DWORD dwSize;
@@ -23,4 +28,61 @@
 HMODULE ModuleFindName(MODULEENTRY *lpModule, LPCSTR lpstrName);
 HMODULE ModuleFindHandle(MODULEENTRY *lpModule, HMODULE hModule);
 
+/* tasks */
+
+typedef struct tagTASKENTRY {
+	DWORD dwSize;
+	HTASK hTask;
+	HTASK hTaskParent;
+	HINSTANCE hInst;
+	HMODULE hModule;
+	WORD wSS;
+	WORD wSP;
+	WORD wStackTop;
+	WORD wStackMinimum;
+	WORD wStackBottom;
+	WORD wcEvents;
+	HGLOBAL hQueue;
+	char szModule[MAX_MODULE_NAME + 1];
+	WORD wPSPOffset;
+	HANDLE hNext;
+} TASKENTRY;
+typedef TASKENTRY *LPTASKENTRY;
+
+BOOL	TaskFirst(LPTASKENTRY lpTask);
+BOOL	TaskNext(LPTASKENTRY lpTask);
+BOOL	TaskFindHandle(LPTASKENTRY lpTask, HTASK hTask);
+DWORD	TaskSetCSIP(HTASK hTask, WORD wCS, WORD wIP);
+DWORD	TaskGetCSIP(HTASK hTask);
+BOOL	TaskSwitch(HTASK hTask, DWORD dwNewCSIP);
+
+/* mem info */
+
+typedef struct tagMEMMANINFO {
+	DWORD dwSize;
+	DWORD dwLargestFreeBlock;
+	DWORD dwMaxPagesAvailable;
+	DWORD dwMaxPagesLockable;
+	DWORD dwTotalLinearSpace;
+	DWORD dwTotalUnlockedPages;
+	DWORD dwFreePages;
+	DWORD dwTotalPages;
+	DWORD dwFreeLinearSpace;
+	DWORD dwSwapFilePages;
+	WORD wPageSize;
+} MEMMANINFO;
+typedef MEMMANINFO *LPMEMMANINFO;
+
+typedef struct tagSYSHEAPINFO {
+	DWORD dwSize;
+	WORD wUserFreePercent;
+	WORD wGDIFreePercent;
+	HGLOBAL hUserSegment;
+	HGLOBAL hGDISegment;
+} SYSHEAPINFO;
+typedef SYSHEAPINFO *LPSYSHEAPINFO;
+
+BOOL MemManInfo(LPMEMMANINFO lpEnhMode);
+BOOL SystemHeapInfo(LPSYSHEAPINFO lpSysHeap);
+
 #endif /* __TOOLHELP_H */
diff --git a/include/windows.h b/include/windows.h
index 3f14d8b..711210a 100644
--- a/include/windows.h
+++ b/include/windows.h
@@ -1496,6 +1496,8 @@
 #define WM_HSCROLL          0x0114
 #define WM_VSCROLL          0x0115
 
+#define WM_ENTERIDLE        0x0121
+
   /* Mouse messages */
 #define WM_MOUSEMOVE	    0x0200
 #define WM_LBUTTONDOWN	    0x0201
@@ -2714,6 +2716,7 @@
 Fb(HMENU,GetSubMenu,HMENU,a,short,b)
 Fb(HMENU,GetSystemMenu,HWND,a,BOOL,b)
 Fb(HMENU,LoadMenu,HANDLE,a,LPSTR,b)
+Fb(HMENU,LookupMenuHandle,HMENU,a,INT,b)
 Fb(HWND,ChildWindowFromPoint,HWND,a,POINT,b)
 Fb(HWND,FindWindow,LPSTR,a,LPSTR,b)
 Fb(HWND,GetDlgItem,HWND,a,WORD,b)
diff --git a/loader/ldtlib.c b/loader/ldtlib.c
index 40929d6..181c4b1 100644
--- a/loader/ldtlib.c
+++ b/loader/ldtlib.c
@@ -5,6 +5,8 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <errno.h>
+#include "autoconf.h"
+
 #ifdef linux
 #include <linux/unistd.h>
 #include <linux/head.h>
diff --git a/loader/resource.c b/loader/resource.c
index 662fa34..b69c5f2 100644
--- a/loader/resource.c
+++ b/loader/resource.c
@@ -37,6 +37,8 @@
 static RESOURCE *Top = NULL;
 extern HINSTANCE hSysRes;
 
+extern HBITMAP BITMAP_LoadOEMBitmap( WORD id );  /* objects/bitmap.c */
+
 HANDLE RSC_LoadResource(int instance, char *rsc_name, int type, 
 			int *image_size_ret);
 void RSC_LoadNameTable(void);
@@ -1153,8 +1155,14 @@
     printf("LoadBitmap: instance = %04x, name = %08x\n",
 	   instance, bmp_name);
 #endif
-    if (instance == (HANDLE)NULL)  instance = hSysRes;
-    if (!(hdc = GetDC(GetDesktopWindow()))) return 0;
+    if (!instance)
+    {
+	  /* Try to create an OEM bitmap */
+	hbitmap = BITMAP_LoadOEMBitmap( ((int)bmp_name) & 0xffff );
+	if (hbitmap) return hbitmap;
+	  /* Failed -> load it from sysres.dll */
+	instance = hSysRes;
+    }
 
     rsc_mem = RSC_LoadResource(instance, bmp_name, NE_RSCTYPE_BITMAP, 
 			       &image_size);
@@ -1163,6 +1171,7 @@
 	return 0;
 	}
     lp = (long *) GlobalLinearLock(rsc_mem);
+    if (!(hdc = GetDC(0))) lp = NULL;
     if (lp == NULL)
     {
 	GlobalFree(rsc_mem);
diff --git a/loader/task.c b/loader/task.c
index 569c64b..d227640 100644
--- a/loader/task.c
+++ b/loader/task.c
@@ -10,6 +10,8 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <sys/types.h>
+#include <unistd.h>
 #include "windows.h"
 #include "wine.h"
 #include "task.h"
@@ -17,7 +19,6 @@
 static LPWINETASKENTRY lpTaskList = NULL;
 static int nTaskCount = 0;
 
-
 /**********************************************************************
  *				GetCurrentTask	[KERNEL.36]
  */
@@ -122,9 +123,14 @@
  */
 HANDLE CreateNewTask(HINSTANCE hInst, HTASK hTaskParent)
 {
-    HANDLE hTask;
+	HANDLE hTask;
 	LPWINETASKENTRY lpTask = lpTaskList;
 	LPWINETASKENTRY lpNewTask;
+	MODULEENTRY module;
+
+	module.dwSize = sizeof(module);
+	ModuleFindHandle(&module, hInst);
+
 	if (lpTask != NULL) {
 		while (TRUE) {
 			if (lpTask->lpNextTask == NULL) break;
@@ -160,7 +166,7 @@
 	lpNewTask->te.wStackBottom = 0;
 	lpNewTask->te.wcEvents = 0;
 	lpNewTask->te.hQueue = 0;
-	sprintf(lpNewTask->te.szModule, "TASK%04X", hInst);
+	strcpy(lpNewTask->te.szModule, module.szModule);
 	lpNewTask->te.wPSPOffset = 0;
 	lpNewTask->unix_pid = getpid();
 	lpNewTask->lpWndList = (HWND *) malloc(MAXWIN_PER_TASK * sizeof(HWND));
@@ -245,4 +251,55 @@
 	return TRUE;
 }
 
+BOOL TaskFirst(LPTASKENTRY lpTask)
+{
+	printf("TaskFirst(%8x)\n", (int) lpTask);
 
+	if (lpTaskList) {
+		memcpy(lpTask, &lpTaskList->te, lpTask->dwSize);
+		return TRUE;
+	} else
+		return FALSE;
+}
+
+BOOL TaskNext(LPTASKENTRY lpTask)
+{
+	LPWINETASKENTRY list;
+	
+	printf("TaskNext(%8x)\n", (int) lpTask);
+
+	list = lpTaskList;
+	while (list) {
+		if (list->te.hTask == lpTask->hTask) {
+			list = list->lpNextTask;
+			if (list) {
+				memcpy(lpTask, &list->te, lpTask->dwSize);
+				return TRUE;
+			} else
+				return FALSE;
+		}
+		list = list->lpNextTask;
+	}
+	return FALSE;
+}
+
+BOOL TaskFindHandle(LPTASKENTRY lpTask, HTASK hTask)
+{
+	static LPWINETASKENTRY list;
+	
+	printf("TaskFindHandle(%8x,%4x)\n", (int) lpTask, hTask);
+
+	list = lpTaskList;
+	while (list) {
+		if (list->te.hTask == hTask) {
+			list = list->lpNextTask;
+			if (list) {
+				memcpy(lpTask, &list->te, lpTask->dwSize);
+				return TRUE;
+			} else
+				return FALSE;
+		}
+		list = list->lpNextTask;
+	}
+	return FALSE;
+}
diff --git a/memory/global.c b/memory/global.c
index 7509868..117c532 100644
--- a/memory/global.c
+++ b/memory/global.c
@@ -8,6 +8,7 @@
 #include <stdlib.h>
 #include <string.h>
 #include "prototypes.h"
+#include "toolhelp.h"
 #include "heap.h"
 #include "segmem.h"
 
@@ -807,3 +808,11 @@
     printf("GetFreeSpace // return %ld !\n", total_free << 16);
     return total_free << 16;
 }
+
+/**********************************************************************
+ *                      MemManInfo (toolhelp.72)
+ */
+BOOL MemManInfo(LPMEMMANINFO lpmmi)
+{
+	return 1;
+}
diff --git a/misc/file.c b/misc/file.c
index 92359fd..db2293d 100644
--- a/misc/file.c
+++ b/misc/file.c
@@ -23,13 +23,28 @@
 #include <unistd.h>
 #include <time.h>
 #include <windows.h>
+#include <sys/stat.h>
 #include "prototypes.h"
+#include "regfunc.h"
+#include "windows.h"
+#include "wine.h"
+#include "msdos.h"
+#include "registers.h"
+#include "options.h"
+
+#define MAX_PATH 255
 
 /* #define DEBUG_FILE /* */
 
 char WindowsDirectory[256], SystemDirectory[256], TempDirectory[256];
 extern char WindowsPath[256];
 
+extern char WindowsPath[];
+extern WORD ExtendedError;
+
+
+char *GetDosFileName(char *unixfilename);
+
 /***************************************************************************
  _lopen 
 
@@ -116,83 +131,153 @@
 
 /**************************************************************************
  OpenFile
-
- Warning:  This is nearly totally untested.  It compiles, that's it...
-                                            -SL 9/13/93
  **************************************************************************/
 INT OpenFile (LPSTR lpFileName, LPOFSTRUCT ofs, WORD wStyle)
 {
-    int 	base, flags;
-    int		handle;
-	char	buf[256];
-
-#ifdef DEBUG_FILE
-    fprintf(stderr,"OpenFile(%s,<struct>,%04X)\n",lpFileName,wStyle);
-#endif
-
-    base   = wStyle & 0xF;
-    flags  = wStyle & 0xFFF0;
+    int		              handle;
+    struct sigcontext_struct  ccontext;
+                              /* To make macros like EAX happy */
+    struct sigcontext_struct *context=&ccontext; 
+    char                      filename[MAX_PATH+1];
+    int                       action;
+    struct stat               s;
+    struct tm                 *now;
+    int                       res;
+    int                       verify_time;
   
-    flags &= 0xFF0F;  /* strip SHARE bits for now */
-    flags &= 0xD7FF;  /* strip PROMPT & CANCEL bits for now */
-    flags &= 0x7FFF;  /* strip REOPEN bit for now */
-    flags &= 0xFBFF;  /* strib VERIFY bit for now */
+  #ifdef DEBUG_FILE
+      fprintf(stderr,"Openfile(%s,<struct>,%d) ",lpFileName,wStyle);
+  #endif
   
-    if (flags & OF_CREATE) 
-    { 
-	base  |= O_CREAT; 
-	flags &= 0xEFFF; 
-    }
+    action = wStyle & 0xff00;
+  
+  
+    /* OF_CREATE is completly different from all other options, so
+       handle it first */
 
-#ifdef DEBUG_FILE
-    fprintf(stderr,"now %d,%d\n",base,flags);
-#endif
+    if (action & OF_CREATE)
+      {
+      int handle;
+      char *unixfilename;
 
-    if (flags & OF_EXIST) 
-    {
-	printf("OpenFile // OF_EXIST '%s' !\n", lpFileName);
-	handle = _lopen (lpFileName, wStyle);
-	if (handle == -1) {
-		/* Try again with WindowsPath */
-		if (FindFile(buf, sizeof(buf), lpFileName, NULL, WindowsPath) != NULL) {
-			handle = _lopen (buf, wStyle);
-			}
-		}
-	close(handle);
-	return handle;
-    }
-    if (flags & OF_DELETE) 
-    {
-	printf("OpenFile // OF_DELETE '%s' !\n", lpFileName);
-	return unlink(lpFileName);
-    }
-    else 
-    {
-	int  	handle;
-	char 	*UnixFileName;
-	if ((UnixFileName = GetUnixFileName(lpFileName)) == NULL)
-	    return HFILE_ERROR;
-	handle = open(UnixFileName, base, 0666);
-	if (handle == -1) {
-		/* Try again with WindowsPath */
-		if (FindFile(buf, sizeof(buf), lpFileName, NULL, WindowsPath) != NULL) {
-#ifdef DEBUG_FILE
-			printf("OpenFile // file '%s' found !\n", buf);
-#endif
-			UnixFileName = buf;
-			handle = open(UnixFileName, base, 0666);
-			}
-		}
+      if (!(action & OF_REOPEN))
+        strcpy(ofs->szPathName, lpFileName);
+      ofs->cBytes = sizeof(OFSTRUCT);
+      ofs->fFixedDisk = FALSE;
+      ofs->nErrCode = 0;
+      *((int*)ofs->reserved) = 0;
 
-#ifdef DEBUG_FILE
-	fprintf(stderr, "OpenFile: returning %04.4x\n", handle);
-#endif
+      if ((unixfilename = GetUnixFileName (ofs->szPathName)) == NULL)
+      {
+        errno_to_doserr();
+	ofs->nErrCode = ExtendedError;
+        return -1;
+      }
+      handle = open (ofs->szPathName, (wStyle & 0x0003) | O_CREAT, 0x666);
+      if (handle == -1)
+      {
+	errno_to_doserr();
+	ofs->nErrCode = ExtendedError;
+      }   
+      return handle;
+      }
 
-	if (handle == -1)
-	    return HFILE_ERROR;
+
+    /* If path isn't given, try to find the file. */
+
+    if (!(action & OF_REOPEN))
+      {
+	if( !( index(lpFileName,'\\') || index(lpFileName,'/') || 
+	      index(lpFileName,':')))
+	while(1)
+	{
+	  char temp[MAX_PATH+1];
+	  strcpy (filename, lpFileName);
+	  if ( (!stat(GetUnixFileName(filename), &s)) && (S_ISREG(s.st_mode)) )
+	    break;
+	  GetWindowsDirectory (filename,MAX_PATH);
+	  if (filename[1] != ':')
+	    strcat(filename,'\\');
+	  strcat (filename, lpFileName);
+	  if ( (!stat(GetUnixFileName(filename), &s)) && (S_ISREG(s.st_mode)) )
+	    break;
+	  GetSystemDirectory (filename,MAX_PATH);
+	  if (filename[1] != ':')
+	    strcat(filename,'\\');
+	  strcat (filename, lpFileName);
+	  if ( (!stat(GetUnixFileName(filename), &s)) && (S_ISREG(s.st_mode)) )
+	    break;
+	  if (!FindFile(temp,MAX_PATH,lpFileName,NULL,WindowsPath))
+	    {
+	      strcpy(filename, GetDosFileName(temp));
+	      break;
+	    }
+	  strcpy (filename, lpFileName);
+	  break;
+	}
 	else
-	    return handle;
+	  strcpy (filename,lpFileName);
+
+	ofs->cBytes = sizeof(OFSTRUCT);
+	ofs->fFixedDisk = FALSE;
+	strcpy(ofs->szPathName, filename);
+	ofs->nErrCode = 0;
+        if (!(action & OF_VERIFY))
+          *((int*)ofs->reserved) = 0;
     }
+    
+
+    if (action & OF_PARSE)
+      return 0;
+
+    if (action & OF_DELETE)
+      return unlink(ofs->szPathName);
+
+
+    /* Now on to getting some information about that file */
+
+    if (res = stat(GetUnixFileName(ofs->szPathName), &s))
+      {
+      errno_to_doserr();
+      ofs->nErrCode = ExtendedError;
+      return -1;
+    }
+    
+    now = localtime (&s.st_mtime);
+  
+    if (action & OF_VERIFY)
+      verify_time = *((int*)ofs->reserved);
+  
+    *((WORD*)(&ofs->reserved[2]))=
+         ((now->tm_hour * 0x2000) + (now->tm_min * 0x20) + (now->tm_sec / 2));
+    *((WORD*)(&ofs->reserved[0]))=
+         ((now->tm_year * 0x200) + (now->tm_mon * 0x20) + now->tm_mday);
+    
+    if (action & OF_EXIST)
+      return 0;
+
+    if (action & OF_VERIFY)
+      return (verify_time != *((int*)ofs->reserved));
+    
+    
+   /* Now we are actually going to open the file. According to Microsoft's
+       Knowledge Basis, this is done by calling int 21h, ax=3dh. */    
+
+    EAX = 0x00003d00;
+    EAX = (EAX & 0xffffff0f) | (wStyle & 0x0070); /* Handle OF_SHARE_xxx etc. */
+    EAX = (EAX & 0xfffffff0) | (wStyle & 0x0003); /* Handle OF_READ etc. */
+    DS = segment (ofs->szPathName);
+    EDX = (EDX & 0xffff0000) | offset (ofs->szPathName);
+  
+    OpenExistingFile (context);
+
+    if (EFL & 0x00000001)     /* Cflag */
+    {
+      ofs->nErrCode = (AX & 0x00ff);
+      return -1;
+      }
+
+    return AX;
 }
 
 /**************************************************************************
diff --git a/misc/lstr.c b/misc/lstr.c
index 361ea10..28ec8c4 100644
--- a/misc/lstr.c
+++ b/misc/lstr.c
@@ -12,8 +12,10 @@
 #include "regfunc.h"
 #include "windows.h"
 
+#define ToUpper(c)	toupper(c)
+#define ToLower(c)	tolower(c)
 
-  /* Funny to divide them between user and kernel. */
+/* Funny to divide them between user and kernel. */
 
 /* KERNEL.89 */
 LPSTR lstrcat(LPSTR target,LPCSTR source)
@@ -58,44 +60,50 @@
   return strlen(str);
 }
 
-
-/* AnsiUpper USER.431 */
-char FAR* AnsiUpper(char FAR* strOrChar)
+/* IsCharAlpha USER 433 */
+BOOL IsCharAlpha(char ch)
 {
-  /* I am not sure if the locale stuff works with toupper, but then again 
-     I am not sure if the Linux libc locale stuffs works at all */
-/*  if((int)strOrChar<256)
-    return (char FAR*) toupper((int)strOrChar);
-  else { 
-    int i;
-    for(i=0;(i<65536) && strOrChar[i];i++) 
-      strOrChar[i]=toupper(strOrChar[i]); 
-    return strOrChar;	
-  } */
-    int i;
-	for (i = 0; (i < 65536 && strOrChar[i]);i++) 
-		strOrChar[i] = (strOrChar[i] >= 'a' && strOrChar[i] <= 'z') ?
-						strOrChar[i] - ('a' - 'A') : strOrChar[i];
-	return strOrChar;	
+  return isalpha(ch);   /* This is probably not right for NLS */
 }
 
-/* AnsiLower USER.432 */
-char FAR* AnsiLower(char FAR* strOrChar)
+/* IsCharAlphanumeric USER 434 */
+BOOL IsCharAlphanumeric(char ch)
 {
-  /* I am not sure if the locale stuff works with tolower, but then again 
+  return (ch<'0')?0:(ch<'9');
+}
+
+/* IsCharUpper USER 435 */
+BOOL IsCharUpper(char ch)
+{
+  return isupper(ch);
+}
+
+/* IsCharLower USER 436 */
+BOOL IsCharLower(char ch)
+{
+  return islower(ch);
+}
+
+/* AnsiUpper USER.431 */
+LPSTR AnsiUpper(LPSTR strOrChar)
+{
+	char *s = strOrChar;
+  /* I am not sure if the locale stuff works with toupper, but then again 
      I am not sure if the Linux libc locale stuffs works at all */
-/*  if((int)strOrChar<256)
-    return (char FAR*)tolower((int)strOrChar);
-  else {
-    int i;
-    for(i=0;(i<65536)&&strOrChar[i];i++)
-      strOrChar[i]=tolower(strOrChar[i]);
-    return strOrChar;	
-   }*/
-    int i;
-	for (i = 0; (i < 65536 && strOrChar[i]);i++) 
-		strOrChar[i] = (strOrChar[i] >= 'A' && strOrChar[i] <= 'Z') ?
-						strOrChar[i] + ('a' - 'A') : strOrChar[i];
+
+	/* uppercase only one char if strOrChar < 0x10000 */
+	if(HIWORD((DWORD)strOrChar)) {
+		while (*s) {
+			if (IsCharLower(*s))
+				*s = ToUpper(*s);
+			s++;
+		}
+		return strOrChar;
+	} else
+		if (IsCharLower((char) strOrChar))
+			return (LPSTR) ToUpper(strOrChar);
+		else 
+			return (LPSTR) strOrChar;
 }
 
 /* AnsiUpperBuff USER.437 */
@@ -109,6 +117,28 @@
   return i;	
 }
 
+/* AnsiLower USER.432 */
+LPSTR AnsiLower(LPSTR strOrChar)
+{
+	char *s = strOrChar;
+  /* I am not sure if the locale stuff works with toupper, but then again 
+     I am not sure if the Linux libc locale stuffs works at all */
+
+	/* lowercase only one char if strOrChar < 0x10000 */
+	if(HIWORD((DWORD)strOrChar)) {
+		while (*s) {
+			if (IsCharUpper(*s))
+				*s = ToLower(*s);
+			s++;
+		}
+		return strOrChar;
+	} else
+		if (IsCharUpper((char) strOrChar))
+			return (LPSTR) ToLower(strOrChar);
+		else 
+			return (LPSTR) strOrChar;
+}
+
 /* AnsiLowerBuff USER.438 */
 UINT AnsiLowerBuff(LPSTR str,UINT len)
 {
@@ -134,29 +164,6 @@
   return (current==start)?start:current-1;
 }
 
-/* IsCharAlpha USER 433 */
-BOOL IsCharAlpha(char ch)
-{
-  return isalpha(ch);   /* This is probably not right for NLS */
-}
-/* IsCharAlphanumeric USER 434 */
-BOOL IsCharAlphanumeric(char ch)
-{
-  return (ch<'0')?0:(ch<'9');
-}
-
-/* IsCharUpper USER 435 */
-BOOL IsCharUpper(char ch)
-{
-  return isupper(ch);
-}
-
-/* IsCharUpper USER 436 */
-BOOL IsCharLower(char ch)
-{
-  return islower(ch);
-}
-
 static char Oem2Ansi[256];
 static char Ansi2Oem[256];
 
diff --git a/misc/spy.c b/misc/spy.c
index c52db35..efb2210 100644
--- a/misc/spy.c
+++ b/misc/spy.c
@@ -153,7 +153,8 @@
     "WM_TIMER",			/* 0x0113 */
     "WM_HSCROLL",		/* 0x0114 */
     "WM_VSCROLL",		/* 0x0115 */
-    NULL, NULL,
+    "WM_INITMENU",              /* 0x0116 */
+    "WM_INITMENUPOPUP",         /* 0x0117 */
     "WM_SYSTIMER",		/* 0x0118 */
     NULL, NULL, NULL, NULL, NULL, NULL, NULL,
 
diff --git a/misc/user.c b/misc/user.c
index cce820e..609e5ec 100644
--- a/misc/user.c
+++ b/misc/user.c
@@ -17,6 +17,7 @@
 extern BOOL ATOM_Init();
 extern BOOL GDI_Init();
 extern void SYSMETRICS_Init();
+extern BOOL MENU_Init();
 extern BOOL WIN_CreateDesktopWindow();
 
 #ifndef WINELIB
@@ -69,6 +70,9 @@
       /* Initialize dialog manager */
     if (!DIALOG_Init()) return 0;
 
+      /* Initialize menus */
+    if (!MENU_Init()) return 0;
+
       /* Create system message queue */
     queueSize = GetProfileInt( "windows", "TypeAhead", 120 );
     if (!MSG_CreateSysMsgQueue( queueSize )) return 0;
diff --git a/misc/winsocket.c b/misc/winsocket.c
index cd7fb53..5195e2a 100644
--- a/misc/winsocket.c
+++ b/misc/winsocket.c
@@ -136,8 +136,47 @@
 {
 	wsa_errno = wsaerrno();
 }
- 
-SOCKET Winsock_accept(SOCKET s, struct sockaddr FAR *addr, INT FAR *addrlen)
+
+static void convert_sockopt(INT *level, INT *optname)
+{
+/* $%#%!@! why couldn't they use the same values for both winsock and unix ? */
+
+	switch (*level) {
+		case -1: 
+			*level = SOL_SOCKET;
+			switch (*optname) {
+			case 0x01:	*optname = SO_DEBUG;
+					break;
+			case 0x04:	*optname = SO_REUSEADDR;
+					break;
+			case 0x08:	*optname = SO_KEEPALIVE;
+					break;
+			case 0x10:	*optname = SO_DONTROUTE;
+					break;
+			case 0x20:	*optname = SO_BROADCAST;
+					break;
+			case 0x80:	*optname = SO_LINGER;
+					break;
+			case 0x100:	*optname = SO_OOBINLINE;
+					break;
+			case 0x1001:	*optname = SO_SNDBUF;
+					break;
+			case 0x1002:	*optname = SO_RCVBUF;
+					break;
+			case 0x1007:	*optname = SO_ERROR;
+					break;
+			case 0x1008:	*optname = SO_TYPE;
+					break;
+				default: 
+					fprintf(stderr, "convert_sockopt() unknown optname %d\n", optname);
+					break;
+			}
+			break;
+		case 6:	*optname = IPPROTO_TCP;
+	}
+}
+
+SOCKET Winsock_accept(SOCKET s, struct sockaddr *addr, INT *addrlen)
 {
 	int sock;
 
@@ -152,7 +191,7 @@
 	return sock;
 }
 
-INT Winsock_bind(SOCKET s, struct sockaddr FAR *name, INT namelen)
+INT Winsock_bind(SOCKET s, struct sockaddr *name, INT namelen)
 {
 #ifdef DEBUG_WINSOCK
 	fprintf(stderr, "WSA_bind: socket %d, ptr %8x, length %d\n", s, (int) name, namelen);
@@ -181,7 +220,7 @@
 	return 0;
 }
 
-INT Winsock_connect(SOCKET s, struct sockaddr FAR *name, INT namelen)
+INT Winsock_connect(SOCKET s, struct sockaddr *name, INT namelen)
 {
 #ifdef DEBUG_WINSOCK
 	fprintf(stderr, "WSA_connect: socket %d, ptr %8x, length %d\n", s, (int) name, namelen);
@@ -195,7 +234,7 @@
 	return 0;
 }
 
-INT Winsock_getpeername(SOCKET s, struct sockaddr FAR *name, INT FAR *namelen)
+INT Winsock_getpeername(SOCKET s, struct sockaddr *name, INT *namelen)
 {
 #ifdef DEBUG_WINSOCK
 	fprintf(stderr, "WSA_getpeername: socket: %d, ptr %8x, ptr %8x\n", s, (int) name, *namelen);
@@ -209,7 +248,7 @@
 	return 0;
 }
 
-INT Winsock_getsockname(SOCKET s, struct sockaddr FAR *name, INT FAR *namelen)
+INT Winsock_getsockname(SOCKET s, struct sockaddr *name, INT *namelen)
 {
 #ifdef DEBUG_WINSOCK
 	fprintf(stderr, "WSA_getsockname: socket: %d, ptr %8x, ptr %8x\n", s, (int) name, (int) *namelen);
@@ -221,12 +260,15 @@
 	return 0;
 }
 
-INT Winsock_getsockopt(SOCKET s, INT loptname, char FAR *optval, INT FAR *optlen)
+INT
+Winsock_getsockopt(SOCKET s, INT level, INT optname, char *optval, INT *optlen)
 {
 #ifdef DEBUG_WINSOCK
-	fprintf(stderr, "WSA_getsockopt: socket: %d, opt %d, ptr %8x, ptr %8x\n", s, loptname, (int) optval, (int) *optlen);
+	fprintf(stderr, "WSA_getsockopt: socket: %d, opt %d, ptr %8x, ptr %8x\n", s, level, (int) optval, (int) *optlen);
 #endif
-	if (getsockopt(s, 0, (int) loptname, optval, (int *) optlen) < 0) {
+	convert_sockopt(&level, &optname);
+
+	if (getsockopt(s, (int) level, optname, optval, (int *) optlen) < 0) {
         	errno_to_wsaerrno();
         	return SOCKET_ERROR;
 	}
@@ -243,7 +285,7 @@
 	return( htons(hostshort) );
 }
 
-u_long Winsock_inet_addr(char FAR *cp)
+u_long Winsock_inet_addr(char *cp)
 {
 	return( inet_addr(cp) );
 }
@@ -266,7 +308,7 @@
 	return (char *) &heap->ntoa_buffer;
 }
 
-INT Winsock_ioctlsocket(SOCKET s, long cmd, u_long FAR *argp)
+INT Winsock_ioctlsocket(SOCKET s, long cmd, u_long *argp)
 {
 #ifdef DEBUG_WINSOCK
 	fprintf(stderr, "WSA_ioctl: socket %d, cmd %d, ptr %8x\n", s, cmd, (int) argp);
@@ -302,7 +344,7 @@
 	return( ntohs(netshort) );
 }
 
-INT Winsock_recv(SOCKET s, char FAR *buf, INT len, INT flags)
+INT Winsock_recv(SOCKET s, char *buf, INT len, INT flags)
 {
 	int length;
 
@@ -317,8 +359,8 @@
 	return length;
 }
 
-INT Winsock_recvfrom(SOCKET s, char FAR *buf, INT len, INT flags, 
-		struct sockaddr FAR *from, int FAR *fromlen)
+INT Winsock_recvfrom(SOCKET s, char *buf, INT len, INT flags, 
+		struct sockaddr *from, int *fromlen)
 {
 	int length;
 
@@ -333,8 +375,8 @@
 	return length;
 }
 
-INT Winsock_select(INT nfds, fd_set FAR *readfds, fd_set FAR *writefds,
-	fd_set FAR *exceptfds, struct timeval FAR *timeout)
+INT Winsock_select(INT nfds, fd_set *readfds, fd_set *writefds,
+	fd_set *exceptfds, struct timeval *timeout)
 {
 #ifdef DEBUG_WINSOCK
 	fprintf(stderr, "WSA_select: fd # %d, ptr %8x, ptr %8x, ptr %*X\n", nfds, readfds, writefds, exceptfds);
@@ -343,7 +385,7 @@
 	return(select(nfds, readfds, writefds, exceptfds, timeout));
 }
 
-INT Winsock_send(SOCKET s, char FAR *buf, INT len, INT flags)
+INT Winsock_send(SOCKET s, char *buf, INT len, INT flags)
 {
 	int length;
 
@@ -358,8 +400,8 @@
 	return length;
 }
 
-INT Winsock_sendto(SOCKET s, char FAR *buf, INT len, INT flags,
-		struct sockaddr FAR *to, INT tolen)
+INT Winsock_sendto(SOCKET s, char *buf, INT len, INT flags,
+		struct sockaddr *to, INT tolen)
 {
 	int length;
 
@@ -374,13 +416,14 @@
 	return length;
 }
 
-INT Winsock_setsockopt(SOCKET s, INT level, INT optname, const char FAR *optval, 
+INT Winsock_setsockopt(SOCKET s, INT level, INT optname, const char *optval, 
 			INT optlen)
 {
 #ifdef DEBUG_WINSOCK
 	fprintf(stderr, "WSA_setsockopt: socket %d, level %d, opt %d, ptr %8x, len %d\n", s, level, optname, (int) optval, optlen);
 #endif
-
+	convert_sockopt(&level, &optname);
+	
 	if (setsockopt(s, level, optname, optval, optlen) < 0) {
         	errno_to_wsaerrno();
         	return SOCKET_ERROR;
@@ -430,7 +473,7 @@
     return sock;
 }
 
-struct hostent *Winsock_gethostbyaddr(const char FAR *addr, INT len, INT type)
+struct hostent *Winsock_gethostbyaddr(const char *addr, INT len, INT type)
 {
 	struct hostent *host;
 
@@ -447,7 +490,7 @@
 	return (struct hostent *) &heap->hostent_addr;
 }
 
-struct hostent *Winsock_gethostbyname(const char FAR *name)
+struct hostent *Winsock_gethostbyname(const char *name)
 {
 	struct hostent *host;
 
@@ -464,7 +507,7 @@
 	return (struct hostent *) &heap->hostent_name;
 }
 
-int Winsock_gethostname(char FAR *name, INT namelen)
+int Winsock_gethostname(char *name, INT namelen)
 {
 
 #ifdef DEBUG_WINSOCK
@@ -478,7 +521,7 @@
 	return 0;
 }          
 
-struct protoent *Winsock_getprotobyname(char FAR *name)
+struct protoent *Winsock_getprotobyname(char *name)
 {
 	struct protoent *proto;
 
@@ -512,7 +555,7 @@
 	return (struct protoent *) &heap->protoent_number;
 }
 
-struct servent *Winsock_getservbyname(const char FAR *name, const char FAR *proto)
+struct servent *Winsock_getservbyname(const char *name, const char *proto)
 {
 	struct servent *service;
 
@@ -529,7 +572,7 @@
 	return (struct servent *) &heap->servent_name;
 }
 
-struct servent *Winsock_getservbyport(INT port, const char FAR *proto)
+struct servent *Winsock_getservbyport(INT port, const char *proto)
 {
 	struct servent *service;
 
@@ -597,8 +640,8 @@
 }
 
 
-HANDLE WSAAsyncGetHostByAddr(HWND hWnd, u_int wMsg, const char FAR *addr,
-		 INT len, INT type, char FAR *buf, INT buflen)
+HANDLE WSAAsyncGetHostByAddr(HWND hWnd, u_int wMsg, const char *addr,
+		 INT len, INT type, char *buf, INT buflen)
 {
 	HANDLE handle;
 	struct hostent *host;
@@ -619,8 +662,8 @@
 }
 
 
-HANDLE WSAAsyncGetHostByName(HWND hWnd, u_int wMsg, const char FAR *name, 
-			char FAR *buf, INT buflen)
+HANDLE WSAAsyncGetHostByName(HWND hWnd, u_int wMsg, const char *name, 
+			char *buf, INT buflen)
 {
 	HANDLE handle;
 	struct hostent *host;
@@ -641,8 +684,8 @@
 }                     
 
 
-HANDLE WSAAsyncGetProtoByName(HWND hWnd, u_int wMsg, const char FAR *name, 
-			char FAR *buf, INT buflen)
+HANDLE WSAAsyncGetProtoByName(HWND hWnd, u_int wMsg, const char *name, 
+			char *buf, INT buflen)
 {
 	HANDLE handle;
 	struct protoent *proto;
@@ -664,7 +707,7 @@
 
 
 HANDLE WSAAsyncGetProtoByNumber(HWND hWnd, u_int wMsg, INT number, 
-			char FAR *buf, INT buflen)
+			char *buf, INT buflen)
 {
 	HANDLE handle;
 	struct protoent *proto;
@@ -685,8 +728,8 @@
 }
 
 
-HANDLE WSAAsyncGetServByName(HWND hWnd, u_int wMsg, const char FAR *name, 
-			const char FAR *proto, char FAR *buf, INT buflen)
+HANDLE WSAAsyncGetServByName(HWND hWnd, u_int wMsg, const char *name, 
+			const char *proto, char *buf, INT buflen)
 {
 	HANDLE handle;
 	struct servent *service;
@@ -707,8 +750,8 @@
 }
 
 
-HANDLE WSAAsyncGetServByPort(HWND hWnd, u_int wMsg, INT port, const char FAR 
-			*proto, char FAR *buf, INT buflen)
+HANDLE WSAAsyncGetServByPort(HWND hWnd, u_int wMsg, INT port, const char 
+			*proto, char *buf, INT buflen)
 {
 	HANDLE handle;
 	struct servent *service;
diff --git a/miscemu/emulate.c b/miscemu/emulate.c
index 1b69503..78b49a9 100644
--- a/miscemu/emulate.c
+++ b/miscemu/emulate.c
@@ -28,19 +28,19 @@
 
 }
 
-int
+void
 WIN87_WinEm87Info(struct Win87EmInfoStruct *pWIS, int cbWin87EmInfoStruct)
 {
   printf( "__WinEm87Info(%p,%d)\n",pWIS,cbWin87EmInfoStruct);
 }
 
-int
+void
 WIN87_WinEm87Restore(void *pWin87EmSaveArea, int cbWin87EmSaveArea)
 {
   printf( "__WinEm87Restore(%p,%d)\n",pWin87EmSaveArea,cbWin87EmSaveArea);
 }
 
-int
+void
 WIN87_WinEm87Save(void *pWin87EmSaveArea, int cbWin87EmSaveArea)
 {
   printf( "__WinEm87Save(%p,%d)\n",pWin87EmSaveArea,cbWin87EmSaveArea);
diff --git a/miscemu/int10.c b/miscemu/int10.c
index 1d49f5e..632f279 100644
--- a/miscemu/int10.c
+++ b/miscemu/int10.c
@@ -1,6 +1,6 @@
 #include <stdio.h>
 #include <stdlib.h>
-#include "msdos.h"
+#include "registers.h"
 #include "wine.h"
 
 void IntBarf(int i, struct sigcontext_struct *context)
@@ -13,23 +13,22 @@
 
 int do_int10(struct sigcontext_struct *context)
 {
-	switch((context->sc_eax >> 8) & 0xff)
-	{
+	switch(AH) {
 	case 0x0f:
-		EAX = (EAX & 0xffffff00) | 0x5b;
+		AL = 0x5b;
 		break;
 
 	case 0x12:
-		if ((EBX & 0xff) == 0x10) {
-			EBX = (EBX & 0xffff0000) | 0x0003;
-			ECX = (ECX & 0xffff0000) | 0x0009;
+		if (BL == 0x10) {
+			BX = 0x0003;
+			CX = 0x0009;
 		}
 		break;
 			
 	case 0x1a:
-		EBX = (EBX & 0xffff0000) | 0x0008;
+		BX = 0x0008;
 		break;
-		
+
 	default:
 		IntBarf(0x10, context);
 	};
diff --git a/miscemu/int13.c b/miscemu/int13.c
index 55fb5b2..8fb128e 100644
--- a/miscemu/int13.c
+++ b/miscemu/int13.c
@@ -1,29 +1,28 @@
 #include <stdio.h>
 #include <stdlib.h>
-#include "msdos.h"
+#include "registers.h"
 #include "wine.h"
 
 int do_int13(struct sigcontext_struct *context)
 {
-	switch((context->sc_eax >> 8) & 0xff)
-	{
+	switch(AH) {
 	case 0x00:                            /* RESET DISK SYSTEM     */
 	case 0x04:                            /* VERIFY DISK SECTOR(S) */
-		EAX = (EAX & 0xffff00ff);
+		AH = 0;
 		break;
 	       
 	case 0x05:                                     /* FORMAT TRACK */
-		EAX = (EAX & 0xffff00ff) | 0x0c;
+		AH = 0x0c;
 		SetCflag;
 		break;
 
 	case 0x06:             /* FORMAT TRACK AND SET BAD SECTOR FLAGS */
 	case 0x07:             /* FORMAT DRIVE STARTING AT GIVEN TRACK  */ 
-		EAX = (EAX & 0xffff00ff) | 0x0c;
+		AH = 0x0c;
 		break;
 
 	case 0x08:                              /* GET DRIVE PARAMETERS  */
-		EAX = (EAX & 0xffff00ff) | ((EDX & 0x00000080)? 0x07: 0x01);
+		AH = (DL & 0x80) ? 0x07 : 0x01;
 		SetCflag;
 		break;
 
@@ -33,20 +32,17 @@
 	case 0x10:         /* CHECK IF DRIVE READY                        */
 	case 0x11:         /* RECALIBRATE DRIVE                           */
 	case 0x14:         /* CONTROLLER INTERNAL DIAGNOSTIC              */
-		EAX = (EAX & 0xffff00ff);
+		AH = 0;
 		break;
 
 	case 0x0e:                    /* READ SECTOR BUFFER (XT only)      */
 	case 0x0f:                    /* WRITE SECTOR BUFFER (XT only)     */
         case 0x12:                    /* CONTROLLER RAM DIAGNOSTIC (XT,PS) */
 	case 0x13:                    /* DRIVE DIAGNOSTIC (XT,PS)          */
-		EAX = (EAX & 0xffff00ff) | 0x01;
+		AH = 0x01;
 		SetCflag;
 		break;
 
-
-
-
 	default:
 		IntBarf(0x13, context);
 	};
diff --git a/miscemu/int15.c b/miscemu/int15.c
index 054a7e3..67a0b7a 100644
--- a/miscemu/int15.c
+++ b/miscemu/int15.c
@@ -1,12 +1,11 @@
 #include <stdio.h>
 #include <stdlib.h>
-#include "msdos.h"
+#include "registers.h"
 #include "wine.h"
 
 int do_int15(struct sigcontext_struct *context)
 {
-	switch((context->sc_eax >> 8) & 0xff)
-	{
+	switch(AH) {
 	case 0xc0:
 		
 	default:
diff --git a/miscemu/int16.c b/miscemu/int16.c
index 88ff49d..33ecef5 100644
--- a/miscemu/int16.c
+++ b/miscemu/int16.c
@@ -1,12 +1,11 @@
 #include <stdio.h>
 #include <stdlib.h>
-#include "msdos.h"
+#include "registers.h"
 #include "wine.h"
 
 int do_int16(struct sigcontext_struct *context)
 {
-	switch((context->sc_eax >> 8) & 0xff)
-	{
+	switch(AH) {
 	case 0xc0:
 		
 	default:
diff --git a/miscemu/int1a.c b/miscemu/int1a.c
index 95b19bd..f43fef3 100644
--- a/miscemu/int1a.c
+++ b/miscemu/int1a.c
@@ -1,7 +1,7 @@
 #include <time.h>
 #include <stdio.h>
 #include <stdlib.h>
-#include "msdos.h"
+#include "registers.h"
 #include "wine.h"
 #include "options.h"
 
@@ -23,13 +23,13 @@
 	       AX, BX, CX, DX, SI, DI, DS, ES);
     }
 
-	switch((context->sc_eax >> 8) & 0xff){
+	switch(AH) {
 	case 0:
 		ltime = time(NULL);
 		ticks = (int) (ltime * HZ);
-		context->sc_ecx = ticks >> 16;
-		context->sc_edx = ticks & 0x0000FFFF;
-		context->sc_eax = 0;  /* No midnight rollover */
+		CX = ticks >> 16;
+		DX = ticks & 0x0000FFFF;
+		AX = 0;  /* No midnight rollover */
 		printf("int1a_00 // ltime=%ld ticks=%ld\n", ltime, ticks);
 		break;
 		
@@ -37,14 +37,14 @@
 		ltime = time(NULL);
 		bdtime = localtime(&ltime);
 		
-		context->sc_ecx = (BIN_TO_BCD(bdtime->tm_hour)<<8) | BIN_TO_BCD(bdtime->tm_min);
-		context->sc_edx = (BIN_TO_BCD(bdtime->tm_sec)<<8);
+		CX = (BIN_TO_BCD(bdtime->tm_hour)<<8) | BIN_TO_BCD(bdtime->tm_min);
+		DX = (BIN_TO_BCD(bdtime->tm_sec)<<8);
 
 	case 4:
 		ltime = time(NULL);
 		bdtime = localtime(&ltime);
-		context->sc_ecx = (BIN_TO_BCD(bdtime->tm_year/100)<<8) | BIN_TO_BCD((bdtime->tm_year-1900)%100);
-		context->sc_edx = (BIN_TO_BCD(bdtime->tm_mon)<<8) | BIN_TO_BCD(bdtime->tm_mday);
+		CX = (BIN_TO_BCD(bdtime->tm_year/100)<<8) | BIN_TO_BCD((bdtime->tm_year-1900)%100);
+		DX = (BIN_TO_BCD(bdtime->tm_mon)<<8) | BIN_TO_BCD(bdtime->tm_mday);
 		break;
 
 		/* setting the time,date or RTC is not allow -EB */
diff --git a/miscemu/int21.c b/miscemu/int21.c
index 2485f59..5ed34e0 100644
--- a/miscemu/int21.c
+++ b/miscemu/int21.c
@@ -7,15 +7,20 @@
 #include <errno.h>
 #include <stdio.h>
 #include <stdlib.h>
+#include <sys/file.h>
 #include <string.h>
 #include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/types.h>
 #include <unistd.h>
 #include <utime.h>
+#include <ctype.h>
 #include "prototypes.h"
 #include "regfunc.h"
 #include "windows.h"
 #include "wine.h"
 #include "msdos.h"
+#include "registers.h"
 #include "options.h"
 
 WORD ExtendedError, CodePage = 437;
@@ -29,6 +34,9 @@
 };
 static struct DosHeap *heap;
 
+WORD sharing_retries = 3;      /* number of retries at sharing violation */
+WORD sharing_pause = 1;        /* pause between retries */
+
 extern char TempDirectory[];
 
 static int Error(int e, int class, int el)
@@ -41,7 +49,7 @@
 	return e;
 }
 
-static void errno_to_doserr(void)
+void errno_to_doserr(void)
 {
 	switch (errno) {
 		case EAGAIN:
@@ -138,28 +146,28 @@
 	int drive;
 	long size,available;
 
-	if (!(EDX & 0xff))
+	if (DL == 0)
 		drive = DOS_GetDefaultDrive();
 	else
-		drive = (EDX & 0xff) - 1;
+		drive = DL - 1;
 	
 	if (!DOS_ValidDrive(drive)) {
 		Error(InvalidDrive, EC_MediaError , EL_Disk);
-		EAX |= 0xffffL;	
+		AX = 0xffff;
 		return;
 	}
 	
 	if (!DOS_GetFreeSpace(drive, &size, &available)) {
 		Error(GeneralFailure, EC_MediaError , EL_Disk);
-		EAX |= 0xffffL;
+		AX = 0xffff;
 		return;
 	}
 
-	EAX = (EAX & 0xffff0000) | 4;	
-	ECX = (ECX & 0xffff0000) | 512;
+	AX = 4;	
+	CX = 512;
 
-	EBX = (EBX & 0xffff0000) | (available / (CX * AX));
-	EDX = (EDX & 0xffff0000) | (size / (CX * AX));
+	BX = (available / (CX * AX));
+	DX = (size / (CX * AX));
 	Error (0,0,0);
 }
 
@@ -169,43 +177,41 @@
 	long size, available;
 	BYTE mediaID;
 	
-	drive = EDX & 0xffL;
-	
-	if (!DOS_ValidDrive(drive)) {
-		EAX = (EAX & 0xffff0000) | 4;
-		ECX = (ECX & 0xffff0000) | 512;
-		EDX = (EDX & 0xffff0000);
+	if (!DOS_ValidDrive(DL)) {
+		AX = 4;
+		CX = 512;
+		DX = 0;
 		Error (InvalidDrive, EC_MediaError, EL_Disk);
 		return;
 	}
 
-	if (!DOS_GetFreeSpace(drive, &size, &available)) {
+	if (!DOS_GetFreeSpace(DL, &size, &available)) {
 		Error(GeneralFailure, EC_MediaError , EL_Disk);
-		EAX |= 0xffffL;
+		AX = 0xffff;
 		return;
 	}
 	
-	EAX = (EAX & 0xffff0000) | 4;	
-	ECX = (ECX & 0xffff0000) | 512;
-	EDX = (EDX & 0xffff0000) | (size / (CX * AX));
+	EAX = 4;
+	ECX = 512;
+	EDX = (size / (CX * AX));
 
 	mediaID = 0xf0;
 
 	DS = segment(mediaID);
-	EBX = offset(mediaID);	
+	BX = offset(mediaID);	
 	Error (0,0,0);
 }
 
 static void GetDefDriveAllocInfo(struct sigcontext_struct *context)
 {
-	EDX = DOS_GetDefaultDrive();
+	DX = DOS_GetDefaultDrive();
 	GetDriveAllocInfo(context);
 }
 
 static void GetDrivePB(struct sigcontext_struct *context)
 {
 	Error (InvalidDrive, EC_MediaError, EL_Disk);
-	EAX = (EAX & 0xffff0000) | 0xffL; 
+	AX = 0x00ff;
 		/* I'm sorry but I only got networked drives :-) */
 }
 
@@ -217,7 +223,7 @@
 	/* can't read from stdout / stderr */
 	if ((BX == 1) || (BX == 2)) {
 		Error (InvalidHandle, EL_Unknown, EC_Unknown);
-		EAX = (EAX & 0xffff0000) | InvalidHandle;
+		AX = InvalidHandle;
 		SetCflag;
 		return;
 	}
@@ -226,19 +232,19 @@
 	if (BX == 0) {
 		*ptr = EOF;
 		Error (0,0,0);
-		EAX = (EAX & 0xffff0000) | 1;
+		AX = 1;
 		ResetCflag;
 		return;
 	} else {
 		size = read(BX, ptr, CX);
 		if (size == -1) {
 			errno_to_doserr();
-			EAX = (EAX & 0xffffff00) | ExtendedError;
+			AL = ExtendedError;
 			SetCflag;
 			return;
 		}		
 		Error (0,0,0);
-		EAX = (EAX & 0xffff0000) | size;
+		AX = size;
 		ResetCflag;
 	}
 }
@@ -264,24 +270,24 @@
 		fflush(stderr);
 
 		Error (0,0,0);
-		EAX = (EAX & 0xffffff00) | CX;
+		AL = CX;
 		ResetCflag;
 	} else {
 		size = write(BX, ptr , CX);
 		if (size == 0) {
 			Error (WriteFault, EC_Unknown, EL_Unknown);
-			EAX = (EAX & 0xffffff00) | ExtendedError;
+			AL = ExtendedError;
 			return;
 		}
 
 		if (size == -1) {
 			errno_to_doserr();
-			EAX = (EAX & 0xffffff00) | ExtendedError;
+			AL = ExtendedError;
 			SetCflag;
 			return;
 		}		
 		Error (0,0,0);
-		EAX = (EAX & 0xffff0000) | size;
+		AX = size;
 		ResetCflag;
 	}
 }
@@ -290,7 +296,7 @@
 {
 	off_t status, fileoffset;
 	
-	switch (EAX & 0xff) {
+	switch (AL) {
 		case 1: fileoffset = SEEK_CUR;
 			break;
 		case 2: fileoffset = SEEK_END;
@@ -302,41 +308,39 @@
 	status = lseek(BX, (CX * 0x100) + DX, fileoffset);
 	if (status == -1) {
 		errno_to_doserr();
-		EAX = (EAX & 0xffffff00) | ExtendedError;			SetCflag;
+		AL = ExtendedError;			SetCflag;
 		return;
 	}		
 	Error (0,0,0);
-	EAX = (EAX & 0xffff0000L) | (status & 0xffff);
-	EDX = (EDX & 0xffff0000L) | ((status >> 16) & 0xffff);
-	
+	AX = (status & 0xffff);
+	DX = ((status >> 16) & 0xffff);
+
 	ResetCflag;
 }
 
 static void ioctlGetDeviceInfo(struct sigcontext_struct *context)
 {
-	WORD handle = EBX & 0xffff;
-
-	switch (handle) {
+	switch (BX) {
 		case 0:
 		case 1:
 		case 2:
-			EDX = (EDX & 0xffff0000) | 0x80d3;
+			DX = 0x80d3;
 			break;
 
 		default:
 		{
 		    struct stat sbuf;
 	    
-		    if (fstat(handle, &sbuf) < 0)
+		    if (fstat(BX, &sbuf) < 0)
 		    {
 			IntBarf(0x21, context);
-			EDX = (EDX & 0xffff0000) | 0x50;
+			DX = 0x50;
 			SetCflag;
 			return;
 		    }
 	    
 		    /* This isn't the right answer, but should be close enough. */
-		    EDX = (EDX & 0xffff0000) | 0x0943;
+		    DX = 0x0943;
 		}
 	}
 	ResetCflag;
@@ -347,16 +351,16 @@
 	BYTE *dataptr = pointer(DS, DX);
 	int drive;
 
-	if (!(EBX & 0xff))
+	if (BL == 0)
 		drive = DOS_GetDefaultDrive();
 	else
-		drive = (EBX & 0xff) - 1;
+		drive = BL - 1;
 
-	if ((ECX & 0xff00) != 0x0800) {
+	if (CH != 0x08) {
 		IntBarf(0x21, context);
 		return;
 	}
-	switch (ECX & 0xff) {
+	switch (CL) {
 		case 0x60: /* get device parameters */
 			   /* used by w4wgrp's winfile */
 			dataptr[0] = 0x04;
@@ -374,7 +378,7 @@
 				setword(&dataptr[4], 80); /* # of cylinders */
 			}
 			CreateBPB(drive, &dataptr[7]);			
-			EAX = (EAX & 0xfffff00);
+			AL = 0;
 			ResetCflag;
 			return;
 		default:
@@ -390,50 +394,52 @@
 	ltime = time(NULL);
 	now = localtime(&ltime);
 
-	ECX = (ECX & 0xffff0000) | (now->tm_year + 1900);
-	EDX = (EDX & 0xffff0000) | ((now->tm_mon + 1) << 8) | now->tm_mday;
-	EAX = (EAX & 0xffff0000) | now->tm_wday;
+	CX = now->tm_year + 1900;
+	DX = ((now->tm_mon + 1) << 8) | now->tm_mday;
+	AX = now->tm_wday;
 }
 
 static void GetSystemTime(struct sigcontext_struct *context)
 {
 	struct tm *now;
-	time_t ltime;
+	struct timeval tv;
 
-	ltime = time(NULL);
-	now = localtime(&ltime);
+	gettimeofday(&tv,NULL);		/* Note use of gettimeofday(), instead of time() */
+	now = localtime(&tv.tv_sec);
 	 
-	ECX = (ECX & 0xffffff00) | (now->tm_hour << 8) | now->tm_min;
-	EDX = (EDX & 0xffffff00) | now->tm_sec << 8;
+	CX = (now->tm_hour<<8) | now->tm_min;
+	DX = (now->tm_sec<<8) | tv.tv_usec/10000;
+					/* Note hundredths of seconds */
 }
 
 static void GetExtendedErrorInfo(struct sigcontext_struct *context)
 {
-	EAX = (EAX & 0xffffff00) | ExtendedError;
-	EBX = (EBX & 0xffff0000) | (ErrorClass << 8) | Action;
-	ECX = (ECX & 0xffff00ff) | (ErrorLocus << 8);
+	AL = ExtendedError;
+	BX = (ErrorClass << 8) | Action;
+	CH = ErrorLocus << 8;
 }
 
 static void CreateFile(struct sigcontext_struct *context)
 {
 	int handle;
 
-	if ((handle = open(GetUnixFileName( pointer(DS,DX)), O_CREAT | O_TRUNC)) == -1) {
+	if ((handle = open(GetUnixFileName( pointer(DS,DX)), 
+           O_CREAT | O_TRUNC | O_RDWR )) == -1) {
 		errno_to_doserr();
-		EAX = (EAX & 0xffffff00) | ExtendedError;
+		AL = ExtendedError;
 		SetCflag;
 		return;
 		}			
 	Error (0,0,0);
-	EBX = (EBX & 0xffff0000) | handle;
-	EAX = (EAX & 0xffffff00) | NoError;
+	EAX = (EAX & 0xffff0000) | handle;
 	ResetCflag;
 }
 
-static void OpenExistingFile(struct sigcontext_struct *context)
+void OpenExistingFile(struct sigcontext_struct *context)
 {
 	int handle;
 	int mode;
+	int lock;
 	
 	switch (AX & 0x0007)
 	{
@@ -450,16 +456,66 @@
 	    break;
 	}
 
-	fprintf(stderr,"OpenExistingFile (%s)\n", pointer(DS,DX));
-	
 	if ((handle = open(GetUnixFileName(pointer(DS,DX)), mode)) == -1) {
 		errno_to_doserr();
-		EAX = (EAX & 0xffffff00) | ExtendedError;
+		AL = ExtendedError;
 		SetCflag;
 		return;
 	}		
+
+        switch (AX & 0x0070)
+	{
+	  case 0x00:    /* compatability mode */
+	  case 0x40:    /* DENYNONE */
+            lock = -1;
+	    break;
+
+	  case 0x30:    /* DENYREAD */
+	    fprintf(stderr,
+	      "OpenExistingFile (%s): DENYREAD changed to DENYALL\n",
+	      pointer(DS,DX));
+	  case 0x10:    /* DENYALL */  
+	    lock = LOCK_EX;
+	    break;
+
+	  case 0x20:    /* DENYWRITE */
+	    lock = LOCK_SH;
+	    break;
+
+	  default:
+	    lock = -1;
+        }
+
+	if (lock != -1)
+        {
+
+	  int result,retries=sharing_retries;
+	  {
+	    result = flock(handle, lock | LOCK_NB);
+	    if ( retries && (!result) )
+	    {
+              int i;
+              for(i=0;i<32768*((int)sharing_pause);i++)
+		  result++;                          /* stop the optimizer */
+              for(i=0;i<32768*((int)sharing_pause);i++)
+		  result--;
+	    }
+          }
+	  while( (!result) && (!(retries--)) );
+
+	  if(result)  
+	  {
+	    errno_to_doserr();
+	    EAX = (EAX & 0xffffff00) | ExtendedError;
+	    close(handle);
+	    SetCflag;
+	    return;
+	  }
+
+        }
+
 	Error (0,0,0);
-	EAX = (EBX & 0xffff0000) | handle;
+	EAX = (EAX & 0xffff0000) | handle;
 	ResetCflag;
 }
 
@@ -467,12 +523,12 @@
 {
 	if (close(BX) == -1) {
 		errno_to_doserr();
-		EAX = (EAX & 0xffffff00) | ExtendedError;
+		AL = ExtendedError;
 		SetCflag;
 		return;
 	}
 	Error (0,0,0);
-	EAX = (EAX & 0xffffff00) | NoError;
+	AL = NoError;
 	ResetCflag;
 }
 
@@ -498,13 +554,13 @@
 	fprintf(stderr,"int21: makedir %s\n", pointer(DS,DX) );
 	
 	if ((dirname = GetUnixFileName( pointer(DS,DX) ))== NULL) {
-		EAX = (EAX & 0xffffff00) | CanNotMakeDir;
+		AL = CanNotMakeDir;
 		SetCflag;
 		return;
 	}
 
 	if (mkdir(dirname,0) == -1) {
-		EAX = (EAX & 0xffffff00) | CanNotMakeDir;
+		AL = CanNotMakeDir;
 		SetCflag;
 		return;
 	}
@@ -531,19 +587,19 @@
 	fprintf(stderr,"int21: removedir %s\n", pointer(DS,DX) );
 
 	if ((dirname = GetUnixFileName( pointer(DS,DX) ))== NULL) {
-		EAX = (EAX & 0xffffff00) | CanNotMakeDir;
+		AL = CanNotMakeDir;
 		SetCflag;
 		return;
 	}
 
 /*
 	if (strcmp(unixname,DosDrives[drive].CurrentDirectory)) {
-		EAX = (EAX & 0xffffff00) | CanNotRemoveCwd;
+		AL = CanNotRemoveCwd;
 		SetCflag;
 	}
 */	
 	if (rmdir(dirname) == -1) {
-		EAX = (EAX & 0xffffff00) | CanNotMakeDir; 
+		AL = CanNotMakeDir; 
 		SetCflag;
 	} 
 	ResetCflag;
@@ -558,23 +614,23 @@
 {
 	struct dosdirent *dp;
 	
-	dp = (struct dosdirent *)(dta + 0x0d);
+        memcpy(&dp, dta+0x0d, sizeof(dp));
 
 	do {
 		if ((dp = DOS_readdir(dp)) == NULL) {
 			Error(NoMoreFiles, EC_MediaError , EL_Disk);
-			EAX = (EAX & 0xffffff00) | NoMoreFiles;
+			AL = NoMoreFiles;
 			SetCflag;
 			return;
 		}
 	} while (*(dta + 0x0c) != dp->attribute);
-				
+	
 	setword(&dta[0x16], 0x1234); /* time */
 	setword(&dta[0x18], 0x1234); /* date */
 	setdword(&dta[0x1a], dp->filesize);
 	strncpy(dta + 0x1e, dp->filename, 13);
 
-	EAX = (EAX & 0xffffff00);
+	AL;
 	ResetCflag;
 	return;
 }
@@ -589,7 +645,7 @@
 
 		if (!DOS_ValidDrive(drive)) {
 			Error(InvalidDrive, EC_MediaError , EL_Disk);
-			EAX = (EAX & 0xffffff00L) | InvalidDrive;
+			AL = InvalidDrive;
 			SetCflag;
 			return;
 		}
@@ -606,14 +662,14 @@
 		if (DOS_GetVolumeLabel(drive) != NULL) 
 			strncpy(dta + 0x1e, DOS_GetVolumeLabel(drive), 8);
 
-		EAX = (EAX & 0xffffff00L);
+		AL = 0;
 		ResetCflag;
 		return;
 	}
 
 	if ((dp = DOS_opendir(path)) == NULL) {
 		Error(PathNotFound, EC_MediaError, EL_Disk);
-		EAX = (EAX & 0xffffff00L) | FileNotFound;
+		AL = FileNotFound;
 		SetCflag;
 		return;
 	}
@@ -629,7 +685,7 @@
 	struct tm *now;
 
 	if ((filename = GetUnixFileName( pointer(DS,DX) ))== NULL) {
-		EAX = (EAX & 0xffffff00) | FileNotFound;
+		AL = FileNotFound;
 		SetCflag;
 		return;
 	}
@@ -637,8 +693,8 @@
 	 	
 	now = localtime (&filestat.st_mtime);
 	
-	ECX = (ECX & 0xffff0000) | ((now->tm_hour * 0x2000) + (now->tm_min * 0x20) + now->tm_sec/2);
-	EDX = (EDX & 0xffff0000) | ((now->tm_year * 0x200) + (now->tm_mon * 0x20) + now->tm_mday);
+	CX = ((now->tm_hour * 0x2000) + (now->tm_min * 0x20) + now->tm_sec/2);
+	DX = ((now->tm_year * 0x200) + (now->tm_mon * 0x20) + now->tm_mday);
 
 	ResetCflag;
 }
@@ -669,14 +725,14 @@
 	handle = open(GetUnixFileName(temp), O_CREAT | O_TRUNC | O_RDWR);
 
 	if (handle == -1) {
-		EAX = (EAX & 0xffffff00) | WriteProtected;
+		AL = WriteProtected;
 		SetCflag;
 		return;
 	}
 
 	strcpy(pointer(DS,DX), temp);
 	
-	EAX = (EAX & 0xffff0000) | handle;
+	AX = handle;
 	ResetCflag;
 }
 
@@ -684,13 +740,13 @@
 {
 	int handle;
 	
-	if ((handle = open(GetUnixFileName( pointer(DS,DX) ), O_CREAT | O_TRUNC | O_RDWR)) == -1) {
-		EAX = (EAX & 0xffffff00) | WriteProtected;
+	if ((handle = open(GetUnixFileName( pointer(DS,DX) ), O_CREAT | O_EXCL | O_RDWR)) == -1) {
+		AL = WriteProtected;
 		SetCflag;
 		return;
 	}
 
-	EAX = (EAX & 0xffff0000) | handle;
+	AX = handle;
 	ResetCflag;
 }
 
@@ -698,13 +754,13 @@
 {
 	int drive;
 
-	if ((EDX & 0xff) == 0)
+	if (DL == 0)
 		drive = DOS_GetDefaultDrive();
 	else
-		drive = (EDX & 0xff)-1;
+		drive = DL - 1;
 
 	if (!DOS_ValidDrive(drive)) {
-		EAX = (EAX & 0xffffff00) | InvalidDrive;
+		AL = InvalidDrive;
 		SetCflag;
 		return;
 	}
@@ -719,13 +775,13 @@
 	BYTE *dataptr = pointer(DS, DX);
 	DWORD serialnumber;
 	
-	if ((EBX & 0xff) == 0)
+	if (BL == 0)
 		drive = DOS_GetDefaultDrive();
 	else
-		drive = (EBX & 0xff) - 1;
+		drive = BL - 1;
 
 	if (!DOS_ValidDrive(drive)) {
-		EAX = (EAX & 0xffffff00) |InvalidDrive;
+		AL =InvalidDrive;
 		SetCflag;
 		return;
 	}
@@ -737,7 +793,7 @@
 	strncpy(dataptr + 6, DOS_GetVolumeLabel(drive), 8);
 	strncpy(dataptr + 0x11, "FAT16   ", 8);
 	
-	EAX = (EAX & 0xffffff00);
+	AL;
 	ResetCflag;
 }
 
@@ -747,13 +803,13 @@
 	BYTE *dataptr = pointer(DS, DX);
 	DWORD serialnumber;
 
-	if ((EBX & 0xff) == 0)
+	if (BL == 0)
 		drive = DOS_GetDefaultDrive();
 	else
-		drive = (EBX & 0xff) - 1;
+		drive = BL - 1;
 
 	if (!DOS_ValidDrive(drive)) {
-		EAX = (EAX & 0xffffff00) | InvalidDrive;
+		AL = InvalidDrive;
 		SetCflag;
 		return;
 	}
@@ -762,7 +818,7 @@
 			(dataptr[4] << 24);
 
 	DOS_SetSerialNumber(drive, serialnumber);
-	EAX = (EAX & 0xffffff00) | 1L;
+	AL = 1L;
 	ResetCflag;
 }
 
@@ -803,7 +859,7 @@
 				strncpy(dta, DOS_GetVolumeLabel(drive), 8);
 			*(dta + 0x0b) = FA_DIREC;
 
-			EAX = (EAX & 0xffffff00);
+			AL;
 			return;
 		}
 	}
@@ -833,7 +889,7 @@
 
 	if ((dp = DOS_opendir(temp)) == NULL) {
 		Error(InvalidDrive, EC_MediaError , EL_Disk);
-		EAX = (EAX & 0xffffff00) | 0xffL;
+		AL = 0xffL;
 		return;
 	}
 
@@ -849,7 +905,7 @@
 		/* unlink(GetUnixFileName(temp)); */
 	}
 	DOS_closedir(dp);
-	EAX = (EAX & 0xffffff00);
+	AL;
 }
 
 static void RenameFileFCB(struct sigcontext_struct *context)
@@ -875,7 +931,7 @@
 
 	if ((dp = DOS_opendir(temp)) == NULL) {
 		Error(InvalidDrive, EC_MediaError , EL_Disk);
-		EAX = (EAX & 0xffffff00) | 0xffL;
+		AL = 0xffL;
 		return;
 	}
 
@@ -894,15 +950,95 @@
 		fprintf(stderr, "int21: renamefile %s -> %s\n", oldname, newname);
 	}
 	DOS_closedir(dp);
-	EAX = (EAX & 0xffffff00);
+	AL;
 }
 
+
+
+static void fLock (struct sigcontext_struct * context)
+{
+    struct flock f;
+    int result,retries=sharing_retries;
+
+    f.l_start = MAKELONG(DX,CX);
+    f.l_len   = MAKELONG(DI,SI);
+    f.l_whence = 0;
+    f.l_pid = 0;
+
+    switch ( AX & 0xff )
+    {
+        case 0x00: /* LOCK */
+	  f.l_type = F_WRLCK;
+          break;
+
+	case 0x01: /* UNLOCK */
+          f.l_type = F_UNLCK;
+	  break;
+
+	default:
+	  EAX = (EAX & 0xffff0000) | 0x0001;
+	  SetCflag;
+	  return;
+     }
+ 
+     {
+          result = fcntl(BX,F_SETLK,&f); 
+          if ( retries && (!result) )
+          {
+              int i;
+              for(i=0;i<32768*((int)sharing_pause);i++)
+                  result++;                          /* stop the optimizer */
+              for(i=0;i<32768*((int)sharing_pause);i++)
+                  result--;
+          }
+      }
+      while( (!result) && (!(retries--)) );
+
+      if(result)  
+      {
+         errno_to_doserr();
+         EAX = (EAX & 0xffffff00) | ExtendedError;
+         SetCflag;
+         return;
+      }
+
+       Error (0,0,0);
+       ResetCflag;
+} 
+
+
+static void GetFileAttribute (struct sigcontext_struct * context)
+{
+  char *filename = pointer (DS,DX);
+  struct stat s;
+  int res,cx; 
+
+  res = stat(GetUnixFileName(filename), &s);
+  if (res==-1)
+  {
+    errno_to_doserr();
+    EAX = (EAX & 0xffffff00) | ExtendedError;
+    SetCflag;
+    return;
+  }
+  
+  cx = 0;
+  if (S_ISDIR(s.st_mode))
+    cx|=0x10;
+  if ((S_IWRITE & s.st_mode) != S_IWRITE)
+    cx|=0x01;
+
+  ECX = (ECX & 0xffff0000) | cx;
+  ResetCflag;
+  Error (0,0,0); 
+}
+
+
+
 /************************************************************************/
 
 int do_int21(struct sigcontext_struct * context)
 {
-    int ah;
-
     if (Options.relay_debug)
     {
 	printf("int21: AX %04x, BX %04x, CX %04x, DX %04x, "
@@ -910,9 +1046,7 @@
 	       AX, BX, CX, DX, SI, DI, DS, ES);
     }
 
-    ah = (EAX >> 8) & 0xffL;
-
-    if (ah == 0x59) 
+    if (AH == 0x59) 
     {
 	GetExtendedErrorInfo(context);
 	return 1;
@@ -920,7 +1054,7 @@
     else 
     {
 	Error (0,0,0);
-	switch(ah) 
+	switch(AH) 
 	{
 	  case 0x00: /* TERMINATE PROGRAM */
 	    exit(0);
@@ -970,17 +1104,21 @@
 	    EAX &= 0xff00;
 	    break;
 	
+	  case 0x5c: /* "FLOCK" - RECORD LOCKING */
+	    fLock(context);
+	    break;
+
 	  case 0x0d: /* DISK BUFFER FLUSH */
             ResetCflag; /* dos 6+ only */
             break;
 
 	  case 0x0e: /* SELECT DEFAULT DRIVE */
-		if (!DOS_ValidDrive(EDX & 0xff)) {
+		if (!DOS_ValidDrive(DL)) {
 			Error (InvalidDrive, EC_MediaError, EL_Disk);
 			return;
 		} else {
-			DOS_SetDefaultDrive(EDX & 0xff);
-			EAX = (EAX &0xffffff00) | MAX_DOS_DRIVES; 
+			DOS_SetDefaultDrive(DL);
+			AX = MAX_DOS_DRIVES; 
 			Error(0,0,0);
 		}
 		break;
@@ -998,7 +1136,7 @@
             break;
 
 	  case 0x19: /* GET CURRENT DEFAULT DRIVE */
-		EAX = (EAX & 0xffffff00) | DOS_GetDefaultDrive();
+		AL = DOS_GetDefaultDrive();
 		Error (0,0,0);
 	    break;
 	    
@@ -1020,7 +1158,7 @@
 		
 	  case 0x25: /* SET INTERRUPT VECTOR */
 	    /* Ignore any attempt to set a segment vector */
- 		fprintf(stderr, "int21: set interrupt vector %2x (%04x:%04x)\n", AX & 0xff, DS, DX);
+ 		fprintf(stderr, "int21: set interrupt vector %2x (%04x:%04x)\n", AL, DS, DX);
             break;
 
 	  case 0x2a: /* GET SYSTEM DATE */
@@ -1033,13 +1171,13 @@
 
 	  case 0x2f: /* GET DISK TRANSFER AREA ADDRESS */
             ES = segment(dta);
-            EBX = (EBX & 0xffff0000) | offset(dta);
+            BX = offset(dta);
             break;
             
 	  case 0x30: /* GET DOS VERSION */
-	    EAX = (EAX & 0xffff0000) | DOSVERSION;
-	    EBX = (EBX & 0xffff0000) | 0x0012;     /* 0x123456 is Wine's serial # */
-	    ECX = (ECX & 0xffff0000) | 0x3456;
+	    AX = DOSVERSION;
+	    BX = 0x0012;     /* 0x123456 is Wine's serial # */
+	    CX = 0x3456;
 	    break;
 
 	  case 0x31: /* TERMINATE AND STAY RESIDENT */
@@ -1051,9 +1189,9 @@
 	    break;
 
 	  case 0x33: /* MULTIPLEXED */
-	    switch (EAX & 0xff) {
+	    switch (AL) {
 	      case 0x00: /* GET CURRENT EXTENDED BREAK STATE */
-		if (!(EAX & 0xff)) 
+		if (!(AL)) 
 		    EDX &= 0xff00L;
 		break;
 
@@ -1061,11 +1199,11 @@
 		break;		
 		
 	      case 0x02: /* GET AND SET EXTENDED CONTROL-BREAK CHECKING STATE*/
-		EDX &= 0xff00L;
+		DL = 0;
 		break;
 
 	      case 0x05: /* GET BOOT DRIVE */
-		EDX = (EDX & 0xff00) | 2;
+		DL = 2;
 		/* c: is Wine's bootdrive */
 		break;
 				
@@ -1081,8 +1219,8 @@
 	    break;	
 	    
 	  case 0x34: /* GET ADDRESS OF INDOS FLAG */
-		ES  = (ES & 0xffff0000) | segment(heap->InDosFlag);
-		EBX = (EBX & 0xffff0000) | offset(heap->InDosFlag);
+		ES = segment(heap->InDosFlag);
+		BX = offset(heap->InDosFlag);
 	    break;
 
 	  case 0x35: /* GET INTERRUPT VECTOR */
@@ -1090,7 +1228,7 @@
 	    		if anyone ever tries to use it */
 	    fprintf(stderr, "int21: get interrupt vector %2x\n", AX & 0xff);
 	    ES = 0;
-	    EBX = 0;
+	    BX = 0;
 	    break;
 
 	  case 0x36: /* GET FREE DISK SPACE */
@@ -1098,8 +1236,7 @@
 	    break;
 
 	  case 0x38: /* GET COUNTRY-SPECIFIC INFORMATION */
-	    EAX &= 0xff00;
-	    EAX |= 0x02; /* no country support available */
+	    AX = 0x02; /* no country support available */
 	    SetCflag;
 	    break;
 		
@@ -1138,7 +1275,7 @@
 	  case 0x41: /* "UNLINK" - DELETE FILE */
 		if (unlink( GetUnixFileName( pointer(DS,DX)) ) == -1) {
 			errno_to_doserr();
-			EAX = (EAX & 0xffffff00) | ExtendedError;
+			AL = ExtendedError;
 			SetCflag;
 			return;
 		}		
@@ -1151,11 +1288,10 @@
 	    break;
 	    
 	  case 0x43: /* FILE ATTRIBUTES */
-	    switch (EAX & 0xff) 
+	    switch (AL) 
 	    {
 	      case 0x00:
-			EAX &= 0xfffff00L;
-			ResetCflag;
+                        GetFileAttribute(context);
 		break;
 	      case 0x01:
 			ResetCflag;
@@ -1164,18 +1300,27 @@
 	    break;
 		
 	  case 0x44: /* IOCTL */
-	    switch (EAX & 0xff) 
+	    switch (AL) 
 	    {
               case 0x00:
                 ioctlGetDeviceInfo(context);
 		break;
 		   
 	      case 0x09:   /* CHECK IF BLOCK DEVICE REMOTE */
-		EDX = (EDX & 0xffff0000) | (1<<9) | (1<<12);
+		EDX = (EDX & 0xffff0000) | (1<<9) | (1<<12) | (1<<15);
 		ResetCflag;
 		break;
 
 	      case 0x0b:   /* SET SHARING RETRY COUNT */
+		if (!CX)
+		{ 
+		  EAX = (EAX & 0xffff0000) | 0x0001;
+		  SetCflag;
+		  break;
+		}
+		sharing_pause = CX;
+		if (!DX)
+		  sharing_retries = DX;
 		ResetCflag;
 		break;
 
@@ -1191,13 +1336,13 @@
 
 	  case 0x45: /* "DUP" - DUPLICATE FILE HANDLE */
 	  case 0x46: /* "DUP2", "FORCEDUP" - FORCE DUPLICATE FILE HANDLE */
-		EAX = (EAX & 0xffff0000) | dup(BX);
+		AX = dup(BX);
 		ResetCflag;
 	    break;
 
 	  case 0x47: /* "CWD" - GET CURRENT DIRECTORY */	
 	    GetCurrentDirectory(context);
-	    EAX = (EAX & 0xffff0000) | 0x0100; 
+	    AX = 0x0100; 
 	    /* intlist: many Microsoft products for Windows rely on this */
 	    break;
 	
@@ -1212,11 +1357,11 @@
 	    break;		
 	
 	  case 0x4c: /* "EXIT" - TERMINATE WITH RETURN CODE */
-	    exit(EAX & 0xff);
+	    exit(AL);
 	    break;
 		
 	  case 0x4d: /* GET RETURN CODE */
-	    EAX = (EAX & 0xffffff00) | NoError; /* normal exit */
+	    AL = NoError; /* normal exit */
 	    break;
 
 	  case 0x4e: /* "FINDFIRST" - FIND FIRST MATCHING FILE */
@@ -1229,7 +1374,7 @@
 			
 	  case 0x52: /* "SYSVARS" - GET LIST OF LISTS */
 		ES = 0x0;
-		EBX = (EBX & 0xffff0000);
+		BX = 0x0;
 		IntBarf(0x21, context);
 	    break;
 		
@@ -1238,7 +1383,7 @@
 	    break;
 	
 	  case 0x57: /* FILE DATE AND TIME */
-	    switch (EAX & 0xff) 
+	    switch (AL) 
 	    {
 	      case 0x00:
 		GetFileDateTime(context);
@@ -1250,10 +1395,10 @@
 	    break;
 
 	  case 0x58: /* GET OR SET MEMORY/UMB ALLOCATION STRATEGY */
-	    switch (EAX & 0xff) 
+	    switch (AL) 
 	    {
 	      case 0x00:
-		EAX = (EAX & 0xffffff00) | 0x01L;
+		AL = 0x01L;
 		break;
 	      case 0x02:
 		EAX &= 0xff00L;
@@ -1273,25 +1418,21 @@
 	    CreateNewFile(context);
 	    break;
 	
-	  case 0x5c: /* "FLOCK" - RECORD LOCKING */
-		IntBarf(0x21, context);
-	    break;	
-
 	  case 0x5d: /* NETWORK */
 	  case 0x5e:
 	    /* network software not installed */
-	    EAX = (EAX & 0xfffff00) | NoNetwork;
+	    AL = NoNetwork;
 	    SetCflag;
 	    break;
 	
 	  case 0x5f: /* NETWORK */
-	    switch (EAX & 0xff) 
+	    switch (AL) 
 	    {
 	      case 0x07: /* ENABLE DRIVE */
-		if (!DOS_EnableDrive(EDX & 0xff)) 
+		if (!DOS_EnableDrive(DL)) 
 		{
 		    Error(InvalidDrive, EC_MediaError , EL_Disk);
-		    EAX = (EAX & 0xfffff00) | InvalidDrive;
+		    AL = InvalidDrive;
 		    SetCflag;
 		    break;
 		} 
@@ -1301,10 +1442,10 @@
 		    break;
 		}
 	      case 0x08: /* DISABLE DRIVE */
-		if (!DOS_DisableDrive(EDX & 0xff)) 
+		if (!DOS_DisableDrive(DL)) 
 		{
 		    Error(InvalidDrive, EC_MediaError , EL_Disk);
-		    EAX = (EAX & 0xfffff00) | InvalidDrive;
+		    AL = InvalidDrive;
 		    SetCflag;
 		    break;
 		} 
@@ -1315,7 +1456,7 @@
 		}
 	      default:
 		/* network software not installed */
-		EAX = (EAX & 0xfffff00) | NoNetwork; 
+		AL = NoNetwork; 
 		SetCflag;
 		break;
 	    }
@@ -1335,11 +1476,10 @@
 	    break;
 	
 	  case 0x66: /* GLOBAL CODE PAGE TABLE */
-	    switch (EAX & 0xff) 
-	    {
+	    switch (AL) {
 	      case 0x01:
-		EBX = CodePage;
-		EDX = BX;
+		BX = CodePage;
+		DX = BX;
 		ResetCflag;
 		break;			
 	      case 0x02: 
@@ -1358,7 +1498,7 @@
 	    break;		
 	
 	  case 0x69: /* DISK SERIAL NUMBER */
-	    switch (EAX & 0xff) 
+	    switch (AL) 
 	    {
 	      case 0x00:
 		GetDiskSerialNumber(context);
diff --git a/miscemu/int25.c b/miscemu/int25.c
index 9a9a366..af79ec4 100644
--- a/miscemu/int25.c
+++ b/miscemu/int25.c
@@ -1,5 +1,6 @@
 #include <stdio.h>
 #include <stdlib.h>
+#include "registers.h"
 #include "msdos.h"
 #include "wine.h"
 
@@ -8,15 +9,14 @@
 	BYTE *dataptr = pointer(DS, BX);
 	DWORD begin, length;
 
-	if( (ECX & 0xffff) == 0xffff)
-	{
+	if (CX == 0xffff) {
 		begin = getdword(dataptr);
 		length = getword(&dataptr[4]);
 		dataptr = (BYTE *) getdword(&dataptr[6]);
 			
 	} else {
-		begin = EDX & 0xffff;
-		length = ECX & 0xffff;
+		begin = DX;
+		length = CX;
 	}
 	fprintf(stderr, "int25: abs diskread, drive %d, sector %d, "
 	"count %d, buffer %d\n", EAX & 0xff, begin, length, (int) dataptr);
diff --git a/miscemu/int26.c b/miscemu/int26.c
index 0308d37..ff145b1 100644
--- a/miscemu/int26.c
+++ b/miscemu/int26.c
@@ -1,5 +1,6 @@
 #include <stdio.h>
 #include <stdlib.h>
+#include "registers.h"
 #include "msdos.h"
 #include "wine.h"
 
@@ -8,15 +9,14 @@
 	BYTE *dataptr = pointer(DS, BX);
 	DWORD begin, length;
 
-	if( (ECX & 0xffff) == 0xffff)
-	{
+	if (CX == 0xffff) {
 		begin = getdword(dataptr);
 		length = getword(&dataptr[4]);
 		dataptr = (BYTE *) getdword(&dataptr[6]);
 			
 	} else {
-		begin = EDX & 0xffff;
-		length = ECX & 0xffff;
+		begin = DX;
+		length = CX;
 	}
 		
 	fprintf(stderr,"int26: abs diskwrite, drive %d, sector %d, count %d,"
diff --git a/miscemu/int2f.c b/miscemu/int2f.c
index c652bba..e1a6195 100644
--- a/miscemu/int2f.c
+++ b/miscemu/int2f.c
@@ -1,6 +1,6 @@
 #include <stdio.h>
 #include <stdlib.h>
-#include "msdos.h"
+#include "registers.h"
 #include "wine.h"
 
 int do_int2f_16(struct sigcontext_struct *context);
@@ -10,8 +10,8 @@
 {
 	switch((context->sc_eax >> 8) & 0xff)
 	{
-	case 0x10: /* share isn't installed */
-	        EAX = (EAX & 0xffffff00) | 0x01;
+	case 0x10: /* share is installed */
+	        EAX = (EAX & 0xffffff00) | 0xff;
 		break;
 
 	case 0x15: /* mscdex */
diff --git a/miscemu/int31.c b/miscemu/int31.c
index 3d4500c..d738772 100644
--- a/miscemu/int31.c
+++ b/miscemu/int31.c
@@ -1,6 +1,6 @@
 #include <stdio.h>
 #include <stdlib.h>
-#include "msdos.h"
+#include "registers.h"
 #include "wine.h"
 
 typedef struct {
diff --git a/miscemu/ioports.c b/miscemu/ioports.c
index 35560a2..07d6af3 100644
--- a/miscemu/ioports.c
+++ b/miscemu/ioports.c
@@ -1,7 +1,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <time.h>
-#include "msdos.h"
+#include "registers.h"
 #include "wine.h"
 
 static BYTE cmosaddress;
@@ -18,15 +18,14 @@
 
 void inportb(struct sigcontext_struct *context)
 {
-	fprintf(stderr, "IO: inb (%x)\n", EDX & 0xffff);
+	fprintf(stderr, "IO: inb (%x)\n", DX);
 
-	switch(EDX & 0xffff)
-	{
+	switch(DX) {
 		case 0x70:
-			EAX = (EAX & 0xffffff00L) | cmosaddress;
+			AL = cmosaddress;
 			break;
 		case 0x71:
-			EAX = (EAX & 0xffffff00L) | cmosimage[cmosaddress & 0x3f];
+			AL = cmosimage[cmosaddress & 0x3f];
 			break;
 		default:
 	}
@@ -34,22 +33,22 @@
 
 void inport(struct sigcontext_struct *context)
 {
-	fprintf(stderr, "IO: in (%x)\n", EDX & 0xffff);
+	fprintf(stderr, "IO: in (%x)\n", DX);
 
-	EAX = (EAX & 0xffff0000L) | 0xffff;
+	AX = 0xffff;
 }
 
 void outportb(struct sigcontext_struct *context)
 {
-	fprintf(stderr, "IO: outb (%x), %x\n", EDX & 0xffff, EAX & 0xff);
+	fprintf(stderr, "IO: outb (%x), %x\n", DX, AX);
 
 	switch (EDX & 0xffff)
 	{
 		case 0x70:
-			cmosaddress = EAX & 0x7f;
+			cmosaddress = AL & 0x7f;
 			break;
 		case 0x71:
-			cmosimage[cmosaddress & 0x3f] = EAX & 0xff;
+			cmosimage[cmosaddress & 0x3f] = AL;
 			break;
 		default:
 	}
@@ -57,5 +56,5 @@
 
 void outport(struct sigcontext_struct *context)
 {
-	fprintf(stderr, "IO: out (%x), %x\n", EDX & 0xffff, EAX & 0xffff);
+	fprintf(stderr, "IO: out (%x), %x\n", DX, AX);
 }
diff --git a/objects/bitmap.c b/objects/bitmap.c
index b068a2a..cd4f623 100644
--- a/objects/bitmap.c
+++ b/objects/bitmap.c
@@ -12,6 +12,9 @@
 #include "gdi.h"
 #include "bitmap.h"
 
+  /* Include OEM bitmaps */
+#include "bitmaps/check_mark"
+#include "bitmaps/menu_arrow"
 
   /* Handle of the bitmap selected by default in a memory DC */
 HBITMAP BITMAP_hbitmapMemDC = 0;
@@ -74,6 +77,59 @@
 
 
 /***********************************************************************
+ *           BITMAP_LoadOEMBitmap
+ */
+HBITMAP BITMAP_LoadOEMBitmap( WORD id )
+{
+    BITMAPOBJ * bmpObjPtr;
+    HBITMAP hbitmap;
+    WORD width, height;
+    char *data;
+
+    switch(id)
+    {
+    case OBM_MNARROW:
+	width  = menu_arrow_width;
+	height = menu_arrow_height;
+	data   = menu_arrow_bits;
+	break;
+
+    case OBM_CHECK:
+	width  = check_mark_width;
+	height = check_mark_height;
+	data   = check_mark_bits;
+	break;
+
+    default:
+	return 0;
+    }
+    
+      /* Create the BITMAPOBJ */
+    if (!(hbitmap = GDI_AllocObject( sizeof(BITMAPOBJ), BITMAP_MAGIC )))
+	return 0;
+    bmpObjPtr = (BITMAPOBJ *) GDI_HEAP_ADDR( hbitmap );
+    bmpObjPtr->size.cx = 0;
+    bmpObjPtr->size.cy = 0;
+    bmpObjPtr->bitmap.bmType       = 0;
+    bmpObjPtr->bitmap.bmWidth      = width;
+    bmpObjPtr->bitmap.bmHeight     = height;
+    bmpObjPtr->bitmap.bmWidthBytes = (width + 15) / 16 * 2;
+    bmpObjPtr->bitmap.bmPlanes     = 1;
+    bmpObjPtr->bitmap.bmBitsPixel  = 1;
+    bmpObjPtr->bitmap.bmBits       = NULL;
+
+      /* Create the pixmap */
+    if (!(bmpObjPtr->pixmap = XCreateBitmapFromData( display, rootWindow,
+						     data, width, height )))
+    {
+	GDI_HEAP_FREE( hbitmap );
+	return 0;
+    }
+    return hbitmap;
+}
+
+
+/***********************************************************************
  *           CreateBitmap    (GDI.48)
  */
 HBITMAP CreateBitmap( short width, short height, 
diff --git a/objects/dcvalues.c b/objects/dcvalues.c
index 33b51ac..c1fafaf 100644
--- a/objects/dcvalues.c
+++ b/objects/dcvalues.c
@@ -73,7 +73,7 @@
 { \
     DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC ); \
     if (!dc) return 0; \
-    return dc->w.ret_x | (dc->w.ret_y << 16); \
+    return MAKELONG( dc->w.ret_x, dc->w.ret_y << 16 ); \
 }
 
 #define DC_GET_VAL_EX( func_name, ret_x, ret_y ) \
@@ -127,7 +127,6 @@
 DC_GET_VAL( COLORREF, GetBkColor, backgroundColor )               /* GDI.75 */
 DC_GET_VAL( WORD, GetBkMode, backgroundMode )                     /* GDI.76 */
 DC_GET_X_Y( DWORD, GetCurrentPosition, CursPosX, CursPosY )       /* GDI.78 */
-DC_GET_X_Y( DWORD, GetDCOrg, DCOrgX, DCOrgY )                     /* GDI.79 */
 DC_GET_VAL( WORD, GetMapMode, MapMode )                           /* GDI.81 */
 DC_GET_VAL( WORD, GetPolyFillMode, polyFillMode )                 /* GDI.84 */
 DC_GET_VAL( WORD, GetROP2, ROPmode )                              /* GDI.85 */
diff --git a/objects/dib.c b/objects/dib.c
index c6d9d44..6042cb2 100644
--- a/objects/dib.c
+++ b/objects/dib.c
@@ -128,6 +128,71 @@
     }
 }
 
+#define check_xy(x,y) \
+	if (x > width) { \
+		x = 0; \
+		if (lines) \
+			lines--; \
+	}
+
+/***********************************************************************
+ *           DIB_SetImageBits_RLE4
+ *
+ * SetDIBits for a 4-bit deep compressed DIB.
+ */
+static void DIB_SetImageBits_RLE4( WORD lines, BYTE *bits, WORD width,
+			        WORD *colors, XImage *bmpImage )
+{
+	int x = 0, c, length;
+	BYTE *begin = bits;
+	
+	lines--;
+	while (1) {
+		length = *bits++;
+		if (length) {	/* encoded */
+			c = *bits++;
+			while (length--) {
+				XPutPixel(bmpImage, x++, lines, colors[c >> 4]);
+				check_xy(x, y);
+				if (length) {
+					length--;
+					XPutPixel(bmpImage, x++, lines, colors[c & 0xf]);
+					check_xy(x, y);
+				}
+			}
+		} else {
+			length = *bits++;
+			switch (length) {
+				case 0: /* eol */
+					x = 0;
+					lines--;
+					continue;
+
+				case 1: /* eopicture */
+					return;
+
+				case 2:	/* delta */
+					x += *bits++;
+					lines -= *bits++;
+					continue;
+
+				default: /* absolute */
+					while (length--) {
+						c = *bits++;
+						XPutPixel(bmpImage, x++, lines, colors[c >> 4]);
+						check_xy(x, y);
+						if (length) {
+							length--;
+							XPutPixel(bmpImage, x++, lines, colors[c & 0xf]);
+							check_xy(x, y);
+						}
+					}
+					if ((bits - begin) & 1)
+						bits++;
+			}
+		}
+	}
+}
 
 /***********************************************************************
  *           DIB_SetImageBits_8
@@ -148,6 +213,62 @@
     }
 }
 
+/***********************************************************************
+ *           DIB_SetImageBits_RLE8
+ *
+ * SetDIBits for an 8-bit deep compressed DIB.
+ */
+static void DIB_SetImageBits_RLE8( WORD lines, BYTE *bits, WORD width,
+			        WORD *colors, XImage *bmpImage )
+{
+	int x = 0, i, length;
+	BYTE *begin = bits;
+
+	lines--;
+	while (1) {
+		length = *bits++;
+		if (length) {	/* encoded */
+			while (length--) {
+				XPutPixel(bmpImage, x++, lines, colors[*bits]);
+				if (x > width) {
+					x = 0;
+					if (lines)
+						lines--;
+				}
+			}
+			bits++;
+		} else {
+			length = *bits++;
+			switch (length) {
+				case 0: /* eol */
+					x = 0;
+					lines--;
+					continue;
+
+				case 1: /* eopicture */
+					return;
+
+				case 2:	/* delta */
+					x += *bits++;
+					lines -= *bits++;
+					continue;
+
+				default: /* absolute */
+					for (i = length; i ; i--) {
+						XPutPixel(bmpImage, x++, lines,
+						colors[*bits++]);
+						if (x > width) {
+							x = 0;
+							if (lines)
+								lines--;
+						}
+					}
+					if ((bits - begin) & 1)
+						bits++;
+			}
+		}
+	}
+}
 
 /***********************************************************************
  *           DIB_SetImageBits_24
@@ -228,11 +349,19 @@
 			    colorMapping, bmpImage );
 	break;
     case 4:
-	DIB_SetImageBits_4( lines, bits, info->bmiHeader.biWidth,
+	if (info->bmiHeader.biCompression)
+		DIB_SetImageBits_RLE4( lines, bits, info->bmiHeader.biWidth,
+			    colorMapping, bmpImage );
+	else	
+		DIB_SetImageBits_4( lines, bits, info->bmiHeader.biWidth,
 			    colorMapping, bmpImage );
 	break;
     case 8:
-	DIB_SetImageBits_8( lines, bits, info->bmiHeader.biWidth,
+	if (info->bmiHeader.biCompression)
+		DIB_SetImageBits_RLE8( lines, bits, info->bmiHeader.biWidth,
+			    colorMapping, bmpImage );
+	else
+		DIB_SetImageBits_8( lines, bits, info->bmiHeader.biWidth,
 			    colorMapping, bmpImage );
 	break;
     case 24:
diff --git a/objects/metafile.c b/objects/metafile.c
index 544e6e4..fd9c3ae 100644
--- a/objects/metafile.c
+++ b/objects/metafile.c
@@ -103,8 +103,8 @@
     mf = (METAFILE *)GlobalLock(dc->w.hMetaFile);
     mh = (METAHEADER *)GlobalLock(mf->hMetaHdr);
 
-    /* Construct the end of metafile record - this is undocumented
-     * but is created by MS Windows 3.1.
+    /* Construct the end of metafile record - this is documented
+     * in SDK Knowledgebase Q99334.
      */
     if (!MF_MetaParam0(dc, META_EOF))
     {
diff --git a/objects/text.c b/objects/text.c
index f8be278..10a6a75 100644
--- a/objects/text.c
+++ b/objects/text.c
@@ -451,4 +451,15 @@
 	return FALSE;
 }
 
+/***********************************************************************
+ *			GetTabbedTextExtent		[USER.197]
+ */
+DWORD GetTabbedTextExtent(HDC hDC, LPSTR lpString, int nCount, 
+	int nTabPositions, LPINT lpnTabStopPositions)
+{
+	printf("EMPTY STUB !!! GetTabbedTextExtent(); !\n");
+
+	return (18 << 16) | (nCount * 18);
+}
+
 
diff --git a/windows/dc.c b/windows/dc.c
index 056329a..9c8a274 100644
--- a/windows/dc.c
+++ b/windows/dc.c
@@ -532,6 +532,23 @@
 
 
 /***********************************************************************
+ *           GetDCOrg    (GDI.79)
+ */
+DWORD GetDCOrg( HDC hdc )
+{
+    Window root;
+    int x, y, w, h, border, depth;
+
+    DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
+    if (!dc) return 0;
+    if (dc->w.flags & DC_MEMORY) return 0;
+    XGetGeometry( display, dc->u.x.drawable, &root,
+		  &x, &y, &w, &h, &border, &depth );
+    return MAKELONG( dc->w.DCOrgX + (WORD)x, dc->w.DCOrgY + (WORD)y );
+}
+
+
+/***********************************************************************
  *           SetDCOrg    (GDI.117)
  */
 DWORD SetDCOrg( HDC hdc, short x, short y )
diff --git a/windows/defdlg.c b/windows/defdlg.c
index 8405dc3..2e5607d 100644
--- a/windows/defdlg.c
+++ b/windows/defdlg.c
@@ -50,6 +50,14 @@
 
 	case WM_NCDESTROY:
 
+	      /* Free dialog heap (if created) */
+	    if (dlgInfo->hDialogHeap)
+	    {
+		GlobalUnlock(dlgInfo->hDialogHeap);
+		GlobalFree(dlgInfo->hDialogHeap);
+		dlgInfo->hDialogHeap = 0;
+	    }
+
 	      /* Delete font */
 	    if (dlgInfo->hUserFont)
 	    {
diff --git a/windows/defwnd.c b/windows/defwnd.c
index 1adc1e3..12443b1 100644
--- a/windows/defwnd.c
+++ b/windows/defwnd.c
@@ -26,9 +26,6 @@
 extern LONG NC_HandleSysCommand( HWND hwnd, WORD wParam, POINT pt );
 extern LONG NC_HandleSetCursor( HWND hwnd, WORD wParam, LONG lParam );
 extern LONG WINPOS_HandleWindowPosChanging( WINDOWPOS *winpos ); /* winpos.c */
-extern void NC_TrackSysMenu( HWND hwnd ); /* menu.c */
-extern BOOL ActivateMenuBarFocus(HWND hWnd); /* menu.c */
-
 
 
 /***********************************************************************
@@ -229,13 +226,12 @@
 	return NC_HandleSysCommand( hwnd, wParam, MAKEPOINT(lParam) );
 
     case WM_SYSKEYDOWN:
-		if (wParam == VK_MENU) ActivateMenuBarFocus(hwnd);
-		break;    	
+	if (wParam == VK_MENU)
+	    SendMessage( hwnd, WM_SYSCOMMAND, SC_KEYMENU, 0L );
+	break;
+
     case WM_SYSKEYUP:
 		break;    	
-    case WM_MENUCHAR:
-		MessageBeep(0);
-		break;    	
     case WM_MEASUREITEM:
 		measure = (MEASUREITEMSTRUCT *)lParam;
 		switch(measure->CtlType) {
diff --git a/windows/dialog.c b/windows/dialog.c
index e91d95a..7b28b2d 100644
--- a/windows/dialog.c
+++ b/windows/dialog.c
@@ -15,6 +15,8 @@
 #include "dialog.h"
 #include "win.h"
 #include "user.h"
+#include "message.h"
+#include "heap.h"
 
 
   /* Dialog base units */
@@ -208,6 +210,8 @@
     DWORD exStyle = 0;
     WORD xUnit = xBaseUnit;
     WORD yUnit = yBaseUnit;
+    void *dlgHeapBase;
+    MDESC *dlgHeap;
 
       /* Parse dialog template */
 
@@ -278,15 +282,16 @@
 	return 0;
     }
 
-    ShowWindow(hwnd, SW_SHOWNORMAL);
-    UpdateWindow(hwnd);
-
       /* Create control windows */
 
 #ifdef DEBUG_DIALOG
     printf( " BEGIN\n" );
 #endif	
 
+    wndPtr = WIN_FindWndPtr( hwnd );
+    dlgInfo = (DIALOGINFO *)wndPtr->wExtra;
+    dlgInfo->hDialogHeap = 0;
+
     for (i = 0; i < template.header->nbItems; i++)
     {
 	DLGCONTROLHEADER * next_header;
@@ -303,16 +308,39 @@
 	printf(" %d, %d, %d, %d, %d, %08x\n", header->id, header->x, header->y, 
 		header->cx, header->cy, header->style );
 #endif
-	if ((strcmp(class, "STATIC") == 0) & ((header->style & SS_ICON) == SS_ICON)) {
-	    header->cx = 32;
-	    header->cy = 32;
+
+	if ((strcmp(class, "EDIT") == 0) &&
+	            ((header->style & DS_LOCALEDIT) != DS_LOCALEDIT)) {
+	    if (!dlgInfo->hDialogHeap) {
+		dlgInfo->hDialogHeap = GlobalAlloc(GMEM_FIXED, 0x10000);
+		if (!dlgInfo->hDialogHeap) {
+		    printf("CreateDialogIndirectParam: Insufficient memory ",
+			   "to create heap for edit control\n");
+		    continue;
+		}
+		dlgHeapBase = GlobalLock(dlgInfo->hDialogHeap);
+		HEAP_Init(&dlgHeap, dlgHeapBase, 0x10000);
 	    }
-	header->style |= WS_CHILD;
-	CreateWindowEx( WS_EX_NOPARENTNOTIFY, 
-		       class, text, header->style,
-		       header->x * xUnit / 4, header->y * yUnit / 8,
-		       header->cx * xUnit / 4, header->cy * yUnit / 8,
-		       hwnd, header->id, hInst, NULL );
+	    header->style |= WS_CHILD;
+	    CreateWindowEx( WS_EX_NOPARENTNOTIFY, 
+			   class, text, header->style,
+			   header->x * xUnit / 4, header->y * yUnit / 8,
+			   header->cx * xUnit / 4, header->cy * yUnit / 8,
+			   hwnd, header->id, HIWORD((LONG)dlgHeapBase), NULL );
+	}
+	else {
+	    if ((strcmp(class, "STATIC") == 0) & 
+		((header->style & SS_ICON) == SS_ICON)) {
+		header->cx = 32;
+		header->cy = 32;
+	    }
+	    header->style |= WS_CHILD;
+	    CreateWindowEx( WS_EX_NOPARENTNOTIFY, 
+			   class, text, header->style,
+			   header->x * xUnit / 4, header->y * yUnit / 8,
+			   header->cx * xUnit / 4, header->cy * yUnit / 8,
+			   hwnd, header->id, hInst, NULL );
+	}
 	header = next_header;
     }    
 
@@ -322,8 +350,6 @@
     
       /* Initialise dialog extra data */
 
-    wndPtr = WIN_FindWndPtr( hwnd );
-    dlgInfo = (DIALOGINFO *)wndPtr->wExtra;
     dlgInfo->dlgProc   = dlgProc;
     dlgInfo->hUserFont = hFont;
     dlgInfo->hMenu     = hMenu;
@@ -346,7 +372,7 @@
 /***********************************************************************
  *           DIALOG_DoDialogBox
  */
-static int DIALOG_DoDialogBox( HWND hwnd )
+static int DIALOG_DoDialogBox( HWND hwnd, HWND owner )
 {
     WND * wndPtr;
     DIALOGINFO * dlgInfo;
@@ -360,7 +386,8 @@
     dlgInfo = (DIALOGINFO *)wndPtr->wExtra;
     ShowWindow( hwnd, SW_SHOW );
 
-    while (MSG_InternalGetMessage( lpmsg, hwnd, MSGF_DIALOGBOX, TRUE ))
+    while (MSG_InternalGetMessage( lpmsg, hwnd, owner, MSGF_DIALOGBOX,
+				   PM_REMOVE, TRUE ))
     {
 	if (!IsDialogMessage( hwnd, lpmsg))
 	{
@@ -399,7 +426,7 @@
 	    hInst, dlgTemplate, owner, dlgProc, param );
 #endif
     hwnd = CreateDialogParam( hInst, dlgTemplate, owner, dlgProc, param );
-    if (hwnd) return DIALOG_DoDialogBox( hwnd );
+    if (hwnd) return DIALOG_DoDialogBox( hwnd, owner );
     return -1;
 }
 
@@ -426,7 +453,7 @@
     if (!(ptr = GlobalLock( dlgTemplate ))) return -1;
     hwnd = CreateDialogIndirectParam( hInst, ptr, owner, dlgProc, param );
     GlobalUnlock( dlgTemplate );
-    if (hwnd) return DIALOG_DoDialogBox( hwnd );
+    if (hwnd) return DIALOG_DoDialogBox( hwnd, owner );
     return -1;
 }
 
diff --git a/windows/mdi.c b/windows/mdi.c
index 0835c8a..80dd6d7 100644
--- a/windows/mdi.c
+++ b/windows/mdi.c
@@ -12,10 +12,12 @@
 #include "mdi.h"
 #include "user.h"
 #include "sysmetrics.h"
-#include "menu.h"
 
 #define DEBUG_MDI /* */
 
+extern WORD MENU_DrawMenuBar( HDC hDC, LPRECT lprect,
+			      HMENU hmenu, BOOL suppress_draw );  /* menu.c */
+
 /**********************************************************************
  *					MDIRecreateMenuList
  */
@@ -80,7 +82,7 @@
 			  WS_MAXIMIZEBOX | WS_MINIMIZEBOX | WS_SYSMENU |
 			  WS_THICKFRAME | WS_VISIBLE | cs->style,
 			  cs->x, cs->y, cs->cx, cs->cy, parent, (HMENU) 0,
-			  w->hInstance, (LPSTR) cs->lParam);
+			  w->hInstance, (LPSTR) cs);
 
     if (hwnd)
     {
@@ -569,9 +571,7 @@
 	rect.right -= SYSMETRICS_CXSIZE;
 	rect.bottom = rect.top + SYSMETRICS_CYMENU;
 
-	StdDrawMenuBar(hdc, &rect, (LPPOPUPMENU) GlobalLock(wndPtr->wIDmenu), 
-		       FALSE);
-	GlobalUnlock(wndPtr->wIDmenu);
+	MENU_DrawMenuBar(hdc, &rect, wndPtr->wIDmenu, FALSE);
 	
 	DeleteDC(hdcMem);
 	ReleaseDC(hwndFrame, hdc);
diff --git a/windows/message.c b/windows/message.c
index dcb8e5c..fdac135 100644
--- a/windows/message.c
+++ b/windows/message.c
@@ -205,7 +205,7 @@
  *   the coordinates to client coordinates.
  * - Send the WM_SETCURSOR message.
  */
-static BOOL MSG_TranslateMouseMsg( MSG *msg )
+static BOOL MSG_TranslateMouseMsg( MSG *msg, BOOL remove )
 {
     BOOL eatMsg = FALSE;
     static DWORD lastClickTime = 0;
@@ -280,9 +280,12 @@
 	    case WM_MBUTTONDOWN: msg->message = WM_MBUTTONDBLCLK; break;
 	}
 
-	lastClickTime = msg->time;
-	lastClickMsg  = msg->message;
-	lastClickPos  = msg->pt;
+	if (remove)
+	{
+	    lastClickTime = msg->time;
+	    lastClickMsg  = msg->message;
+	    lastClickPos  = msg->pt;
+	}
     }
 
       /* Build the translated message */
@@ -631,7 +634,7 @@
 
 	    if ((msg->message >= WM_MOUSEFIRST) &&
 		(msg->message <= WM_MOUSELAST))
-		if (!MSG_TranslateMouseMsg( msg )) 
+		if (!MSG_TranslateMouseMsg( msg, flags & PM_REMOVE )) 
 		{
 		    MSG_RemoveMsg( sysMsgQueue, pos );
 		    continue;
@@ -690,20 +693,30 @@
  * 'hwnd' must be the handle of the dialog or menu window.
  * 'code' is the message filter value (MSGF_??? codes).
  */
-BOOL MSG_InternalGetMessage( LPMSG msg, HWND hwnd, short code, BOOL sendIdle ) 
+BOOL MSG_InternalGetMessage( LPMSG msg, HWND hwnd, HWND hwndOwner, short code,
+			     WORD flags, BOOL sendIdle ) 
 {
-    do
+    for (;;)
     {
 	if (sendIdle)
 	{
-	    if (MSG_PeekMessage(appMsgQueue, msg, 0, 0, 0, PM_REMOVE, TRUE))
-		continue;
-	    /* FIXME: to which window should we send this? */
-	    /* SendMessage( hwnd, WM_ENTERIDLE, code, (LPARAM)hwnd ); */
+	    if (!MSG_PeekMessage( appMsgQueue, msg, 0, 0, 0, flags, TRUE ))
+	    {
+		  /* No message present -> send ENTERIDLE and wait */
+		SendMessage( hwndOwner, WM_ENTERIDLE, code, (LPARAM)hwnd );
+		MSG_PeekMessage( appMsgQueue, msg, 0, 0, 0, flags, FALSE );
+	    }
 	}
-	MSG_PeekMessage( appMsgQueue, msg, 0, 0, 0, PM_REMOVE, FALSE );
-    } while (CallMsgFilter( msg, code ) != 0);
-    return (msg->message != WM_QUIT);
+	else  /* Always wait for a message */
+	    MSG_PeekMessage( appMsgQueue, msg, 0, 0, 0, flags, FALSE );
+
+	if (!CallMsgFilter( msg, code )) return (msg->message != WM_QUIT);
+
+	  /* Message filtered -> remove it from the queue */
+	  /* if it's still there. */
+	if (!(flags & PM_REMOVE))
+	    MSG_PeekMessage( appMsgQueue, msg, 0, 0, 0, PM_REMOVE, TRUE );
+    }
 }
 
 
diff --git a/windows/nonclient.c b/windows/nonclient.c
index c364b02..2bb188e 100644
--- a/windows/nonclient.c
+++ b/windows/nonclient.c
@@ -12,7 +12,6 @@
 #include "sysmetrics.h"
 #include "user.h"
 #include "scroll.h"
-#include "menu.h"
 #include "syscolor.h"
 
 static HBITMAP hbitmapClose = 0;
@@ -24,11 +23,19 @@
 static HBITMAP hbitmapRestore = 0;
 static HBITMAP hbitmapRestoreD = 0;
 
+#define SC_ABOUTWINE    	(SC_SCREENSAVE+1)
+extern HINSTANCE hSysRes;
+extern BOOL AboutWine_Proc( HWND hDlg, WORD msg, WORD wParam, LONG lParam );
+
 extern void WINPOS_GetMinMaxInfo( HWND hwnd, POINT *maxSize, POINT *maxPos,
 			    POINT *minTrack, POINT *maxTrack );  /* winpos.c */
 extern void CURSOR_SetWinCursor( HWND hwnd, HCURSOR hcursor );   /* cursor.c */
 extern WORD MENU_GetMenuBarHeight( HWND hwnd, WORD menubarWidth,
 				   int orgX, int orgY );         /* menu.c */
+extern void MENU_TrackMouseMenuBar( HWND hwnd, POINT pt );       /* menu.c */
+extern void MENU_TrackKbdMenuBar( HWND hwnd, WORD wParam );      /* menu.c */
+extern WORD MENU_DrawMenuBar( HDC hDC, LPRECT lprect,
+			      HMENU hmenu, BOOL suppress_draw ); /* menu.c */
 
 
   /* Some useful macros */
@@ -70,8 +77,8 @@
     }
 
     if ((style & WS_CAPTION) == WS_CAPTION)
-	rect->top -= SYSMETRICS_CYCAPTION - 1;
-    if (menu) rect->top -= SYSMETRICS_CYMENU + 1;
+	rect->top -= SYSMETRICS_CYCAPTION - SYSMETRICS_CYBORDER;
+    if (menu) rect->top -= SYSMETRICS_CYMENU + SYSMETRICS_CYBORDER;
 
     if (style & WS_VSCROLL) rect->right  += SYSMETRICS_CXVSCROLL;
     if (style & WS_HSCROLL) rect->bottom += SYSMETRICS_CYHSCROLL;
@@ -237,8 +244,9 @@
 	if (!PtInRect( &rect, pt ))
 	{
 	      /* Check system menu */
-	    if ((wndPtr->dwStyle & WS_SYSMENU) && (pt.x <= SYSMETRICS_CXSIZE))
-		return HTSYSMENU;
+	    if (wndPtr->dwStyle & WS_SYSMENU)
+		rect.left += SYSMETRICS_CXSIZE;
+	    if (pt.x <= rect.left) return HTSYSMENU;
 	      /* Check maximize box */
 	    if (wndPtr->dwStyle & WS_MAXIMIZEBOX)
 		rect.right -= SYSMETRICS_CXSIZE + 1;
@@ -311,7 +319,7 @@
 /***********************************************************************
  *           NC_DrawSysButton
  */
-static void NC_DrawSysButton( HWND hwnd, HDC hdc, BOOL down )
+void NC_DrawSysButton( HWND hwnd, HDC hdc, BOOL down )
 {
     RECT rect;
     WND *wndPtr = WIN_FindWndPtr( hwnd );
@@ -611,19 +619,17 @@
     if ((wndPtr->dwStyle & WS_CAPTION) == WS_CAPTION)
     {
 	RECT r = rect;
-	rect.top += SYSMETRICS_CYSIZE + 1;
-	r.bottom = rect.top - 1;
+	r.bottom = rect.top + SYSMETRICS_CYSIZE;
+	rect.top += SYSMETRICS_CYSIZE + SYSMETRICS_CYBORDER;
 	NC_DrawCaption( hdc, &r, hwnd, wndPtr->dwStyle, active );
     }
 
     if (HAS_MENU(wndPtr))
     {
-	LPPOPUPMENU lpMenu = (LPPOPUPMENU) GlobalLock( wndPtr->wIDmenu );
 	RECT r = rect;
-	r.bottom = rect.top + lpMenu->Height;
-	rect.top += lpMenu->Height;
-	StdDrawMenuBar( hdc, &r, lpMenu, suppress_menupaint );
-	GlobalUnlock( wndPtr->wIDmenu );
+	r.bottom = rect.top + SYSMETRICS_CYMENU;  /* default height */
+	rect.top += MENU_DrawMenuBar( hdc, &r, (HMENU)wndPtr->wIDmenu,
+				      suppress_menupaint );
     }
 
     if (wndPtr->dwStyle & (WS_VSCROLL | WS_HSCROLL)) {
@@ -1111,27 +1117,33 @@
     ReleaseCapture();
 }
 
-
 /***********************************************************************
- *           NC_TrackMouseMenuBar
+ *           NC_TrackSysMenu
  *
- * Track a mouse events for the MenuBar.
+ * Track a mouse button press on the system menu.
  */
-static void NC_TrackMouseMenuBar( HWND hwnd, WORD wParam, POINT pt )
+static void NC_TrackSysMenu( HWND hwnd, HDC hdc, POINT pt )
 {
-    WND		*wndPtr;
-    LPPOPUPMENU lppop;
-    MSG 	msg;
-    wndPtr = WIN_FindWndPtr(hwnd);
-    lppop = (LPPOPUPMENU)GlobalLock(wndPtr->wIDmenu);
-#ifdef DEBUG_MENU
-    printf("NC_TrackMouseMenuBar // wndPtr=%08X lppop=%08X !\n", wndPtr, lppop);
-#endif
-    ScreenToClient(hwnd, &pt);
-    pt.y += lppop->rect.bottom;
-    SetCapture(hwnd);
-    MenuButtonDown(hwnd, lppop, pt.x, pt.y);
-    GlobalUnlock(wndPtr->wIDmenu);
+    RECT rect;
+    WND *wndPtr = WIN_FindWndPtr( hwnd );
+
+    if (!(wndPtr->dwStyle & WS_SYSMENU)) return;
+      /* If window has a menu, track the menu bar normally */
+    if (HAS_MENU(wndPtr)) MENU_TrackMouseMenuBar( hwnd, pt );
+    else
+    {
+	  /* Otherwise track the system menu like a normal popup menu */
+	NC_GetInsideRect( hwnd, &rect );
+	OffsetRect( &rect, wndPtr->rectWindow.left, wndPtr->rectWindow.top );
+	if (wndPtr->dwStyle & WS_CHILD)
+	    ClientToScreen( wndPtr->hwndParent, (POINT *)&rect );
+	rect.right = rect.left + SYSMETRICS_CXSIZE;
+	rect.bottom = rect.top + SYSMETRICS_CYSIZE;
+	NC_DrawSysButton( hwnd, hdc, TRUE );
+	TrackPopupMenu( wndPtr->hSysMenu, TPM_LEFTALIGN | TPM_LEFTBUTTON,
+		        rect.left, rect.bottom, 0, hwnd, &rect );
+	NC_DrawSysButton( hwnd, hdc, FALSE );
+    }
 }
 
 
@@ -1151,8 +1163,7 @@
 	break;
 
     case HTSYSMENU:
-	NC_DrawSysButton( hwnd, hdc, TRUE );
-	NC_TrackSysMenu(hwnd);
+	NC_TrackSysMenu( hwnd, hdc, MAKEPOINT(lParam) );
 	break;
 
     case HTMENU:
@@ -1263,22 +1274,28 @@
 	break;
 
     case SC_MOUSEMENU:
-	NC_TrackMouseMenuBar( hwnd, wParam, pt );
+	MENU_TrackMouseMenuBar( hwnd, pt );
 	break;
 
     case SC_KEYMENU:
-/*	NC_KeyMenuBar( hwnd, wParam, pt ); */
+	MENU_TrackKbdMenuBar( hwnd, wParam );
 	break;
 	
     case SC_ARRANGE:
 	break;
 
     case SC_TASKLIST:
-    case SC_SCREENSAVE:
+	/* WinExec( "taskman.exe", SW_SHOWNORMAL ); */
+	break;
+
     case SC_HOTKEY:
 	break;
+
+    case SC_SCREENSAVE:
+	if (wParam == SC_ABOUTWINE)
+	    DialogBox( hSysRes, MAKEINTRESOURCE(2), 
+		       hwnd, (FARPROC)AboutWine_Proc );
+	break;
     }
     return 0;
 }
-
-
diff --git a/windows/utility.c b/windows/utility.c
index 32f1e59..afec604 100644
--- a/windows/utility.c
+++ b/windows/utility.c
@@ -382,21 +382,14 @@
 
 int wvsprintf(LPSTR buf, LPSTR format, LPSTR args)
 {
-	char qualified_fmt[1536];
 	char *newargs;
 	int result;
 
-	/* 1.5K is a safe value as wvsprintf can only handle buffers up to
-	1K and in a worst case such a buffer would look like "%i%i%i..." */
-
 	if(!buf || !format) return 0;
 
-	/* Change the format string so that ints are handled as short by
-	   default */
-
 	/* Convert agruments to 32-bit values */
 	newargs = UTILITY_convertArgs(format, args);
-	result = vsprintf(buf, qualified_fmt, newargs);
+	result = vsprintf(buf, format, newargs);
 
 	free(newargs);
 	return result;
diff --git a/windows/win.c b/windows/win.c
index 8aeba56..3924908 100644
--- a/windows/win.c
+++ b/windows/win.c
@@ -247,6 +247,7 @@
     HANDLE class, hwnd;
     CLASS *classPtr;
     WND *wndPtr, *parentPtr = NULL;
+    POINT maxSize, maxPos, minTrack, maxTrack;
     CREATESTRUCT *createStruct;
     HANDLE hcreateStruct;
     int wmcreate;
@@ -379,6 +380,19 @@
 
     win_attr.save_under = ((classPtr->wc.style & CS_SAVEBITS) != 0);
 
+    WINPOS_GetMinMaxInfo( hwnd, &maxSize, &maxPos, &minTrack, &maxTrack );
+
+    if ( maxSize.x < width)
+      {
+	width = maxSize.x;
+	wndPtr->rectWindow.right = x + width;
+      }
+    if ( maxSize.y < height)
+      {
+	height = maxSize.y;
+	wndPtr->rectWindow.bottom = y + height;
+      }
+    
     wndPtr->window = XCreateWindow( display, parentPtr->window,
 		   x + parentPtr->rectClient.left - parentPtr->rectWindow.left,
 		   y + parentPtr->rectClient.top - parentPtr->rectWindow.top,