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/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;
 }