Release 0.4.7

Mon Nov  1 14:40:21 1993  julliard@di.epfl.ch (Alexandre Julliard)

	* [if1632/user.spec]
	Removed some duplicate entries.

	* [include/dialog.h] [windows/dialog.c]
	Implemented dialog units and fonts.
	Added preliminary loading of dialog resources.
	Preliminary implementation of DialogBox().
	Implemented Get/SetDlgItem* functions.

	* [windows/win.c]
	Implemented WM_PARENTNOTIFY message.
	Implemented CreateWindowEx() and GetWindow().
	Completed DestroyWindow().

Mon Nov  1 18:19:34 1993  Erik Bos

	* [loader/signal.c]
	Added support for int 0x11 & 0x12.

        * [loader/int21.c]
	Improved function handling.

Sun Oct 31 12:38:09 1993  David Metcalfe <david@prism.demon.co.uk>

	* [objects/font.c]
	Implemented GetCharWidth().

Wed Oct 27 09:56:06 1993  John Brezak <brezak@ch.hp.com>

	* [Makefile]
        Use GNU malloc.

	* [include/int21.h include/wine.h]
        Change sc_eflags to sc_efl .

	* [include/wine.h]
        Fix misplaced #endif
        Include <signal.h> for NetBSD

	* [loader/int21.c]
        Don't include <sys/vfs.h> in NetBSD
        Do include <sys/mount.h> in NetBSD
        Cleanup some lint.

Mon Oct 26 17:59:01 1993  Erik Bos

        * [include/int21.h]
        Added.

        * [loader/int21.c]
        Added support for many dos ints.

        * [misc/file.c] [include/files.h]
        Moved OPEN_MAX and DosDriveStruct to files.h.

Sun Oct 24 13:36:50 1993  David Metcalfe <david@prism.demon.co.uk>

	* [controls/button.c]
	Implemented CHECKBOX, AUTOCHECKBOX, 3STATE, AUTO3STATE,
	RADIOBUTTON, AUTORADIOBUTTON, GROUPBOX controls, together with
	a preliminary USERBUTTON control.

	* [objects/text.c]
	Corrected bugs in TEXT_NextLine() and added handling of prefix
	character.

	* [controls/button.c]
	Disabled focus handling by commenting out SetFocus() calls until
	serious bug can be found.

Oct  20, 93 martin2@trgcorp.solucorp.qc.ca (Martin Ayotte)

	* [controls/listbox.c]
	Listbox control window
		Painting cleanup, new messages processed.

	* [controls/scroll.c]
	Scroll bar control window
		Painting cleanup.

	* [controls/combo.c]
	Combo box control window
		Painting cleanup.

Tue Oct 12 17:50:11 1993  julliard@di.epfl.ch (Alexandre Julliard)

	* [objects/color.c] [objects/palette.c] [windows/syscolor.c]
	Better support for the private color map.
	Using a private map is now the default.

	* [windows/win.c]
	Bug fix.

	* [include/dialog.h] [windows/dialog.c]
	Implemented CreateDialog*() and IsDialogMessage().

	* [misc/xt.c] [windows/defwnd.c]
	Moved DefWindowProc() to defwnd.c.
	Added WM_NCCREATE, WM_NCDESTROY and WM_CTLCOLOR handling.

	* [windows/defdlg.c]
	Started the implementation of DefDlgProc().

	* [windows/win.c]
	Added WM_NCCREATE and WM_NCDESTROY messages.
	Implemented IsChild().

Tue Oct 12 17:50:20 1993  David Metcalfe <david@prism.demon.co.uk>

	* [windows/focus.c]
	Implemented GetFocus() and SetFocus().

	* [windows/event.c]
	Added processing of FocusIn and FocusOut events.

	* [windows/graphics.c]
	Added DrawFocusRect().

Sat Oct  9 14:36:57 1993  Erik Bos

	* [loader/int1a.c]
	Added more function handling.

Wed Oct  6 12:21:22 1993  Erik Bos

	* [loader/signal.c]
	Split signal.c into int1a.c, int21.c and signal.c.

