Release 940912

Thu Aug 25 15:24:36 EDT 1994            <jrichard@cs.uml.edu>

        * [include/win.h]
        Removed seperate X window for icon, added icon width,height.

	* [include/windows.h]
	Commented out the old SW_xxx emum and added defines since
	they aren't enumerated.

	* [windows/dce.c]
        Removed some older IsIconic checks from GetDCEx(), functionality
        is now in nonclient and generic wine window handling code.
        Lots of thanks to Alexandre Julliard all the hints and
        help...

        * [windows/defwnd.c]
        Removed call to NC_HandleNCPaintIcon() under case WM_PAINTICON,
        WM_PAINTICON now calls NC_HandleNCPaint.  

        * [windows/event.c]
        Removed IsIconic checks.

        * [windows/icon.c]
        Removed everything in this file for now... could be used later.
        Icon functionality is now handled by the generic wine windows
        handling functions.
        
        * [windows/mdi.c]
        Added a ShowWindow in MDIRestoreChild().  MDI child windows now
        show up when deiconified.  Removed IsIconic checks.

        * [windows/message.c]
        Removed old icon routines from hardware_event().

        * [windows/nonclient.c]
        Changed NC_HandleNCCalcSize() so it doesn't change the size
        of an icon window.  Made NC_InternalNCHitTest() on an Iconic
        window always return HTCAPTION.  Made NC_HandleNCLButtonDblClk()
        on an Iconic window always send a SC_RESTORE message.

        * [windows/painting.c]
        Changed RedrawWindow() so it doesn't redraw an iconic window
        unless it has to (no icon for this class).
        
        * [windows/win.c]
        Removed creation of seperate icon window from CreateWindowEx().
        
        * [windows/winpos.c]
        Added saving and restoring of window rectangle during
        iconification/deiconification to ShowWindow().  Added
	functions to recursively hide and show children... called
	by ShowWindow during iconification/deiconification.

Sat, 27 Aug 1994 18:47:34 +0100 (MET DST)  micky@marie.physik.tu-berlin.de (Michael Patra)

        * [windows/message.c]
        WaitMessage(): Fixed handling of wm_timer-messages

        * [miscemu/int21.c]
        FindNextFCB(): Rewritten to support other functions than just
        returning the volume label

	* [misc/file.c]
	OpenFile(): Fix in handling of OF_CREATE

Wed Aug 24 19:40:42 PDT 1994  Andrew Lagodzinski  (andrew@netcom.com)

	* [if1632/user.spec]
	Added SetParent.

	* [windows/win.c]
	Added SetParent.

Fri Aug 19 16:37:00 1994  Thomas Sandford <t.d.g.sandford@bradford.ac.uk>

	* [loader/selector.c]
	Many changes throughout file to correct handling of shared memory
	function return codes. FreeBSD and SunOS shm functions return
	-1 not 0 on error. If Linux is different, these changes
	will have to be backed out.
	CleanupSelectors(): this is a new (internal) call to free
	up all selectors (and shm handles/memory) for use on exit.

	* [include/segmem.h]
	Change comment to reflect new use of shm_key

	* [misc/main.c]
	called_at_exit(): add call to CleanupSelectors()

Mon Aug 22 18:19:25 1994  Alexandre Julliard  (julliard@lamisun.epfl.ch)

	* [controls/button.c]
	Use OBM_CHECKBOXES to draw check boxes with correct colors.
	Fixed bug with WM_SETTEXT handling.
	A few drawing optimisations.

	* [controls/menu.c]
	Implemented correct \t and \a handling in menu items.
	Implemented help items (flush right) on menu bar.
	Added WM_ENTERMENULOOP and WM_EXITMENULOOP messages.

	* [controls/static.c]
	Fixed SS_ICON controls and implemented STM_SETICON message
	handling.

	* [controls/widget.c]
	Set cursor to IDC_ARROW for built-in classes.

	* [include/options.h] [misc/main.c]
	Backing store is now off by default.

	* [objects/region.c]
	Use X regions for rectangle and polygon regions: *major* speed
	improvement.

	* [windows/dialog.c]
	Fixed the fix for integer ids in controls. SS_ICON controls in
	dialogs should work now.
	Implemented DS_ABSALIGN style.

	* [windows/graphics.c]
	Implemented InvertRgn().
	New internal function GRAPH_DrawBitmap() to draw bitmaps faster
	than with CreateCompatibleDC() + BitBlt().

	* [windows/message.c]
	Determining the window for a mouse message is now done at
	GetMessage() time.
	Modified PeekMessage() handling to avoid needlessly flushing the
	output queue.

	* [windows/timer.c]
	Check for restart of a timer (SetTimer call with the same hwnd and
	id than an existing timer).
diff --git a/ChangeLog b/ChangeLog
index e7dfebd..1e09a06 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,4 +1,140 @@
 ----------------------------------------------------------------------
+Thu Aug 25 15:24:36 EDT 1994            <jrichard@cs.uml.edu>
+
+        * [include/win.h]
+        Removed seperate X window for icon, added icon width,height.
+
+	* [include/windows.h]
+	Commented out the old SW_xxx emum and added defines since
+	they aren't enumerated.
+
+	* [windows/dce.c]
+        Removed some older IsIconic checks from GetDCEx(), functionality
+        is now in nonclient and generic wine window handling code.
+        Lots of thanks to Alexandre Julliard all the hints and
+        help...
+
+        * [windows/defwnd.c]
+        Removed call to NC_HandleNCPaintIcon() under case WM_PAINTICON,
+        WM_PAINTICON now calls NC_HandleNCPaint.  
+
+        * [windows/event.c]
+        Removed IsIconic checks.
+
+        * [windows/icon.c]
+        Removed everything in this file for now... could be used later.
+        Icon functionality is now handled by the generic wine windows
+        handling functions.
+        
+        * [windows/mdi.c]
+        Added a ShowWindow in MDIRestoreChild().  MDI child windows now
+        show up when deiconified.  Removed IsIconic checks.
+
+        * [windows/message.c]
+        Removed old icon routines from hardware_event().
+
+        * [windows/nonclient.c]
+        Changed NC_HandleNCCalcSize() so it doesn't change the size
+        of an icon window.  Made NC_InternalNCHitTest() on an Iconic
+        window always return HTCAPTION.  Made NC_HandleNCLButtonDblClk()
+        on an Iconic window always send a SC_RESTORE message.
+
+        * [windows/painting.c]
+        Changed RedrawWindow() so it doesn't redraw an iconic window
+        unless it has to (no icon for this class).
+        
+        * [windows/win.c]
+        Removed creation of seperate icon window from CreateWindowEx().
+        
+        * [windows/winpos.c]
+        Added saving and restoring of window rectangle during
+        iconification/deiconification to ShowWindow().  Added
+	functions to recursively hide and show children... called
+	by ShowWindow during iconification/deiconification.
+
+Sat, 27 Aug 1994 18:47:34 +0100 (MET DST)  micky@marie.physik.tu-berlin.de (Michael Patra)
+
+        * [windows/message.c]
+        WaitMessage(): Fixed handling of wm_timer-messages
+
+        * [miscemu/int21.c]
+        FindNextFCB(): Rewritten to support other functions than just
+        returning the volume label
+
+	* [misc/file.c]
+	OpenFile(): Fix in handling of OF_CREATE
+
+Wed Aug 24 19:40:42 PDT 1994  Andrew Lagodzinski  (andrew@netcom.com)
+
+	* [if1632/user.spec]
+	Added SetParent.
+
+	* [windows/win.c]
+	Added SetParent.
+
+Fri Aug 19 16:37:00 1994  Thomas Sandford <t.d.g.sandford@bradford.ac.uk>
+
+	* [loader/selector.c]
+	Many changes throughout file to correct handling of shared memory
+	function return codes. FreeBSD and SunOS shm functions return
+	-1 not 0 on error. If Linux is different, these changes
+	will have to be backed out.
+	CleanupSelectors(): this is a new (internal) call to free
+	up all selectors (and shm handles/memory) for use on exit.
+
+	* [include/segmem.h]
+	Change comment to reflect new use of shm_key
+
+	* [misc/main.c]
+	called_at_exit(): add call to CleanupSelectors()
+
+Mon Aug 22 18:19:25 1994  Alexandre Julliard  (julliard@lamisun.epfl.ch)
+
+	* [controls/button.c]
+	Use OBM_CHECKBOXES to draw check boxes with correct colors.
+	Fixed bug with WM_SETTEXT handling.
+	A few drawing optimisations.
+
+	* [controls/menu.c]
+	Implemented correct \t and \a handling in menu items.
+	Implemented help items (flush right) on menu bar.
+	Added WM_ENTERMENULOOP and WM_EXITMENULOOP messages.
+
+	* [controls/static.c]
+	Fixed SS_ICON controls and implemented STM_SETICON message
+	handling.
+
+	* [controls/widget.c]
+	Set cursor to IDC_ARROW for built-in classes.
+
+	* [include/options.h] [misc/main.c]
+	Backing store is now off by default.
+
+	* [objects/region.c]
+	Use X regions for rectangle and polygon regions: *major* speed
+	improvement.
+
+	* [windows/dialog.c]
+	Fixed the fix for integer ids in controls. SS_ICON controls in
+	dialogs should work now.
+	Implemented DS_ABSALIGN style.
+
+	* [windows/graphics.c]
+	Implemented InvertRgn().
+	New internal function GRAPH_DrawBitmap() to draw bitmaps faster
+	than with CreateCompatibleDC() + BitBlt().
+
+	* [windows/message.c]
+	Determining the window for a mouse message is now done at
+	GetMessage() time.
+	Modified PeekMessage() handling to avoid needlessly flushing the
+	output queue.
+
+	* [windows/timer.c]
+	Check for restart of a timer (SetTimer call with the same hwnd and
+	id than an existing timer).
+
+----------------------------------------------------------------------
 Tue Aug  9 23:58:29 MET DST 1994	<erik@hacktic.nl>
 
 	* [misc/file.c]
diff --git a/controls/button.c b/controls/button.c
index a5d3946..7e2d99e 100644
--- a/controls/button.c
+++ b/controls/button.c
@@ -12,15 +12,19 @@
 #include "user.h"
 #include "syscolor.h"
 
-LONG ButtonWndProc(HWND hWnd, WORD uMsg, WORD wParam, LONG lParam);
 
-static BOOL pressed;
+LONG ButtonWndProc(HWND hWnd, WORD uMsg, WORD wParam, LONG lParam);
 
 #define NOTIFY_PARENT(hWndCntrl, wNotifyCode) \
 	SendMessage(GetParent(hWndCntrl), WM_COMMAND, \
 		GetDlgCtrlID(hWndCntrl), MAKELPARAM(hWndCntrl, wNotifyCode));
 #define DIM(array)	((sizeof array)/(sizeof array[0]))
 
+extern BOOL GRAPH_DrawBitmap( HDC hdc, HBITMAP hbitmap, int xdest, int ydest,
+			      int xsrc, int ysrc, int width, int height,
+			      int rop );              /* windows/graphics.c */
+extern void DEFWND_SetText( HWND hwnd, LPSTR text );  /* windows/defwnd.c */
+
 static LONG PB_Paint(HWND hWnd);
 static LONG PB_LButtonDown(HWND hWnd, WORD wParam, LONG lParam);
 static LONG PB_LButtonUp(HWND hWnd, WORD wParam, LONG lParam);
@@ -54,136 +58,60 @@
 
 typedef struct
 {
-    LONG (*paintfn)();
-    LONG (*lButtonDownfn)();
-    LONG (*lButtonUpfn)();
-    LONG (*lButtonDblClkfn)();
-    LONG (*killFocusfn)();
-    LONG (*setCheckfn)();
-    LONG (*getCheckfn)();
+    LONG (*paintfn)( HWND );
+    LONG (*lButtonDownfn)( HWND, WORD, LONG );
+    LONG (*lButtonUpfn)( HWND, WORD, LONG );
+    LONG (*lButtonDblClkfn)( HWND, WORD, LONG );
+    LONG (*killFocusfn)( HWND );
+    LONG (*setCheckfn)( HWND, WORD );
+    LONG (*getCheckfn)( HWND );
 } BTNFN;
 
 #define MAX_BTN_TYPE  12
 
 static BTNFN btnfn[MAX_BTN_TYPE] =
 {
-    { 
-	(LONG(*)())PB_Paint,                       /* BS_PUSHBUTTON */
-	(LONG(*)())PB_LButtonDown,
-	(LONG(*)())PB_LButtonUp,
-	(LONG(*)())PB_LButtonDblClk,
-	(LONG(*)())PB_KillFocus,
-	(LONG(*)())NULL,
-	(LONG(*)())NULL
-    },
-    { 
-	(LONG(*)())PB_Paint,                       /* BS_DEFPUSHBUTTON */
-	(LONG(*)())PB_LButtonDown,
-	(LONG(*)())PB_LButtonUp,
-	(LONG(*)())PB_LButtonDblClk,
-	(LONG(*)())PB_KillFocus,
-	(LONG(*)())NULL,
-	(LONG(*)())NULL
-    },
-    {
-	(LONG(*)())CB_Paint,                       /* BS_CHECKBOX */
-	(LONG(*)())CB_LButtonDown,
-	(LONG(*)())CB_LButtonUp,
-	(LONG(*)())CB_LButtonDblClk,
-	(LONG(*)())CB_KillFocus,
-	(LONG(*)())CB_SetCheck,
-	(LONG(*)())CB_GetCheck
-    },
-    {
-	(LONG(*)())CB_Paint,                       /* BS_AUTOCHECKBOX */
-	(LONG(*)())CB_LButtonDown,
-	(LONG(*)())CB_LButtonUp,
-	(LONG(*)())CB_LButtonDblClk,
-	(LONG(*)())CB_KillFocus,
-	(LONG(*)())CB_SetCheck,
-	(LONG(*)())CB_GetCheck
-    },
-    {
-	(LONG(*)())RB_Paint,                       /* BS_RADIOBUTTON */
-	(LONG(*)())RB_LButtonDown,
-	(LONG(*)())RB_LButtonUp,
-	(LONG(*)())RB_LButtonDblClk,
-	(LONG(*)())RB_KillFocus,
-	(LONG(*)())RB_SetCheck,
-	(LONG(*)())RB_GetCheck
-    },
-    {
-	(LONG(*)())CB_Paint,                       /* BS_3STATE */
-	(LONG(*)())CB_LButtonDown,
-	(LONG(*)())CB_LButtonUp,
-	(LONG(*)())CB_LButtonDblClk,
-	(LONG(*)())CB_KillFocus,
-	(LONG(*)())CB_SetCheck,
-	(LONG(*)())CB_GetCheck
-    },
-    {
-	(LONG(*)())CB_Paint,                       /* BS_AUTO3STATE */
-	(LONG(*)())CB_LButtonDown,
-	(LONG(*)())CB_LButtonUp,
-	(LONG(*)())CB_LButtonDblClk,
-	(LONG(*)())CB_KillFocus,
-	(LONG(*)())CB_SetCheck,
-	(LONG(*)())CB_GetCheck
-    },
-    {
-	(LONG(*)())GB_Paint,                       /* BS_GROUPBOX */
-	(LONG(*)())NULL,
-	(LONG(*)())NULL,
-	(LONG(*)())NULL,
-	(LONG(*)())NULL,
-	(LONG(*)())NULL,
-	(LONG(*)())NULL
-    },
-    {
-	(LONG(*)())UB_Paint,                       /* BS_USERBUTTON */
-	(LONG(*)())UB_LButtonDown,
-	(LONG(*)())UB_LButtonUp,
-	(LONG(*)())NULL,
-	(LONG(*)())UB_KillFocus,
-	(LONG(*)())NULL,
-	(LONG(*)())NULL
-    },
-    {
-	(LONG(*)())RB_Paint,                       /* BS_AUTORADIOBUTTON */
-	(LONG(*)())RB_LButtonDown,
-	(LONG(*)())RB_LButtonUp,
-	(LONG(*)())RB_LButtonDblClk,
-	(LONG(*)())RB_KillFocus,
-	(LONG(*)())RB_SetCheck,
-	(LONG(*)())RB_GetCheck
-    },
-    {
-	(LONG(*)())NULL,                           /* Not defined */
-	(LONG(*)())NULL,
-	(LONG(*)())NULL,
-	(LONG(*)())NULL,
-	(LONG(*)())NULL,
-	(LONG(*)())NULL,
-	(LONG(*)())NULL
-    },
-    { 
-	(LONG(*)())OB_Paint,                       /* BS_OWNERDRAW */
-	(LONG(*)())OB_LButtonDown,
-	(LONG(*)())OB_LButtonUp,
-	(LONG(*)())NULL,
-	(LONG(*)())OB_KillFocus,
-	(LONG(*)())NULL,
-	(LONG(*)())NULL
-    },
+    /* BS_PUSHBUTTON */
+    { PB_Paint, PB_LButtonDown, PB_LButtonUp, PB_LButtonDblClk, 
+      PB_KillFocus, NULL, NULL },
+    /* BS_DEFPUSHBUTTON */
+    { PB_Paint, PB_LButtonDown, PB_LButtonUp, PB_LButtonDblClk,
+      PB_KillFocus, NULL, NULL },
+    /* BS_CHECKBOX */
+    { CB_Paint, CB_LButtonDown, CB_LButtonUp, CB_LButtonDblClk,
+      CB_KillFocus, CB_SetCheck, CB_GetCheck },
+    /* BS_AUTOCHECKBOX */
+    { CB_Paint, CB_LButtonDown, CB_LButtonUp, CB_LButtonDblClk,
+      CB_KillFocus, CB_SetCheck, CB_GetCheck },
+    /* BS_RADIOBUTTON */
+    { RB_Paint, RB_LButtonDown, RB_LButtonUp, RB_LButtonDblClk,
+      RB_KillFocus, RB_SetCheck, RB_GetCheck },
+    /* BS_3STATE */
+    { CB_Paint, CB_LButtonDown, CB_LButtonUp, CB_LButtonDblClk,
+      CB_KillFocus, CB_SetCheck, CB_GetCheck },
+    /* BS_AUTO3STATE */
+    { CB_Paint, CB_LButtonDown, CB_LButtonUp, CB_LButtonDblClk,
+      CB_KillFocus, CB_SetCheck, CB_GetCheck },
+    /* BS_GROUPBOX */
+    { GB_Paint, NULL, NULL, NULL, NULL, NULL, NULL },
+    /* BS_USERBUTTON */
+    { UB_Paint, UB_LButtonDown, UB_LButtonUp, NULL, UB_KillFocus, NULL, NULL },
+    /* BS_AUTORADIOBUTTON */
+    { RB_Paint, RB_LButtonDown, RB_LButtonUp, RB_LButtonDblClk,
+      RB_KillFocus, RB_SetCheck, RB_GetCheck },
+    /* Not defined */
+    { NULL, NULL, NULL, NULL, NULL, NULL, NULL },
+    /* BS_OWNERDRAW */
+    { OB_Paint, OB_LButtonDown, OB_LButtonUp, NULL, OB_KillFocus, NULL, NULL }
 };
 