Tue Oct  5 22:12:40 1993  David Metcalfe

	* [controls/static.c] [control/widgets.c]
	Static control class.

	* [objects/text.c]
	Added processing of additional DT_ flags to DrawText().

	* [windows/win.c] [misc/xt.c]
	Added SetWindowText() and WM_SETTEXT processing.

Tue Oct  5 22:12:40 1993  Martin Ayotte

	* [controls/listbox.c]
	Listbox control window

	* [controls/scroll.c]
	Scroll bar control window

	* [controls/combo.c]
	Combo box control window

	* [include/combo.h]
	Combo box definitions

	* [include/listbox.h]
	Listbox definitions

	* [include/scroll.h]
	Scroll bar definitions

Sat Oct  2 09:35:54 1993  Bob Amstadt  (bob at pooh)

	* [if1632/callback.c]
	Fixed bug in MakeProcInstance().

	* [debugger/info.c]
	Changed x/w and x/b to display in hex.

	* [debugger/i386-pinsn.c]
	Added code to properly unassemble 16-bit indexing.

Fri Oct  1 08:29:05 1993  Bob Amstadt  (bob at pooh)

	* [loader/files.c] [misc/profile.c]
	System initialization file is now called "wine.ini" and can
	be located in the current directory, the user's home directory,
	or any directories specified in the WINEPATH environment variable.

	* [tools/build.c] [if1632/call.S] [include/regfunc.h]
	Changed register function stack to match sigcontext structure.

Thu Sep 30 22:30:21 1993  Bob Amstadt  (bob at pooh)

	* [loader/files.c]
	Created function to search a path for files to load.

	* [loader/wine.c]
	Modified exe and dll file loading to search through path
	specified by the environment variable WINEPATH.

Thu Sep 30 22:30:21 1993  Eric Youngdale

	* [loader/signal.c]
	Bug fix.

Thu Sep 30 22:30:21 1993  John Brezak

	* [debugger/dbg.y] [debugger/debug.l] [debugger/dtest.c] 
	  [debugger/obstack.h]
	Updates to allow debugger to function under NetBSD.
diff --git a/controls/button.c b/controls/button.c
index f843beb..1a13b9d 100644
--- a/controls/button.c
+++ b/controls/button.c
@@ -1,33 +1,53 @@
-/* File: button.c -- MS-Windows(tm) compatible "Button" replacement widget
+/* File: button.c -- Button type widgets
  *
- *                   programmed by Johannes Ruscheinski for the Linux WABI
- *                   project.
- *		     (C) 1993 by Johannes Ruscheinski
- *
- *                   Modifications by David Metcalfe
+ * Copyright (C) 1993 Johannes Ruscheinski
+ * Copyright (C) 1993 David Metcalfe
  */
 
+static char Copyright1[] = "Copyright Johannes Ruscheinski, 1993";
+static char Copyright2[] = "Copyright David Metcalfe, 1993";
+
 #include <windows.h>
 #include "win.h"
 
 LONG ButtonWndProc(HWND hWnd, WORD uMsg, WORD wParam, LONG lParam);
 
-static COLORREF color_windowframe, color_btnface, color_btnshadow,
-		color_btntext, color_btnhighlight;
+static COLORREF color_windowtext, color_windowframe, color_btnface, 
+                color_btnshadow, color_btntext, color_btnhighlight;
 
 static BOOL pressed;
 
 #define NOTIFY_PARENT(hWndCntrl, wNotifyCode) \
 	SendMessage(GetParent(hWndCntrl), WM_COMMAND, \
-		    GetDlgCtrlID(hWndCntrl), MAKELPARAM(hWndCntrl, wNotifyCode));
+		GetDlgCtrlID(hWndCntrl), MAKELPARAM(hWndCntrl, wNotifyCode));
 #define DIM(array)	((sizeof array)/(sizeof array[0]))
 
 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);
 static LONG PB_LButtonDblClk(HWND hWnd, WORD wParam, LONG lParam);
+static LONG PB_KillFocus(HWND hwnd);
 static void DrawRaisedPushButton(HDC hDC, HWND hButton, RECT rc);
 static void DrawPressedPushButton(HDC hDC, HWND hButton, RECT rc);
+static LONG CB_Paint(HWND hWnd);
+static LONG CB_LButtonDown(HWND hWnd, WORD wParam, LONG lParam);
+static LONG CB_LButtonUp(HWND hWnd, WORD wParam, LONG lParam);
+static LONG CB_LButtonDblClk(HWND hWnd, WORD wParam, LONG lParam);
+static LONG CB_KillFocus(HWND hWnd);
+static LONG CB_SetCheck(HWND hWnd, WORD wParam);
+static LONG CB_GetCheck(HWND hWnd);
+static LONG RB_Paint(HWND hWnd);
+static LONG RB_LButtonDown(HWND hWnd, WORD wParam, LONG lParam);
+static LONG RB_LButtonUp(HWND hWnd, WORD wParam, LONG lParam);
+static LONG RB_LButtonDblClk(HWND hWnd, WORD wParam, LONG lParam);
+static LONG RB_KillFocus(HWND hWnd);
+static LONG RB_SetCheck(HWND hWnd, WORD wParam);
+static LONG RB_GetCheck(HWND hWnd);
+static LONG GB_Paint(HWND hWnd);
+static LONG UB_Paint(HWND hWnd);
+static LONG UB_LButtonDown(HWND hWnd, WORD wParam, LONG lParam);
+static LONG UB_LButtonUp(HWND hWnd, WORD wParam, LONG lParam);
+static LONG UB_KillFocus(HWND hWnd);
 
 typedef struct
 {
@@ -35,9 +55,12 @@
     LONG (*lButtonDownfn)();
     LONG (*lButtonUpfn)();
     LONG (*lButtonDblClkfn)();
+    LONG (*killFocusfn)();
+    LONG (*setCheckfn)();
+    LONG (*getCheckfn)();
 } BTNFN;
 
-#define MAX_BTN_TYPE  2
+#define MAX_BTN_TYPE  10
 
 static BTNFN btnfn[MAX_BTN_TYPE] =
 {
@@ -45,13 +68,91 @@
 	(LONG(*)())PB_Paint,                       /* BS_PUSHBUTTON */
 	(LONG(*)())PB_LButtonDown,
 	(LONG(*)())PB_LButtonUp,
-	(LONG(*)())PB_LButtonDblClk
+	(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_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
     }
 };
 
@@ -80,42 +181,49 @@
 		else
 		{
 		    /* initialise colours used for button rendering: */
+		    color_windowtext   = GetSysColor(COLOR_WINDOWTEXT);
 		    color_windowframe  = GetSysColor(COLOR_WINDOWFRAME);
 		    color_btnface      = GetSysColor(COLOR_BTNFACE);
 		    color_btnshadow    = GetSysColor(COLOR_BTNSHADOW);
 		    color_btntext      = GetSysColor(COLOR_BTNTEXT);
 		    color_btnhighlight = GetSysColor(COLOR_BTNHIGHLIGHT);
 
+		    (WORD)(*(wndPtr->wExtra)) = 0;
 		    pressed = FALSE;
 		    lResult = 0L;
 		}
 		break;
 
 	case WM_PAINT:
-		(btnfn[style].paintfn)(hWnd);
+		if (btnfn[style].paintfn)
+		    (btnfn[style].paintfn)(hWnd);
 		break;
 
 	case WM_LBUTTONDOWN:
-		(btnfn[style].lButtonDownfn)(hWnd, wParam, lParam);
+		if (btnfn[style].lButtonDownfn)
+		    (btnfn[style].lButtonDownfn)(hWnd, wParam, lParam);
 		break;
 
 	case WM_LBUTTONUP:
-		(btnfn[style].lButtonUpfn)(hWnd, wParam, lParam);
+		if (btnfn[style].lButtonUpfn)
+		    (btnfn[style].lButtonUpfn)(hWnd, wParam, lParam);
 		break;
 
 	case WM_LBUTTONDBLCLK:
-		(btnfn[style].lButtonDblClkfn)(hWnd, wParam, lParam);
+		if (btnfn[style].lButtonDblClkfn)
+		    (btnfn[style].lButtonDblClkfn)(hWnd, wParam, lParam);
 		break;
 
 	case WM_SETFOCUS:
 		break;
 
 	case WM_KILLFOCUS:
-		InvalidateRect(hWnd, NULL, FALSE);
-		UpdateWindow(hWnd);
+		if (btnfn[style].killFocusfn)
+		    (btnfn[style].killFocusfn)(hWnd);
 		break;
 
 	case WM_SYSCOLORCHANGE:
+		color_windowtext   = GetSysColor(COLOR_WINDOWTEXT);
 		color_windowframe  = GetSysColor(COLOR_WINDOWFRAME);
 		color_btnface      = GetSysColor(COLOR_BTNFACE);
 		color_btnshadow    = GetSysColor(COLOR_BTNSHADOW);
@@ -124,6 +232,16 @@
 		InvalidateRect(hWnd, NULL, TRUE);
 		break;
 
+	case BM_SETCHECK:
+		if (btnfn[style].setCheckfn)
+		    (btnfn[style].setCheckfn)(hWnd, wParam);
+		break;
+
+	case BM_GETCHECK:
+		if (btnfn[style].getCheckfn)
+		    (btnfn[style].getCheckfn)(hWnd);
+		break;
+
 	default:
 		lResult = DefWindowProc(hWnd, uMsg, wParam, lParam);
 		break;
@@ -155,7 +273,7 @@
 
 static LONG PB_LButtonDown(HWND hWnd, WORD wParam, LONG lParam)
 {
-/*  SetFocus(hWnd);   */
+/*    SetFocus(hWnd); */
     SetCapture(hWnd);
     pressed = TRUE;
     InvalidateRect(hWnd, NULL, FALSE);
@@ -184,6 +302,13 @@
 	NOTIFY_PARENT(hWnd, BN_DOUBLECLICKED);
 }
 
+static LONG PB_KillFocus(HWND hWnd)
+{
+    pressed = FALSE;
+    InvalidateRect(hWnd, NULL, FALSE);
+    UpdateWindow(hWnd);
+}
+
 static void DrawRaisedPushButton(HDC hDC, HWND hButton, RECT rc)
 {
 	HPEN hOldPen, hFramePen;
@@ -255,19 +380,16 @@
 	CombineRgn(rgn, rgn1, rgn2, RGN_AND);
 	FillRgn(hDC, rgn2, hShadowBrush);
 
-#if 0
 	/* do we have the focus? */
 	if (len >= 1 && GetFocus() == hButton) {
 		dwTextSize = GetTextExtent(hDC, text, len);
-		delta = ((rc.right - rc.left) - LOWORD(dwTextSize) + 1) >> 1;
+		delta = ((rc.right - rc.left) - LOWORD(dwTextSize) - 1) >> 1;
 		rc.left += delta;	rc.right -= delta;
 		GetTextMetrics(hDC, &tm);
-		delta = ((rc.bottom - rc.top) -
-			 tm.tmHeight + tm.tmInternalLeading) >> 1;
+		delta = ((rc.bottom - rc.top) - tm.tmHeight - 1) >> 1;
 		rc.top += delta; 	rc.bottom -= delta;
 		DrawFocusRect(hDC, &rc);
 	}
-#endif
 
 	SelectObject(hDC, (HANDLE)hOldPen);
 	SelectObject(hDC, (HANDLE)hOldBrush);
@@ -275,10 +397,8 @@
 	DeleteObject((HANDLE)hShadowBrush);
 	DeleteObject((HANDLE)hBackgrndBrush);
 	DeleteObject((HANDLE)rgn1);
-#if 0
 	DeleteObject((HANDLE)rgn2);
 	DeleteObject((HANDLE)rgn);
-#endif
 }
 
 
@@ -320,19 +440,16 @@
 			 DT_SINGLELINE | DT_CENTER| DT_VCENTER);
 	}
 
-#if 0
 	/* do we have the focus? */
 	if (len >= 1 && GetFocus() == hButton) {
 		dwTextSize = GetTextExtent(hDC, text, len);
-		delta = ((rc.right - rc.left) - LOWORD(dwTextSize)) >> 1;
+		delta = ((rc.right - rc.left) - LOWORD(dwTextSize) - 1) >> 1;
 		rc.left += delta;	rc.right -= delta;
 		GetTextMetrics(hDC, &tm);
-		delta = ((rc.bottom - rc.top) -
-			 tm.tmHeight + tm.tmInternalLeading) >> 1;
+		delta = ((rc.bottom - rc.top) - tm.tmHeight - 1) >> 1;
 		rc.top += delta; 	rc.bottom -= delta;
 		DrawFocusRect(hDC, &rc);
 	}