+static HBITMAP hbitmapCheckBoxes = 0;
+static WORD checkBoxWidth = 0, checkBoxHeight = 0;
+
 
 LONG ButtonWndProc(HWND hWnd, WORD uMsg, WORD wParam, LONG lParam)
 {
 	LONG lResult = 0;
-	HDC hDC;
-	RECT rc;
-
 	WND *wndPtr = WIN_FindWndPtr(hWnd);
 	LONG style = wndPtr->dwStyle & 0x0000000F;
 
@@ -197,12 +125,20 @@
 		break;
 
 	case WM_CREATE:
+		if (!hbitmapCheckBoxes)
+		{
+		    BITMAP bmp;
+		    hbitmapCheckBoxes = LoadBitmap( 0, MAKEINTRESOURCE(OBM_CHECKBOXES) );
+		    GetObject( hbitmapCheckBoxes, sizeof(bmp), (LPSTR)&bmp );
+		    checkBoxWidth  = bmp.bmWidth / 4;
+		    checkBoxHeight = bmp.bmHeight / 3;
+		}
+		
 		if (style < 0L || style >= (LONG)DIM(btnfn))
 		    lResult = -1L;
 		else
 		{
 		    (WORD)(*(wndPtr->wExtra)) = 0;
-		    pressed = FALSE;
 		    lResult = 0L;
 		}
 		break;
@@ -227,6 +163,12 @@
 		    (btnfn[style].lButtonDblClkfn)(hWnd, wParam, lParam);
 		break;
 
+        case WM_SETTEXT:
+		DEFWND_SetText( hWnd, (LPSTR)lParam );
+		InvalidateRect( hWnd, NULL, FALSE );
+		UpdateWindow( hWnd );
+		return 0;
+
 	case WM_SETFOCUS:
 		break;
 
@@ -270,76 +212,71 @@
 
     hDC = BeginPaint(hWnd, &ps);
     GetClientRect(hWnd, &rc);
-    if (pressed)
+    if (GetCapture() == hWnd)
 	DrawPressedPushButton(hDC, hWnd, rc);
     else
 	DrawRaisedPushButton(hDC, hWnd, rc);
     EndPaint(hWnd, &ps);
+    return 0;
 }
 
 static LONG PB_LButtonDown(HWND hWnd, WORD wParam, LONG lParam)
 {
     SetFocus(hWnd);
     SetCapture(hWnd);
-    pressed = TRUE;
     InvalidateRect(hWnd, NULL, FALSE);
     UpdateWindow(hWnd);
+    return 0;
 }
 
 static LONG PB_LButtonUp(HWND hWnd, WORD wParam, LONG lParam)
 {
     RECT rc;
 
-    pressed = FALSE;
     ReleaseCapture();
     GetClientRect(hWnd, &rc);
     if (PtInRect(&rc, MAKEPOINT(lParam)))
 	NOTIFY_PARENT(hWnd, BN_CLICKED);
     InvalidateRect(hWnd, NULL, FALSE);
     UpdateWindow(hWnd);
+    return 0;
 }
 
 static LONG PB_LButtonDblClk(HWND hWnd, WORD wParam, LONG lParam)
 {
-    RECT rc;
-
-    GetClientRect(hWnd, &rc);
-    if (PtInRect(&rc, MAKEPOINT(lParam)))
-	NOTIFY_PARENT(hWnd, BN_DOUBLECLICKED);
+    NOTIFY_PARENT(hWnd, BN_DOUBLECLICKED);
+    return 0;
 }
 
 static LONG PB_KillFocus(HWND hWnd)
 {
-    pressed = FALSE;
     InvalidateRect(hWnd, NULL, FALSE);
     UpdateWindow(hWnd);
+    return 0;
 }
 
 static void DrawRaisedPushButton(HDC hDC, HWND hButton, RECT rc)
 {
 	HPEN hOldPen;
 	HBRUSH hOldBrush;
-	HRGN rgn1, rgn2, rgn;
+	HRGN rgn;
 	int len;
-	static char text[50+1];
+	char *text;
 	POINT points[6];
 	DWORD dwTextSize;
 	int delta;
 	TEXTMETRIC tm;
+	WND *wndPtr = WIN_FindWndPtr( hButton );
 
 	hOldPen = (HPEN)SelectObject(hDC, sysColorObjects.hpenWindowFrame);
 	hOldBrush = (HBRUSH)SelectObject(hDC, sysColorObjects.hbrushBtnFace);
 	SetBkMode(hDC, TRANSPARENT);
-
-	rgn = CreateRectRgn(0, 0,  0,  0);
-	rgn1 = CreateRectRgn(rc.left, rc.top, rc.right, rc.bottom);
-
-	SendMessage(GetParent(hButton), WM_CTLCOLOR, (WORD)hDC,
-		    MAKELPARAM(hButton, CTLCOLOR_BTN));
+	SetTextColor( hDC, GetSysColor(COLOR_BTNTEXT) );
 	Rectangle(hDC, rc.left, rc.top, rc.right, rc.bottom);
 
 	/* draw button label, if any: */
-	len = GetWindowText(hButton, text, sizeof text);
+	text = USER_HEAP_ADDR( wndPtr->hText );
+	len = strlen(text);
 	if (len >= 1) {
 		rc.left--;	rc.bottom--;
 		DrawText(hDC, text, len, &rc,
@@ -359,9 +296,8 @@
 	points[4].y = rc.top+1;
 	points[5].x = rc.left+2;
 	points[5].y = rc.top+1;
-	rgn2 = CreatePolygonRgn(points, DIM(points), ALTERNATE);
-	CombineRgn(rgn, rgn1, rgn2, RGN_AND);
-	FillRgn(hDC, rgn2, sysColorObjects.hbrushBtnHighlight);
+	rgn = CreatePolygonRgn(points, DIM(points), ALTERNATE);
+	FillRgn(hDC, rgn, sysColorObjects.hbrushBtnHighlight);
 
 	/* draw button shadow: */
 	points[0].x = rc.left+2;
@@ -376,9 +312,8 @@
 	points[4].y = rc.top;
 	points[5].x = rc.right-1;
 	points[5].y = rc.bottom;
-	rgn2 = CreatePolygonRgn(points, DIM(points), ALTERNATE);
-	CombineRgn(rgn, rgn1, rgn2, RGN_AND);
-	FillRgn(hDC, rgn2, sysColorObjects.hbrushBtnShadow);
+	rgn = CreatePolygonRgn(points, DIM(points), ALTERNATE);
+	FillRgn(hDC, rgn, sysColorObjects.hbrushBtnShadow);
 
 	/* do we have the focus? */
 	if (len >= 1 && GetFocus() == hButton) {
@@ -393,8 +328,6 @@
 
 	SelectObject(hDC, (HANDLE)hOldPen);
 	SelectObject(hDC, (HANDLE)hOldBrush);
-	DeleteObject((HANDLE)rgn1);
-	DeleteObject((HANDLE)rgn2);
 	DeleteObject((HANDLE)rgn);
 }
 
@@ -404,18 +337,16 @@
 	HPEN hOldPen;
 	HBRUSH hOldBrush;
 	int len;
-	static char text[50+1];
+	char *text;
 	DWORD dwTextSize;
 	int delta;
 	TEXTMETRIC tm;
+	WND *wndPtr = WIN_FindWndPtr( hButton );
 
 	hOldBrush = (HBRUSH)SelectObject(hDC, sysColorObjects.hbrushBtnFace);
 	hOldPen = (HPEN)SelectObject(hDC, sysColorObjects.hpenWindowFrame);
 	SetBkMode(hDC, TRANSPARENT);
-
-	/* give parent a chance to alter parameters: */
-	SendMessage(GetParent(hButton), WM_CTLCOLOR, (WORD)hDC,
-		    MAKELPARAM(hButton, CTLCOLOR_BTN));
+	SetTextColor( hDC, GetSysColor(COLOR_BTNTEXT) );
 	Rectangle(hDC, rc.left, rc.top, rc.right, rc.bottom);
 
 	/* draw button shadow: */
@@ -424,7 +355,8 @@
 	PatBlt(hDC, rc.left+1, rc.top+1, rc.right-rc.left-2, 1, PATCOPY );
 
 	/* draw button label, if any: */
-	len = GetWindowText(hButton, text, sizeof text);
+	text = USER_HEAP_ADDR( wndPtr->hText );
+	len = strlen(text);
 	if (len >= 1) {
 		rc.top++;	rc.left++;
 		DrawText(hDC, text, len, &rc,
@@ -454,13 +386,11 @@
 static LONG CB_Paint(HWND hWnd)
 {
     PAINTSTRUCT ps;
-    RECT rc, rc3;
+    RECT rc;
     HDC hDC;
-    HPEN hOldPen;
-    HBRUSH hBrush, hGrayBrush;
+    HBRUSH hBrush;
     int textlen, delta;
     char *text;
-    HANDLE hText;
     TEXTMETRIC tm;
     SIZE size;
     WND *wndPtr = WIN_FindWndPtr(hWnd);
@@ -468,44 +398,23 @@
     hDC = BeginPaint(hWnd, &ps);
     GetClientRect(hWnd, &rc);
 
-    hOldPen = (HPEN)SelectObject(hDC, sysColorObjects.hpenWindowText);
-    hGrayBrush = (HBRUSH)GetStockObject(LTGRAY_BRUSH);
-
     hBrush = SendMessage(GetParent(hWnd), WM_CTLCOLOR, (WORD)hDC,
 			 MAKELPARAM(hWnd, CTLCOLOR_BTN));
     FillRect(hDC, &rc, hBrush);
 
-    textlen = GetWindowTextLength(hWnd);
-    hText = USER_HEAP_ALLOC(0, textlen+1);
-    text = USER_HEAP_ADDR(hText);
-    GetWindowText(hWnd, text, textlen+1);
+    text = USER_HEAP_ADDR( wndPtr->hText );
+    textlen = strlen( text );
     GetTextMetrics(hDC, &tm);
-
     delta = (rc.bottom - rc.top - tm.tmHeight) >> 1;
-    Rectangle(hDC, 0, rc.top + delta, tm.tmHeight, tm.tmHeight + delta);
-    if (pressed)
-	Rectangle(hDC, 1, rc.top + delta + 1, tm.tmHeight - 1, 
-		                              tm.tmHeight + delta - 1);
 
-    switch ((WORD)(*(wndPtr->wExtra)))
-    {
-    case 1:
-	MoveTo(hDC, 0, rc.top + delta);
-	LineTo(hDC, tm.tmHeight - 1, tm.tmHeight + delta - 1);
-	MoveTo(hDC, 0, tm.tmHeight + delta - 1);
-	LineTo(hDC, tm.tmHeight - 1, rc.top + delta);
-	break;
+    GRAPH_DrawBitmap( hDC, hbitmapCheckBoxes,
+		      rc.left, rc.top + delta,
+		      ((GetCapture() == hWnd) ?  2*checkBoxWidth : 0) +
+		      (wndPtr->wExtra[0] ? checkBoxWidth : 0),
+		      ((wndPtr->wExtra[0] == 2) ? 2*checkBoxHeight : 0),
+		      checkBoxWidth, checkBoxHeight, SRCCOPY );
 
-    case 2:
-	rc3.left = 1;
-	rc3.top = rc.top + delta + 1;
-	rc3.right = tm.tmHeight - 1;
-	rc3.bottom = tm.tmHeight + delta - 1;
-	FillRect(hDC, &rc3, hGrayBrush);
-	break;
-    }
-
-    rc.left = tm.tmHeight + tm.tmAveCharWidth / 2;
+    rc.left = checkBoxWidth + tm.tmAveCharWidth / 2;
     DrawText(hDC, text, textlen, &rc, DT_SINGLELINE | DT_VCENTER);
 
     /* do we have the focus? */
@@ -519,53 +428,30 @@
 	DrawFocusRect(hDC, &rc);
     }
 
-    SelectObject(hDC, hOldPen);
-    USER_HEAP_FREE(hText);
     EndPaint(hWnd, &ps);
+    return 0;
 }
 
 static LONG CB_LButtonDown(HWND hWnd, WORD wParam, LONG lParam)
 {
     RECT rc;
-    HDC hDC;
-    TEXTMETRIC tm;
-    int delta;
 
-    hDC = GetDC(hWnd);
-    GetTextMetrics(hDC, &tm);
-    ReleaseDC(hWnd, hDC);
     GetClientRect(hWnd, &rc);
-    delta = (rc.bottom - rc.top - tm.tmHeight) >> 1;
-    rc.top += delta;
-    rc.bottom = tm.tmHeight + delta;
-    if (PtInRect(&rc, MAKEPOINT(lParam)))
-    {
-	SetFocus(hWnd);
-	SetCapture(hWnd);
-	pressed = TRUE;
-	InvalidateRect(hWnd, NULL, FALSE);
-	UpdateWindow(hWnd);
-    }
+    SetFocus(hWnd);
+    SetCapture(hWnd);
+    InvalidateRect(hWnd, NULL, FALSE);
+    UpdateWindow(hWnd);
+    return 0;
 }
 
 static LONG CB_LButtonUp(HWND hWnd, WORD wParam, LONG lParam)
 {
     RECT rc;
-    HDC hDC;
-    TEXTMETRIC tm;
-    int delta;
     WND *wndPtr = WIN_FindWndPtr(hWnd);
     LONG style;
 
-    pressed = FALSE;
     ReleaseCapture();
-    hDC = GetDC(hWnd);
-    GetTextMetrics(hDC, &tm);
-    ReleaseDC(hWnd, hDC);
     GetClientRect(hWnd, &rc);
-    delta = (rc.bottom - rc.top - tm.tmHeight) >> 1;
-    rc.top += delta;
-    rc.bottom = tm.tmHeight + delta;
 
     if (PtInRect(&rc, MAKEPOINT(lParam)))
     {
@@ -604,31 +490,20 @@
     }
     InvalidateRect(hWnd, NULL, FALSE);
     UpdateWindow(hWnd);
+    return 0;
 }
 
 static LONG CB_LButtonDblClk(HWND hWnd, WORD wParam, LONG lParam)
 {
-    RECT rc;
-    HDC hDC;
-    TEXTMETRIC tm;
-    int delta;
-
-    hDC = GetDC(hWnd);
-    GetTextMetrics(hDC, &tm);
-    ReleaseDC(hWnd, hDC);
-    GetClientRect(hWnd, &rc);
-    delta = (rc.bottom - rc.top - tm.tmHeight) >> 1;
-    rc.top += delta;
-    rc.bottom = tm.tmHeight + delta;
-    if (PtInRect(&rc, MAKEPOINT(lParam)))
-	NOTIFY_PARENT(hWnd, BN_DOUBLECLICKED);
+    NOTIFY_PARENT(hWnd, BN_DOUBLECLICKED);
+    return 0;
 }
 
 static LONG CB_KillFocus(HWND hWnd)
 {
-    pressed = FALSE;
     InvalidateRect(hWnd, NULL, FALSE);
     UpdateWindow(hWnd);
+    return 0;
 }
 
 static LONG CB_SetCheck(HWND hWnd, WORD wParam)
@@ -637,10 +512,14 @@
 
     if ((WORD)(*(wndPtr->wExtra)) != wParam)
     {
+	RECT rect;
+	GetClientRect( hWnd, &rect );
+	rect.right = rect.left + checkBoxWidth; /* Only invalidate check-box */
 	(WORD)(*(wndPtr->wExtra)) = wParam;
-	InvalidateRect(hWnd, NULL, FALSE);
+	InvalidateRect(hWnd, &rect, FALSE);
 	UpdateWindow(hWnd);
     }
+    return 0;
 }
 
 static LONG CB_GetCheck(HWND hWnd)
@@ -662,11 +541,9 @@
     PAINTSTRUCT ps;
     RECT rc;
     HDC hDC;
-    HPEN hOldPen;
-    HBRUSH hBrush, hOldBrush;
+    HBRUSH hBrush;
     int textlen, delta;
     char *text;
-    HANDLE hText;
     TEXTMETRIC tm;
     SIZE size;
     WND *wndPtr = WIN_FindWndPtr(hWnd);
@@ -674,37 +551,23 @@
     hDC = BeginPaint(hWnd, &ps);
     GetClientRect(hWnd, &rc);
 
-    hOldPen = (HPEN)SelectObject(hDC, sysColorObjects.hpenWindowText);
-
     hBrush = SendMessage(GetParent(hWnd), WM_CTLCOLOR, (WORD)hDC,
 			 MAKELPARAM(hWnd, CTLCOLOR_BTN));
     FillRect(hDC, &rc, hBrush);
 
-    textlen = GetWindowTextLength(hWnd);
-    hText = USER_HEAP_ALLOC(0, textlen+1);
-    text = USER_HEAP_ADDR(hText);
-    GetWindowText(hWnd, text, textlen+1);
     GetTextMetrics(hDC, &tm);
-
     delta = (rc.bottom - rc.top - tm.tmHeight) >> 1;
-    Ellipse(hDC, 0, rc.top + delta, tm.tmHeight, tm.tmHeight + delta);
-    if (pressed)
-	Ellipse(hDC, 1, rc.top + delta + 1, tm.tmHeight - 1, 
-		                              tm.tmHeight + delta - 1);
+    GRAPH_DrawBitmap( hDC, hbitmapCheckBoxes,
+		      rc.left, rc.top + delta,
+		      ((GetCapture() == hWnd) ?  2*checkBoxWidth : 0) +
+		      (wndPtr->wExtra[0] ? checkBoxWidth : 0), checkBoxHeight,
+		      checkBoxWidth, checkBoxHeight, SRCCOPY );
 
-    if ((WORD)(*(wndPtr->wExtra)) == 1)
-    {
-	hBrush = CreateSolidBrush( GetNearestColor(hDC, GetSysColor(COLOR_WINDOWTEXT)));
-	hOldBrush = (HBRUSH)SelectObject(hDC, (HANDLE)hBrush);
-	Ellipse(hDC, 3, rc.top + delta + 3, tm.tmHeight - 3,
-		                            tm.tmHeight + delta -3); 
-	SelectObject(hDC, (HANDLE)hOldBrush);
-	DeleteObject((HANDLE)hBrush);
-    }
-
-    rc.left = tm.tmHeight + tm.tmAveCharWidth / 2;
+    text = USER_HEAP_ADDR( wndPtr->hText );
+    textlen = strlen( text );
+    rc.left = checkBoxWidth + tm.tmAveCharWidth / 2;
     DrawText(hDC, text, textlen, &rc, DT_SINGLELINE | DT_VCENTER);
-
+    
     /* do we have the focus? */
     if (GetFocus() == hWnd)
     {
@@ -716,53 +579,31 @@
 	DrawFocusRect(hDC, &rc);
     }
 
-    SelectObject(hDC, hOldPen );
-    USER_HEAP_FREE(hText);
     EndPaint(hWnd, &ps);
+    return 0;
 }
 
 static LONG RB_LButtonDown(HWND hWnd, WORD wParam, LONG lParam)
 {
     RECT rc;
-    HDC hDC;
-    TEXTMETRIC tm;
-    int delta;
 
-    hDC = GetDC(hWnd);
-    GetTextMetrics(hDC, &tm);
-    ReleaseDC(hWnd, hDC);
     GetClientRect(hWnd, &rc);
-    delta = (rc.bottom - rc.top - tm.tmHeight) >> 1;
-    rc.top += delta;
-    rc.bottom = tm.tmHeight + delta;
-    if (PtInRect(&rc, MAKEPOINT(lParam)))
-    {
-	SetFocus(hWnd);
-	SetCapture(hWnd);
-	pressed = TRUE;
-	InvalidateRect(hWnd, NULL, FALSE);
-	UpdateWindow(hWnd);
-    }
+    if (GetFocus() != hWnd) SetFocus(hWnd);
+    else rc.right = rc.left + checkBoxWidth;
+    SetCapture(hWnd);
+    InvalidateRect(hWnd, &rc, FALSE);
+    UpdateWindow(hWnd);
+    return 0;
 }
 
 static LONG RB_LButtonUp(HWND hWnd, WORD wParam, LONG lParam)
 {
     RECT rc;
-    HDC hDC;
-    TEXTMETRIC tm;
-    int delta;
     WND *wndPtr = WIN_FindWndPtr(hWnd);
     LONG style;
 
-    pressed = FALSE;
     ReleaseCapture();
-    hDC = GetDC(hWnd);
-    GetTextMetrics(hDC, &tm);
-    ReleaseDC(hWnd, hDC);
     GetClientRect(hWnd, &rc);
-    delta = (rc.bottom - rc.top - tm.tmHeight) >> 1;
-    rc.top += delta;
-    rc.bottom = tm.tmHeight + delta;
 
     if (PtInRect(&rc, MAKEPOINT(lParam)))
     {
@@ -771,33 +612,24 @@
 	    (WORD)(*(wndPtr->wExtra)) = 1;
 	NOTIFY_PARENT(hWnd, BN_CLICKED);
     }
-    InvalidateRect(hWnd, NULL, FALSE);
+    rc.right = rc.left + checkBoxWidth;
+    InvalidateRect(hWnd, &rc, FALSE);
     UpdateWindow(hWnd);
+    return 0;
 }
 
+
 static LONG RB_LButtonDblClk(HWND hWnd, WORD wParam, LONG lParam)
 {
-    RECT rc;
-    HDC hDC;
-    TEXTMETRIC tm;
-    int delta;
-
-    hDC = GetDC(hWnd);
-    GetTextMetrics(hDC, &tm);
-    ReleaseDC(hWnd, hDC);
-    GetClientRect(hWnd, &rc);
-    delta = (rc.bottom - rc.top - tm.tmHeight) >> 1;
-    rc.top += delta;
-    rc.bottom = tm.tmHeight + delta;
-    if (PtInRect(&rc, MAKEPOINT(lParam)))
-	NOTIFY_PARENT(hWnd, BN_DOUBLECLICKED);
+    NOTIFY_PARENT(hWnd, BN_DOUBLECLICKED);
+    return 0;
 }
 
 static LONG RB_KillFocus(HWND hWnd)
 {
-    pressed = FALSE;
     InvalidateRect(hWnd, NULL, FALSE);
     UpdateWindow(hWnd);
+    return 0;
 }
 
 static LONG RB_SetCheck(HWND hWnd, WORD wParam)
@@ -806,10 +638,14 @@
 
     if ((WORD)(*(wndPtr->wExtra)) != wParam)
     {
+	RECT rc;
+	GetClientRect( hWnd, &rc );
+	rc.right = rc.left + checkBoxWidth;
 	(WORD)(*(wndPtr->wExtra)) = wParam;
-	InvalidateRect(hWnd, NULL, FALSE);
+	InvalidateRect(hWnd, &rc, FALSE);
 	UpdateWindow(hWnd);
     }
+    return 0;
 }
 
 static LONG RB_GetCheck(HWND hWnd)
@@ -831,39 +667,38 @@
     PAINTSTRUCT ps;
     RECT rc;
     HDC hDC;
-    HPEN hOldPen;
     HBRUSH hBrush;
-    int textlen;
     char *text;
-    HANDLE hText;
     SIZE size;
+    WND *wndPtr = WIN_FindWndPtr( hWnd );
 
     hDC = BeginPaint(hWnd, &ps);
     GetClientRect(hWnd, &rc);
 
-    hOldPen = (HPEN)SelectObject(hDC, sysColorObjects.hpenWindowText);
-
+    SelectObject( hDC, sysColorObjects.hpenWindowFrame );
     hBrush = SendMessage(GetParent(hWnd), WM_CTLCOLOR, (WORD)hDC,
 			 MAKELPARAM(hWnd, CTLCOLOR_BTN));
     FillRect(hDC, &rc, hBrush);
 
-    textlen = GetWindowTextLength(hWnd);
-    hText = USER_HEAP_ALLOC(0, textlen+1);
-    text = USER_HEAP_ADDR(hText);
-    GetWindowText(hWnd, text, textlen+1);
-    GetTextExtentPoint(hDC, text, textlen, &size);
+    text = USER_HEAP_ADDR( wndPtr->hText );
+    GetTextExtentPoint(hDC, text, strlen(text), &size);
 
-    rc.top = 5;
-    Rectangle(hDC, rc.left, rc.top, rc.right, rc.bottom);
+    MoveTo( hDC, 8, 5 );
+    LineTo( hDC, rc.left, 5 );
+    LineTo( hDC, rc.left, rc.bottom-1 );
+    LineTo( hDC, rc.right-1, rc.bottom-1 );
+    LineTo( hDC, rc.right-1, 5 );
+    LineTo( hDC, rc.left + size.cx + 12, 5 );
+
     rc.left = 10;
     rc.top = 0;
     rc.right = rc.left + size.cx + 1;
     rc.bottom = size.cy;
-    DrawText(hDC, text, textlen, &rc, DT_SINGLELINE);
+    SetTextColor( hDC, GetSysColor(COLOR_WINDOWTEXT) );
+    DrawText(hDC, text, -1, &rc, DT_SINGLELINE );
 
-    SelectObject(hDC, hOldPen );
-    USER_HEAP_FREE(hText);
     EndPaint(hWnd, &ps);
+    return 0;
 }
 
 
@@ -892,19 +727,16 @@
 	DrawFocusRect(hDC, &rc);
 
     EndPaint(hWnd, &ps);
+    return 0;
 }
 
 static LONG UB_LButtonDown(HWND hWnd, WORD wParam, LONG lParam)
 {
-    RECT rc;
-
     SetFocus(hWnd);
     SetCapture(hWnd);
-    GetClientRect(hWnd, &rc);
-    if (PtInRect(&rc, MAKEPOINT(lParam)))
-	NOTIFY_PARENT(hWnd, BN_HILITE);
     InvalidateRect(hWnd, NULL, FALSE);
     UpdateWindow(hWnd);
+    return 0;
 }
 
 static LONG UB_LButtonUp(HWND hWnd, WORD wParam, LONG lParam)
@@ -920,12 +752,14 @@
     }
     InvalidateRect(hWnd, NULL, FALSE);
     UpdateWindow(hWnd);
+    return 0;
 }
 
 static LONG UB_KillFocus(HWND hWnd)
 {
     InvalidateRect(hWnd, NULL, FALSE);
     UpdateWindow(hWnd);
+    return 0;
 }
 
 
@@ -955,33 +789,31 @@
     SendMessage(GetParent(hWnd), WM_DRAWITEM, 1, (LPARAM)lpdis); 
     USER_HEAP_FREE(hDis);
     EndPaint(hWnd, &ps);
+    return 0;
 }
 
 static LONG OB_LButtonDown(HWND hWnd, WORD wParam, LONG lParam)
 {
     HDC 	hDC;
-    RECT 	rc;
     HANDLE	hDis;
     LPDRAWITEMSTRUCT lpdis;
     WND *wndPtr = WIN_FindWndPtr(hWnd);
     SetFocus(hWnd);
     SetCapture(hWnd);
     hDC = GetDC(hWnd);
-    GetClientRect(hWnd, &rc);
-    if (PtInRect(&rc, MAKEPOINT(lParam)))
-	NOTIFY_PARENT(hWnd, BN_CLICKED);
-    GetClientRect(hWnd, &rc);
+    NOTIFY_PARENT(hWnd, BN_CLICKED);
     hDis = USER_HEAP_ALLOC(GMEM_MOVEABLE, sizeof(DRAWITEMSTRUCT));
     lpdis = (LPDRAWITEMSTRUCT)USER_HEAP_ADDR(hDis);
     lpdis->hDC = hDC;
     lpdis->itemID = 0;
-    CopyRect(&lpdis->rcItem, &rc);
+    GetClientRect( hWnd, &lpdis->rcItem );
     lpdis->CtlID = wndPtr->wIDmenu;
     lpdis->CtlType = ODT_BUTTON;
     lpdis->itemAction = ODA_SELECT;
     SendMessage(GetParent(hWnd), WM_DRAWITEM, 1, (LPARAM)lpdis); 
     USER_HEAP_FREE(hDis);
     ReleaseDC(hWnd, hDC);
+    return 0;
 }
 
 static LONG OB_LButtonUp(HWND hWnd, WORD wParam, LONG lParam)
@@ -996,7 +828,6 @@
     GetClientRect(hWnd, &rc);
     if (PtInRect(&rc, MAKEPOINT(lParam)))
 	NOTIFY_PARENT(hWnd, BN_CLICKED);
-    GetClientRect(hWnd, &rc);
     hDis = USER_HEAP_ALLOC(GMEM_MOVEABLE, sizeof(DRAWITEMSTRUCT));
     lpdis = (LPDRAWITEMSTRUCT)USER_HEAP_ADDR(hDis);
     lpdis->hDC = hDC;
@@ -1008,11 +839,13 @@
     SendMessage(GetParent(hWnd), WM_DRAWITEM, 1, (LPARAM)lpdis); 
     USER_HEAP_FREE(hDis);
     ReleaseDC(hWnd, hDC);
+    return 0;
 }
 
 static LONG OB_KillFocus(HWND hWnd)
 {
     InvalidateRect(hWnd, NULL, FALSE);
     UpdateWindow(hWnd);
+    return 0;
 }
 
diff --git a/controls/desktop.c b/controls/desktop.c
index e1f5d7f..4045177 100644
--- a/controls/desktop.c
+++ b/controls/desktop.c
@@ -8,11 +8,15 @@
 
 #include <fcntl.h>
 #include <stdio.h>
+#include <stdlib.h>
 #include <string.h>
 #include "win.h"
 #include "desktop.h"
 #include "prototypes.h"
 
+extern BOOL GRAPH_DrawBitmap( HDC hdc, HBITMAP hbitmap, int xdest, int ydest,
+			      int xsrc, int ysrc, int width, int height,
+			      int rop );                     /* graphics.c */
 
 /***********************************************************************
  *           DESKTOP_LoadBitmap
@@ -85,17 +89,15 @@
     if (infoPtr->hbitmapWallPaper)
     {
 	int x, y;
-	HDC hdcmem;
 
-	hdcmem = CreateCompatibleDC( hdc );
-	SelectObject( hdcmem, infoPtr->hbitmapWallPaper );
 	if (infoPtr->fTileWallPaper)
 	{
 	    for (y = 0; y < rect.bottom; y += infoPtr->bitmapSize.cy)
 		for (x = 0; x < rect.right; x += infoPtr->bitmapSize.cx)
-		    BitBlt( hdc, x, y,
-			    infoPtr->bitmapSize.cx, infoPtr->bitmapSize.cy,
-			    hdcmem, 0, 0, SRCCOPY );
+		    GRAPH_DrawBitmap( hdc, infoPtr->hbitmapWallPaper,
+				      x, y, 0, 0, 
+				      infoPtr->bitmapSize.cx,
+				      infoPtr->bitmapSize.cy, SRCCOPY );
 	}
 	else
 	{
@@ -103,10 +105,10 @@
 	    y = (rect.top + rect.bottom - infoPtr->bitmapSize.cy) / 2;
 	    if (x < 0) x = 0;
 	    if (y < 0) y = 0;
-	    BitBlt( hdc, x, y, infoPtr->bitmapSize.cx, infoPtr->bitmapSize.cy,
-		    hdcmem, 0, 0, SRCCOPY );
+	    GRAPH_DrawBitmap( hdc, infoPtr->hbitmapWallPaper, x, y, 0, 0, 
+			      infoPtr->bitmapSize.cx, infoPtr->bitmapSize.cy,
+			      SRCCOPY );
 	}
-	DeleteDC( hdcmem );
     }
 
     return 1;
diff --git a/controls/menu.c b/controls/menu.c
index 0f791c7..16e515d 100644
--- a/controls/menu.c
+++ b/controls/menu.c
@@ -38,6 +38,9 @@
   /* Space between 2 menu bar items */
 #define MENU_BAR_ITEMS_SPACE  16
 
+  /* Minimum width of a tab character */
+#define MENU_TAB_SPACE        8
+
   /* Height of a separator item */
 #define SEPARATOR_HEIGHT      5
 
@@ -52,6 +55,9 @@
 
 extern void NC_DrawSysButton(HWND hwnd, HDC hdc, BOOL down);  /* nonclient.c */
 extern void CURSOR_SetWinCursor( HWND hwnd, HCURSOR hcursor );   /* cursor.c */
+extern BOOL GRAPH_DrawBitmap( HDC hdc, HBITMAP hbitmap, int xdest, int ydest,
+			      int xsrc, int ysrc, int width, int height,
+			      int rop );                     /* graphics.c */
 
 extern HINSTANCE hSysRes;
 
@@ -59,9 +65,6 @@
 static HBITMAP hStdCheck = 0;
 static HBITMAP hStdMnArrow = 0;
 
-WORD GetSelectionKey(LPSTR str);
-LPSTR GetShortCutString(LPSTR str);
-int GetShortCutPos(LPSTR str);
 HMENU CopySysMenu();
 WORD * ParseMenuResource(WORD *first_item, int level, HMENU hMenu);
 
@@ -225,9 +228,14 @@
 
     menu = (POPUPMENU *) USER_HEAP_ADDR( hmenu );
     lpitem = (MENUITEM *) USER_HEAP_ADDR( menu->hItems );
+    key = toupper(key);
     for (i = 0; i < menu->nItems; i++, lpitem++)
     {
-	if (toupper(key) == lpitem->sel_key) return i;
+	if (IS_STRING_ITEM(lpitem->item_flags))
+	{
+	    char *p = strchr( lpitem->item_text, '&' );
+	    if (p && (p[1] != '&') && (toupper(p[1]) == key)) return i;
+	}
     }
     menuchar = SendMessage( hwndOwner, WM_MENUCHAR, key,
 			    MAKELONG( menu->wFlags, hmenu ) );
@@ -242,11 +250,14 @@
  *
  * Calculate the size of the menu item and store it in lpitem->rect.
  */