-#endif
 
 	SelectObject(hDC, (HANDLE)hOldPen);
 	SelectObject(hDC, (HANDLE)hOldBrush);
@@ -342,10 +459,498 @@
 }
 
 
+/**********************************************************************
+ *       Check Box Functions
+ */
+
+static LONG CB_Paint(HWND hWnd)
+{
+    PAINTSTRUCT ps;
+    RECT rc, rc3;
+    HDC hDC;
+    HPEN hPen, hOldPen;
+    HBRUSH hBrush, hGrayBrush;
+    int textlen, delta;
+    char *text;
+    HANDLE hText;
+    TEXTMETRIC tm;
+    SIZE size;
+    WND *wndPtr = WIN_FindWndPtr(hWnd);
+
+    hDC = BeginPaint(hWnd, &ps);
+    GetClientRect(hWnd, &rc);
+
+    hPen = CreatePen(PS_SOLID, 1, color_windowtext);
+    hOldPen = (HPEN)SelectObject(hDC, (HANDLE)hPen);
+    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 = LocalAlloc(LMEM_MOVEABLE, textlen+1);
+    text = LocalLock(hText);
+    GetWindowText(hWnd, text, textlen+1);
+    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;
+
+    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;
+    DrawText(hDC, text, textlen, &rc, DT_SINGLELINE | DT_VCENTER);
+
+    /* do we have the focus? */
+    if (GetFocus() == hWnd)
+    {
+	GetTextExtentPoint(hDC, text, textlen, &size);
+	rc.top += delta - 1;
+	rc.bottom -= delta + 1;
+	rc.left--;
+	rc.right = rc.left + size.cx + 2;
+	DrawFocusRect(hDC, &rc);
+    }
+
+    LocalUnlock(hText);
+    LocalFree(hText);
+    GlobalUnlock(hWnd);
+    EndPaint(hWnd, &ps);
+}
+
+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;
+    rc.right = tm.tmHeight;
+    if (PtInRect(&rc, MAKEPOINT(lParam)))
+    {
+/*	SetFocus(hWnd); */
+	SetCapture(hWnd);
+	pressed = TRUE;
+	InvalidateRect(hWnd, NULL, FALSE);
+	UpdateWindow(hWnd);
+    }
+}
+
+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;
+    rc.right = tm.tmHeight;
+
+    if (PtInRect(&rc, MAKEPOINT(lParam)))
+    {
+	style = wndPtr->dwStyle & 0x0000000F;
+	if (style == BS_AUTOCHECKBOX)
+	{
+	    switch ((WORD)(*(wndPtr->wExtra)))
+	    {
+	    case 0:
+		(WORD)(*(wndPtr->wExtra)) = 1;
+		break;
+
+	    case 1:
+		(WORD)(*(wndPtr->wExtra)) = 0;
+		break;
+	    }
+	}
+	else if (style == BS_AUTO3STATE)
+	{
+	    switch ((WORD)(*(wndPtr->wExtra)))
+	    {
+	    case 0:
+		(WORD)(*(wndPtr->wExtra)) = 1;
+		break;
+
+	    case 1:
+		(WORD)(*(wndPtr->wExtra)) = 2;
+		break;
+
+	    case 2:
+		(WORD)(*(wndPtr->wExtra)) = 0;
+		break;
+	    }
+	}
+	NOTIFY_PARENT(hWnd, BN_CLICKED);
+    }
+    GlobalUnlock(hWnd);
+    InvalidateRect(hWnd, NULL, FALSE);
+    UpdateWindow(hWnd);
+}
+
+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;
+    rc.right = tm.tmHeight;
+    if (PtInRect(&rc, MAKEPOINT(lParam)))
+	NOTIFY_PARENT(hWnd, BN_DOUBLECLICKED);
+}
+
+static LONG CB_KillFocus(HWND hWnd)
+{
+    pressed = FALSE;
+    InvalidateRect(hWnd, NULL, FALSE);
+    UpdateWindow(hWnd);
+}
+
+static LONG CB_SetCheck(HWND hWnd, WORD wParam)
+{
+    WND *wndPtr = WIN_FindWndPtr(hWnd);
+
+    if ((WORD)(*(wndPtr->wExtra)) != wParam)
+    {
+	(WORD)(*(wndPtr->wExtra)) = wParam;
+	InvalidateRect(hWnd, NULL, FALSE);
+	UpdateWindow(hWnd);
+    }
+    GlobalUnlock(hWnd);
+}
+
+static LONG CB_GetCheck(HWND hWnd)
+{
+    WORD wResult;
+    WND *wndPtr = WIN_FindWndPtr(hWnd);
+
+    wResult = (WORD)(*(wndPtr->wExtra));
+    GlobalUnlock(hWnd);
+    return (LONG)wResult;
+}
 
 
+/**********************************************************************
+ *       Radio Button Functions
+ */
+
+static LONG RB_Paint(HWND hWnd)
+{
+    PAINTSTRUCT ps;
+    RECT rc;
+    HDC hDC;
+    HPEN hPen, hOldPen;
+    HBRUSH hBrush, hOldBrush;
+    int textlen, delta;
+    char *text;
+    HANDLE hText;
+    TEXTMETRIC tm;
+    SIZE size;
+    WND *wndPtr = WIN_FindWndPtr(hWnd);
+
+    hDC = BeginPaint(hWnd, &ps);
+    GetClientRect(hWnd, &rc);
+
+    hPen = CreatePen(PS_SOLID, 1, color_windowtext);
+    hOldPen = (HPEN)SelectObject(hDC, (HANDLE)hPen);
+
+    hBrush = SendMessage(GetParent(hWnd), WM_CTLCOLOR, (WORD)hDC,
+			 MAKELPARAM(hWnd, CTLCOLOR_BTN));
+    FillRect(hDC, &rc, hBrush);
+
+    textlen = GetWindowTextLength(hWnd);
+    hText = LocalAlloc(LMEM_MOVEABLE, textlen+1);
+    text = LocalLock(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);
+
+    if ((WORD)(*(wndPtr->wExtra)) == 1)
+    {
+	hBrush = CreateSolidBrush(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;
+    DrawText(hDC, text, textlen, &rc, DT_SINGLELINE | DT_VCENTER);
+
+    /* do we have the focus? */
+    if (GetFocus() == hWnd)
+    {
+	GetTextExtentPoint(hDC, text, textlen, &size);
+	rc.top += delta - 1;
+	rc.bottom -= delta + 1;
+	rc.left--;
+	rc.right = rc.left + size.cx + 2;
+	DrawFocusRect(hDC, &rc);
+    }
+
+    LocalUnlock(hText);
+    LocalFree(hText);
+    GlobalUnlock(hWnd);
+    EndPaint(hWnd, &ps);
+}
+
+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;
+    rc.right = tm.tmHeight;
+    if (PtInRect(&rc, MAKEPOINT(lParam)))
+    {
+/*	SetFocus(hWnd); */
+	SetCapture(hWnd);
+	pressed = TRUE;
+	InvalidateRect(hWnd, NULL, FALSE);
+	UpdateWindow(hWnd);
+    }
+}
+
+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;
+    rc.right = tm.tmHeight;
+
+    if (PtInRect(&rc, MAKEPOINT(lParam)))
+    {
+	style = wndPtr->dwStyle & 0x0000000F;
+	if (style == BS_AUTORADIOBUTTON)
+	    (WORD)(*(wndPtr->wExtra)) = 1;
+	NOTIFY_PARENT(hWnd, BN_CLICKED);
+    }
+    GlobalUnlock(hWnd);
+    InvalidateRect(hWnd, NULL, FALSE);
+    UpdateWindow(hWnd);
+}
+
+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;
+    rc.right = tm.tmHeight;
+    if (PtInRect(&rc, MAKEPOINT(lParam)))
+	NOTIFY_PARENT(hWnd, BN_DOUBLECLICKED);
+}
+
+static LONG RB_KillFocus(HWND hWnd)
+{
+    pressed = FALSE;
+    InvalidateRect(hWnd, NULL, FALSE);
+    UpdateWindow(hWnd);
+}
+
+static LONG RB_SetCheck(HWND hWnd, WORD wParam)
+{
+    WND *wndPtr = WIN_FindWndPtr(hWnd);
+
+    if ((WORD)(*(wndPtr->wExtra)) != wParam)
+    {
+	(WORD)(*(wndPtr->wExtra)) = wParam;
+	InvalidateRect(hWnd, NULL, FALSE);
+	UpdateWindow(hWnd);
+    }
+    GlobalUnlock(hWnd);
+}
+
+static LONG RB_GetCheck(HWND hWnd)
+{
+    WORD wResult;
+    WND *wndPtr = WIN_FindWndPtr(hWnd);
+
+    wResult = (WORD)(*(wndPtr->wExtra));
+    GlobalUnlock(hWnd);
+    return (LONG)wResult;
+}
 
 
+/**********************************************************************
+ *       Group Box Functions
+ */
+
+static LONG GB_Paint(HWND hWnd)
+{
+    PAINTSTRUCT ps;
+    RECT rc;
+    HDC hDC;
+    HPEN hPen, hOldPen;
+    HBRUSH hBrush;
+    int textlen;
+    char *text;
+    HANDLE hText;
+    SIZE size;
+
+    hDC = BeginPaint(hWnd, &ps);
+    GetClientRect(hWnd, &rc);
+
+    hPen = CreatePen(PS_SOLID, 1, color_windowtext);
+    hOldPen = (HPEN)SelectObject(hDC, (HANDLE)hPen);
+
+    hBrush = SendMessage(GetParent(hWnd), WM_CTLCOLOR, (WORD)hDC,
+			 MAKELPARAM(hWnd, CTLCOLOR_BTN));
+    FillRect(hDC, &rc, hBrush);
+
+    textlen = GetWindowTextLength(hWnd);
+    hText = LocalAlloc(LMEM_MOVEABLE, textlen+1);
+    text = LocalLock(hText);
+    GetWindowText(hWnd, text, textlen+1);
+    GetTextExtentPoint(hDC, text, textlen, &size);
+
+    rc.top = 5;
+    Rectangle(hDC, rc.left, rc.top, rc.right, rc.bottom);
+    rc.left = 10;
+    rc.top = 0;
+    rc.right = rc.left + size.cx + 1;
+    rc.bottom = size.cy;
+    DrawText(hDC, text, textlen, &rc, DT_SINGLELINE);
+
+    LocalUnlock(hText);
+    LocalFree(hText);
+    EndPaint(hWnd, &ps);
+}
 
 
+/**********************************************************************
+ *       User Button Functions
+ */
+
+static LONG UB_Paint(HWND hWnd)
+{
+    PAINTSTRUCT ps;
+    HDC hDC;
+    RECT rc;
+    HBRUSH hBrush;
+
+    hDC = BeginPaint(hWnd, &ps);
+    GetClientRect(hWnd, &rc);
+
+    hBrush = SendMessage(GetParent(hWnd), WM_CTLCOLOR, (WORD)hDC,
+			 MAKELPARAM(hWnd, CTLCOLOR_BTN));
+    FillRect(hDC, &rc, hBrush);
+
+    NOTIFY_PARENT(hWnd, BN_PAINT);
+
+    /* do we have the focus? */
+    if (GetFocus() == hWnd)
+	DrawFocusRect(hDC, &rc);
+
+    EndPaint(hWnd, &ps);
+}
+
+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);
+}
+
+static LONG UB_LButtonUp(HWND hWnd, WORD wParam, LONG lParam)
+{
+    RECT rc;
+
+    ReleaseCapture();
+    GetClientRect(hWnd, &rc);
+    if (PtInRect(&rc, MAKEPOINT(lParam)))
+	NOTIFY_PARENT(hWnd, BN_UNHILITE);
+    InvalidateRect(hWnd, NULL, FALSE);
+    UpdateWindow(hWnd);
+}
+
+static LONG UB_KillFocus(HWND hWnd)
+{
+    InvalidateRect(hWnd, NULL, FALSE);
+    UpdateWindow(hWnd);
+}