-static void MENU_CalcItemSize( HDC hdc, LPMENUITEM lpitem,
+static void MENU_CalcItemSize( HDC hdc, LPMENUITEM lpitem, HWND hwndOwner,
 			       int orgX, int orgY, BOOL menuBar )
 {
     DWORD dwSize;
+    char *p;
+
     SetRect( &lpitem->rect, orgX, orgY, orgX, orgY );
+    lpitem->xTab = 0;
 
     if (lpitem->item_flags & MF_SEPARATOR)
     {
@@ -264,8 +275,7 @@
     if (lpitem->item_flags & MF_BITMAP)
     {
 	BITMAP bm;
-	HBITMAP hbitmap = (HBITMAP)LOWORD((LONG)lpitem->item_text);
-	GetObject(hbitmap, sizeof(BITMAP), (LPSTR)&bm);
+	GetObject( (HBITMAP)lpitem->hText, sizeof(BITMAP), (LPSTR)&bm );
 	lpitem->rect.right  += bm.bmWidth;
 	lpitem->rect.bottom += bm.bmHeight;
 	return;
@@ -273,10 +283,26 @@
     
       /* If we get here, then it is a text item */
 
-    if (menuBar) lpitem->rect.right += MENU_BAR_ITEMS_SPACE;
     dwSize = GetTextExtent( hdc, lpitem->item_text, strlen(lpitem->item_text));
     lpitem->rect.right  += LOWORD(dwSize);
     lpitem->rect.bottom += max( HIWORD(dwSize), SYSMETRICS_CYMENU );
+
+    if (menuBar) lpitem->rect.right += MENU_BAR_ITEMS_SPACE;
+    else if ((p = strchr( lpitem->item_text, '\t' )) != NULL)
+    {
+	  /* Item contains a tab (only meaningful in popup menus) */
+	lpitem->xTab = check_bitmap_width + MENU_TAB_SPACE + 
+	                 LOWORD( GetTextExtent( hdc, lpitem->item_text,
+					       (int)(p - lpitem->item_text) ));
+	lpitem->rect.right += MENU_TAB_SPACE;
+    }
+    else
+    {
+	if (strchr( lpitem->item_text, '\b' ))
+	    lpitem->rect.right += MENU_TAB_SPACE;
+	lpitem->xTab = lpitem->rect.right - check_bitmap_width 
+	                - arrow_bitmap_width;
+    }
 }
 
 
@@ -285,11 +311,12 @@
  *
  * Calculate the size of a popup menu.
  */
-static void MENU_PopupMenuCalcSize( LPPOPUPMENU lppop )
+static void MENU_PopupMenuCalcSize( LPPOPUPMENU lppop, HWND hwndOwner )
 {
     LPMENUITEM  items, lpitem;
     HDC hdc;
-    int start, i, orgX, orgY, maxX;
+    int start, i;
+    int orgX, orgY, maxX, maxTab, maxTabWidth;
 
     lppop->Width = lppop->Height = 0;
     if (lppop->nItems == 0) return;
@@ -301,19 +328,30 @@
 	lpitem = &items[start];
 	orgX = maxX;
 	orgY = 0;
+	maxTab = maxTabWidth = 0;
 
 	  /* Parse items until column break or end of menu */
 	for (i = start; i < lppop->nItems; i++, lpitem++)
 	{
 	    if ((i != start) &&
 		(lpitem->item_flags & (MF_MENUBREAK | MF_MENUBARBREAK))) break;
-	    MENU_CalcItemSize( hdc, lpitem, orgX, orgY, FALSE );
+	    MENU_CalcItemSize( hdc, lpitem, hwndOwner, orgX, orgY, FALSE );
 	    maxX = max( maxX, lpitem->rect.right );
 	    orgY = lpitem->rect.bottom;
+	    if (lpitem->xTab)
+	    {
+		maxTab = max( maxTab, lpitem->xTab );
+		maxTabWidth = max(maxTabWidth,lpitem->rect.right-lpitem->xTab);
+	    }
 	}
 
 	  /* Finish the column (set all items to the largest width found) */
-	while (start < i) items[start++].rect.right = maxX;
+	maxX = max( maxX, maxTab + maxTabWidth );
+	for (lpitem = &items[start]; start < i; start++, lpitem++)
+	{
+	    lpitem->rect.right = maxX;
+	    if (lpitem->xTab) lpitem->xTab = maxTab;
+	}
 	lppop->Height = max( lppop->Height, orgY );
     }
 
@@ -327,10 +365,11 @@
  *
  * Calculate the size of the menu bar.
  */
-static void MENU_MenuBarCalcSize( HDC hdc, LPRECT lprect, LPPOPUPMENU lppop )
+static void MENU_MenuBarCalcSize( HDC hdc, LPRECT lprect, LPPOPUPMENU lppop,
+				  HWND hwndOwner )
 {
     LPMENUITEM lpitem, items;
-    int start, i, orgX, orgY, maxY;
+    int start, i, orgX, orgY, maxY, helpPos;
 
     if ((lprect == NULL) || (lppop == NULL)) return;
     if (lppop->nItems == 0) return;
@@ -343,6 +382,7 @@
     lppop->Height = 0;
     maxY = lprect->top;
     start = 0;
+    helpPos = -1;
     while (start < lppop->nItems)
     {
 	lpitem = &items[start];
@@ -352,9 +392,10 @@
 	  /* Parse items until line break or end of menu */
 	for (i = start; i < lppop->nItems; i++, lpitem++)
 	{
+	    if ((helpPos == -1) && (lpitem->item_flags & MF_HELP)) helpPos = i;
 	    if ((i != start) &&
 		(lpitem->item_flags & (MF_MENUBREAK | MF_MENUBARBREAK))) break;
-	    MENU_CalcItemSize( hdc, lpitem, orgX, orgY, TRUE );
+	    MENU_CalcItemSize( hdc, lpitem, hwndOwner, orgX, orgY, TRUE );
 	    if (lpitem->rect.right > lprect->right)
 	    {
 		if (i != start) break;
@@ -370,6 +411,23 @@
 
     lprect->bottom = maxY;
     lppop->Height = lprect->bottom - lprect->top;
+
+      /* Flush right all items between the MF_HELP and the last item */
+      /* (if several lines, only move the last line) */
+    if (helpPos != -1)
+    {
+	lpitem = &items[lppop->nItems-1];
+	orgY = lpitem->rect.top;
+	orgX = lprect->right;
+	for (i = lppop->nItems - 1; i >= helpPos; i--, lpitem--)
+	{
+	    if (lpitem->rect.top != orgY) break;    /* Other line */
+	    if (lpitem->rect.right >= orgX) break;  /* Too far right already */
+	    lpitem->rect.left += orgX - lpitem->rect.right;
+	    lpitem->rect.right = orgX;
+	    orgX = lpitem->rect.left;
+	}
+    }
 }
 
 
@@ -406,6 +464,7 @@
 	SelectObject( hdc, sysColorObjects.hpenWindowFrame );
 	MoveTo( hdc, rect.left, rect.top + SEPARATOR_HEIGHT/2 );
 	LineTo( hdc, rect.right, rect.top + SEPARATOR_HEIGHT/2 );
+	return;
     }
 
       /* Setup colors */
@@ -433,40 +492,29 @@
 
 	if (lpitem->item_flags & MF_CHECKED)
 	{
-	    HDC hMemDC = CreateCompatibleDC( hdc );
-	    if (lpitem->hCheckBit == 0)	SelectObject(hMemDC, hStdCheck);
-	    else SelectObject(hMemDC, lpitem->hCheckBit);
-	    BitBlt( hdc, rect.left,
-		    (rect.top + rect.bottom - check_bitmap_height) / 2,
-		    check_bitmap_width, check_bitmap_height,
-		    hMemDC, 0, 0, SRCCOPY );
-	    DeleteDC( hMemDC );
+	    GRAPH_DrawBitmap(hdc, lpitem->hCheckBit ? lpitem->hCheckBit :
+			     hStdCheck, rect.left,
+			     (rect.top+rect.bottom-check_bitmap_height) / 2,
+			     0, 0, check_bitmap_width, check_bitmap_height,
+			     SRCCOPY);
 	}
-	else  /* Not checked */
+	else if (lpitem->hUnCheckBit != 0)  /* Not checked */
 	{
-	    if (lpitem->hUnCheckBit != 0)
-	    {
-		HDC hMemDC = CreateCompatibleDC( hdc );
-		SelectObject(hMemDC, lpitem->hUnCheckBit);
-		BitBlt( hdc, rect.left,
-		       (rect.top + rect.bottom - check_bitmap_height) / 2,
-		       check_bitmap_width, check_bitmap_height,
-		       hMemDC, 0, 0, SRCCOPY );
-		DeleteDC( hMemDC );
-	    }
+	    GRAPH_DrawBitmap(hdc, lpitem->hUnCheckBit, rect.left,
+			     (rect.top+rect.bottom-check_bitmap_height) / 2,
+			     0, 0, check_bitmap_width, check_bitmap_height,
+			     SRCCOPY);
 	}
 
 	  /* Draw the popup-menu arrow */
 
 	if (lpitem->item_flags & MF_POPUP)
 	{
-	    HDC hMemDC = CreateCompatibleDC( hdc );
-	    SelectObject(hMemDC, hStdMnArrow);
-	    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 );
-	    DeleteDC(hMemDC);
+	    GRAPH_DrawBitmap( hdc, hStdMnArrow,
+			      rect.right-arrow_bitmap_width-1,
+			      (rect.top+rect.bottom-arrow_bitmap_height) / 2,
+			      0, 0, arrow_bitmap_width, arrow_bitmap_height,
+			      SRCCOPY );
 	}
 
 	rect.left += check_bitmap_width;
@@ -477,33 +525,43 @@
 
     if (lpitem->item_flags & MF_BITMAP)
     {
-	HBITMAP hbitmap = (HBITMAP)LOWORD((LONG)lpitem->item_text);
-	HDC hMemDC = CreateCompatibleDC( hdc );
-	SelectObject( hMemDC, hbitmap );
-	BitBlt( hdc, rect.left, rect.top,
-	        rect.right-rect.left, rect.bottom-rect.top,
-	        hMemDC, 0, 0, SRCCOPY );
-	DeleteDC( hMemDC );
+	GRAPH_DrawBitmap( hdc, (HBITMAP)lpitem->hText, rect.left, rect.top,
+			  0, 0, rect.right-rect.left, rect.bottom-rect.top,
+			  SRCCOPY );
 	return;
     }
     /* No bitmap - process text if present */
     else if ((lpitem->item_text) != ((char *) NULL)) 
     {
-	int x = GetShortCutPos(lpitem->item_text);
+	register int i;
+
 	if (menuBar)
 	{
 	    rect.left += MENU_BAR_ITEMS_SPACE / 2;
 	    rect.right -= MENU_BAR_ITEMS_SPACE / 2;
+	    i = strlen( lpitem->item_text );
 	}
-	if (x != -1)
+	else
 	{
-	    DrawText( hdc, lpitem->item_text, x, &rect,
-		      DT_LEFT | DT_VCENTER | DT_SINGLELINE );
-	    DrawText( hdc, lpitem->item_text + x, -1, &rect,
-		      DT_RIGHT | DT_VCENTER | DT_SINGLELINE );
+	    for (i = 0; lpitem->item_text[i]; i++)
+		if ((lpitem->item_text[i] == '\t') || 
+		    (lpitem->item_text[i] == '\b')) break;
 	}
-	else DrawText( hdc, lpitem->item_text, -1, &rect,
-		       DT_LEFT | DT_VCENTER | DT_SINGLELINE );
+	
+	DrawText( hdc, lpitem->item_text, i, &rect,
+		 DT_LEFT | DT_VCENTER | DT_SINGLELINE );
+
+	if (lpitem->item_text[i])  /* There's a tab or flush-right char */
+	{
+	    if (lpitem->item_text[i] == '\t')
+	    {
+		rect.left = lpitem->xTab;
+		DrawText( hdc, lpitem->item_text + i + 1, -1, &rect,
+			  DT_LEFT | DT_VCENTER | DT_SINGLELINE );
+	    }
+	    else DrawText( hdc, lpitem->item_text + i + 1, -1, &rect,
+			   DT_RIGHT | DT_VCENTER | DT_SINGLELINE );
+	}
     }
 }
 
@@ -535,18 +593,20 @@
  *
  * Paint a menu bar. Returns the height of the menu bar.
  */
-WORD MENU_DrawMenuBar(HDC hDC, LPRECT lprect, HMENU hmenu, BOOL suppress_draw)
+WORD MENU_DrawMenuBar(HDC hDC, LPRECT lprect, HWND hwnd, BOOL suppress_draw)
 {
     LPPOPUPMENU lppop;
     LPMENUITEM lpitem;
     int i;
-
-    lppop = (LPPOPUPMENU) USER_HEAP_ADDR( hmenu );
+    WND *wndPtr = WIN_FindWndPtr( hwnd );
+    
+    lppop = (LPPOPUPMENU) USER_HEAP_ADDR( wndPtr->wIDmenu );
     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 (lppop->Height == 0) MENU_MenuBarCalcSize(hDC, lprect, lppop, hwnd);
+    lprect->bottom = lprect->top + lppop->Height;
     if (suppress_draw) return lppop->Height;
     
     FillRect(hDC, lprect, sysColorObjects.hbrushMenu );
@@ -582,7 +642,7 @@
     }
     SendMessage( hwndOwner, WM_INITMENUPOPUP, hmenu,
 		 MAKELONG( id, (menu->wFlags & MF_POPUP) ? 1 : 0 ));
-    MENU_PopupMenuCalcSize( menu );
+    MENU_PopupMenuCalcSize( menu, hwndOwner );
     if (!menu->hWnd)
     {
 	WND *wndPtr = WIN_FindWndPtr( hwndOwner );
@@ -1302,8 +1362,10 @@
 void MENU_TrackMouseMenuBar( HWND hwnd, POINT pt )
 {
     WND *wndPtr = WIN_FindWndPtr( hwnd );
+    SendMessage( hwnd, WM_ENTERMENULOOP, 0, 0 );
     MENU_TrackMenu( (HMENU)wndPtr->wIDmenu, TPM_LEFTALIGN | TPM_LEFTBUTTON,
 		    pt.x, pt.y, hwnd, NULL );
+    SendMessage( hwnd, WM_EXITMENULOOP, 0, 0 );
 }
 
 
@@ -1315,11 +1377,13 @@
 void MENU_TrackKbdMenuBar( HWND hwnd, WORD wParam )
 {
     WND *wndPtr = WIN_FindWndPtr( hwnd );
+    SendMessage( hwnd, WM_ENTERMENULOOP, 0, 0 );
       /* 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 );
+    SendMessage( hwnd, WM_EXITMENULOOP, 0, 0 );
 }
 
 
@@ -1343,9 +1407,6 @@
     {
     case WM_CREATE:
 	{
-#ifdef DEBUG_MENU
-	    printf("PopupMenu WM_CREATE lParam=%08X !\n", lParam);
-#endif
 	    CREATESTRUCT *createStruct = (CREATESTRUCT *)lParam;
 	    HMENU hmenu = (HMENU) ((int)createStruct->lpCreateParams & 0xffff);
 	    SetWindowWord( hwnd, 0, hmenu );
@@ -1388,76 +1449,12 @@
     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 );
+    MENU_MenuBarCalcSize( hdc, &rectBar, lppop, hwnd );
     ReleaseDC( hwnd, hdc );
     return lppop->Height;
 }
 
 
-
-
-
-WORD GetSelectionKey(LPSTR str)
-{
-	int		i;
-	WORD	sel_key;
-	for (i = 0; i < strlen(str); i++) {
-		if (str[i] == '&' && str[i + 1] != '&') {
-			sel_key = str[i + 1];
-			if (sel_key >= 'a' && sel_key <= 'z') sel_key -= 'a' - 'A';
-#ifdef DEBUG_MENU
-			printf("GetSelectionKey // %04X\n", sel_key);
-#endif
-			return sel_key;
-			}
-		}
-#ifdef DEBUG_MENU
-	printf("GetSelectionKey NULL \n");
-#endif
-	return 0;
-}
-
-
-
-LPSTR GetShortCutString(LPSTR str)
-{
-	int		i;
-	LPSTR	str2;
-	for (i = 0; i < strlen(str); i++) {
-		if (str[i] == '\t' && str[i + 1] != '\t') {
-			str2 = &str[i + 1];
-#ifdef DEBUG_MENUSHORTCUT
-			printf("GetShortCutString // '%s' \n", str2);
-#endif
-			return str2;
-			}
-		}
-#ifdef DEBUG_MENUSHORTCUT
-	printf("GetShortCutString NULL \n");
-#endif
-	return NULL;
-}
-
-
-
-int GetShortCutPos(LPSTR str)
-{
-	int		i;
-	for (i = 0; i < strlen(str); i++) {
-		if (str[i] == '\t' && str[i + 1] != '\t') {
-#ifdef DEBUG_MENUSHORTCUT
-			printf("GetShortCutPos = %d \n", i);
-#endif
-			return i;
-			}
-		}
-#ifdef DEBUG_MENUSHORTCUT
-	printf("GetShortCutString NULL \n");
-#endif
-	return -1;
-}
-
-
 /**********************************************************************
  *			ChangeMenu		[USER.153]
  */
@@ -1688,12 +1685,22 @@
 
     if (IS_STRING_ITEM(wFlags))
     {
+	  /* Item beginning with a backspace is a help item */
+	if (lpNewItem[0] == '\b')
+	{
+	    lpitem->item_flags |= MF_HELP;
+	    lpNewItem++;
+	}
 	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 if (wFlags & MF_BITMAP) lpitem->hText = LOWORD((DWORD)lpNewItem);
     else lpitem->item_text = lpNewItem;
+
+    if (wFlags & MF_POPUP)  /* Set the MF_POPUP flag on the popup-menu */
+	((POPUPMENU *)USER_HEAP_ADDR(wItemID))->wFlags |= MF_POPUP;
+
     SetRectEmpty( &lpitem->rect );
     lpitem->hCheckBit   = hStdCheck;
     lpitem->hUnCheckBit = 0;
@@ -1786,8 +1793,8 @@
 	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 if (wFlags & MF_BITMAP) lpitem->hText = LOWORD((DWORD)lpNewItem);
     else lpitem->item_text = lpNewItem;
     SetRectEmpty( &lpitem->rect );
     return TRUE;
diff --git a/controls/static.c b/controls/static.c
index 409fd03..5d71bc9 100644
--- a/controls/static.c
+++ b/controls/static.c
@@ -12,7 +12,7 @@
 #include "win.h"
 #include "user.h"
 
-LONG StaticWndProc(HWND hWnd, WORD uMsg, WORD wParam, LONG lParam);
+extern void DEFWND_SetText( HWND hwnd, LPSTR text );  /* windows/defwnd.c */
 
 static LONG PaintTextfn(HWND hwnd);
 static LONG PaintRectfn(HWND hwnd);
@@ -67,6 +67,27 @@
 	    InvalidateRect(hWnd, NULL, FALSE);
 	    break;
 
+	case WM_NCCREATE:
+	    if (style == SS_ICON)
+	    {
+		  /* Note: we use wndPtr->hText to store the icon handle */
+		CREATESTRUCT * createStruct = (CREATESTRUCT *)lParam;
+		if (createStruct->lpszName)
+		    wndPtr->hText = LoadIcon( createStruct->hInstance,
+					      createStruct->lpszName );
+		return 1;
+	    }
+	    else return DefWindowProc(hWnd, uMsg, wParam, lParam);
+
+	case WM_NCDESTROY:
+	    if (style == SS_ICON)
+	    {
+		if (wndPtr->hText) DestroyIcon( wndPtr->hText );
+		wndPtr->hText = 0;
+		return 0;
+	    }
+	    else return DefWindowProc(hWnd, uMsg, wParam, lParam);
+
 	case WM_CREATE:
 	    if (style < 0L || style >= (LONG)DIM(staticfn)) {
 		lResult = -1L;
@@ -100,27 +121,26 @@
 	    break;
 
 	case WM_SETTEXT:
-	    if (wndPtr->hText)
-		USER_HEAP_FREE(wndPtr->hText);
-
-	    wndPtr->hText = USER_HEAP_ALLOC(GMEM_MOVEABLE, 
-					    strlen((LPSTR)lParam) + 1);
-	    textPtr = (LPSTR)USER_HEAP_ADDR(wndPtr->hText);
-	    strcpy(textPtr, (LPSTR)lParam);
-	    InvalidateRect(hWnd, NULL, TRUE);
+	    if (style == SS_ICON) break;
+	    DEFWND_SetText( hWnd, (LPSTR)lParam );
+	    InvalidateRect( hWnd, NULL, FALSE );
+	    UpdateWindow( hWnd );
 	    break;
 
-	case WM_KEYDOWN:
-	case WM_KEYUP:
-	case WM_CHAR:
-	case WM_LBUTTONDOWN:
-	case WM_LBUTTONUP:
-	case WM_MBUTTONDOWN:
-	case WM_MBUTTONUP:
-	case WM_RBUTTONDOWN:
-	case WM_RBUTTONUP:
-	case WM_MOUSEMOVE:
-	    return(SendMessage(wndPtr->hwndParent, uMsg, wParam, lParam));
+	case WM_NCHITTEST:
+	    return HTTRANSPARENT;
+
+	case STM_GETICON:
+	    if (style != SS_ICON) return 0;
+	    return (HICON)wndPtr->hText;
+
+	case STM_SETICON:
+	    if (style != SS_ICON) return 0;
+	    if (wndPtr->hText) DestroyIcon( wndPtr->hText );
+	    wndPtr->hText = wParam;
+	    InvalidateRect( hWnd, NULL, TRUE );
+	    UpdateWindow( hWnd );
+	    return 0;
 
 	default:
 		lResult = DefWindowProc(hWnd, uMsg, wParam, lParam);
@@ -280,30 +300,11 @@
     PAINTSTRUCT ps;
     RECT 	rc;
     HDC 	hdc;
-    LPSTR	textPtr;
-    HICON	hIcon;
 
     wndPtr = WIN_FindWndPtr(hwnd);
     hdc = BeginPaint(hwnd, &ps);
     GetClientRect(hwnd, &rc);
     FillRect(hdc, &rc, GetStockObject(WHITE_BRUSH));
-    textPtr = (LPSTR)USER_HEAP_ADDR(wndPtr->hText);
-    printf("SS_ICON : textPtr='%8x' / left=%d top=%d right=%d bottom=%d \n", 
-    		textPtr, rc.left, rc.top, rc.right, rc.bottom);
-/*
-    SetWindowPos(hwnd, (HWND)NULL, 0, 0, 32, 32,
-		SWP_NOZORDER | SWP_NOMOVE);
-    GetClientRect(hwnd, &rc);
-    printf("SS_ICON : textPtr='%s' / left=%d top=%d right=%d bottom=%d \n", 
-    		textPtr, rc.left, rc.top, rc.right, rc.bottom);
-*/
-    hIcon = LoadIcon(wndPtr->hInstance, textPtr);
-    DrawIcon(hdc, rc.left, rc.top, hIcon);
+    if (wndPtr->hText) DrawIcon(hdc, rc.left, rc.top, wndPtr->hText );
     EndPaint(hwnd, &ps);
 }
-
-
-
-
-
-
diff --git a/controls/widgets.c b/controls/widgets.c
index c6866c6..104b135 100644
--- a/controls/widgets.c
+++ b/controls/widgets.c
@@ -40,7 +40,7 @@
       0, 0, 0, 0, NULL, POPUPMENU_CLASS_NAME },
     { CS_GLOBALCLASS, (LONG(*)())DesktopWndProc, 0, sizeof(DESKTOPINFO),
       0, 0, 0, 0, NULL, DESKTOP_CLASS_NAME },
-    { CS_GLOBALCLASS, (LONG(*)())DefDlgProc, 0, DLGWINDOWEXTRA,
+    { CS_GLOBALCLASS | CS_SAVEBITS, (LONG(*)())DefDlgProc, 0, DLGWINDOWEXTRA,
       0, 0, 0, 0, NULL, DIALOG_CLASS_NAME },
     { CS_GLOBALCLASS, (LONG(*)())MDIClientWndProc, 0, sizeof(MDICLIENTINFO),
       0, 0, 0, STOCK_LTGRAY_BRUSH, NULL, "MDICLIENT" }
@@ -58,9 +58,12 @@
 BOOL WIDGETS_Init(void)
 {
     int i;
-    for (i = 0; i < NB_BUILTIN_CLASSES; i++)
+    WNDCLASS *class = WIDGETS_BuiltinClasses;
+
+    for (i = 0; i < NB_BUILTIN_CLASSES; i++, class++)
     {
-	if (!RegisterClass(&WIDGETS_BuiltinClasses[i])) return FALSE;
+	class->hCursor = LoadCursor( 0, IDC_ARROW );
+	if (!RegisterClass( class )) return FALSE;
     }
     return TRUE;
 }
diff --git a/if1632/Imakefile b/if1632/Imakefile
index cc922a0..4f25af0 100644
--- a/if1632/Imakefile
+++ b/if1632/Imakefile
@@ -72,5 +72,5 @@
 install::
 
 clean::
-	$(RM) dll* dtb* pop.h
+	$(RM) dll* dtb* pop.h call.s
 	touch pop.h
diff --git a/if1632/gdi.spec b/if1632/gdi.spec
index b39fef7..a4665f8 100644
--- a/if1632/gdi.spec
+++ b/if1632/gdi.spec
@@ -54,7 +54,7 @@
 39  pascal RestoreDC(word s_word) RestoreDC(1 2)
 40  pascal FillRgn(word word word) FillRgn(1 2 3)
 #41  pascal FrameRgn
-#42  pascal InvertRgn
+42  pascal InvertRgn(word word) InvertRgn(1 2)
 43  pascal PaintRgn(word word) PaintRgn(1 2)
 44  pascal SelectClipRgn(word word) SelectClipRgn(1 2)
 45  pascal SelectObject(word word) SelectObject(1 2)
diff --git a/if1632/user.spec b/if1632/user.spec
index 371b3d7..6798d12 100644
--- a/if1632/user.spec
+++ b/if1632/user.spec
@@ -241,7 +241,7 @@
 #231 GETSYSTEMDEBUGSTATE
 232 pascal SetWindowPos(word word word word word word word) 
            SetWindowPos(1 2 3 4 5 6 7)
-#233 SETPARENT
+233 pascal SetParent(word word) SetParent(1 2)
 234 pascal UnhookWindowsHook(s_word ptr) UnhookWindowsHook(1 2)
 235 pascal DefHookProc(s_word word long ptr) DefHookProc(1 2 3 4)
 236 pascal GetCapture() GetCapture()
diff --git a/include/bitmaps/check_boxes b/include/bitmaps/check_boxes
new file mode 100644
index 0000000..44c0363
--- /dev/null
+++ b/include/bitmaps/check_boxes
@@ -0,0 +1,26 @@
+#define check_boxes_width 56
+#define check_boxes_height 39
+static char check_boxes_bits[] = {
+   0xff, 0xdf, 0xff, 0xf7, 0xff, 0xfd, 0x7f, 0x01, 0xd0, 0x00, 0xf6, 0xff,
+   0xfd, 0x7f, 0x01, 0x50, 0x01, 0x35, 0x80, 0x1d, 0x70, 0x01, 0x50, 0x82,
+   0x34, 0x80, 0x2d, 0x68, 0x01, 0x50, 0x44, 0x34, 0x80, 0x4d, 0x64, 0x01,
+   0x50, 0x28, 0x34, 0x80, 0x8d, 0x62, 0x01, 0x50, 0x10, 0x34, 0x80, 0x0d,
+   0x61, 0x01, 0x50, 0x28, 0x34, 0x80, 0x8d, 0x62, 0x01, 0x50, 0x44, 0x34,
+   0x80, 0x4d, 0x64, 0x01, 0x50, 0x82, 0x34, 0x80, 0x2d, 0x68, 0x01, 0x50,
+   0x01, 0x35, 0x80, 0x1d, 0x70, 0x01, 0xd0, 0x00, 0xf6, 0xff, 0xfd, 0x7f,
+   0xff, 0xdf, 0xff, 0xf7, 0xff, 0xfd, 0x7f, 0xe0, 0x00, 0x38, 0x00, 0x0e,
+   0x80, 0x03, 0x18, 0x03, 0xc6, 0x80, 0x3f, 0xe0, 0x0f, 0x04, 0x04, 0x01,
+   0xc1, 0x71, 0x70, 0x1c, 0x02, 0x88, 0x38, 0xe2, 0xe0, 0xb8, 0x3b, 0x02,
+   0x88, 0x7c, 0x62, 0xc0, 0xd8, 0x37, 0x01, 0x50, 0xfe, 0x34, 0x80, 0xed,
+   0x6f, 0x01, 0x50, 0xfe, 0x34, 0x80, 0xed, 0x6f, 0x01, 0x50, 0xfe, 0x34,
+   0x80, 0xed, 0x6f, 0x02, 0x88, 0x7c, 0x62, 0xc0, 0xd8, 0x37, 0x02, 0x88,
+   0x38, 0xe2, 0xe0, 0xb8, 0x3b, 0x04, 0x04, 0x01, 0xc1, 0x71, 0x70, 0x1c,
+   0x18, 0x03, 0xc6, 0x80, 0x3f, 0xe0, 0x0f, 0xe0, 0x00, 0x38, 0x00, 0x0e,
+   0x80, 0x03, 0x00, 0xc0, 0xff, 0x07, 0x00, 0xfc, 0x7f, 0x00, 0xc0, 0xaa,
+   0x06, 0x00, 0xfc, 0x7f, 0x00, 0x40, 0x55, 0x05, 0x00, 0x5c, 0x75, 0x00,
+   0xc0, 0xaa, 0x06, 0x00, 0xac, 0x6a, 0x00, 0x40, 0x55, 0x05, 0x00, 0x5c,
+   0x75, 0x00, 0xc0, 0xaa, 0x06, 0x00, 0xac, 0x6a, 0x00, 0x40, 0x55, 0x05,
+   0x00, 0x5c, 0x75, 0x00, 0xc0, 0xaa, 0x06, 0x00, 0xac, 0x6a, 0x00, 0x40,
+   0x55, 0x05, 0x00, 0x5c, 0x75, 0x00, 0xc0, 0xaa, 0x06, 0x00, 0xac, 0x6a,
+   0x00, 0x40, 0x55, 0x05, 0x00, 0x5c, 0x75, 0x00, 0xc0, 0xaa, 0x06, 0x00,
+   0xfc, 0x7f, 0x00, 0xc0, 0xff, 0x07, 0x00, 0xfc, 0x7f};
diff --git a/include/gdi.h b/include/gdi.h
index 1920d07..b86d508 100644
--- a/include/gdi.h
+++ b/include/gdi.h
@@ -8,6 +8,7 @@
 #define GDI_H
 
 #include <X11/Xlib.h>
+#include <X11/Xutil.h>
 
 #include "windows.h"
 #include "segmem.h"
@@ -32,6 +33,7 @@
     WORD        type;
     RECT        box;
     Pixmap      pixmap;
+    Region      xrgn;
 } REGION;
 
 typedef struct tagGDIOBJHDR
diff --git a/include/menu.h b/include/menu.h
index 2e0f7ca..fad8bb1 100644
--- a/include/menu.h
+++ b/include/menu.h
@@ -11,14 +11,14 @@
 
 typedef struct tagMENUITEM
 {
-    WORD	item_flags;
-    WORD	item_id;
-    RECT	rect;
-    WORD	sel_key;
-    HBITMAP	hCheckBit;
-    HBITMAP	hUnCheckBit;
+    WORD	item_flags;    /* Item flags */
+    WORD	item_id;       /* Item or popup id */
+    RECT	rect;          /* Item area (relative to menu window) */
+    WORD        xTab;          /* X position of text after Tab */
+    HBITMAP	hCheckBit;     /* Bitmap for checked item */
+    HBITMAP	hUnCheckBit;   /* Bitmap for unchecked item */
+    HANDLE      hText;	       /* Handle to item string or bitmap */
     char	*item_text;
-	HANDLE	hText;	
 } MENUITEM, *LPMENUITEM;
 
 
diff --git a/include/msdos.h b/include/msdos.h
index e5443f1..e2b6450 100644
--- a/include/msdos.h
+++ b/include/msdos.h
@@ -14,6 +14,18 @@
 	long filetime;
 };
 
+struct fcb {
+        BYTE drive;
+	char name[8];
+	char extension[3];
+	BYTE dummy1[4];
+	int filesize;
+	WORD date_write;
+	WORD time_write;
+	struct dosdirent *directory;
+	BYTE dummy2[9];
+};
+
 #define DOSVERSION 0x0330;
 #define MAX_DOS_DRIVES	26
 
diff --git a/include/options.h b/include/options.h
index 3caf1fd..e8bed9f 100644
--- a/include/options.h
+++ b/include/options.h
@@ -13,8 +13,8 @@
     char * desktopGeometry; /* NULL when no desktop */
     char * programName;     /* To use when loading resources */
     int    usePrivateMap;
-    int    synchronous;
-    int    nobackingstore;
+    int    synchronous;     /* X synchronous mode */
+    int    backingstore;    /* Use backing store */
     short  cmdShow;
     int    relay_debug;
     int    debug;
diff --git a/include/segmem.h b/include/segmem.h
index afe7741..c5b03c6 100644
--- a/include/segmem.h
+++ b/include/segmem.h
@@ -55,7 +55,7 @@
     unsigned short owner;	/* Handle of owner program		*/
     unsigned char  type;	/* DATA or CODE				*/
 #ifdef HAVE_IPC
-    key_t	   shm_key;	/* Shared memory key or IPC_PRIVATE     */
+    key_t	   shm_key;	/* Shared memory key or -1              */
 #endif
 } SEGDESC;
 
diff --git a/include/win.h b/include/win.h
index 1c3fcc8..22290dd 100644
--- a/include/win.h
+++ b/include/win.h
@@ -42,19 +42,20 @@
     DWORD        dwStyle;        /* Window style (from CreateWindow) */
     DWORD        dwExStyle;      /* Extended style (from CreateWindowEx) */
     HANDLE       hdce;           /* Window DCE (if CS_OWNDC or CS_CLASSDC) */
-    void		 *VScroll;		 /* Vertical ScrollBar Struct Pointer */
-    void		 *HScroll;		 /* Horizontal ScrollBar Struct Pointer */
+    void         *VScroll;       /* Vertical ScrollBar Struct Pointer */
+    void         *HScroll;       /* Horizontal ScrollBar Struct Pointer */
     WORD         scroll_flags;   /* scrolls flags (vert & horz visible) */
     WORD         wIDmenu;        /* ID or hmenu (from CreateWindow) */
     HANDLE       hText;          /* Handle of window text */
     WORD         flags;          /* Misc. flags (see below) */
     Window       window;         /* X window */
-    Window       icon;           /* icon's X window */
     HICON        hIcon;          /* icon's MS-windows handle */
-    RECT         rectClientSave;       /* where client rect is saved when icon*/
-    HMENU		 hSysMenu;		 /* window's copy of System Menu */
+    WORD	 iconWidth;	 /* width of icon */
+    WORD	 iconHeight;     /* height of icon */
+    RECT         rectClientSave; /* where client rect is saved when icon*/
+    HMENU        hSysMenu;	 /* window's copy of System Menu */
     HANDLE       hProp;          /* Handle of Properties List */
-    HTASK 		 hTask;          /* Task Handle of the owner */
+    HTASK        hTask;          /* Task Handle of the owner */
     WORD         wExtra[1];      /* Window extra bytes */
 } WND;
 
diff --git a/include/windows.h b/include/windows.h
index 711210a..5443498 100644
--- a/include/windows.h
+++ b/include/windows.h
@@ -1513,6 +1513,8 @@
 #define WM_MOUSELAST	    WM_MBUTTONDBLCLK
 
 #define WM_PARENTNOTIFY     0x0210
+#define WM_ENTERMENULOOP    0x0211
+#define WM_EXITMENULOOP     0x0212
 
 #define WM_MDICREATE	    0x0220
 #define WM_MDIDESTROY	    0x0221
@@ -1565,9 +1567,29 @@
 #define SW_PARENTOPENING    3
 #define SW_OTHERRESTORED    4
 
-enum { SW_HIDE, SW_SHOWNORMAL, SW_NORMAL, SW_SHOWMINIMIZED, SW_SHOWMAXIMIZED,
-	SW_MAXIMIZE, SW_SHOWNOACTIVATE, SW_SHOW, SW_MINIMIZE,
-	SW_SHOWMINNOACTIVE, SW_SHOWNA, SW_RESTORE };
+/*
+enum { SW_HIDE, SW_SHOWNORMAL, SW_NORMAL, SW_SHOWMINIMIZED,
+	SW_SHOWMAXIMIZED, SW_MAXIMIZE, SW_SHOWNOACTIVATE, SW_SHOW,
+	SW_MINIMIZE, SW_SHOWMINNOACTIVE, SW_SHOWNA, SW_RESTORE,
+	SW_INTERNAL_HIDE, SW_INTERNAL_RESTORE };
+*/
+
+
+#define SW_HIDE             0
+#define SW_SHOWNORMAL       1
+#define SW_NORMAL           1
+#define SW_SHOWMINIMIZED    2
+#define SW_SHOWMAXIMIZED    3
+#define SW_MAXIMIZE         3
+#define SW_SHOWNOACTIVATE   4
+#define SW_SHOW             5
+#define SW_MINIMIZE         6
+#define SW_SHOWMINNOACTIVE  7
+#define SW_SHOWNA           8
+#define SW_RESTORE          9
+#define SW_INTERNAL_HIDE    20
+#define SW_INTERNAL_RESTORE 21
+
 
   /* WM_SIZE message wParam values */
 #define SIZE_RESTORED        0
diff --git a/loader/selector.c b/loader/selector.c
index c2faab8..03711aa 100644
--- a/loader/selector.c
+++ b/loader/selector.c
@@ -156,19 +156,23 @@
      * to get one.  In this case, we'll also have to copy the data
      * to protect it.
      */
-    if (s_old->shm_key == 0)
+    if (s_old->shm_key == -1)
     {
-	s_old->shm_key = shmget(IPC_PRIVATE, s_old->length, 0600);
-	if (s_old->shm_key == 0)
+	s_old->shm_key = shmget(IPC_PRIVATE, s_old->length, IPC_CREAT);
+	if (s_old->shm_key == -1)
 	{
-	    if (s_new)
+	    if (s_new) {
 		memset(s_new, 0, sizeof(*s_new));
+		s_new->shm_key = -1;
+	    }
 	    return -1;
 	}
-	if (shmat(s_old->shm_key, base_addr, 0) == NULL)
+	if (shmat(s_old->shm_key, base_addr, 0) == (char *) -1)
 	{
-	    if (s_new)
+	    if (s_new) {
 		memset(s_new, 0, sizeof(*s_new));
+		s_new->shm_key = -1;
+	    }
 	    shmctl(s_old->shm_key, IPC_RMID, NULL);
 	    return -1;
 	}
@@ -183,10 +187,12 @@
      */
     else
     {
-	if (shmat(s_old->shm_key, base_addr, 0) == NULL)
+	if (shmat(s_old->shm_key, base_addr, 0) == (char *) -1)
 	{
-	    if (s_new)
+	    if (s_new) {
 		memset(s_new, 0, sizeof(*s_new));
+		s_new->shm_key = -1;
+	    }
 	    return -1;
 	}
     }
@@ -257,6 +263,9 @@
     else
     {
 	memset(s_new, 0, sizeof(*s_new));
+#ifdef HAVE_IPC
+	s_new->shm_key = -1;
+#endif
 	SelectorMap[i_new] = i_new;
     }
 
@@ -401,6 +410,19 @@
 }
 
 /**********************************************************************
+ *					CleanupSelectors
+ */
+
+void CleanupSelectors(void)
+{
+    int sel_idx;
+
+    for (sel_idx = FIRST_SELECTOR; sel_idx < MAX_SELECTORS; sel_idx++)
+	if (SelectorMap[sel_idx])
+	    FreeSelector((sel_idx << 3) | 7);
+}
+
+/**********************************************************************
  *					FreeSelector
  */
 WORD FreeSelector(WORD sel)
@@ -417,10 +439,11 @@
 	return 0;
     
     s = &Segments[sel_idx];
-    if (s->shm_key == 0)
+    if (s->shm_key == -1)
     {
 	munmap(s->base_addr, ((s->length + PAGE_SIZE) & ~(PAGE_SIZE - 1)));
 	memset(s, 0, sizeof(*s));
+	s->shm_key = -1;
 	SelectorMap[sel_idx] = 0;
     }
     else
@@ -436,6 +459,7 @@
 	    shmctl(s->shm_key, IPC_RMID, NULL);
 	    
 	memset(s, 0, sizeof(*s));
+	s->shm_key = -1;
 	SelectorMap[sel_idx] = 0;
     }
     
@@ -521,12 +545,17 @@
 				     MAP_FIXED | MAP_PRIVATE | MAP_ANON, 
 				     -1, 0);
 #endif
-
+#ifdef HAVE_IPC
+	s->shm_key = -1;
+#endif
 	if (set_ldt_entry(i, (unsigned long) s->base_addr, 
 			  (s->length - 1) & 0xffff, 0, 
 			  contents, read_only, 0) < 0)
 	{
 	    memset(s, 0, sizeof(*s));
+#ifdef HAVE_IPC
+	    s->shm_key = -1;
+#endif
 	    return NULL;
 	}
 
@@ -982,6 +1011,9 @@
 	    myerror("CreateSelectors: GlobalAlloc() failed");
 
 	s->base_addr = (void *) ((LONG) s->selector << 16);
+#ifdef HAVE_IPC
+	s->shm_key = -1;
+#endif
 	if (!(s->flags & NE_SEGFLAGS_DATA))
 	    PrestoChangoSelector(s->selector, s->selector);
 	else
diff --git a/misc/file.c b/misc/file.c
index db2293d..0551a6a 100644
--- a/misc/file.c
+++ b/misc/file.c
@@ -173,7 +173,7 @@
 	ofs->nErrCode = ExtendedError;
         return -1;
       }
-      handle = open (ofs->szPathName, (wStyle & 0x0003) | O_CREAT, 0x666);
+      handle = open (unixfilename, (wStyle & 0x0003) | O_CREAT, 0x666);
       if (handle == -1)
       {
 	errno_to_doserr();
diff --git a/misc/main.c b/misc/main.c
index 4479cdc..623c6ed 100644
--- a/misc/main.c
+++ b/misc/main.c
@@ -52,7 +52,7 @@
     NULL,           /* programName */
     FALSE,          /* usePrivateMap */
     FALSE,          /* synchronous */
-    FALSE,          /* no backing store */
+    FALSE,          /* backing store */
     SW_SHOWNORMAL,  /* cmdShow */
     FALSE
 };
@@ -60,6 +60,7 @@
 
 static XrmOptionDescRec optionsTable[] =
 {
+    { "-backingstore",  ".backingstore",    XrmoptionNoArg,  (caddr_t)"on" },
     { "-desktop",       ".desktop",         XrmoptionSepArg, (caddr_t)NULL },
     { "-depth",         ".depth",           XrmoptionSepArg, (caddr_t)NULL },
     { "-display",       ".display",         XrmoptionSepArg, (caddr_t)NULL },
@@ -67,7 +68,6 @@
     { "-name",          ".name",            XrmoptionSepArg, (caddr_t)NULL },
     { "-privatemap",    ".privatemap",      XrmoptionNoArg,  (caddr_t)"on" },
     { "-synchronous",   ".synchronous",     XrmoptionNoArg,  (caddr_t)"on" },
-    { "-nobackingstore",".nobackingstore",  XrmoptionNoArg,  (caddr_t)"on" },
     { "-spy",           ".spy",             XrmoptionSepArg, (caddr_t)NULL },
     { "-debug",         ".debug",           XrmoptionNoArg,  (caddr_t)"on" },
     { "-relaydbg",      ".relaydbg",        XrmoptionNoArg,  (caddr_t)"on" }
@@ -87,7 +87,7 @@
   "    -name name      Set the application name\n" \
   "    -privatemap     Use a private color map\n" \
   "    -synchronous    Turn on synchronous display mode\n" \
-  "    -nobackingstore Turn off backing store\n" \
+  "    -backingstore   Turn on backing store\n" \
   "    -spy file       Turn on message spying to the specified file\n" \
   "    -relaydbg       Display call relay information\n"
 
@@ -242,8 +242,8 @@
 	Options.usePrivateMap = TRUE;
     if (MAIN_GetResource( db, ".synchronous", &value ))
 	Options.synchronous = TRUE;
-    if (MAIN_GetResource( db, ".nobackingstore", &value ))
-	Options.nobackingstore = TRUE;	
+    if (MAIN_GetResource( db, ".backingstore", &value ))
+	Options.backingstore = TRUE;	
     if (MAIN_GetResource( db, ".relaydbg", &value ))
 	Options.relay_debug = TRUE;
     if (MAIN_GetResource( db, ".debug", &value ))
@@ -350,6 +350,7 @@
     sync_profiles();
     MAIN_RestoreSetup();
     WSACleanup();
+    CleanupSelectors();
 }
 
 /***********************************************************************
diff --git a/miscemu/int21.c b/miscemu/int21.c
index 5ed34e0..7596aa4 100644
--- a/miscemu/int21.c
+++ b/miscemu/int21.c
@@ -841,31 +841,70 @@
 static void FindFirstFCB(struct sigcontext_struct *context)
 {
 	BYTE *fcb = pointer(DS, DX);
+	struct fcb *standard_fcb;
+	struct fcb *output_fcb;
 	int drive;
+	char path[12];
 
 	DumpFCB( fcb );
-
-	if (*fcb)
-		drive = *fcb - 1;
+	
+	if ((*fcb) == 0xff)
+	  {
+	    standard_fcb = fcb + 7;
+	    output_fcb = dta + 7;
+	    *dta = 0xff;
+	  }
 	else
-		drive = DOS_GetDefaultDrive();
+	  {
+	    standard_fcb = fcb;
+	    output_fcb = dta;
+	  }
 
-	if (*(fcb - 7) == 0xff) {
-		if (*(fcb - 1) == FA_DIREC) {
-			/* return volume label */
+	if (standard_fcb->drive)
+	  {
+	    drive = standard_fcb->drive - 1;
+	    if (!DOS_ValidDrive(drive))
+	      {
+		Error (InvalidDrive, EC_MediaError, EL_Disk);
+		AL = 0xff;
+		return;
+	      }
+	  }
+	else
+	  drive = DOS_GetDefaultDrive();
 
-			memset(dta, ' ', 11);
-			if (DOS_GetVolumeLabel(drive) != NULL) 
-				strncpy(dta, DOS_GetVolumeLabel(drive), 8);
-			*(dta + 0x0b) = FA_DIREC;
+	output_fcb->drive = drive;
 
-			AL;
-			return;
-		}
-	}
-	IntBarf(0x21, context);
+	if (*(fcb) == 0xff) 
+	  {
+	    if (*(fcb+6) & FA_LABEL)      /* return volume label */
+	      {
+		*(dta+6) = FA_LABEL;
+		memset(&output_fcb->name, ' ', 11);
+		if (DOS_GetVolumeLabel(drive) != NULL) 
+		  {
+		    strncpy(&output_fcb->name, DOS_GetVolumeLabel(drive), 11);
+		    AL = 0x00;
+		    return;
+		  }
+	      }
+	  }
+
+	strncpy(&(output_fcb->name),&(standard_fcb->name),11);
+	if (*fcb == 0xff)
+	  *(dta+6) = ( *(fcb+6) & (!FA_DIREC));
+
+	sprintf(path,"%c:*.*",drive+'A');
+	if ((output_fcb->directory = DOS_opendir(path))==NULL)
+	  {
+	    Error (PathNotFound, EC_MediaError, EL_Disk);
+	    AL = 0xff;
+	    return;
+	  }
+	
 }
 
+
 static void DeleteFileFCB(struct sigcontext_struct *context)
 {
 	BYTE *fcb = pointer(DS, DX);
diff --git a/objects/bitmap.c b/objects/bitmap.c
index cd4f623..93b0e4a 100644
--- a/objects/bitmap.c
+++ b/objects/bitmap.c
@@ -13,6 +13,7 @@
 #include "bitmap.h"
 
   /* Include OEM bitmaps */
+#include "bitmaps/check_boxes"
 #include "bitmaps/check_mark"
 #include "bitmaps/menu_arrow"
 
@@ -64,7 +65,7 @@
     extern void _XInitImageFuncPtrs( XImage* );
     XImage * image;
 
-    image = XCreateImage( XT_display, DefaultVisualOfScreen(screen),
+    image = XCreateImage( display, DefaultVisualOfScreen(screen),
 			  bmp->bmBitsPixel, ZPixmap, 0, bmpData,
 			  bmp->bmWidth, bmp->bmHeight, 16, bmp->bmWidthBytes );
     if (!image) return 0;
@@ -94,6 +95,12 @@
 	data   = menu_arrow_bits;
 	break;
 
+    case OBM_CHECKBOXES:
+	width  = check_boxes_width;
+	height = check_boxes_height;
+	data   = check_boxes_bits;
+	break;
+	
     case OBM_CHECK:
 	width  = check_mark_width;
 	height = check_mark_height;
diff --git a/objects/clipping.c b/objects/clipping.c
index a5240ff..9675b9c 100644
--- a/objects/clipping.c
+++ b/objects/clipping.c
@@ -21,7 +21,12 @@
     if (dc->w.hGCClipRgn)
     {
 	RGNOBJ *obj = (RGNOBJ *) GDI_GetObjPtr(dc->w.hGCClipRgn, REGION_MAGIC);
-	if (obj->region.pixmap)
+	if (obj->region.xrgn)
+	{
+	    XSetRegion( display, dc->u.x.gc, obj->region.xrgn );
+	    XSetClipOrigin( display, dc->u.x.gc, dc->w.DCOrgX, dc->w.DCOrgY );
+	}
+	else if (obj->region.pixmap)
 	{
 	    XSetClipMask( display, dc->u.x.gc, obj->region.pixmap );
 	    XSetClipOrigin( display, dc->u.x.gc,
diff --git a/objects/region.c b/objects/region.c
index afe4dd4..74ec57b 100644
--- a/objects/region.c
+++ b/objects/region.c
@@ -1,15 +1,14 @@
 /*
  * GDI region objects
  *
- * Copyright 1993 Alexandre Julliard
+ * Copyright 1993, 1994 Alexandre Julliard
  */
 
-static char Copyright[] = "Copyright  Alexandre Julliard, 1993";
+static char Copyright[] = "Copyright  Alexandre Julliard, 1993, 1994";
 
 #include <stdlib.h>
 #include <stdio.h>
-#include <X11/Xlib.h>
-#include <X11/Xutil.h>
+
 #include "gdi.h"
 
   /* GC used for region operations */
@@ -26,11 +25,11 @@
     tmpPixmap = XCreatePixmap( display, rootWindow, 1, 1, 1 );
     if (tmpPixmap)
     {
-	regionGC = XCreateGC( XT_display, tmpPixmap, 0, NULL );
-	XFreePixmap( XT_display, tmpPixmap );
+	regionGC = XCreateGC( display, tmpPixmap, 0, NULL );
+	XFreePixmap( display, tmpPixmap );
 	if (!regionGC) return FALSE;
-	XSetForeground( XT_display, regionGC, 1 );
-	XSetGraphicsExposures( XT_display, regionGC, False );
+	XSetForeground( display, regionGC, 1 );
+	XSetGraphicsExposures( display, regionGC, False );
 	return TRUE;
     }
     else return FALSE;
@@ -38,12 +37,34 @@
 
 
 /***********************************************************************
+ *           REGION_MakePixmap
+ *
+ * Make a pixmap of an X region.
+ */
+static BOOL REGION_MakePixmap( REGION *region )
+{
+    int width = region->box.right - region->box.left;
+    int height = region->box.bottom - region->box.top;
+
+    if (!region->xrgn) return TRUE;  /* Null region */
+    region->pixmap = XCreatePixmap( display, rootWindow, width, height, 1 );
+    if (!region->pixmap) return FALSE;
+    XSetRegion( display, regionGC, region->xrgn );
+    XSetClipOrigin( display, regionGC, region->box.left, region->box.top );
+    XSetFunction( display, regionGC, GXcopy );
+    XFillRectangle( display, region->pixmap, regionGC, 0, 0, width, height );
+    XSetClipMask( display, regionGC, None );  /* Clear clip region */
+    return TRUE;
+}
+
+
+/***********************************************************************
  *           REGION_SetRect
  *
- * Set the bounding box of the region and create the pixmap.
+ * Set the bounding box of the region and create the pixmap (or the X rgn).
  * The hrgn must be valid.
  */
-static BOOL REGION_SetRect( HRGN hrgn, LPRECT rect )
+static BOOL REGION_SetRect( HRGN hrgn, LPRECT rect, BOOL createXrgn )
 {
     int width, height;
 
@@ -60,21 +81,33 @@
 	region->box.top    = 0;
 	region->box.bottom = 0;
 	region->pixmap     = 0;
+	region->xrgn       = 0;
 	return TRUE;
     }
-    region->type = SIMPLEREGION;
-    region->box  = *rect;
-    
-      /* Create pixmap */
+    region->type   = SIMPLEREGION;
+    region->box    = *rect;
+    region->xrgn   = 0;
+    region->pixmap = 0;
 
-    region->pixmap = XCreatePixmap( display, rootWindow, width, height, 1 );
-    if (!region->pixmap) return FALSE;
+    if (createXrgn)  /* Create and set the X region */
+    {
+	Region tmprgn;
+	XRectangle xrect = { region->box.left, region->box.top, width, height};
 
-      /* Fill pixmap */
-
-    XSetFunction( XT_display, regionGC, GXclear );
-    XFillRectangle( XT_display, region->pixmap, regionGC,
-		    0, 0, width, height );
+	if (!(tmprgn = XCreateRegion())) return FALSE;
+	if ((region->xrgn = XCreateRegion()))
+	    XUnionRectWithRegion( &xrect, tmprgn, region->xrgn );
+	XDestroyRegion( tmprgn );
+	if (!region->xrgn) return FALSE;
+    }
+    else  /* Create the pixmap */
+    {
+	region->pixmap = XCreatePixmap( display, rootWindow, width, height, 1);
+	if (!region->pixmap) return FALSE;
+	  /* Fill the pixmap */
+	XSetFunction( display, regionGC, GXclear );
+	XFillRectangle(display, region->pixmap, regionGC, 0, 0, width, height);
+    }
     return TRUE;
 }
 
@@ -84,7 +117,8 @@
  */
 BOOL REGION_DeleteObject( HRGN hrgn, RGNOBJ * obj )
 {
-    if (obj->region.pixmap) XFreePixmap( XT_display, obj->region.pixmap );
+    if (obj->region.pixmap) XFreePixmap( display, obj->region.pixmap );
+    if (obj->region.xrgn) XDestroyRegion( obj->region.xrgn );
     return GDI_FreeObject( hrgn );
 }
 
@@ -100,6 +134,7 @@
     printf( "OffsetRgn: %d %d,%d\n", hrgn, x, y );
 #endif
     OffsetRect( &obj->region.box, x, y );
+    if (obj->region.xrgn) XOffsetRegion( obj->region.xrgn, x, y );
     return obj->region.type;
 }
 
@@ -134,7 +169,6 @@
  */
 HRGN CreateRectRgnIndirect( LPRECT rect )
 {
-    RGNOBJ * rgnObj;
     HRGN hrgn;
 
 #ifdef DEBUG_REGION
@@ -145,24 +179,11 @@
       /* Create region */
 
     if (!(hrgn = GDI_AllocObject( sizeof(RGNOBJ), REGION_MAGIC ))) return 0;
-    if (!REGION_SetRect( hrgn, rect ))
+    if (!REGION_SetRect( hrgn, rect, TRUE ))
     {
 	GDI_FreeObject( hrgn );
 	return 0;
     }
-    rgnObj = (RGNOBJ *) GDI_HEAP_ADDR( hrgn );
-
-      /* Fill pixmap */
-    
-    if (rgnObj->region.type != NULLREGION)
-    {
-	int width  = rgnObj->region.box.right - rgnObj->region.box.left;
-	int height = rgnObj->region.box.bottom - rgnObj->region.box.top;
-	XSetFunction( XT_display, regionGC, GXcopy );
-	XFillRectangle( XT_display, rgnObj->region.pixmap, regionGC,
-		        0, 0, width, height );
-    }
-    
     return hrgn;
 }
 
@@ -185,7 +206,7 @@
       /* Create region */
 
     if (!(hrgn = GDI_AllocObject( sizeof(RGNOBJ), REGION_MAGIC ))) return 0;
-    if (!REGION_SetRect( hrgn, &rect ))
+    if (!REGION_SetRect( hrgn, &rect, FALSE ))
     {
 	GDI_FreeObject( hrgn );
 	return 0;
@@ -198,23 +219,23 @@
     {
 	int width  = rgnObj->region.box.right - rgnObj->region.box.left;
 	int height = rgnObj->region.box.bottom - rgnObj->region.box.top;
-	XSetFunction( XT_display, regionGC, GXcopy );
-	XFillRectangle( XT_display, rgnObj->region.pixmap, regionGC,
+	XSetFunction( display, regionGC, GXcopy );
+	XFillRectangle( display, rgnObj->region.pixmap, regionGC,
 		        0, ellipse_height / 2,
 		        width, height - ellipse_height );
-	XFillRectangle( XT_display, rgnObj->region.pixmap, regionGC,
+	XFillRectangle( display, rgnObj->region.pixmap, regionGC,
 		        ellipse_width / 2, 0,
 		        width - ellipse_width, height );
-	XFillArc( XT_display, rgnObj->region.pixmap, regionGC,
+	XFillArc( display, rgnObj->region.pixmap, regionGC,
 		  0, 0,
 		  ellipse_width, ellipse_height, 0, 360*64 );
-	XFillArc( XT_display, rgnObj->region.pixmap, regionGC,
+	XFillArc( display, rgnObj->region.pixmap, regionGC,
 		  width - ellipse_width, 0,
 		  ellipse_width, ellipse_height, 0, 360*64 );
-	XFillArc( XT_display, rgnObj->region.pixmap, regionGC,
+	XFillArc( display, rgnObj->region.pixmap, regionGC,
 		  0, height - ellipse_height,
 		  ellipse_width, ellipse_height, 0, 360*64 );
-	XFillArc( XT_display, rgnObj->region.pixmap, regionGC,
+	XFillArc( display, rgnObj->region.pixmap, regionGC,
 		  width - ellipse_width, height - ellipse_height,
 		  ellipse_width, ellipse_height, 0, 360*64 );
     }
@@ -238,21 +259,9 @@
       /* Free previous pixmap */
 
     if (!(rgnObj = (RGNOBJ *) GDI_GetObjPtr( hrgn, REGION_MAGIC ))) return;
-    if (rgnObj->region.pixmap) 
-	XFreePixmap( XT_display, rgnObj->region.pixmap );
-
-    if (!REGION_SetRect( hrgn, &rect )) return;
-
-      /* Fill pixmap */
-    
-    if (rgnObj->region.type != NULLREGION)
-    {
-	int width  = rgnObj->region.box.right - rgnObj->region.box.left;
-	int height = rgnObj->region.box.bottom - rgnObj->region.box.top;
-	XSetFunction( XT_display, regionGC, GXcopy );
-	XFillRectangle( XT_display, rgnObj->region.pixmap, regionGC,
-		        0, 0, width, height );
-    }
+    if (rgnObj->region.pixmap) XFreePixmap( display, rgnObj->region.pixmap );
+    if (rgnObj->region.xrgn) XDestroyRegion( rgnObj->region.xrgn );
+    REGION_SetRect( hrgn, &rect, TRUE );
 }
 
 
@@ -282,7 +291,7 @@
       /* Create region */
 
     if (!(hrgn = GDI_AllocObject( sizeof(RGNOBJ), REGION_MAGIC ))) return 0;
-    if (!REGION_SetRect( hrgn, rect ))
+    if (!REGION_SetRect( hrgn, rect, FALSE ))
     {
 	GDI_FreeObject( hrgn );
 	return 0;
@@ -295,8 +304,8 @@
     {
 	int width  = rgnObj->region.box.right - rgnObj->region.box.left;
 	int height = rgnObj->region.box.bottom - rgnObj->region.box.top;
-	XSetFunction( XT_display, regionGC, GXcopy );
-	XFillArc( XT_display, rgnObj->region.pixmap, regionGC,
+	XSetFunction( display, regionGC, GXcopy );
+	XFillArc( display, rgnObj->region.pixmap, regionGC,
 		  0, 0, width, height, 0, 360*64 );
     }
     
@@ -321,70 +330,67 @@
 {
     RGNOBJ * rgnObj;
     HRGN hrgn;
-    RECT box;
-    int i, j, totalPoints;
-    POINT * pt;
-    XPoint * xpoints;
-    
-    if (!nbpolygons) return 0;
+    int i, j, maxPoints;
+    XPoint *xpoints, *pt;
+    XRectangle rect;
+    Region xrgn;
+
 #ifdef DEBUG_REGION
     printf( "CreatePolyPolygonRgn: %d polygons\n", nbpolygons );
 #endif
-    
-      /* Find bounding box */
 
-    box.top   = box.left   = 32767;
-    box.right = box.bottom = 0;
-    for (i = totalPoints = 0, pt = points; i < nbpolygons; i++)
+      /* Allocate points array */
+
+    if (!nbpolygons) return 0;
+    for (i = maxPoints = 0; i < nbpolygons; i++)
+	if (maxPoints < count[i]) maxPoints = count[i];
+    if (!maxPoints) return 0;
+    if (!(xpoints = (XPoint *) malloc( sizeof(XPoint) * maxPoints )))
+	return 0;
+
+      /* Allocate region */
+
+    if (!(hrgn = GDI_AllocObject( sizeof(RGNOBJ), REGION_MAGIC )))
     {
-	totalPoints += count[i];
-	for (j = 0; j < count[i]; j++, pt++)
-	{
-	    if (pt->x < box.left) box.left = pt->x;
-	    if (pt->x > box.right) box.right = pt->x;
-	    if (pt->y < box.top) box.top = pt->y;
-	    if (pt->y > box.bottom) box.bottom = pt->y;
-	}
-    }        
-    if (!totalPoints) return 0;
-    
-      /* Build points array */
-
-    xpoints = (XPoint *) malloc( sizeof(XPoint) * totalPoints );
-    if (!xpoints) return 0;
-    for (i = 0, pt = points; i < totalPoints; i++, pt++)
-    {
-	xpoints[i].x = pt->x - box.left;
-	xpoints[i].y = pt->y - box.top;
-    }
-
-      /* Create region */
-
-    if (!(hrgn = GDI_AllocObject( sizeof(RGNOBJ), REGION_MAGIC )) ||
-	!REGION_SetRect( hrgn, &box ))
-    {
-	if (hrgn) GDI_FreeObject( hrgn );
 	free( xpoints );
 	return 0;
     }
     rgnObj = (RGNOBJ *) GDI_HEAP_ADDR( hrgn );
+    rgnObj->region.type   = SIMPLEREGION;
+    rgnObj->region.pixmap = 0;
 
-      /* Fill pixmap */
+      /* Create X region */
 
-    if (rgnObj->region.type != NULLREGION)
+    for (i = 0; i < nbpolygons; i++, count++)
     {
-	XSetFunction( XT_display, regionGC, GXcopy );
-	if (mode == WINDING) XSetFillRule( XT_display, regionGC, WindingRule );
-	else XSetFillRule( XT_display, regionGC, EvenOddRule );
-	for (i = j = 0; i < nbpolygons; i++)
+	for (j = *count, pt = xpoints; j > 0; j--, points++, pt++)
 	{
-	    XFillPolygon( XT_display, rgnObj->region.pixmap, regionGC,
-			  &xpoints[j], count[i], Complex, CoordModeOrigin );
-	    j += count[i];
+	    pt->x = points->x;
+	    pt->y = points->y;
 	}
+	xrgn = XPolygonRegion( xpoints, *count,
+			       (mode == WINDING) ? WindingRule : EvenOddRule );
+	if (!xrgn) break;
+	if (i > 0)
+	{
+	    Region tmprgn = XCreateRegion();
+	    if (mode == WINDING) XUnionRegion(xrgn,rgnObj->region.xrgn,tmprgn);
+	    else XXorRegion( xrgn, rgnObj->region.xrgn, tmprgn );
+	    XDestroyRegion( rgnObj->region.xrgn );
+	    rgnObj->region.xrgn = tmprgn;
+	}
+	else rgnObj->region.xrgn = xrgn;
     }
-    
+
     free( xpoints );
+    if (!xrgn)
+    {
+	GDI_FreeObject( hrgn );
+	return 0;
+    }
+    XClipBox( rgnObj->region.xrgn, &rect );
+    SetRect( &rgnObj->region.box, rect.x, rect.y,
+	     rect.x + rect.width, rect.y + rect.height);
     return hrgn;
 }
 
@@ -394,19 +400,25 @@
  */
 BOOL PtInRegion( HRGN hrgn, short x, short y )
 {
-    XImage * image;
     BOOL res;
     RGNOBJ * obj;
     POINT pt = { x, y };
     
     if (!(obj = (RGNOBJ *) GDI_GetObjPtr( hrgn, REGION_MAGIC ))) return FALSE;
     if (!PtInRect( &obj->region.box, pt )) return FALSE;
-    image = XGetImage( XT_display, obj->region.pixmap,
-		       x - obj->region.box.left, y - obj->region.box.top,
-		       1, 1, AllPlanes, ZPixmap );
-    if (!image) return FALSE;
-    res = (XGetPixel( image, 0, 0 ) != 0);
-    XDestroyImage( image );
+    if (obj->region.xrgn)
+    {
+	return XPointInRegion( obj->region.xrgn, x, y );
+    }
+    else
+    {
+	XImage *image = XGetImage( display, obj->region.pixmap,
+			    x - obj->region.box.left, y - obj->region.box.top,
+			    1, 1, AllPlanes, ZPixmap );
+	if (!image) return FALSE;
+	res = (XGetPixel( image, 0, 0 ) != 0);
+	XDestroyImage( image );
+    }
     return res;
 }
 
@@ -422,24 +434,33 @@
     int x, y;
     
     if (!(obj = (RGNOBJ *) GDI_GetObjPtr( hrgn, REGION_MAGIC ))) return FALSE;
-    if (!IntersectRect( &intersect, &obj->region.box, rect )) return FALSE;
+    if (obj->region.xrgn)
+    {
+	return (XRectInRegion( obj->region.xrgn, rect->left, rect->top,
+			       rect->right-rect->left,
+			       rect->bottom-rect->top ) != RectangleOut);
+    }
+    else
+    {
+	if (!IntersectRect( &intersect, &obj->region.box, rect )) return FALSE;
     
-    image = XGetImage( XT_display, obj->region.pixmap,
-		       intersect.left - obj->region.box.left,
-		       intersect.top - obj->region.box.top,
-		       intersect.right - intersect.left,
-		       intersect.bottom - intersect.top,
-		       AllPlanes, ZPixmap );
-    if (!image) return FALSE;
-    for (y = 0; y < image->height; y++)
-	for (x = 0; x < image->width; x++)
-	    if (XGetPixel( image, x, y ) != 0)
-	    {
-		XDestroyImage( image );
-		return TRUE;
-	    }
+	image = XGetImage( display, obj->region.pixmap,
+			   intersect.left - obj->region.box.left,
+			   intersect.top - obj->region.box.top,
+			   intersect.right - intersect.left,
+			   intersect.bottom - intersect.top,
+			   AllPlanes, ZPixmap );
+	if (!image) return FALSE;
+	for (y = 0; y < image->height; y++)
+	    for (x = 0; x < image->width; x++)
+		if (XGetPixel( image, x, y ) != 0)
+		{
+		    XDestroyImage( image );
+		    return TRUE;
+		}
     
-    XDestroyImage( image );
+	XDestroyImage( image );
+    }
     return FALSE;
 }
 
@@ -451,6 +472,7 @@
 {
     RGNOBJ *obj1, *obj2;
     XImage *image1, *image2;
+    Pixmap pixmap1, pixmap2;
     int width, height, x, y;
 
       /* Compare bounding boxes */
@@ -461,19 +483,27 @@
 	return (obj2->region.type == NULLREGION);
     else if (obj2->region.type == NULLREGION) return FALSE;
     if (!EqualRect( &obj1->region.box, &obj2->region.box )) return FALSE;
-
+    if (obj1->region.xrgn && obj2->region.xrgn)
+    {
+	return XEqualRegion( obj1->region.xrgn, obj2->region.xrgn );
+    }
+    
       /* Get pixmap contents */
 
+    if (!(pixmap1 = obj1->region.pixmap) &&
+	!REGION_MakePixmap( &obj1->region )) return FALSE;
+    if (!(pixmap2 = obj2->region.pixmap) &&
+	!REGION_MakePixmap( &obj2->region )) return FALSE;
     width  = obj1->region.box.right - obj1->region.box.left;
     height = obj1->region.box.bottom - obj1->region.box.top;
-    image1 = XGetImage( XT_display, obj1->region.pixmap,
+    image1 = XGetImage( display, obj1->region.pixmap,
+			0, 0, width, height, AllPlanes, ZPixmap );
+    image2 = XGetImage( display, obj2->region.pixmap,
 		        0, 0, width, height, AllPlanes, ZPixmap );
-    if (!image1) return FALSE;
-    image2 = XGetImage( XT_display, obj2->region.pixmap,
-		        0, 0, width, height, AllPlanes, ZPixmap );
-    if (!image2)
+    if (!image1 || !image2)
     {
-	XDestroyImage( image1 );
+	if (image1) XDestroyImage( image1 );
+	if (image2) XDestroyImage( image2 );
 	return FALSE;
     }
     
@@ -503,7 +533,7 @@
 {
     RECT inter;
     if (!IntersectRect( &inter, &dest->box, &src->box )) return;
-    XCopyArea( XT_display, src->pixmap, dest->pixmap, regionGC,
+    XCopyArea( display, src->pixmap, dest->pixmap, regionGC,
 	       inter.left - src->box.left, inter.top - src->box.top,
 	       inter.right - inter.left, inter.bottom - inter.top,
 	       inter.left - dest->box.left, inter.top - dest->box.top );
@@ -533,6 +563,68 @@
 	    return ERROR;
     region = &destObj->region;
 
+    if (src1Obj->region.xrgn && ((mode == RGN_COPY) || src2Obj->region.xrgn))
+    {
+	/* Perform the operation with X regions */
+
+	if (region->pixmap) XFreePixmap( display, region->pixmap );
+	region->pixmap = 0;
+	if (!region->xrgn) region->xrgn = XCreateRegion();
+	switch(mode)
+	{
+	case RGN_AND:
+	    XIntersectRegion( src1Obj->region.xrgn, src2Obj->region.xrgn,
+			      region->xrgn );
+	    break;
+	case RGN_OR:
+	    XUnionRegion( src1Obj->region.xrgn, src2Obj->region.xrgn,
+			  region->xrgn );
+	    break;
+	case RGN_XOR:
+	    XXorRegion( src1Obj->region.xrgn, src2Obj->region.xrgn,
+			region->xrgn );
+	    break;
+	case RGN_DIFF:
+	    XSubtractRegion( src1Obj->region.xrgn, src2Obj->region.xrgn,
+			     region->xrgn );
+	    break;
+	case RGN_COPY:
+	    {
+		Region tmprgn = XCreateRegion();
+		XUnionRegion( tmprgn, src1Obj->region.xrgn, region->xrgn );
+		XDestroyRegion( tmprgn );
+	    }
+	    break;
+	default:
+	    return ERROR;
+	}
+	if (XEmptyRegion(region->xrgn))
+	{
+	    region->type = NULLREGION;
+	    region->xrgn = 0;
+	    return NULLREGION;
+	}
+	else
+	{
+	    XRectangle rect;
+	    XClipBox( region->xrgn, &rect );
+	    region->type       = COMPLEXREGION;
+	    region->box.left   = rect.x;
+	    region->box.top    = rect.y;
+	    region->box.right  = rect.x + rect.width;
+	    region->box.bottom = rect.y + rect.height;
+	    return COMPLEXREGION;
+	}
+    }
+    else  /* Create pixmaps if needed */
+    {
+	if (!src1Obj->region.pixmap)
+	    if (!REGION_MakePixmap( &src1Obj->region )) return ERROR;
+	if ((mode != RGN_COPY) && !src2Obj->region.pixmap)
+	    if (!REGION_MakePixmap( &src2Obj->region )) return ERROR;
+    }
+    
+
     switch(mode)
     {
       case RGN_AND:
@@ -564,11 +656,13 @@
 	return ERROR;
     }
 
-    if (region->pixmap) XFreePixmap( XT_display, region->pixmap );    
+    if (region->pixmap) XFreePixmap( display, region->pixmap );
+    if (region->xrgn) XDestroyRegion( region->xrgn );
     if (!res)
     {
 	region->type   = NULLREGION;
 	region->pixmap = 0;
+	region->xrgn   = 0;
 	return NULLREGION;
     }
     
@@ -587,39 +681,40 @@
 	exit(1);
     }
     region->pixmap = XCreatePixmap( display, rootWindow, width, height, 1 );
+    region->xrgn   = 0;
 
     switch(mode)
     {
       case RGN_AND:
-	  XSetFunction( XT_display, regionGC, GXcopy );
+	  XSetFunction( display, regionGC, GXcopy );
 	  REGION_CopyIntersection( region, &src1Obj->region );
-	  XSetFunction( XT_display, regionGC, GXand );
+	  XSetFunction( display, regionGC, GXand );
 	  REGION_CopyIntersection( region, &src2Obj->region );
 	  break;
 
       case RGN_OR:
       case RGN_XOR:
-	  XSetFunction( XT_display, regionGC, GXclear );
-	  XFillRectangle( XT_display, region->pixmap, regionGC,
+	  XSetFunction( display, regionGC, GXclear );
+	  XFillRectangle( display, region->pixmap, regionGC,
 			  0, 0, width, height );
-	  XSetFunction( XT_display, regionGC, (mode == RGN_OR) ? GXor : GXxor);
+	  XSetFunction( display, regionGC, (mode == RGN_OR) ? GXor : GXxor);
 	  REGION_CopyIntersection( region, &src1Obj->region );
 	  REGION_CopyIntersection( region, &src2Obj->region );
 	  break;
 	  
       case RGN_DIFF:
-	  XSetFunction( XT_display, regionGC, GXclear );
-	  XFillRectangle( XT_display, region->pixmap, regionGC,
+	  XSetFunction( display, regionGC, GXclear );
+	  XFillRectangle( display, region->pixmap, regionGC,
 			  0, 0, width, height );
-	  XSetFunction( XT_display, regionGC, GXcopy );
+	  XSetFunction( display, regionGC, GXcopy );
 	  REGION_CopyIntersection( region, &src1Obj->region );
-	  XSetFunction( XT_display, regionGC, GXandInverted );
+	  XSetFunction( display, regionGC, GXandInverted );
 	  REGION_CopyIntersection( region, &src2Obj->region );
 	  break;
 	  
       case RGN_COPY:
-	  XSetFunction( XT_display, regionGC, GXcopy );
-	  XCopyArea( XT_display, src1Obj->region.pixmap, region->pixmap,
+	  XSetFunction( display, regionGC, GXcopy );
+	  XCopyArea( display, src1Obj->region.pixmap, region->pixmap,
 		     regionGC, 0, 0, width, height, 0, 0 );
 	  break;
     }
diff --git a/windows/dce.c b/windows/dce.c
index 58216b4..2148af1 100644
--- a/windows/dce.c
+++ b/windows/dce.c
@@ -183,25 +183,6 @@
 	    dc->w.DCSizeX = wndPtr->rectWindow.right - wndPtr->rectWindow.left;
 	    dc->w.DCSizeY = wndPtr->rectWindow.bottom - wndPtr->rectWindow.top;
 	}
-	else if (IsIconic(hwnd))                /* if we have an icon */
-        {
-            /* more things are hardcoded here than should be,
-             * I assume the icon windows is 100 pixels 1/2 of which is 50
-             * this just sets up the dc so it knows about the size of
-             * the icon area
-             */
-            dc->u.x.drawable = wndPtr->icon;
-            if (wndPtr->hIcon != (HICON)NULL) {
-                lpico = (ICONALLOC *)GlobalLock(wndPtr->hIcon);
-                dc->w.DCSizeX = /* (int)lpico->descriptor.Width */ 100;
-                dc->w.DCSizeY = (int)lpico->descriptor.Height + 20;
-            } else {
-                dc->w.DCOrgX = /* 64 */ 100;            /* assume max size */
-                dc->w.DCOrgY = 64 + 20;
-            }
-            dc->w.DCOrgX  = 0;
-            dc->w.DCOrgY  = 0;
-        }
 	else
 	{
 	    dc->w.DCOrgX  = wndPtr->rectClient.left - wndPtr->rectWindow.left;
@@ -223,11 +204,12 @@
     if ((flags & DCX_INTERSECTRGN) || (flags & DCX_EXCLUDERGN))
     {
 	HRGN hrgn = CreateRectRgn( 0, 0, 0, 0 );
-	if (hrgn && !IsIconic(hwnd))
+	if (hrgn)
 	{
 	    if (CombineRgn( hrgn, InquireVisRgn(hdc), hrgnClip,
-			    (flags & DCX_INTERSECTRGN) ? RGN_AND : RGN_DIFF ))
+			    (flags & DCX_INTERSECTRGN) ? RGN_AND : RGN_DIFF )) {
 		SelectVisRgn( hdc, hrgn );
+	    }
 	    DeleteObject( hrgn );
 	}
     }
diff --git a/windows/defwnd.c b/windows/defwnd.c
index 12443b1..071e681 100644
--- a/windows/defwnd.c
+++ b/windows/defwnd.c
@@ -44,6 +44,7 @@
     strcpy( textPtr, text );
 }
 
+#include <assert.h>
 
 /***********************************************************************
  *           DefWindowProc   (USER.107)
@@ -75,13 +76,10 @@
     case WM_NCCALCSIZE:
 	return NC_HandleNCCalcSize( hwnd, (NCCALCSIZE_PARAMS *)lParam );
 
+    case WM_PAINTICON: 
     case WM_NCPAINT:
 	return NC_HandleNCPaint( hwnd, (HRGN)wParam );
 
-    case WM_PAINTICON:
-        printf("going to call NC_HandleNCPaintIcon\n");
-        return NC_HandleNCPaintIcon( hwnd );
-
 
     case WM_NCHITTEST:
 	return NC_HandleNCHitTest( hwnd, MAKEPOINT(lParam) );
@@ -89,6 +87,7 @@
     case WM_NCLBUTTONDOWN:
 	return NC_HandleNCLButtonDown( hwnd, wParam, lParam );
 
+    case WM_LBUTTONDBLCLK:
     case WM_NCLBUTTONDBLCLK:
 	return NC_HandleNCLButtonDblClk( hwnd, wParam, lParam );
 
diff --git a/windows/dialog.c b/windows/dialog.c
index 7b28b2d..eeb5311 100644
--- a/windows/dialog.c
+++ b/windows/dialog.c
@@ -78,12 +78,14 @@
 	*class = p;
 	p += strlen(p) + 1;
     }
-/* FIXME: how can I determine if the resource id is an integer or a string ? */
-    if (*p == 0xff) { 
-/*	*(DWORD*)text = (*p << 8) | *p;*/
-	*(DWORD*)text = 0xebeb;
+    if (*p == 0xff)
+    {
+	  /* Integer id, not documented (?). Only works for SS_ICON controls */
+	*text = (char *)MAKEINTRESOURCE( p[1] + 256*p[2] );
 	p += 4;
-    } else {
+    }
+    else
+    {
 	*text = p;
 	p += strlen(p) + 2;
     }
@@ -263,8 +265,10 @@
       /* Create dialog main window */
 
     rect.left = rect.top = 0;
-    rect.right = template.header->cx * xUnit / 4;
-    rect.bottom = template.header->cy * yUnit / 8;
+    if (!(template.header->style & DS_ABSALIGN))
+	ClientToScreen( owner, (POINT *)&rect );
+    rect.right = rect.left + template.header->cx * xUnit / 4;
+    rect.bottom = rect.top + template.header->cy * yUnit / 8;
     if (template.header->style & DS_MODALFRAME) exStyle |= WS_EX_DLGMODALFRAME;
     AdjustWindowRectEx( &rect, template.header->style, hMenu, exStyle );
 
@@ -300,11 +304,8 @@
 
 #ifdef DEBUG_DIALOG
 	printf( "   %s ", class);
-	if ((DWORD*)text < 0x10000)
-		printf("'%4X'", (DWORD*)text);
-	else
-		printf("'%s'", text);
-	
+	if ((int)text & 0xffff0000) printf("'%s'", text);
+	else printf("%4X", (int)text & 0xffff);
 	printf(" %d, %d, %d, %d, %d, %08x\n", header->id, header->x, header->y, 
 		header->cx, header->cy, header->style );
 #endif
@@ -329,11 +330,6 @@
 			   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,
diff --git a/windows/event.c b/windows/event.c
index 4b6b3fd..a1dd581 100644
--- a/windows/event.c
+++ b/windows/event.c
@@ -252,13 +252,6 @@
     WND * wndPtr = WIN_FindWndPtr( hwnd );
     if (!wndPtr) return;
 
-    if (IsIconic(hwnd) && wndPtr->hIcon)
-    {
-        SendMessage(hwnd, WM_PAINTICON, 0, 0);
-       return;
-    }  
-
-
       /* Make position relative to client area instead of window */
     rect.left = event->x - (wndPtr->rectClient.left - wndPtr->rectWindow.left);
     rect.top  = event->y - (wndPtr->rectClient.top - wndPtr->rectWindow.top);
diff --git a/windows/graphics.c b/windows/graphics.c
index 089e3cc..b3c9307 100644
--- a/windows/graphics.c
+++ b/windows/graphics.c
@@ -18,6 +18,8 @@
 #include "gdi.h"
 #include "syscolor.h"
 
+extern const int DC_XROPfunction[];
+
 extern int COLOR_ToPhysical( DC *dc, COLORREF color );
 
 static inline swap_int(int *a, int *b)
@@ -473,6 +475,10 @@
     DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
     if (!dc) return 0;
 
+#ifdef SOLITAIRE_SPEED_HACK
+    return 0;
+#endif
+
     x = dc->w.DCOrgX + XLPTODP( dc, x );
     y = dc->w.DCOrgY + YLPTODP( dc, y );
     if ((x < 0) || (y < 0)) return 0;
@@ -552,6 +558,20 @@
 
 
 /***********************************************************************
+ *           InvertRgn    (GDI.42)
+ */
+BOOL InvertRgn( HDC hdc, HRGN hrgn )
+{
+    HBRUSH prevBrush = SelectObject( hdc, GetStockObject(BLACK_BRUSH) );
+    WORD prevROP = SetROP2( hdc, R2_NOT );
+    BOOL retval = PaintRgn( hdc, hrgn );
+    SelectObject( hdc, prevBrush );
+    SetROP2( hdc, prevROP );
+    return retval;
+}
+
+
+/***********************************************************************
  *           DrawFocusRect    (USER.466)
  */
 void DrawFocusRect( HDC hdc, LPRECT rc )
@@ -583,6 +603,44 @@
 
 
 /**********************************************************************
+ *          GRAPH_DrawBitmap
+ *
+ * Short-cut function to blit a bitmap into a device.
+ * Faster than CreateCompatibleDC() + SelectBitmap() + BitBlt() + DeleteDC().
+ */
+BOOL GRAPH_DrawBitmap( HDC hdc, HBITMAP hbitmap, int xdest, int ydest,
+		       int xsrc, int ysrc, int width, int height, int rop )
+{
+    XGCValues val;
+    BITMAPOBJ *bmp;
+    DC *dc;
+    
+    if (!(dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC ))) return FALSE;
+    if (!(bmp = (BITMAPOBJ *) GDI_GetObjPtr( hbitmap, BITMAP_MAGIC )))
+	return FALSE;
+    val.function   = DC_XROPfunction[(rop >> 16) & 0x0f];
+    val.foreground = dc->w.textPixel;
+    val.background = dc->w.backgroundPixel;
+    XChangeGC(display, dc->u.x.gc, GCFunction|GCForeground|GCBackground, &val);
+    if (bmp->bitmap.bmBitsPixel == 1)
+    {
+	XCopyPlane( display, bmp->pixmap, dc->u.x.drawable, dc->u.x.gc,
+		    xsrc, ysrc, width, height,
+		    dc->w.DCOrgX + xdest, dc->w.DCOrgY + ydest, 1 );
+	return TRUE;
+    }
+    else if (bmp->bitmap.bmBitsPixel == dc->w.bitsPerPixel)
+    {
+	XCopyArea( display, bmp->pixmap, dc->u.x.drawable, dc->u.x.gc,
+		   xsrc, ysrc, width, height,
+		   dc->w.DCOrgX + xdest, dc->w.DCOrgY + ydest );
+	return TRUE;
+    }
+    else return FALSE;
+}
+
+
+/**********************************************************************
  *          DrawReliefRect  (Not a MSWin Call)
  */
 void DrawReliefRect( HDC hdc, RECT rect, int thickness, BOOL pressed )
diff --git a/windows/icon.c b/windows/icon.c
index ba7d94d..8b13789 100644
--- a/windows/icon.c
+++ b/windows/icon.c
@@ -1,187 +1 @@
 
-/*
- * Iconification functions
- *
- * Copyright 1994 John Richardson
- */
-
-static char Copyright[] = "Copyright  John Richardson, 1994";
-
-#include "win.h"
-#include "class.h"
-#include "message.h"
-#include "sysmetrics.h"
-#include "user.h"
-#include "scroll.h"
-#include "menu.h"
-#include "icon.h"
-
-RECT myrect;
-
-
-ICON_Iconify(HWND hwnd)
-{
-	WND *wndPtr = WIN_FindWndPtr( hwnd );
-	GC testgc;
-	WND *parwPtr;
-	
-#ifdef DEBUG_ICON
-	printf("ICON_Iconify %d\n", hwnd);
-#endif
-
-	parwPtr = WIN_FindWndPtr(wndPtr->hwndParent);
-	if (parwPtr == NULL) {
-		printf("argh, the parent is NULL, what to do?\n");
-		exit(1);
-	}
-	wndPtr->dwStyle |= WS_MINIMIZE; 
- 	XUnmapWindow(display, wndPtr->window); 
-	if (wndPtr->icon == NULL) {
-		printf("argh, couldn't find icon\n");
-		exit(1);
-	}
-#ifdef DEBUG_ICON
-	printf("parent edge values are %d, %d\n",  parwPtr->rectWindow.left,
-				parwPtr->rectWindow.bottom);
-#endif
-	wndPtr->ptIconPos.x = parwPtr->rectWindow.left + 10;
-	wndPtr->ptIconPos.y = parwPtr->rectWindow.bottom - 80;
-
-#ifdef NOT
-        wndPtr->rectWindow.right = 100;
-        wndPtr->rectWindow.bottom = 32;
-        wndPtr->rectNormal.right = 1000;
-        wndPtr->rectNormal.bottom = 32;
-        wndPtr->rectClient.top= wndPtr->ptIconPos.y;
-	wndPtr->rectClient.left= wndPtr->ptIconPos.x;
-
-        wndPtr->rectClient.right = 100;
-	wndPtr->rectClient.bottom = 64;
-#endif
-	wndPtr->rectClientSave = wndPtr->rectNormal;
-	myrect = wndPtr->rectClient;
-
-	MoveWindow(hwnd, wndPtr->ptIconPos.x, wndPtr->ptIconPos.y,
-			100, 64+20, FALSE);
-
-	XMoveWindow(display, wndPtr->icon, 
-		wndPtr->ptIconPos.x, wndPtr->ptIconPos.y);
-
-	XMapWindow(display, wndPtr->icon);
-
-	SendMessage(hwnd, WM_PAINTICON, 0, 0);
-#ifdef DEBUG_ICON
-        printf("done with iconify\n");
-#endif
-}
-
-
-BOOL ICON_isAtPoint(HWND hwnd, POINT pt)
-{
-       	WND *wndPtr = WIN_FindWndPtr( hwnd );
-	int iconWidth, iconHeight;
-
-/****************
-	if (wndPtr->hwndParent != GetDesktopWindow()) { 
-        	pt.x -= wndPtr->rectClient.left;
-        	pt.y -= wndPtr->rectClient.top;
-	} 
-*****************/
- 
-	
-	if (wndPtr->hIcon != (HICON)NULL) {
-		ICONALLOC   *lpico;
-      		lpico = (ICONALLOC *)GlobalLock(wndPtr->hIcon);
-      		iconWidth = (int)lpico->descriptor.Width;
-      		iconHeight = (int)lpico->descriptor.Height;
-    	} else {
-      		iconWidth = 64;
-      		iconHeight = 64;
-    	}	
-
-#ifdef DEBUG_ICON
-        printf("icon x,y is %d,%d\n",
-		wndPtr->ptIconPos.x, wndPtr->ptIconPos.y);
-
-        printf("icon end x,y is %d,%d\n",
-		wndPtr->ptIconPos.x + 100, 
-		wndPtr->ptIconPos.y + iconHeight + 20);
-
-        printf("mouse pt x,y is %d,%d\n", pt.x, pt.y);
-
-	printf("%d\n", IsIconic(hwnd));
-	printf("%d\n", (pt.x >= wndPtr->ptIconPos.x));
-	printf("%d\n", (pt.x < wndPtr->ptIconPos.x + 100));
-	printf("%d\n", (pt.y >= wndPtr->ptIconPos.y));
-	printf("%d\n", (pt.y < wndPtr->ptIconPos.y + iconHeight + 20));
-	printf("%d\n", !(wndPtr->dwStyle & WS_DISABLED));
-	printf("%d\n",  (wndPtr->dwStyle & WS_VISIBLE));
-	printf("%d\n", !(wndPtr->dwExStyle & WS_EX_TRANSPARENT));
-#endif
-	
-        if ( IsIconic(hwnd) &&
-            (pt.x >= wndPtr->ptIconPos.x) &&
-            (pt.x < wndPtr->ptIconPos.x + 100) &&
-            (pt.y >= wndPtr->ptIconPos.y) &&
-            (pt.y < wndPtr->ptIconPos.y + iconHeight + 20) &&
-            !(wndPtr->dwStyle & WS_DISABLED) &&
-            (wndPtr->dwStyle & WS_VISIBLE) &&
-            !(wndPtr->dwExStyle & WS_EX_TRANSPARENT))
-        {
-#ifdef DEBUG_ICON
-		printf("got a winner!\n");
-#endif
-		return 1;
-        } 
- 
-	return 0;
-	
-}
-
-HWND ICON_findIconFromPoint(POINT pt)
-{
-    	HWND hwnd = GetTopWindow( GetDesktopWindow() );
-    	WND *wndPtr;
-	HWND hwndRet = 0;
-
-    	while (hwnd) {
-
-        	if ( !(wndPtr=WIN_FindWndPtr(hwnd)))  return 0;
-      		if (ICON_isAtPoint(hwnd, pt))  {
-#ifdef DEBUG_ICON
-			printf("returning\n");
-#endif
-			return hwndRet = hwnd;
-		} else {
-#ifdef DEBUG_ICON
-			printf("checking child\n");
-#endif
-      			hwnd = wndPtr->hwndChild;
-		}
-    	}
-	return hwndRet;
-}
-
-
-ICON_Deiconify(HWND hwnd)
-{
-	WND *wndPtr = WIN_FindWndPtr( hwnd );
-
-#ifdef DEBUG_ICON
-	printf("deiconifying\n");
-#endif
-	XUnmapWindow(display, wndPtr->icon); 
-	wndPtr->dwStyle &= ~WS_MINIMIZE;
-/*	wndPtr->rectNormal = myrect;
-*/
-	MoveWindow(hwnd, 
-		wndPtr->rectClientSave.left, 
-		wndPtr->rectClientSave.top,
-		wndPtr->rectClientSave.right - wndPtr->rectClientSave.left, 
-		wndPtr->rectClientSave.bottom - wndPtr->rectClientSave.top, 
-		FALSE);
-
-	XMapWindow(display, wndPtr->window);
-}
-
-
diff --git a/windows/mdi.c b/windows/mdi.c
index 80dd6d7..66a511e 100644
--- a/windows/mdi.c
+++ b/windows/mdi.c
@@ -16,7 +16,7 @@
 #define DEBUG_MDI /* */
 
 extern WORD MENU_DrawMenuBar( HDC hDC, LPRECT lprect,
-			      HMENU hmenu, BOOL suppress_draw );  /* menu.c */
+			      HWND hwnd, BOOL suppress_draw );  /* menu.c */
 
 /**********************************************************************
  *					MDIRecreateMenuList
@@ -310,6 +310,7 @@
     
     ci->flagChildMaximized = FALSE;
 
+    ShowWindow(child, SW_RESTORE);		/* display the window */
     SendMessage(GetParent(parent), WM_NCPAINT, 1, 0);
     MDIBringChildToTop(parent, child, FALSE, FALSE);
 
@@ -571,7 +572,7 @@
 	rect.right -= SYSMETRICS_CXSIZE;
 	rect.bottom = rect.top + SYSMETRICS_CYMENU;
 
-	MENU_DrawMenuBar(hdc, &rect, wndPtr->wIDmenu, FALSE);
+	MENU_DrawMenuBar(hdc, &rect, hwndFrame, FALSE);
 	
 	DeleteDC(hdcMem);
 	ReleaseDC(hwndFrame, hdc);
@@ -751,8 +752,6 @@
 	    return SendMessage(GetParent(hwnd), WM_MDIMAXIMIZE, hwnd, 0);
 
 	  case SC_RESTORE:
-	    if (IsIconic(hwnd))
-	        ICON_Deiconify(hwnd);
 	    return SendMessage(GetParent(hwnd), WM_MDIRESTORE, hwnd, 0);
 	}
 	break;
diff --git a/windows/message.c b/windows/message.c
index fdac135..6d7a21a 100644
--- a/windows/message.c
+++ b/windows/message.c
@@ -198,6 +198,7 @@
  * Return value indicates whether the translated message must be passed
  * to the user.
  * Actions performed:
+ * - Find the window for this message.
  * - Translate button-down messages in double-clicks.
  * - Send the WM_NCHITTEST message to find where the cursor is.
  * - Activate the window if needed.
@@ -208,6 +209,7 @@
 static BOOL MSG_TranslateMouseMsg( MSG *msg, BOOL remove )
 {
     BOOL eatMsg = FALSE;
+    LONG hittest_result;
     static DWORD lastClickTime = 0;
     static WORD  lastClickMsg = 0;
     static POINT lastClickPos = { 0, 0 };
@@ -216,10 +218,29 @@
 		       (msg->message == WM_RBUTTONDOWN) ||
 		       (msg->message == WM_MBUTTONDOWN));
 
+      /* Find the window */
+
+    if (GetCapture())
+    {
+	msg->hwnd = GetCapture();
+	msg->lParam = MAKELONG( msg->pt.x, msg->pt.y );
+	ScreenToClient( msg->hwnd, (LPPOINT)&msg->lParam );
+	return TRUE;  /* No need to further process the message */
+    }
+    else msg->hwnd = WindowFromPoint( msg->pt );
+
       /* Send the WM_NCHITTEST message */
 
-    LONG hittest_result = SendMessage( msg->hwnd, WM_NCHITTEST, 0,
-				       MAKELONG( msg->pt.x, msg->pt.y ) );
+    hittest_result = SendMessage( msg->hwnd, WM_NCHITTEST, 0,
+				  MAKELONG( msg->pt.x, msg->pt.y ) );
+    while ((hittest_result == HTTRANSPARENT) && (msg->hwnd))
+    {
+	msg->hwnd = GetParent(msg->hwnd);
+	if (!msg->hwnd)
+	    hittest_result = SendMessage( msg->hwnd, WM_NCHITTEST, 0,
+					  MAKELONG( msg->pt.x, msg->pt.y ) );
+    }
+    if (!msg->hwnd) msg->hwnd = GetDesktopWindow();
 
       /* Send the WM_PARENTNOTIFY message */
 
@@ -305,6 +326,29 @@
 }
 
 
+/***********************************************************************
+ *           MSG_TranslateKeyboardMsg
+ *
+ * Translate an keyboard hardware event into a real message.
+ * Return value indicates whether the translated message must be passed
+ * to the user.
+ */
+static BOOL MSG_TranslateKeyboardMsg( MSG *msg )
+{
+      /* Should check Ctrl-Esc and PrintScreen here */
+
+    msg->hwnd = GetFocus();
+    if (!msg->hwnd)
+    {
+	  /* Send the message to the active window instead,  */
+	  /* translating messages to their WM_SYS equivalent */
+	msg->hwnd = GetActiveWindow();
+	msg->message += WM_SYSKEYDOWN - WM_KEYDOWN;
+    }
+    return TRUE;
+}
+
+
 /**********************************************************************
  *		SetDoubleClickTime  (USER.20)
  */
@@ -391,30 +435,6 @@
     msg.pt.x    = xPos & 0xffff;
     msg.pt.y    = yPos & 0xffff;
 
-      /* Determine the hwnd for this message */
-      /* Maybe this should be done in GetMessage() */
-
-    if (msg.hwnd = ICON_findIconFromPoint(msg.pt)) {
-       SendMessage( msg.hwnd, WM_SYSCOMMAND, SC_RESTORE, *(LONG*)&msg.pt );
-       return;
-    }
-
-
-    if ((message >= WM_MOUSEFIRST) && (message <= WM_MOUSELAST))
-    {
-	  /* Mouse event */
-	if (GetCapture()) msg.hwnd = GetCapture();
-	else msg.hwnd = WindowFromPoint( msg.pt );
-    }
-    else if ((message >= WM_KEYFIRST) && (message <= WM_KEYLAST))
-    {
-	  /* Keyboard event */
-	msg.hwnd = GetFocus();
-	if (!msg.hwnd && ((message==WM_KEYDOWN) || (message==WM_SYSKEYDOWN)))
-	    MessageBeep(0);  /* Beep on key press if no focus */
-    }
-    if (!msg.hwnd) return;  /* No window for this message */
-
       /* Merge with previous event if possible */
 
     if (sysMsgQueue->msgCount && (message == WM_MOUSEMOVE))
@@ -438,6 +458,7 @@
  * Like GetMessage(), but only return mouse and keyboard events.
  * Used internally for window moving and resizing. Mouse messages
  * are not translated.
+ * Warning: msg->hwnd is always 0.
  */
 BOOL MSG_GetHardwareMessage( LPMSG msg )
 {
@@ -560,6 +581,9 @@
     int pos, mask;
     LONG nextExp;  /* Next timer expiration time */
     XEvent event;
+    fd_set read_set;
+    struct timeval timeout;
+    int fd = ConnectionNumber(display);
 
     if (first || last)
     {
@@ -572,25 +596,9 @@
     }
     else mask = QS_MOUSE | QS_KEY | QS_POSTMESSAGE | QS_TIMER | QS_PAINT;
 
-    while (XPending( display ))
-    {
-	XNextEvent( display, &event );
-	EVENT_ProcessEvent( &event );
-    }    
-
     while(1)
     {    
-	  /* First handle a WM_QUIT message */
-	if (msgQueue->wPostQMsg)
-	{
-	    msg->hwnd    = hwnd;
-	    msg->message = WM_QUIT;
-	    msg->wParam  = msgQueue->wExitCode;
-	    msg->lParam  = 0;
-	    break;
-	}
-
-	  /* Then handle a message put by SendMessage() */
+	  /* First handle a message put by SendMessage() */
 	if (msgQueue->status & QS_SENDMESSAGE)
 	{
 	    if (!hwnd || (msgQueue->hWnd == hwnd))
@@ -623,7 +631,7 @@
 	}
 
 	  /* Now find a hardware event */
-	pos = MSG_FindMsg( sysMsgQueue, hwnd, first, last );
+	pos = MSG_FindMsg( sysMsgQueue, 0, first, last );
 	if (pos != -1)
 	{
 	    QMSG *qmsg = &sysMsgQueue->messages[pos];
@@ -639,10 +647,27 @@
 		    MSG_RemoveMsg( sysMsgQueue, pos );
 		    continue;
 		}
+	    else if ((msg->message >= WM_KEYFIRST) &&
+		     (msg->message <= WM_KEYLAST))
+		if (!MSG_TranslateKeyboardMsg( msg )) 
+		{
+		    MSG_RemoveMsg( sysMsgQueue, pos );
+		    continue;
+		}
 	    if (flags & PM_REMOVE) MSG_RemoveMsg( sysMsgQueue, pos );
 	    break;
 	}
 
+	  /* Now handle a WM_QUIT message */
+	if (msgQueue->wPostQMsg)
+	{
+	    msg->hwnd    = hwnd;
+	    msg->message = WM_QUIT;
+	    msg->wParam  = msgQueue->wExitCode;
+	    msg->lParam  = 0;
+	    break;
+	}
+
 	  /* Now find a WM_PAINT message */
 	if ((msgQueue->status & QS_PAINT) && (mask & QS_PAINT))
 	{
@@ -662,21 +687,27 @@
 	else nextExp = -1;  /* No timeout needed */
 
 	  /* Wait until something happens */
-	if (peek) return FALSE;
-	if (!XPending( display ) && (nextExp != -1))
+	FD_ZERO( &read_set );
+	FD_SET( fd, &read_set );
+	if (peek)
 	{
-	    fd_set read_set;
-	    struct timeval timeout;
-	    int fd = ConnectionNumber(display);
-	    FD_ZERO( &read_set );
-	    FD_SET( fd, &read_set );
+	    timeout.tv_sec = 0;
+	    timeout.tv_usec = 0;
+	    if (select( fd+1, &read_set, NULL, NULL, &timeout ) != 1)
+		return FALSE;  /* No data waiting to be read */
+	}
+	else if (!XPending( display ) && (nextExp != -1))
+	{
 	    timeout.tv_sec = nextExp / 1000;
 	    timeout.tv_usec = (nextExp % 1000) * 1000;
 	    if (select( fd+1, &read_set, NULL, NULL, &timeout ) != 1)
 		continue;  /* On timeout or error, restart from the start */
 	}
-	XNextEvent( display, &event );
-	EVENT_ProcessEvent( &event );
+	while (XPending( display ))
+	{
+	    XNextEvent( display, &event );
+	    EVENT_ProcessEvent( &event );
+	}
     }
 
       /* We got a message */
@@ -825,11 +856,10 @@
             (appMsgQueue->status & (QS_SENDMESSAGE | QS_PAINT)) ||
             (appMsgQueue->msgCount) || (sysMsgQueue->msgCount) )
             break;
+	nextExp = -1;
         if ((appMsgQueue->status & QS_TIMER) && 
             TIMER_CheckTimer( &nextExp, &msg, 0, FALSE))
             break;
-        else
-            nextExp=-1;
 
         if (!XPending( display ) && (nextExp != -1))
         {
diff --git a/windows/nonclient.c b/windows/nonclient.c
index 2bb188e..5909530 100644
--- a/windows/nonclient.c
+++ b/windows/nonclient.c
@@ -30,12 +30,15 @@
 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 BOOL GRAPH_DrawBitmap( HDC hdc, HBITMAP hbitmap, int xdest, int ydest,
+			      int xsrc, int ysrc, int width, int height,
+			      int rop );                     /* graphics.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 */
+			      HWND hwnd, BOOL suppress_draw ); /* menu.c */
 
 
   /* Some useful macros */
@@ -126,6 +129,12 @@
 
     if (!wndPtr) return 0;
 
+    /*
+     * we don't want to change the size if hwnd is an icon since
+     * there are no window manager handles on an icon
+     */
+    if(IsIconic(hwnd)) return 0;
+
     NC_AdjustRect( &tmpRect, wndPtr->dwStyle, FALSE, wndPtr->dwExStyle );
     params->rgrc[0].left   -= tmpRect.left;
     params->rgrc[0].top    -= tmpRect.top;
@@ -174,22 +183,34 @@
 
 
 /***********************************************************************
- *           NC_InternalNCHitTest
+ *           NC_HandleNCHitTest
  *
- * Perform the hit test calculation, but whithout testing the capture
- * window.
+ * Handle a WM_NCHITTEST message. Called from DefWindowProc().
  */
-static LONG NC_InternalNCHitTest( HWND hwnd, POINT pt )
+LONG NC_HandleNCHitTest( HWND hwnd, POINT pt )
 {
     RECT rect;
     WND *wndPtr = WIN_FindWndPtr( hwnd );
     if (!wndPtr) return HTERROR;
 
+#ifdef DEBUG_NONCLIENT
+    printf( "NC_HandleNCHitTest: hwnd=%x pt=%d,%d\n", hwnd, pt.x, pt.y );
+#endif
+
     GetWindowRect( hwnd, &rect );
     if (!PtInRect( &rect, pt )) return HTNOWHERE;
 
-      /* Check borders */
+    /*
+     * if this is a iconic window, we don't care were the hit
+     * occured, only that it did occur, just return HTCAPTION 
+     * so the caller knows the icon did get hit
+     */
+    if (IsIconic(hwnd))
+    {
+        return HTCAPTION;       /* change this to something meaningful? */
+    }
 
+      /* Check borders */
     if (HAS_THICKFRAME( wndPtr->dwStyle ))
     {
 	InflateRect( &rect, -SYSMETRICS_CXFRAME, -SYSMETRICS_CYFRAME );
@@ -302,39 +323,18 @@
 
 
 /***********************************************************************
- *           NC_HandleNCHitTest
- *
- * Handle a WM_NCHITTEST message. Called from DefWindowProc().
- */
-LONG NC_HandleNCHitTest( HWND hwnd, POINT pt )
-{
-#ifdef DEBUG_NONCLIENT
-    printf( "NC_HandleNCHitTest: hwnd=%x pt=%d,%d\n", hwnd, pt.x, pt.y );
-#endif
-    if (hwnd == GetCapture()) return HTCLIENT;
-    return NC_InternalNCHitTest( hwnd, pt );
-}
-
-
-/***********************************************************************
  *           NC_DrawSysButton
  */
 void NC_DrawSysButton( HWND hwnd, HDC hdc, BOOL down )
 {
     RECT rect;
     WND *wndPtr = WIN_FindWndPtr( hwnd );
-    HDC hdcMem = CreateCompatibleDC( hdc );
-    if (hdcMem)
-    {
-	NC_GetInsideRect( hwnd, &rect );
-	if (wndPtr->dwStyle & WS_CHILD)
-		SelectObject( hdcMem, hbitmapMDIClose );
-	else
-		SelectObject( hdcMem, hbitmapClose );
-	BitBlt( hdc, rect.left, rect.top, SYSMETRICS_CXSIZE,
-	       SYSMETRICS_CYSIZE, hdcMem, 1, 1, down ? NOTSRCCOPY : SRCCOPY );
-	DeleteDC( hdcMem );
-    }
+    NC_GetInsideRect( hwnd, &rect );
+    GRAPH_DrawBitmap( hdc, (wndPtr->dwStyle & WS_CHILD) ?
+		      hbitmapMDIClose : hbitmapClose,
+		      rect.left, rect.top,
+		      1, 1, SYSMETRICS_CXSIZE, SYSMETRICS_CYSIZE,
+		      down ? NOTSRCCOPY : SRCCOPY );
 }
 
 
@@ -344,17 +344,12 @@
 static void NC_DrawMaxButton( HWND hwnd, HDC hdc, BOOL down )
 {
     RECT rect;
-    HDC hdcMem = CreateCompatibleDC( hdc );
-    if (hdcMem)
-    {
-	NC_GetInsideRect( hwnd, &rect );
-	if (IsZoomed(hwnd))
-	    SelectObject( hdcMem, down ? hbitmapRestoreD : hbitmapRestore );
-	else SelectObject( hdcMem, down ? hbitmapMaximizeD : hbitmapMaximize );
-	BitBlt( hdc, rect.right - SYSMETRICS_CXSIZE - 1, rect.top - 1,
-	      SYSMETRICS_CXSIZE+2, SYSMETRICS_CYSIZE+2, hdcMem, 0, 0, SRCCOPY);
-	DeleteDC( hdcMem );
-    }
+    NC_GetInsideRect( hwnd, &rect );
+    GRAPH_DrawBitmap( hdc, (IsZoomed(hwnd) ?
+			    (down ? hbitmapRestoreD : hbitmapRestore) :
+			    (down ? hbitmapMaximizeD : hbitmapMaximize)),
+		     rect.right - SYSMETRICS_CXSIZE - 1, rect.top - 1,
+		     0, 0, SYSMETRICS_CXSIZE+2, SYSMETRICS_CYSIZE+2, SRCCOPY );
 }
 
 
@@ -365,18 +360,11 @@
 {
     RECT rect;
     WND *wndPtr = WIN_FindWndPtr( hwnd );
-    HDC hdcMem = CreateCompatibleDC( hdc );
-    if (hdcMem)
-    {
-	NC_GetInsideRect( hwnd, &rect );
-	if (wndPtr->dwStyle & WS_MAXIMIZEBOX)
-	    rect.right -= SYSMETRICS_CXSIZE + 1;	
-	if (down) SelectObject( hdcMem, hbitmapMinimizeD );
-	else SelectObject( hdcMem, hbitmapMinimize );
-	BitBlt( hdc, rect.right - SYSMETRICS_CXSIZE - 1, rect.top - 1,
-	      SYSMETRICS_CXSIZE+2, SYSMETRICS_CYSIZE+2, hdcMem, 0, 0, SRCCOPY);
-	DeleteDC( hdcMem );
-    }
+    NC_GetInsideRect( hwnd, &rect );
+    if (wndPtr->dwStyle & WS_MAXIMIZEBOX) rect.right -= SYSMETRICS_CXSIZE + 1;
+    GRAPH_DrawBitmap( hdc, (down ? hbitmapMinimizeD : hbitmapMinimize),
+		     rect.right - SYSMETRICS_CXSIZE - 1, rect.top - 1,
+		     0, 0, SYSMETRICS_CXSIZE+2, SYSMETRICS_CYSIZE+2, SRCCOPY );
 }
 
 
@@ -583,6 +571,27 @@
 	OffsetRgn( hrgn, xoffset, yoffset );  /* Restore region */
     }
     if (!hdc) return;
+
+
+    /*
+     * If this is an icon, we don't want to do any more nonclient painting
+     * of the window manager.
+     * If there is a class icon to draw, draw it
+     */
+    if (IsIconic(hwnd))
+    {
+        if (wndPtr->hIcon)  
+        {
+            SendMessage(hwnd, WM_ICONERASEBKGND, hdc, 0);
+            Rectangle(hdc, wndPtr->rectWindow.left, wndPtr->rectWindow.top,
+                     wndPtr->rectWindow.right, wndPtr->rectWindow.bottom);
+            DrawIcon(hdc, 0, 0, wndPtr->hIcon);
+        }
+      ReleaseDC(hwnd, hdc);
+	
+      return;
+    }
+
     if (ExcludeVisRect( hdc, wndPtr->rectClient.left-wndPtr->rectWindow.left,
 		        wndPtr->rectClient.top-wndPtr->rectWindow.top,
 		        wndPtr->rectClient.right-wndPtr->rectWindow.left,
@@ -628,8 +637,7 @@
     {
 	RECT r = rect;
 	r.bottom = rect.top + SYSMETRICS_CYMENU;  /* default height */
-	rect.top += MENU_DrawMenuBar( hdc, &r, (HMENU)wndPtr->wIDmenu,
-				      suppress_menupaint );
+	rect.top += MENU_DrawMenuBar( hdc, &r, hwnd, suppress_menupaint );
     }
 
     if (wndPtr->dwStyle & (WS_VSCROLL | WS_HSCROLL)) {
@@ -665,46 +673,6 @@
 }
 
 
-NC_DoNCPaintIcon(HWND hwnd)
-{
-      WND *wndPtr = WIN_FindWndPtr(hwnd);
-      PAINTSTRUCT ps;
-      HDC hdc;
-      int ret;
-      DC *dc;
-      GC testgc;
-      int s;
-      char buffer[256];
-
-      printf("painting icon\n");
-      if (wndPtr == NULL) {
-              printf("argh, can't find an icon to draw\n");
-              return;
-      }
-      hdc = BeginPaint(hwnd, &ps);
-
-      ret = DrawIcon(hdc, 100/2 - 16, 0, wndPtr->hIcon);
-      printf("ret is %d\n", ret);
-
-      if (s=GetWindowText(hwnd, buffer, 256))
-      {
-          /*SetBkColor(hdc, TRANSPARENT); */
-          TextOut(hdc, 0, 32, buffer, s);
-      }
-      EndPaint(hwnd, &ps);
-
-      printf("done painting icon\n");
-      
-}
-
-
-LONG NC_HandleNCPaintIcon( HWND hwnd )
-{
-    NC_DoNCPaintIcon(hwnd);
-    return 0;
-}
-
-
 
 /***********************************************************************
  *           NC_HandleNCPaint
@@ -761,8 +729,8 @@
 		CURSOR_SetWinCursor( hwnd, classPtr->wc.hCursor );
 		return TRUE;
 	    }
+	    else return FALSE;
 	}
-	break;
 
     case HTLEFT:
     case HTRIGHT:
@@ -830,7 +798,7 @@
 	    switch(msg.message)
 	    {
 	    case WM_MOUSEMOVE:
-		hittest = NC_InternalNCHitTest( hwnd, msg.pt );
+		hittest = NC_HandleNCHitTest( hwnd, msg.pt );
 		pt = msg.pt;
 		if ((hittest < HTLEFT) || (hittest > HTBOTTOMRIGHT))
 		    hittest = 0;
@@ -890,7 +858,7 @@
     POINT minTrack, maxTrack, capturePoint = pt;
     WND * wndPtr = WIN_FindWndPtr( hwnd );
 
-    if (IsZoomed(hwnd) || IsIconic(hwnd) || !IsWindowVisible(hwnd)) return;
+    if (IsZoomed(hwnd) || !IsWindowVisible(hwnd)) return;
     hittest = wParam & 0x0f;
     thickframe = HAS_THICKFRAME( wndPtr->dwStyle );
 
@@ -1053,7 +1021,7 @@
 	BOOL oldstate = pressed;
 	MSG_GetHardwareMessage( &msg );
 
-	pressed = (NC_InternalNCHitTest( hwnd, msg.pt ) == wParam);
+	pressed = (NC_HandleNCHitTest( hwnd, msg.pt ) == wParam);
 	if (pressed != oldstate)
 	{
 	    if (wParam == HTMINBUTTON) NC_DrawMinButton( hwnd, hdc, pressed );
@@ -1103,7 +1071,7 @@
     do
     {
 	MSG_GetHardwareMessage( &msg );
-	ScreenToClient( msg.hwnd, &msg.pt );
+	ScreenToClient( hwnd, &msg.pt );
 	switch(msg.message)
 	{
 	case WM_LBUTTONUP:
@@ -1210,6 +1178,16 @@
  */
 LONG NC_HandleNCLButtonDblClk( HWND hwnd, WORD wParam, LONG lParam )
 {
+    /*
+     * if this is an icon, send a restore since we are handling
+     * a double click
+     */
+    if (IsIconic(hwnd))
+    {
+      SendMessage(hwnd, WM_SYSCOMMAND, SC_RESTORE, lParam);
+      return 0;
+    } 
+
     switch(wParam)  /* Hit test */
     {
     case HTCAPTION:
@@ -1247,8 +1225,7 @@
 	break;
 
     case SC_MINIMIZE:
-	ICON_Iconify( hwnd );
-	/*ShowWindow( hwnd, SW_MINIMIZE );*/
+	ShowWindow( hwnd, SW_MINIMIZE ); 
 	break;
 
     case SC_MAXIMIZE:
@@ -1256,7 +1233,6 @@
 	break;
 
     case SC_RESTORE:
-	ICON_Deiconify(hwnd);
 	ShowWindow( hwnd, SW_RESTORE );
 	break;
 
diff --git a/windows/painting.c b/windows/painting.c
index abac9b5..8c5658c 100644
--- a/windows/painting.c
+++ b/windows/painting.c
@@ -98,6 +98,14 @@
     if (!hwnd) hwnd = GetDesktopWindow();
     if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
 
+    /* 
+     *	I can't help but feel that this belongs somewhere upstream...
+     *
+     *  Don't redraw the window if it is iconified and we have an
+     *  icon to draw for it
+     */
+    if (IsIconic(hwnd) && wndPtr->hIcon) return FALSE;
+
     GetClientRect( hwnd, &rectClient );
     rectWindow = wndPtr->rectWindow;
     OffsetRect(&rectWindow, -wndPtr->rectClient.left, -wndPtr->rectClient.top);
diff --git a/windows/timer.c b/windows/timer.c
index 641bbe0..6aad7ac 100644
--- a/windows/timer.c
+++ b/windows/timer.c
@@ -134,7 +134,25 @@
 
     if (!timeout) return 0;
     if (!hwnd && !proc) return 0;
-    
+
+      /* Check if there's already a timer with the same hwnd and id */
+
+    if (hwnd)
+    {
+	for (i = 0, pTimer = TimersArray; i < NB_TIMERS; i++, pTimer++)
+	    if ((pTimer->hwnd == hwnd) && (pTimer->id == id) &&
+		(pTimer->timeout != 0))
+	    {
+		  /* Got one: set new values and return */
+		pTimer->timeout = timeout;
+		pTimer->expires = GetTickCount() + timeout;
+		pTimer->proc    = proc;
+		TIMER_RemoveTimer( pTimer );
+		TIMER_InsertTimer( pTimer );
+		return id;
+	    }
+    }
+
       /* Find a free timer */
     
     for (i = 0, pTimer = TimersArray; i < NB_TIMERS; i++, pTimer++)
diff --git a/windows/win.c b/windows/win.c
index 3924908..2c27a76 100644
--- a/windows/win.c
+++ b/windows/win.c
@@ -251,8 +251,7 @@
     CREATESTRUCT *createStruct;
     HANDLE hcreateStruct;
     int wmcreate;
-    XSetWindowAttributes win_attr, icon_attr;
-    int iconWidth, iconHeight;
+    XSetWindowAttributes win_attr;
 
 #ifdef DEBUG_WIN
     printf( "CreateWindowEx: %04X '%s' '%s' %04X %d,%d %dx%d %04X %04X %04X %08X\n",
@@ -373,11 +372,7 @@
 	  /* Only select focus events on top-level override-redirect windows */
 	if (win_attr.override_redirect) win_attr.event_mask |= FocusChangeMask;
     }
-    if (Options.nobackingstore)
-       win_attr.backing_store = NotUseful;
-    else
-       win_attr.backing_store = Always;
-
+    win_attr.backing_store = Options.backingstore ? WhenMapped : NotUseful;
     win_attr.save_under = ((classPtr->wc.style & CS_SAVEBITS) != 0);
 
     WINPOS_GetMinMaxInfo( hwnd, &maxSize, &maxPos, &minTrack, &maxTrack );
@@ -392,7 +387,7 @@
 	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,
@@ -403,42 +398,22 @@
     XStoreName( display, wndPtr->window, windowName );
 
 
-    /* create icon window */
-
-    icon_attr.override_redirect = rootWindow==DefaultRootWindow(display);
-    icon_attr.background_pixel = WhitePixelOfScreen(screen);
-    icon_attr.event_mask = ExposureMask | KeyPressMask |
-                            ButtonPressMask | ButtonReleaseMask;
-
+    /* 
+     * store icon handle, icon handle is kept in class.  If we
+     * have an icon, make the icon size the size of the icon,
+     * if we don't have an icon, just give it 64x64
+     */
     wndPtr->hIcon = classPtr->wc.hIcon;
     if (wndPtr->hIcon != (HICON)NULL) {
       ICONALLOC   *lpico;
       lpico = (ICONALLOC *)GlobalLock(wndPtr->hIcon);
-      printf("icon is %d x %d\n", 
-              (int)lpico->descriptor.Width,
-              (int)lpico->descriptor.Height);
-      iconWidth = (int)lpico->descriptor.Width;
-      iconHeight = (int)lpico->descriptor.Height;
+      wndPtr->iconWidth = (int)lpico->descriptor.Width;
+      wndPtr->iconHeight = (int)lpico->descriptor.Height;
     } else {
-      printf("icon was NULL\n");
-      iconWidth = 64;
-      iconHeight = 64;
+      wndPtr->iconWidth = 64;
+      wndPtr->iconHeight = 64;
     }
 
-    wndPtr->icon = XCreateWindow(display, parentPtr->window,
-                    10, 10, 100, iconHeight+20, 
-                    0, CopyFromParent,
-                    InputOutput, CopyFromParent,
-                    CWBorderPixel | CWEventMask | CWOverrideRedirect, 
-                    &icon_attr);
-   
-    if (style & WS_MINIMIZE) 
-    {
-      style &= ~WS_MINIMIZE;
-    }
- 
-
-
 #ifdef DEBUG_MENU
     printf("CreateWindowEx // menu=%04X instance=%04X classmenu=%08X !\n", 
     	menu, instance, classPtr->wc.lpszMenuName); 
@@ -505,11 +480,12 @@
     else CURSOR_SetWinCursor( hwnd, LoadCursor( 0, IDC_ARROW ));
 
     EVENT_RegisterWindow( wndPtr->window, hwnd );
-    EVENT_RegisterWindow( wndPtr->icon, hwnd );
 
     WIN_SendParentNotify( hwnd, WM_CREATE, MAKELONG( hwnd, wndPtr->wIDmenu ) );
     
     if (style & WS_VISIBLE) ShowWindow( hwnd, SW_SHOW );
+/*    if (style & WS_MINIMIZE) ShowWindow( hwnd, SW_MINIMIZE ); */
+
 #ifdef DEBUG_WIN
     printf( "CreateWindowEx: return %04X \n", hwnd);
 #endif
@@ -805,6 +781,27 @@
     return wndPtr->hwndParent;
 }
 
+/*****************************************************************
+ *         SetParent              (USER.233)
+ */
+HWND SetParent(HWND hwndChild, HWND hwndNewParent)
+{
+    HWND temp;
+
+    WND *wndPtr = WIN_FindWndPtr(hwndChild);
+    if (!wndPtr || !(wndPtr->dwStyle & WS_CHILD)) return 0;
+
+    temp = wndPtr->hwndParent;
+
+    if (hwndNewParent)
+      wndPtr->hwndParent = hwndNewParent;
+    else
+      wndPtr->hwndParent = GetDesktopWindow();
+
+    return temp;
+}
+
+
 
 /*******************************************************************
  *         IsChild    (USER.48)
diff --git a/windows/winpos.c b/windows/winpos.c
index 8e013e7..a9415cd 100644
--- a/windows/winpos.c
+++ b/windows/winpos.c
@@ -10,9 +10,12 @@
 #include "user.h"
 #include "win.h"
 #include "message.h"
+#include <assert.h>
 
 static HWND hwndActive = 0;  /* Currently active window */
 
+/* #define DEBUG_WIN /**/
+
 
 /***********************************************************************
  *           GetWindowRect   (USER.32)
@@ -220,6 +223,45 @@
 }
 
 
+/*
+ * hwnd is the handle to the first child window to hide
+ */
+static void WINPOS_hideChildren(HWND hwnd)
+{
+    WND *wndPtr;
+
+    while (hwnd) {
+	ShowWindow(hwnd, SW_HIDE);
+	wndPtr = WIN_FindWndPtr(hwnd);
+	assert(wndPtr);
+	WINPOS_hideChildren(wndPtr->hwndChild); 
+	hwnd = wndPtr->hwndNext;
+    }
+}
+
+
+static void WINPOS_ChildrenComeOutToPlay(HWND hwnd)
+{
+    WND *wndPtr;
+    
+    while (hwnd) {
+	/*
+	 * we shouldn't really be calling SW_SHOWNOACTIVATE
+	 * here because we wake up all windows, even the ones
+	 * the user has decided to iconify or hide
+	 *
+	 * have to use SHOWNOACTIVATE instead of SHOWNORMAL
+	 * since we are traversing the window tree and don't
+	 * want windows linked/unlined under us
+	 */
+	ShowWindow(hwnd, SW_SHOWNOACTIVATE);
+	wndPtr = WIN_FindWndPtr(hwnd);
+	assert(wndPtr);
+	WINPOS_ChildrenComeOutToPlay(wndPtr->hwndChild); 
+	hwnd = wndPtr->hwndNext;
+    }
+}
+
 /***********************************************************************
  *           ShowWindow   (USER.42)
  */
@@ -227,41 +269,72 @@
 {    
     WND * wndPtr = WIN_FindWndPtr( hwnd );
     BOOL wasVisible;
+    BOOL wasIconic;
     int swpflags = 0;
 
+    if (!wndPtr) return FALSE;
+
 #ifdef DEBUG_WIN
     printf("ShowWindow: hwnd=%04X, cmd=%d\n", hwnd, cmd);
 #endif
-    
-    if (!wndPtr) return FALSE;
+
+    /*
+     *  wasVisible is true if user has not made window invisible 
+     *  wasIconic is true if the window is not iconified
+     */
     wasVisible = (wndPtr->dwStyle & WS_VISIBLE) != 0;
+
     switch(cmd)
     {
         case SW_HIDE:
-	    if (!wasVisible) return FALSE;  /* Nothing to do */
+	    /*
+	     *  if the window wasn't visible to begin with -- just return
+	     */
+	    if (!wasVisible) 
+		return FALSE;  /* Nothing to do */
 	    swpflags |= SWP_HIDEWINDOW | SWP_NOSIZE | SWP_NOMOVE | 
 		        SWP_NOACTIVATE | SWP_NOZORDER;
 	    break;
 
+
 	case SW_SHOWMINNOACTIVE:
 	case SW_SHOWMINIMIZED:
-	case SW_SHOWMAXIMIZED:
-	case SW_MINIMIZE:
+	case SW_MINIMIZE: 
 	    wndPtr->dwStyle |= WS_MINIMIZE;
 	    swpflags |= SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE | 
 		        SWP_NOACTIVATE | SWP_NOZORDER;
+
+	    /*
+	     *	tell children that they are getting hidden
+	     */
+	    WINPOS_hideChildren(wndPtr->hwndChild);
+
+	    /* store the size and position of the window, so we can
+	     *	deiconify it to the same size and position	
+	     */
+            wndPtr->rectNormal = wndPtr->rectWindow; 
+            wndPtr->ptIconPos.x = wndPtr->rectWindow.left;
+            wndPtr->ptIconPos.y = wndPtr->rectWindow.top;
+	    /* move the window to icon size and position and
+	     * tell it that it is going to have to be painted
+	     */
+            MoveWindow(hwnd, wndPtr->ptIconPos.x, wndPtr->ptIconPos.y,
+                        wndPtr->iconWidth, wndPtr->iconHeight, FALSE);
+            SendMessage(hwnd, WM_PAINTICON, 0, 0);
 	    break;
 
+
 	case SW_SHOWNA:
-	case SW_MAXIMIZE:
+	case SW_SHOWMAXIMIZED: /* same as SW_MAXIMIZE: */
 	case SW_SHOW:
 	    swpflags |= SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE;
 	    break;
 
-	case SW_NORMAL:
-	case SW_SHOWNORMAL:
+
+	case SW_SHOWNORMAL:  /* same as SW_NORMAL: */
 	case SW_SHOWNOACTIVATE:
 	case SW_RESTORE:
+	    wasIconic = IsIconic(hwnd);
 	    wndPtr->dwStyle &= ~WS_MINIMIZE;
 	    wndPtr->dwStyle &= ~WS_MAXIMIZE;
 	    swpflags |= SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE;
@@ -270,8 +343,17 @@
 		swpflags |= SWP_NOZORDER;
 		if (GetActiveWindow()) swpflags |= SWP_NOACTIVATE;
 	    }
+	    if (wasIconic) {
+		MoveWindow(hwnd, wndPtr->rectNormal.left, 
+			   wndPtr->rectNormal.top,
+			   wndPtr->rectNormal.right - wndPtr->rectNormal.left, 
+			   wndPtr->rectNormal.bottom - wndPtr->rectNormal.top, 
+			   FALSE);
+	    }
+	    WINPOS_ChildrenComeOutToPlay(wndPtr->hwndChild);
 	    break;
     }
+
     SendMessage( hwnd, WM_SHOWWINDOW, (cmd != SW_HIDE), 0 );
     SetWindowPos( hwnd, 0, 0, 0, 0, 0, swpflags );
 
@@ -288,6 +370,7 @@
 	SendMessage( hwnd, WM_MOVE, 0,
 		   MAKELONG(wndPtr->rectClient.left, wndPtr->rectClient.top) );
     }
+
     return wasVisible;
 }