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/windows/Makefile b/windows/Makefile
index f7de172..812bd34 100644
--- a/windows/Makefile
+++ b/windows/Makefile
@@ -1,7 +1,8 @@
 CFLAGS=$(COPTS) $(DEBUGOPTS) -I$(INCLUDE_DIR)
 
 OBJS=class.o dc.o dce.o event.o message.o win.o timer.o graphics.o \
-    	clipping.o mapping.o painting.o keyboard.o utility.o syscolor.o
+    	clipping.o mapping.o painting.o keyboard.o utility.o syscolor.o \
+	defwnd.o defdlg.o dialog.o focus.o
 
 default: windows.o
 
@@ -9,7 +10,7 @@
 	$(LD) -r -o windows.o $(OBJS)
 
 clean:
-	rm -f *.o *~ *.s dll_* *.a
+	rm -f *.o *~ *.s dll_* *.a *#
 
 depend:
 	$(CC) $(CFLAGS) -M *.c > .depend
diff --git a/windows/defdlg.c b/windows/defdlg.c
new file mode 100644
index 0000000..8405dc3
--- /dev/null
+++ b/windows/defdlg.c
@@ -0,0 +1,76 @@
+/*
+ * Default dialog procedure
+ *
+ * Copyright 1993 Alexandre Julliard
+ */
+
+static char Copyright[] = "Copyright  Alexandre Julliard, 1993";
+
+#include "windows.h"
+#include "dialog.h"
+#include "win.h"
+
+
+/***********************************************************************
+ *           DefDlgProc   (USER.308)
+ */
+LONG DefDlgProc( HWND hwnd, WORD msg, WORD wParam, LONG lParam )
+{
+    DIALOGINFO * dlgInfo;
+    BOOL result = FALSE;
+    WND * wndPtr = WIN_FindWndPtr( hwnd );
+    
+    if (!wndPtr) return 0;
+    dlgInfo = (DIALOGINFO *)&wndPtr->wExtra;
+
+#ifdef DEBUG_DIALOG
+    printf( "DefDlgProc: %d %04x %d %08x\n", hwnd, msg, wParam, lParam );
+#endif
+
+    dlgInfo->msgResult = 0;
+    if (dlgInfo->dlgProc)
+    {
+	  /* Call dialog procedure */
+	result = (BOOL)CallWindowProc( dlgInfo->dlgProc, hwnd, 
+				       msg, wParam, lParam );
+
+	  /* Check if window destroyed by dialog procedure */
+	wndPtr = WIN_FindWndPtr( hwnd );
+	if (!wndPtr) return result;
+    }
+    
+    if (!result) switch(msg)
+    {
+	case WM_INITDIALOG:
+	    break;
+
+        case WM_ERASEBKGND:
+	    FillWindow( hwnd, hwnd, (HDC)wParam, (HBRUSH)CTLCOLOR_DLG );
+	    return TRUE;
+
+	case WM_NCDESTROY:
+
+	      /* Delete font */
+	    if (dlgInfo->hUserFont)
+	    {
+		DeleteObject( dlgInfo->hUserFont );
+		dlgInfo->hUserFont = 0;
+	    }
+
+	      /* Delete menu */
+	    if (dlgInfo->hMenu)
+	    {		
+		DestroyMenu( dlgInfo->hMenu );
+		dlgInfo->hMenu = 0;
+	    }
+
+	      /* Window clean-up */
+	    DefWindowProc( hwnd, msg, wParam, lParam );
+	    break;
+	    
+	default:
+	    return DefWindowProc( hwnd, msg, wParam, lParam );
+    }
+        
+    return result;
+}
diff --git a/windows/defwnd.c b/windows/defwnd.c
new file mode 100644
index 0000000..3d3a280
--- /dev/null
+++ b/windows/defwnd.c
@@ -0,0 +1,151 @@
+/*
+ * Default window procedure
+ *
+ * Copyright 1993 Alexandre Julliard
+ */
+
+static char Copyright[] = "Copyright  Alexandre Julliard, 1993";
+
+#include <X11/Intrinsic.h>
+#include <X11/Shell.h>
+
+#include "windows.h"
+#include "win.h"
+#include "class.h"
+#include "user.h"
+
+
+/***********************************************************************
+ *           DefWindowProc   (USER.107)
+ */
+LONG DefWindowProc( HWND hwnd, WORD msg, WORD wParam, LONG lParam )
+{
+    WND * wndPtr;
+    CLASS * classPtr;
+    LPSTR textPtr;
+    int len;
+    
+#ifdef DEBUG_MESSAGE
+    printf( "DefWindowProc: %d %d %d %08x\n", hwnd, msg, wParam, lParam );
+#endif
+
+    switch(msg)
+    {
+    case WM_NCCREATE:
+	{
+	    CREATESTRUCT * createStruct = (CREATESTRUCT *)lParam;
+	    wndPtr = WIN_FindWndPtr(hwnd);
+	    if (createStruct->lpszName)
+	    {
+		  /* Allocate space for window text */
+		wndPtr->hText = USER_HEAP_ALLOC(GMEM_MOVEABLE, 
+					strlen(createStruct->lpszName) + 1);
+		textPtr = (LPSTR)USER_HEAP_ADDR(wndPtr->hText);
+		strcpy(textPtr, createStruct->lpszName);
+	    }
+	    return 1;
+	}
+	
+    case WM_CREATE:
+	return 0;
+
+    case WM_NCDESTROY:
+	{
+	    wndPtr = WIN_FindWndPtr(hwnd);
+	    if (wndPtr->hText) USER_HEAP_FREE(wndPtr->hText);
+	    wndPtr->hText = 0;
+	    return 0;
+	}
+	
+    case WM_PAINT:
+	{
+	    PAINTSTRUCT paintstruct;
+	    BeginPaint( hwnd, &paintstruct );
+	    EndPaint( hwnd, &paintstruct );
+	    return 0;
+	}
+
+    case WM_CLOSE:
+	DestroyWindow( hwnd );
+	return 0;
+
+    case WM_ERASEBKGND:
+    case WM_ICONERASEBKGND:
+	{
+	    if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return 1;
+	    if (!(classPtr = CLASS_FindClassPtr( wndPtr->hClass ))) return 1;
+	    if (!classPtr->wc.hbrBackground) return 1;
+	    FillWindow( GetParent(hwnd), hwnd, (HDC)wParam,
+		        classPtr->wc.hbrBackground );
+	    return 0;
+	}
+
+    case WM_GETDLGCODE:
+	return 0;
+
+    case WM_CTLCOLOR:
+	{
+	    if (HIWORD(lParam) == CTLCOLOR_SCROLLBAR)
+	    {
+		SetBkColor( (HDC)wParam, RGB(255, 255, 255) );
+		SetTextColor( (HDC)wParam, RGB(0, 0, 0) );
+/*	        hbr = sysClrObjects.hbrScrollbar;
+		UnrealizeObject(hbr); */
+		return GetStockObject(LTGRAY_BRUSH);
+	    }
+	    else
+	    {
+		SetBkColor( (HDC)wParam, GetSysColor(COLOR_WINDOW) );
+		SetTextColor( (HDC)wParam, GetSysColor(COLOR_WINDOWTEXT) );
+/*	        hbr = sysClrObjects.hbrWindow; */
+		return GetStockObject(WHITE_BRUSH);
+	    }
+	}
+	
+    case WM_GETTEXT:
+	{
+	    if (wParam)
+	    {
+		wndPtr = WIN_FindWndPtr(hwnd);
+		if (wndPtr->hText)
+		{
+		    textPtr = (LPSTR)USER_HEAP_ADDR(wndPtr->hText);
+		    if ((int)wParam > (len = strlen(textPtr)))
+		    {
+			strcpy((char *)lParam, textPtr);
+			return (DWORD)len;
+		    }
+		}
+	        lParam = (DWORD)NULL;
+	    }
+	    return (0L);
+	}
+
+    case WM_GETTEXTLENGTH:
+	{
+	    wndPtr = WIN_FindWndPtr(hwnd);
+	    if (wndPtr->hText)
+	    {
+		textPtr = (LPSTR)USER_HEAP_ADDR(wndPtr->hText);
+		return (DWORD)strlen(textPtr);
+	    }
+	    return (0L);
+	}
+
+    case WM_SETTEXT:
+	{
+	    wndPtr = WIN_FindWndPtr(hwnd);
+	    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);
+	    if (wndPtr->shellWidget)
+		XtVaSetValues( wndPtr->shellWidget, XtNtitle, textPtr, NULL );
+	    return (0L);
+	}
+    }
+    return 0;
+}
diff --git a/windows/dialog.c b/windows/dialog.c
new file mode 100644
index 0000000..e60b62d
--- /dev/null
+++ b/windows/dialog.c
@@ -0,0 +1,639 @@
+/*
+ * Dialog functions
+ *
+ * Copyright 1993 Alexandre Julliard
+ */
+
+static char Copyright[] = "Copyright  Alexandre Julliard, 1993";
+
+#include <stdlib.h>
+
+#include "windows.h"
+#include "dialog.h"
+#include "win.h"
+
+
+  /* Dialog base units */
+static WORD xBaseUnit = 0, yBaseUnit = 0;
+
+
+/***********************************************************************
+ *           DIALOG_Init
+ *
+ * Initialisation of the dialog manager.
+ */
+BOOL DIALOG_Init()
+{
+    TEXTMETRIC tm;
+    HDC hdc;
+    
+      /* Calculate the dialog base units */
+
+    if (!(hdc = GetDC( 0 ))) return FALSE;
+    GetTextMetrics( hdc, &tm );
+    ReleaseDC( 0, hdc );
+    xBaseUnit = tm.tmAveCharWidth;
+    yBaseUnit = tm.tmHeight;
+#ifdef DEBUG_DIALOG
+    printf( "DIALOG_Init: base units = %d,%d\n", xBaseUnit, yBaseUnit );
+#endif    
+    return TRUE;
+}
+
+
+/***********************************************************************
+ *           DIALOG_GetControl
+ *
+ * Return the class and text of the control pointed to by ptr,
+ * and return a pointer to the next control.
+ */
+static DLGCONTROLHEADER * DIALOG_GetControl( DLGCONTROLHEADER * ptr,
+					     char ** class, char ** text )
+{
+    unsigned char * p = (unsigned char *)ptr;
+    p += 14;  /* size of control header */
+    if (*p & 0x80)
+    {
+	switch(*p++)
+	{
+	case 0x80: *class = "BUTTON"; break;
+	case 0x81: *class = "EDIT"; break;
+	case 0x82: *class = "STATIC"; break;
+	case 0x83: *class = "LISTBOX"; break;
+	case 0x84: *class = "SCROLLBAR"; break;
+	case 0x85: *class = "COMBOBOX"; break;
+	default:   *class = ""; break;
+	}
+    }
+    else 
+    {
+	*class = p;
+	p += strlen(p) + 1;
+    }
+    *text = p;
+    p += strlen(p) + 2;
+    return (DLGCONTROLHEADER *)p;
+}
+
+
+/***********************************************************************
+ *           DIALOG_ParseTemplate
+ *
+ * Fill a DLGTEMPLATE structure from the dialog template.
+ */
+static void DIALOG_ParseTemplate( LPCSTR template, DLGTEMPLATE * result )
+{
+    int i;
+    unsigned char * p = (unsigned char *)template;
+ 
+    result->header = (DLGTEMPLATEHEADER *)p;
+    p += 13;
+    result->menuName = p;
+    if (*p == 0xff) p += 3;
+    else p += strlen(p) + 1;
+
+    if (*p) result->className = p;
+    else result->className = DIALOG_CLASS_NAME;
+    p += strlen(p) + 1;
+
+    result->caption = p;
+    p += strlen(p) + 1;
+
+    if (result->header->style & DS_SETFONT)
+    {
+	result->pointSize = *(WORD *)p;	p += sizeof(WORD);
+	result->faceName = p;           p += strlen(p) + 1;
+    }
+    result->controls = NULL;
+    if (!result->header->nbItems) return;
+    result->controls = (DLGCONTROL *) malloc( result->header->nbItems * sizeof(DLGCONTROL) );
+    if (!result->controls) return;
+
+    for (i = 0; i < result->header->nbItems; i++)
+    {
+	result->controls[i].header = (DLGCONTROLHEADER *)p;
+	p = (char *)DIALOG_GetControl( result->controls[i].header,
+				      &result->controls[i].class,
+				      &result->controls[i].text );	
+    }
+}
+
+
+/***********************************************************************
+ *           DIALOG_DisplayTemplate
+ */
+#ifdef DEBUG_DIALOG
+static void DIALOG_DisplayTemplate( DLGTEMPLATE * result )
+{
+    int i;
+    DLGCONTROL * ctrl = result->controls;
+    
+    printf( "DIALOG %d, %d, %d, %d\n", result->header->x, result->header->y,
+	    result->header->cx, result->header->cy );
+    printf( " STYLE %08x\n", result->header->style );
+    printf( " CAPTION '%s'\n", result->caption );
+    printf( " CLASS '%s'\n", result->className );
+    if (result->menuName[0] == 0xff)
+	printf( " MENU %d\n", result->menuName[1] + 256*result->menuName[2] );
+    else printf( " MENU '%s'\n", result->menuName );
+    if (result->header->style & DS_SETFONT)
+	printf( " FONT %d,'%s'\n", result->pointSize, result->faceName );
+
+    printf( " BEGIN\n" );
+
+    for (i = 0; i < result->header->nbItems; i++, ctrl++)
+    {
+	printf( "   %s '%s' %d, %d, %d, %d, %d, %08x\n",
+	        ctrl->class, ctrl->text, ctrl->header->id,
+	        ctrl->header->x, ctrl->header->y, ctrl->header->cx,
+	        ctrl->header->cy, ctrl->header->style );
+    }
+    
+    printf( " END\n" );
+}
+#endif  /* DEBUG_DIALOG */
+
+
+/***********************************************************************
+ *           CreateDialog   (USER.89)
+ */
+HWND CreateDialog( HINSTANCE hInst, LPCSTR dlgTemplate,
+		   HWND owner, FARPROC dlgProc )
+{
+    return CreateDialogParam( hInst, dlgTemplate, owner, dlgProc, 0 );
+}
+
+
+/***********************************************************************
+ *           CreateDialogParam   (USER.241)
+ */
+HWND CreateDialogParam( HINSTANCE hInst, LPCSTR dlgTemplate,
+		        HWND owner, FARPROC dlgProc, LPARAM param )
+{
+    HWND hwnd = 0;
+    HANDLE hres, hmem;
+    LPCSTR data;
+    int size;
+
+#ifdef DEBUG_DIALOG
+    printf( "CreateDialogParam: %d,'%s',%d,%p,%d\n",
+	    hInst, dlgTemplate, owner, dlgProc, param );
+#endif
+    
+#if 0
+    if (!(hres = FindResource( hInst, dlgTemplate, RT_DIALOG ))) return 0;
+    if (!(hmem = LoadResource( hInst, hres ))) return 0;
+    if (!(data = LockResource( hmem ))) hwnd = 0;
+    else hwnd = CreateDialogIndirectParam(hInst, data, owner, dlgProc, param);
+    FreeResource( hmem );
+#else
+    hmem = RSC_LoadResource( hInst, dlgTemplate, 0x8005, &size );
+    data = (LPCSTR) GlobalLock( hmem );
+    hwnd = CreateDialogIndirectParam( hInst, data, owner, dlgProc, param );
+    GlobalFree( hmem );
+#endif
+    return hwnd;
+}
+
+
+/***********************************************************************
+ *           CreateDialogIndirect   (USER.219)
+ */
+HWND CreateDialogIndirect( HINSTANCE hInst, LPCSTR dlgTemplate,
+			   HWND owner, FARPROC dlgProc )
+{
+    return CreateDialogIndirectParam( hInst, dlgTemplate, owner, dlgProc, 0 );
+}
+
+
+/***********************************************************************
+ *           CreateDialogIndirectParam   (USER.242)
+ */
+HWND CreateDialogIndirectParam( HINSTANCE hInst, LPCSTR dlgTemplate,
+			        HWND owner, FARPROC dlgProc, LPARAM param )
+{
+    HMENU hMenu = 0;
+    HFONT hFont = 0;
+    HWND hwnd;
+    WND * wndPtr;
+    DLGTEMPLATE template;
+    DIALOGINFO * dlgInfo;
+    WORD xUnit = xBaseUnit;
+    WORD yUnit = yBaseUnit;
+    
+    if (!dlgTemplate) return 0;
+    DIALOG_ParseTemplate( dlgTemplate, &template );
+
+#ifdef DEBUG_DIALOG
+    DIALOG_DisplayTemplate( &template );
+#endif    
+
+      /* Load menu */
+
+    if (template.menuName[0])
+    {
+	if (template.menuName[0] != 0xff) 
+	    hMenu = LoadMenu( hInst, template.menuName );
+	else
+	    hMenu = LoadMenu( hInst, MAKEINTRESOURCE( template.menuName[1] +
+						   256*template.menuName[2] ));
+    }
+
+      /* Create custom font if needed */
+
+    if (template.header->style & DS_SETFONT)
+    {
+	hFont = CreateFont( template.pointSize, 0, 0, 0, FW_DONTCARE,
+			    FALSE, FALSE, FALSE, DEFAULT_CHARSET, 0, 0,
+			    DEFAULT_QUALITY, FF_DONTCARE, template.faceName );
+	if (hFont)
+	{
+	    TEXTMETRIC tm;
+	    HFONT oldFont;
+	    HDC hdc;
+
+	    hdc = GetDC( 0 );
+	    oldFont = SelectObject( hdc, hFont );
+	    GetTextMetrics( hdc, &tm );
+	    SelectObject( hdc, oldFont );
+	    ReleaseDC( 0, hdc );
+	    xUnit = tm.tmAveCharWidth;
+	    yUnit = tm.tmHeight;
+	}
+    }
+
+      /* Create dialog main window */
+
+    hwnd = CreateWindow( template.className, template.caption,
+			 template.header->style & ~WS_VISIBLE,
+			 template.header->x * xUnit / 4,
+			 template.header->y * yUnit / 8,
+			 template.header->cx * xUnit / 4,
+			 template.header->cy * yUnit / 8,
+			 owner, hMenu, hInst,
+			 NULL );
+    if (!hwnd)
+    {
+	if (hFont) DeleteObject( hFont );
+	if (hMenu) DestroyMenu( hMenu );
+	if (template.controls) free( template.controls );
+	return 0;
+    }
+
+      /* Create control windows */
+
+    if (hwnd && template.header->nbItems)
+    {
+	int i;
+	DLGCONTROL * ctrl = template.controls;
+	for (i = 0; i < template.header->nbItems; i++, ctrl++)
+	{
+	    CreateWindowEx( WS_EX_NOPARENTNOTIFY, 
+			    ctrl->class, ctrl->text, ctrl->header->style,
+			    ctrl->header->x * xUnit / 4,
+			    ctrl->header->y * yUnit / 8,
+			    ctrl->header->cx * xUnit / 4,
+			    ctrl->header->cy * yUnit / 8,
+			    hwnd, ctrl->header->id, hInst, NULL );
+	}
+    }
+    
+      /* Initialise dialog extra data */
+
+    wndPtr = WIN_FindWndPtr( hwnd );
+    dlgInfo = (DIALOGINFO *)wndPtr->wExtra;
+    dlgInfo->dlgProc   = dlgProc;
+    dlgInfo->hUserFont = hFont;
+    dlgInfo->hMenu     = hMenu;
+    dlgInfo->xBaseUnit = xUnit;
+    dlgInfo->yBaseUnit = yUnit;
+    dlgInfo->hwndFocus = GetNextDlgTabItem( hwnd,
+			    GetWindow(wndPtr->hwndChild, GW_HWNDLAST), FALSE );
+
+      /* Send initialisation messages and set focus */
+
+    if (dlgInfo->hUserFont) 
+	SendMessage( hwnd, WM_SETFONT, dlgInfo->hUserFont, 0);
+    SendMessage( hwnd, WM_INITDIALOG, dlgInfo->hwndFocus, param );
+    if (SendMessage( hwnd, WM_INITDIALOG, dlgInfo->hwndFocus, param ))
+	SetFocus( dlgInfo->hwndFocus );
+
+      /* Display dialog */
+
+    if (template.header->style & WS_VISIBLE) ShowWindow( hwnd, SW_SHOW );
+    
+    if (template.controls) free( template.controls );
+    return hwnd;
+}
+
+
+/***********************************************************************
+ *           DialogBox   (USER.87)
+ */
+int DialogBox( HINSTANCE hInst, LPCSTR dlgTemplate,
+	       HWND owner, FARPROC dlgProc )
+{
+    HWND hwnd;
+    WND * wndPtr;
+    DIALOGINFO * dlgInfo;
+    MSG msg;
+    int retval;
+
+#ifdef DEBUG_DIALOG
+    printf( "DialogBox: %d,'%s',%d,%p\n", hInst, dlgTemplate, owner, dlgProc );
+#endif
+
+    hwnd = CreateDialog( hInst, dlgTemplate, owner, dlgProc );
+    if (!hwnd) return -1;
+    wndPtr = WIN_FindWndPtr( hwnd );
+    dlgInfo = (DIALOGINFO *)wndPtr->wExtra;
+    while (GetMessage (&msg, 0, 0, 0))
+    {
+	if (!IsDialogMessage( hwnd, &msg))
+	{
+	    TranslateMessage(&msg);
+	    DispatchMessage(&msg);
+	}
+	if (dlgInfo->fEnd) break;
+    }
+    retval = dlgInfo->msgResult;
+    DestroyWindow( hwnd );
+    return retval;
+}
+
+
+/***********************************************************************
+ *           EndDialog   (USER.88)
+ */
+void EndDialog( HWND hwnd, short retval )
+{
+    WND * wndPtr = WIN_FindWndPtr( hwnd );
+    DIALOGINFO * dlgInfo = (DIALOGINFO *)wndPtr->wExtra;
+    dlgInfo->msgResult = retval;
+    dlgInfo->fEnd = TRUE;
+#ifdef DEBUG_DIALOG
+    printf( "EndDialog: %d %d\n", hwnd, retval );
+#endif    
+}
+
+
+/***********************************************************************
+ *           IsDialogMessage   (USER.90)
+ */
+BOOL IsDialogMessage( HWND hwndDlg, LPMSG msg )
+{
+    WND * wndPtr;
+    
+    if (!(wndPtr = WIN_FindWndPtr( hwndDlg ))) return FALSE;
+    if ((hwndDlg != msg->hwnd) && !IsChild( hwndDlg, msg->hwnd )) return FALSE;
+
+    if (msg->message != WM_KEYDOWN)
+    {
+	SendMessage( msg->hwnd, msg->message, msg->wParam, msg->lParam );
+    }
+    else
+    {
+	int dlgCode = SendMessage( msg->hwnd, WM_GETDLGCODE, 0, 0 );
+	/* Process key message */
+	/* .... */
+    }
+    return TRUE;
+}
+
+
+/****************************************************************
+ *         GetDlgCtrlID           (USER.277)
+ */
+int GetDlgCtrlID( HWND hwnd )
+{
+    WND *wndPtr = WIN_FindWndPtr(hwnd);
+    if (wndPtr) return wndPtr->wIDmenu;
+    else return 0;
+}
+ 
+
+/***********************************************************************
+ *           GetDlgItem   (USER.91)
+ */
+HWND GetDlgItem( HWND hwndDlg, WORD id )
+{
+    HWND curChild;
+    WND * childPtr;
+    WND * wndPtr;
+
+    if (!(wndPtr = WIN_FindWndPtr( hwndDlg ))) return 0;
+    curChild = wndPtr->hwndChild;
+    while(curChild)
+    {
+	childPtr = WIN_FindWndPtr( curChild );
+	if (childPtr->wIDmenu == id) return curChild;
+	curChild = childPtr->hwndNext;
+    }
+    return 0;
+}
+
+
+/*******************************************************************
+ *           SendDlgItemMessage   (USER.101)
+ */
+LONG SendDlgItemMessage(HWND hwnd, WORD id, UINT msg, WORD wParam, LONG lParam)
+{
+    HWND hwndCtrl = GetDlgItem( hwnd, id );
+    if (hwndCtrl) return SendMessage( hwndCtrl, msg, wParam, lParam );
+    else return 0;
+}
+
+
+/*******************************************************************
+ *           SetDlgItemText   (USER.92)
+ */
+void SetDlgItemText( HWND hwnd, WORD id, LPSTR lpString )
+{
+    SendDlgItemMessage( hwnd, id, WM_SETTEXT, 0, (DWORD)lpString );
+}
+
+
+/***********************************************************************
+ *           GetDlgItemText   (USER.93)
+ */
+int GetDlgItemText( HWND hwnd, WORD id, LPSTR str, WORD max )
+{
+    return (int)SendDlgItemMessage( hwnd, id, WM_GETTEXT, max, (DWORD)str );
+}
+
+
+/*******************************************************************
+ *           SetDlgItemInt   (USER.94)
+ */
+void SetDlgItemInt( HWND hwnd, WORD id, WORD value, BOOL fSigned )
+{
+    HANDLE hText = LocalAlloc( LMEM_MOVEABLE, 10 );
+    char * str = (char *) LocalLock( hText );
+
+    if (fSigned) sprintf( str, "%d", value );
+    else sprintf( str, "%u", value );
+    SendDlgItemMessage( hwnd, id, WM_SETTEXT, 0, (DWORD)str );
+    LocalUnlock( hText );
+    LocalFree( hText );
+}
+
+
+/***********************************************************************
+ *           GetDlgItemInt   (USER.95)
+ */
+WORD GetDlgItemInt( HWND hwnd, WORD id, BOOL * translated, BOOL fSigned )
+{
+    int len;
+    HANDLE hText;
+    long result;
+    char * str;
+    
+    if (translated) *translated = FALSE;
+    if (!(len = SendDlgItemMessage( hwnd, id, WM_GETTEXTLENGTH, 0, 0 )))
+	return 0;
+    if (!(hText = LocalAlloc(LMEM_MOVEABLE, len+1 )))
+	return 0;
+    str = (char *) LocalLock( hText );
+    if (SendDlgItemMessage( hwnd, id, WM_GETTEXT, len+1, (DWORD)str ))
+    {
+	char * endptr;
+	result = strtol( str, &endptr, 10 );
+	if (endptr && (endptr != str))  /* Conversion was successful */
+	{
+	    if (fSigned)
+	    {
+		if ((result < -32767) || (result > 32767)) result = 0;
+		else if (translated) *translated = TRUE;
+	    }
+	    else
+	    {
+		if ((result < 0) || (result > 65535)) result = 0;
+		else if (translated) *translated = TRUE;
+	    }
+	}
+    }
+    LocalUnlock( hText );
+    LocalFree( hText );
+    return (WORD)result;
+}
+
+
+/***********************************************************************
+ *           CheckDlgButton   (USER.97)
+ */
+void CheckDlgButton( HWND hwnd, WORD id, WORD check )
+{
+    SendDlgItemMessage( hwnd, id, BM_SETCHECK, check, 0 );
+}
+
+
+/***********************************************************************
+ *           IsDlgButtonChecked   (USER.98)
+ */
+WORD IsDlgButtonChecked( HWND hwnd, WORD id )
+{
+    return (WORD)SendDlgItemMessage( hwnd, id, BM_GETCHECK, 0, 0 );
+}
+
+
+/***********************************************************************
+ *           CheckRadioButton   (USER.96)
+ */
+void CheckRadioButton( HWND hwndDlg, WORD firstID, WORD lastID, WORD checkID )
+{
+    HWND button = GetDlgItem( hwndDlg, firstID );
+    while (button != 0)
+    {
+	WND * wndPtr = WIN_FindWndPtr( button );
+	if (!wndPtr) break;
+	SendMessage( button, BM_SETCHECK, (wndPtr->wIDmenu == checkID), 0 );
+        if (wndPtr->wIDmenu == lastID) break;
+	button = wndPtr->hwndNext;
+    }
+}
+
+
+/***********************************************************************
+ *           GetDialogBaseUnits   (USER.243)
+ */
+DWORD GetDialogBaseUnits()
+{
+    return MAKELONG( xBaseUnit, yBaseUnit );
+}
+
+
+/***********************************************************************
+ *           MapDialogRect   (USER.103)
+ */
+void MapDialogRect( HWND hwnd, LPRECT rect )
+{
+    DIALOGINFO * dlgInfo;
+    WND * wndPtr = WIN_FindWndPtr( hwnd );
+    if (!wndPtr) return;
+    dlgInfo = (DIALOGINFO *)wndPtr->wExtra;
+    rect->left   = (rect->left * dlgInfo->xBaseUnit) / 4;
+    rect->right  = (rect->right * dlgInfo->xBaseUnit) / 4;
+    rect->top    = (rect->top * dlgInfo->yBaseUnit) / 8;
+    rect->bottom = (rect->bottom * dlgInfo->yBaseUnit) / 8;
+}
+
+
+/***********************************************************************
+ *           GetNextDlgGroupItem   (USER.227)
+ */
+HWND GetNextDlgGroupItem( HWND hwndDlg, HWND hwndCtrl, BOOL fPrevious )
+{
+    HWND hwnd, hwndLast;
+    WND * dlgPtr, * ctrlPtr, * wndPtr;
+
+    if (!(dlgPtr = WIN_FindWndPtr( hwndDlg ))) return 0;
+    if (!(ctrlPtr = WIN_FindWndPtr( hwndCtrl ))) return 0;
+    if (ctrlPtr->hwndParent != hwndDlg) return 0;
+
+    hwndLast = hwndCtrl;
+    hwnd = ctrlPtr->hwndNext;
+    while (1)
+    {
+	if (!hwnd) hwnd = dlgPtr->hwndChild;
+	if (hwnd == hwndCtrl) break;
+	wndPtr = WIN_FindWndPtr( hwnd );
+	if (wndPtr->dwStyle & WS_TABSTOP)
+	{
+	    hwndLast = hwnd;
+	    if (!fPrevious) break;
+	}
+	hwnd = wndPtr->hwndNext;
+    }
+    return hwndLast;
+    return 0;
+}
+
+
+/***********************************************************************
+ *           GetNextDlgTabItem   (USER.228)
+ */
+HWND GetNextDlgTabItem( HWND hwndDlg, HWND hwndCtrl, BOOL fPrevious )
+{
+    HWND hwnd, hwndLast;
+    WND * dlgPtr, * ctrlPtr, * wndPtr;
+
+    if (!(dlgPtr = WIN_FindWndPtr( hwndDlg ))) return 0;
+    if (!(ctrlPtr = WIN_FindWndPtr( hwndCtrl ))) return 0;
+    if (ctrlPtr->hwndParent != hwndDlg) return 0;
+
+    hwndLast = hwndCtrl;
+    hwnd = ctrlPtr->hwndNext;
+    while (1)
+    {
+	if (!hwnd) hwnd = dlgPtr->hwndChild;
+	if (hwnd == hwndCtrl) break;
+	wndPtr = WIN_FindWndPtr( hwnd );
+	if (wndPtr->dwStyle & WS_TABSTOP)
+	{
+	    hwndLast = hwnd;
+	    if (!fPrevious) break;
+	}
+	hwnd = wndPtr->hwndNext;
+    }
+    return hwndLast;
+}
diff --git a/windows/event.c b/windows/event.c
index 138f057..f9c5e21 100644
--- a/windows/event.c
+++ b/windows/event.c
@@ -25,10 +25,13 @@
 static void EVENT_mouse_motion();
 static void EVENT_mouse_button();
 static void EVENT_structure();
+static void EVENT_focus_change();
 
   /* State variables */
 static HWND captureWnd = 0;
 
+extern HWND hWndFocus;
+
 /***********************************************************************
  *           EVENT_AddHandlers
  *
@@ -46,6 +49,8 @@
 		      EVENT_mouse_button, (XtPointer)hwnd );
     XtAddEventHandler(w, StructureNotifyMask, FALSE,
 		      EVENT_structure, (XtPointer)hwnd );
+    XtAddEventHandler(w, FocusChangeMask, FALSE,
+		      EVENT_focus_change, (XtPointer)hwnd );
 }
 
 
@@ -66,6 +71,8 @@
 			 EVENT_mouse_button, (XtPointer)hwnd );
     XtRemoveEventHandler(w, StructureNotifyMask, FALSE,
 			 EVENT_structure, (XtPointer)hwnd );
+    XtRemoveEventHandler(w, FocusChangeMask, FALSE,
+			 EVENT_focus_change, (XtPointer)hwnd );
 }
 
 
@@ -115,10 +122,18 @@
 		       Boolean *cont_dispatch )
 {
     MSG msg;
-    
+
+    char Str[24]; 
+    XComposeStatus cs; 
+    KeySym key;
+    int count = XLookupString(event, Str, 1, &key, &cs);
+    Str[count] = '\0';
+#ifdef DEBUG_KEY
+    printf("WM_KEY??? : count=%u / %X / '%s'\n",count, Str[0], Str);
+#endif    
     msg.hwnd    = hwnd;
     msg.message = (event->type == KeyRelease) ? WM_KEYUP : WM_KEYDOWN;
-    msg.wParam  = 0;
+    msg.wParam  = Str[0];
     msg.lParam  = (event->x & 0xffff) | (event->y << 16);
     msg.time = event->time;
     msg.pt.x = event->x & 0xffff;
@@ -231,6 +246,47 @@
     }    
 }
 
+
+/**********************************************************************
+ *              EVENT_focus_change
+ *
+ * Handle an X FocusChange event
+ */
+static void EVENT_focus_change( Widget w, int hwnd, XEvent *event, 
+			       Boolean *cont_dispatch )
+{
+    MSG msg;
+    
+    msg.hwnd = hwnd;
+    msg.time = GetTickCount();
+    msg.pt.x = 0;
+    msg.pt.y = 0;
+
+    switch(event->type)
+    {
+      case FocusIn:
+	{
+	    msg.message = WM_SETFOCUS;
+	    msg.wParam = hwnd;
+	    hWndFocus = hwnd;
+
+	}
+	break;
+	
+      case FocusOut:
+	{
+	    if (hWndFocus)
+	    {
+		msg.message = WM_KILLFOCUS;
+		msg.wParam = hwnd;
+		hWndFocus = 0;
+	    }
+	}
+    }    
+    MSG_AddMsg( &msg );
+}
+
+
 /**********************************************************************
  *		SetCapture 	(USER.18)
  */
diff --git a/windows/focus.c b/windows/focus.c
new file mode 100644
index 0000000..ce1a91a2
--- /dev/null
+++ b/windows/focus.c
@@ -0,0 +1,52 @@
+/*
+ * Focus functions
+ *
+ * Copyright 1993 David Metcalfe
+ */
+
+static char Copyright[] = "Copyright  David Metcalfe, 1993";
+
+#include <X11/Intrinsic.h>
+#include <X11/StringDefs.h>
+#include "win.h"
+#include "gdi.h"
+
+HWND hWndFocus = 0;
+
+
+/*****************************************************************
+ *               SetFocus            (USER.22)
+ */
+
+HWND SetFocus(HWND hwnd)
+{
+    HWND hWndPrevFocus;
+    WND *wndPtr;
+
+    hWndPrevFocus = hWndFocus;
+
+    if (hwnd == 0)
+    {
+	XSetInputFocus(XT_display, None, RevertToPointerRoot, CurrentTime);
+    }
+    else
+    {
+	wndPtr = WIN_FindWndPtr(hwnd);
+	XSetInputFocus(XT_display, XtWindow(wndPtr->winWidget),
+		       RevertToParent, CurrentTime);
+    }
+
+    return hWndPrevFocus;
+}
+
+
+/*****************************************************************
+ *               GetFocus            (USER.23)
+ */
+
+HWND GetFocus(void)
+{
+    return hWndFocus;
+}
+
+
diff --git a/windows/graphics.c b/windows/graphics.c
index 338733a..a2a1e32 100644
--- a/windows/graphics.c
+++ b/windows/graphics.c
@@ -365,3 +365,79 @@
     SelectObject( hdc, prevBrush );
     return retval;
 }
+
+
+/***********************************************************************
+ *           DrawFocusRect    (GDI.466)
+ */
+void DrawFocusRect( HDC hdc, LPRECT rc )
+{
+    HPEN hPen, hOldPen;
+    int oldDrawMode, oldBkMode;
+    int left, top, right, bottom;
+    DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
+    if (!dc) return;
+
+    left   = XLPTODP( dc, rc->left );
+    top    = YLPTODP( dc, rc->top );
+    right  = XLPTODP( dc, rc->right );
+    bottom = YLPTODP( dc, rc->bottom );
+    
+    hPen = CreatePen(PS_DOT, 1, GetSysColor(COLOR_WINDOWTEXT)); 
+    hOldPen = (HPEN)SelectObject(hdc, (HANDLE)hPen);
+/*    oldDrawMode = SetROP2(hdc, R2_XORPEN);  */
+    oldBkMode = SetBkMode(hdc, TRANSPARENT);
+
+    if (DC_SetupGCForPen( dc ))
+	XDrawRectangle( XT_display, dc->u.x.drawable, dc->u.x.gc,
+		        left, top, right-left-1, bottom-top-1 );
+
+    SetBkMode(hdc, oldBkMode);
+/*    SetROP2(hdc, oldDrawMode);  */
+    SelectObject(hdc, (HANDLE)hOldPen);
+    DeleteObject((HANDLE)hPen);
+}
+
+
+/**********************************************************************
+ *          Line  (Not a MSWin Call)
+ */
+void Line(HDC hDC, int X1, int Y1, int X2, int Y2)
+{
+MoveTo(hDC, X1, Y1);
+LineTo(hDC, X2, Y2);
+}
+
+
+/**********************************************************************
+ *          DrawReliefRect  (Not a MSWin Call)
+ */
+ void DrawReliefRect(HDC hDC, RECT rect, int ThickNess, int Mode)
+{
+HPEN   hWHITEPen;
+HPEN   hDKGRAYPen;
+HPEN   hOldPen;
+int    OldColor;
+rect.right--;  rect.bottom--;
+hDKGRAYPen = CreatePen(PS_SOLID, 1, 0x00808080L);
+hWHITEPen = GetStockObject(WHITE_PEN);
+hOldPen = SelectObject(hDC, hWHITEPen);
+while(ThickNess > 0) {
+    if (Mode == 0)
+	SelectObject(hDC, hWHITEPen);
+    else
+	SelectObject(hDC, hDKGRAYPen);
+    Line(hDC, rect.left, rect.top, rect.right, rect.top);
+    Line(hDC, rect.left, rect.top, rect.left, rect.bottom + 1);
+    if (Mode == 0)
+	SelectObject(hDC, hDKGRAYPen);
+    else
+	SelectObject(hDC, hWHITEPen);
+    Line(hDC, rect.right, rect.bottom, rect.left, rect.bottom);
+    Line(hDC, rect.right, rect.bottom, rect.right, rect.top - 1);
+    InflateRect(&rect, -1, -1);
+    ThickNess--;
+    }
+SelectObject(hDC, hOldPen);
+DeleteObject(hDKGRAYPen);
+}
diff --git a/windows/syscolor.c b/windows/syscolor.c
index 7594fd1..a3ca9ac 100644
--- a/windows/syscolor.c
+++ b/windows/syscolor.c
@@ -48,22 +48,15 @@
 
 void SYSCOLOR_Init()
 {
-    Colormap map;
     XColor color;
     int i;
 
-    if ((map == COLOR_WinColormap) == CopyFromParent)
-	map = DefaultColormapOfScreen(XT_screen);
-
     for (i = 0; i < NUM_SYS_COLORS; i++)
     {
-	if (XParseColor(XT_display, map, DefSysColors[i], &color))
+	if (XParseColor(XT_display, COLOR_WinColormap, DefSysColors[i], &color))
 	{
-	    if (XAllocColor(XT_display, map, &color))
-	    {
-		SysColors[i] = RGB(color.red >> 8, color.green >> 8,
-				                    color.blue >> 8);
-	    }
+	    SysColors[i] = RGB(color.red >> 8, color.green >> 8,
+			       color.blue >> 8);
 	}
     }
 }
@@ -88,28 +81,11 @@
 
 void SetSysColors(int nChanges, LPINT lpSysColor, COLORREF *lpColorValues)
 {
-    Colormap map;
-    XColor color;
-    char colorStr[8];
     int i;
 
-    if ((map == COLOR_WinColormap) == CopyFromParent)
-	map = DefaultColormapOfScreen(XT_screen);
-
     for (i = 0; i < nChanges; i++)
     {
-	sprintf(colorStr, "#%2.2x%2.2x%2.2x", GetRValue(lpColorValues[i]),
-		GetGValue(lpColorValues[i]), GetBValue(lpColorValues[i]));
-
-	if (XParseColor(XT_display, map, colorStr, &color))
-	{
-	    if (XAllocColor(XT_display, map, &color))
-	    {
-		SysColors[lpSysColor[i]] = RGB(color.red >> 8, 
-						color.green >> 8,
-						color.blue >> 8);
-	    }
-	}
+	SysColors[lpSysColor[i]] = lpColorValues[i];
     }
 
     /* Send WM_SYSCOLORCHANGE message to all windows */
diff --git a/windows/utility.c b/windows/utility.c
index 3c20d87..ab189a0 100644
--- a/windows/utility.c
+++ b/windows/utility.c
@@ -9,6 +9,7 @@
  */
 
 #include <stdio.h>
+#include <stdarg.h>
 #include <ctype.h>
 #include "windows.h"
 
@@ -270,6 +271,21 @@
 	return result;
 };
 
+
+/**************************************************************************
+ *                wsprintf        [USER.420]
+ */
+int wsprintf(LPSTR lpOutput, LPSTR lpFormat, ...)
+{
+va_list  valist;
+int      ArgCnt;
+va_start(valist, lpFormat);
+ArgCnt = vsprintf(lpOutput, lpFormat, valist);
+va_end(valist);
+return (ArgCnt);
+}
+
+
 /*	wvsprintf() is an implementation of vsprintf(). This
  *	implementation converts the arguments to 32-bit integers and
  *	calls the standard library function vsprintf().
diff --git a/windows/win.c b/windows/win.c
index 4d517d3..3e50a37 100644
--- a/windows/win.c
+++ b/windows/win.c
@@ -17,12 +17,14 @@
 #include "user.h"
 
 extern Display * XT_display;
+extern Screen * XT_screen;
 extern Colormap COLOR_WinColormap;
 
 static HWND firstWindow = 0;
 
-void BUTTON_CreateButton(LPSTR className, LPSTR buttonLabel, HWND hwnd);
-
+void SCROLLBAR_CreateScrollBar(LPSTR className, LPSTR Label, HWND hwnd);
+void LISTBOX_CreateListBox(LPSTR className, LPSTR Label, HWND hwnd);
+void COMBOBOX_CreateComboBox(LPSTR className, LPSTR Label, HWND hwnd);
 
 /***********************************************************************
  *           WIN_FindWndPtr
@@ -67,28 +69,61 @@
 
 
 /***********************************************************************
+ *           WIN_SendParentNotify
+ *
+ * Send a WM_PARENTNOTIFY to all ancestors of the given window, unless
+ * the window has the WS_EX_NOPARENTNOTIFY style.
+ */
+static void WIN_SendParentNotify( HWND hwnd, WND * wndPtr, WORD event )
+{
+    HWND current = wndPtr->hwndParent;
+
+    if (wndPtr->dwExStyle & WS_EX_NOPARENTNOTIFY) return;
+    while (current)
+    {
+	SendMessage( current, WM_PARENTNOTIFY, 
+		     event, MAKELONG( hwnd, wndPtr->wIDmenu ) );
+	current = GetParent( current );
+    }
+}
+
+
+/***********************************************************************
  *           CreateWindow   (USER.41)
  */
 HWND CreateWindow( LPSTR className, LPSTR windowName,
 		   DWORD style, short x, short y, short width, short height,
 		   HWND parent, HMENU menu, HANDLE instance, LPSTR data ) 
 {
+    return CreateWindowEx( 0, className, windowName, style,
+			   x, y, width, height, parent, menu, instance, data );
+}
+
+
+/***********************************************************************
+ *           CreateWindowEx   (USER.452)
+ */
+HWND CreateWindowEx( DWORD exStyle, LPSTR className, LPSTR windowName,
+		     DWORD style, short x, short y, short width, short height,
+		     HWND parent, HMENU menu, HANDLE instance, LPSTR data ) 
+{
     HANDLE class, hwnd;
     CLASS *classPtr;
     WND *wndPtr, *parentPtr = NULL;
     CREATESTRUCT *createStruct;
     HANDLE hcreateStruct;
     int wmcreate;
-    LPSTR textPtr;
 
 #ifdef DEBUG_WIN
-    printf( "CreateWindow: %s %s %d,%d %dx%d\n", className, windowName, x, y, width, height );
+    printf( "CreateWindowEx: %s %s %d,%d %dx%d\n", className, windowName, x, y, width, height );
 #endif
 
     if (x == CW_USEDEFAULT) x = 0;
     if (y == CW_USEDEFAULT) y = 0;
     if (width == CW_USEDEFAULT) width = 600;
     if (height == CW_USEDEFAULT) height = 400;
+    if (!width) width = 1;
+    if (!height) height = 1;
 
       /* Find the parent and class */
 
@@ -127,9 +162,10 @@
     wndPtr->hwndLastActive    = 0;
     wndPtr->lpfnWndProc       = classPtr->wc.lpfnWndProc;
     wndPtr->dwStyle           = style;
-    wndPtr->dwExStyle         = 0;
+    wndPtr->dwExStyle         = exStyle;
     wndPtr->hmenuSystem       = 0;
     wndPtr->wIDmenu           = menu;
+    wndPtr->hText             = 0;
     wndPtr->flags             = 0;
 
     if (classPtr->wc.cbWndExtra)
@@ -139,11 +175,6 @@
     else wndPtr->hdc = 0;
     classPtr->cWindows++;
 
-      /* Create buffer for window text */
-    wndPtr->hText = USER_HEAP_ALLOC(GMEM_MOVEABLE, strlen(windowName) + 1);
-    textPtr = (LPSTR)USER_HEAP_ADDR(wndPtr->hText);
-    strcpy(textPtr, windowName);
-
       /* Insert the window in the linked list */
 
     if (parent)
@@ -157,6 +188,21 @@
 	firstWindow = hwnd;
     }
     
+    if (!strcasecmp(className, "SCROLLBAR"))
+    {
+	SCROLLBAR_CreateScrollBar(className, windowName, hwnd);
+	goto WinCreated;
+    }
+    if (!strcasecmp(className, "LISTBOX"))
+    {
+	LISTBOX_CreateListBox(className, windowName, hwnd);
+	goto WinCreated;
+    }
+    if (!strcasecmp(className, "COMBOBOX"))
+    {
+	COMBOBOX_CreateComboBox(className, windowName, hwnd);
+	goto WinCreated;
+    }
       /* Create the widgets */
 
     if (style & WS_CHILD)
@@ -164,19 +210,23 @@
 	wndPtr->shellWidget = 0;
 	if (style & (WS_BORDER | WS_DLGFRAME | WS_THICKFRAME))
 	{ 
+	    int borderCol = 0;
+	    if (COLOR_WinColormap == DefaultColormapOfScreen(XT_screen))
+		borderCol = BlackPixelOfScreen(XT_screen);
 	    wndPtr->winWidget = XtVaCreateManagedWidget(className,
-						    coreWidgetClass,
+						    compositeWidgetClass,
 						    parentPtr->winWidget,
 						    XtNx, x,
 						    XtNy, y,
 						    XtNwidth, width,
 						    XtNheight, height,
+						    XtNborderColor, borderCol,
 						    NULL );
 	}
 	else
 	{
 	    wndPtr->winWidget = XtVaCreateManagedWidget(className,
-						    coreWidgetClass,
+						    compositeWidgetClass,
 						    parentPtr->winWidget,
 						    XtNx, x,
 						    XtNy, y,
@@ -188,15 +238,13 @@
     }
     else
     {
-	wndPtr->shellWidget = XtVaAppCreateShell(className, 
-						 windowName,
+	wndPtr->shellWidget = XtVaAppCreateShell(windowName, 
+						 className,
 						 topLevelShellWidgetClass,
 						 XT_display,
 						 XtNx, x,
 						 XtNy, y,
-#ifdef USE_PRIVATE_MAP
 						 XtNcolormap, COLOR_WinColormap,
-#endif
 						 NULL );
 	wndPtr->compositeWidget = XtVaCreateManagedWidget(className,
 						    formWidgetClass,
@@ -245,6 +293,8 @@
 	}
     }
 
+WinCreated:
+
       /* Send the WM_CREATE message */
 	
     hcreateStruct = GlobalAlloc( GMEM_MOVEABLE, sizeof(CREATESTRUCT) );
@@ -262,8 +312,10 @@
     createStruct->lpszClass      = className;
     createStruct->dwExStyle      = 0;
 
-    wmcreate = CallWindowProc( wndPtr->lpfnWndProc, hwnd, 
-			       WM_CREATE, 0, (LONG) createStruct );
+    wmcreate = SendMessage( hwnd, WM_NCCREATE, 0, (LONG)createStruct );
+    if (!wmcreate) wmcreate = -1;
+    else wmcreate = SendMessage( hwnd, WM_CREATE, 0, (LONG)createStruct );
+
     GlobalUnlock( hcreateStruct );
     GlobalFree( hcreateStruct );
     
@@ -279,6 +331,7 @@
     EVENT_AddHandlers( wndPtr->winWidget, hwnd );
 
     if (style & WS_VISIBLE) ShowWindow( hwnd, SW_SHOW );
+    WIN_SendParentNotify( hwnd, wndPtr, WM_CREATE );
     return hwnd;
 }
 
@@ -287,35 +340,41 @@
  */
 BOOL DestroyWindow( HWND hwnd )
 {
-    WND *wndPtr, *parentPtr;
+    WND * wndPtr;
+    HWND * curWndPtr;
     CLASS * classPtr;
     
-    wndPtr = WIN_FindWndPtr( hwnd );
-    if (!wndPtr) return FALSE;
+      /* Initialisation */
 
-    if (wndPtr->hwndParent)
-    {
-	parentPtr = WIN_FindWndPtr( wndPtr->hwndParent );
-	printf( "INTERNAL ERROR: DestroyWindow: Invalid window parent\n" );
-	return FALSE;
-    }
-    
-    classPtr = CLASS_FindClassPtr( wndPtr->hClass );
-    if (!classPtr)
-    {
-	printf( "INTERNAL ERROR: DestroyWindow: Invalid window class\n" );
-	return FALSE;
-    }
-    
+    if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
+    if (!(classPtr = CLASS_FindClassPtr( wndPtr->hClass ))) return FALSE;
+    WIN_SendParentNotify( hwnd, wndPtr, WM_DESTROY );
+
+      /* Send destroy messages */
+
     SendMessage( hwnd, WM_DESTROY, 0, 0 );
+    SendMessage( hwnd, WM_NCDESTROY, 0, 0 );
     
       /* Destroy all children */
 
-    /* ........... */
+    while (wndPtr->hwndChild)  /* The child removes itself from the list */
+	DestroyWindow( wndPtr->hwndChild );
 
       /* Remove the window from the linked list */
-    
-    /* ........... */
+
+    if (wndPtr->hwndParent)
+    {
+	WND * parentPtr = WIN_FindWndPtr( wndPtr->hwndParent );
+	curWndPtr = &parentPtr->hwndChild;
+    }    
+    else curWndPtr = &firstWindow;
+
+    while (*curWndPtr != hwnd)
+    {
+	WND * curPtr = WIN_FindWndPtr( *curWndPtr );
+	curWndPtr = &curPtr->hwndNext;
+    }
+    *curWndPtr = wndPtr->hwndNext;
 
       /* Destroy the window */
 
@@ -323,13 +382,35 @@
     else XtDestroyWidget( wndPtr->winWidget );
     if (wndPtr->hdc) DeleteDC( wndPtr->hdc );
     classPtr->cWindows--;
-    USER_HEAP_FREE(wndPtr->hText);
     USER_HEAP_FREE( hwnd );
     return TRUE;
 }
 
 
 /***********************************************************************
+ *           GetWindowRect   (USER.32)
+ */
+void GetWindowRect( HWND hwnd, LPRECT rect ) 
+{
+    int x, y, width, height;  
+    WND * wndPtr = WIN_FindWndPtr( hwnd ); 
+
+    if (wndPtr) 
+    {
+	XtVaGetValues(wndPtr->winWidget,
+		      XtNx, &x, XtNy, &y,
+		      XtNwidth, &width,
+		      XtNheight, &height,
+		      NULL );
+	rect->left  = x & 0xffff;
+	rect->top = y & 0xffff;
+	rect->right  = width & 0xffff;
+	rect->bottom = height & 0xffff;
+    }
+}
+
+
+/***********************************************************************
  *           GetClientRect   (USER.33)
  */
 void GetClientRect( HWND hwnd, LPRECT rect ) 
@@ -368,12 +449,60 @@
 	SendMessage( hwnd, WM_SIZE, SIZE_RESTORED, 
 		     (width & 0xffff) | (height << 16) );
 	SendMessage( hwnd, WM_SHOWWINDOW, TRUE, 0 );
+/*
+	printf("ShowWindow(%X, %X); !\n", hwnd, cmd);
+*/
+	switch(cmd)
+	    {
+	    case SW_HIDE:
+		XtSetMappedWhenManaged(wndPtr->winWidget, FALSE);
+		break;
+	    case SW_SHOWNA:
+	    case SW_SHOWMINNOACTIVE:
+	    case SW_SHOWNOACTIVATE:
+	    case SW_MINIMIZE:
+	    case SW_MAXIMIZE:
+	    case SW_SHOWMAXIMIZED:
+	    case SW_SHOWMINIMIZED:
+	    case SW_SHOW:
+	    case SW_NORMAL:
+	    case SW_SHOWNORMAL:
+		XtSetMappedWhenManaged(wndPtr->winWidget, TRUE);
+		break;
+	    default:
+		break;
+	    }
     }
     return TRUE;
 }
 
 
 /***********************************************************************
+ *           MoveWindow   (USER.56)
+ */
+void MoveWindow(HWND hWnd, short x, short y, short w, short h, BOOL bRepaint)
+{    
+    WND * wndPtr = WIN_FindWndPtr( hWnd );
+    if (wndPtr) 
+    {
+	wndPtr->rectClient.left   = x;
+	wndPtr->rectClient.top    = y;
+	wndPtr->rectClient.right  = x + w;
+	wndPtr->rectClient.bottom = y + h;
+	XtVaSetValues(wndPtr->winWidget, XtNx, x, XtNy, y,
+		      XtNwidth, w, XtNheight, h, NULL );
+	SendMessage(hWnd, WM_MOVE, 0, MAKELONG(x, y)); 
+	printf("MoveWindow(%X, %d, %d, %d, %d, %d); !\n", 
+			hWnd, x, y, w, h, bRepaint);
+	if (bRepaint) {
+	    InvalidateRect(hWnd, NULL, TRUE);
+	    UpdateWindow(hWnd);
+	    }
+    }
+}
+
+
+/***********************************************************************
  *           UpdateWindow   (USER.124)
  */
 void UpdateWindow( HWND hwnd )
@@ -441,6 +570,42 @@
 }
 
 
+/***********************************************************************
+ *           SetWindowPos   (USER.232)
+ */
+void SetWindowPos(HWND hWnd, HWND hWndInsertAfter, short x, short y, short w, short h, WORD wFlag)
+{    
+    WND * wndPtr = WIN_FindWndPtr( hWnd );
+    if (wndPtr) 
+    {
+	if ((wFlag & SWP_NOMOVE) == 0) {
+	    wndPtr->rectClient.left   = x;
+	    wndPtr->rectClient.top    = y;
+	    XtVaSetValues(wndPtr->winWidget, XtNx, x, XtNy, y, NULL );
+	    }
+	if ((wFlag & SWP_NOSIZE) == 0) {
+	    wndPtr->rectClient.right  = x + w;
+	    wndPtr->rectClient.bottom = y + h;
+	    XtVaSetValues(wndPtr->winWidget, XtNwidth, w, XtNheight, h, NULL );
+	    }
+	if ((wFlag & SWP_NOREDRAW) == 0) {
+	    InvalidateRect(hWnd, NULL, TRUE);
+	    UpdateWindow(hWnd);
+	    }
+	if ((wFlag & SWP_HIDEWINDOW) == SWP_HIDEWINDOW) 
+	    ShowWindow(hWnd, SW_HIDE);
+	if ((wFlag & SWP_SHOWWINDOW) == SWP_SHOWWINDOW) 
+	    ShowWindow(hWnd, SW_SHOW);
+/*
+	if ((wFlag & SWP_NOACTIVATE) == 0) 
+	    SetActiveWindow(hWnd);
+*/
+	printf("SetWindowPos(%X, %X, %d, %d, %d, %d, %X); !\n", 
+		hWnd, hWndInsertAfter, x, y, w, h, wFlag);
+    }
+}
+
+
 /**********************************************************************
  *           GetDesktopWindow        (USER.286)
  */
@@ -502,7 +667,7 @@
     {
 	case GWL_STYLE:   return wndPtr->dwStyle;
         case GWL_EXSTYLE: return wndPtr->dwExStyle;
-	case GWL_WNDPROC: return wndPtr->lpfnWndProc;
+	case GWL_WNDPROC: return (LONG)wndPtr->lpfnWndProc;
     }
     return 0;
 }
@@ -521,7 +686,7 @@
     {
 	case GWL_STYLE:   ptr = &wndPtr->dwStyle;
         case GWL_EXSTYLE: ptr = &wndPtr->dwExStyle;
-	case GWL_WNDPROC: ptr = &wndPtr->lpfnWndProc;
+	case GWL_WNDPROC: ptr = (LONG *)(&wndPtr->lpfnWndProc);
 	default: return 0;
     }
     retval = *ptr;
@@ -533,32 +698,16 @@
 /*****************************************************************
  *         GetParent              (USER.46)
  */
-
 HWND GetParent(HWND hwnd)
 {
     WND *wndPtr = WIN_FindWndPtr(hwnd);
-    HWND hwndParent = wndPtr->hwndParent;
-    GlobalUnlock(hwnd);
-    return hwndParent;
-}
-
-/****************************************************************
- *         GetDlgCtrlID           (USER.277)
- */
-
-int GetDlgCtrlID(HWND hwnd)
-{
-    WND *wndPtr = WIN_FindWndPtr(hwnd);
-    int ctrlID = wndPtr->wIDmenu;
-    GlobalUnlock(hwnd);
-    return ctrlID;
+    return wndPtr->hwndParent;
 }
 
 
 /*******************************************************************
  *         GetWindowText          (USER.36)
  */
-
 int GetWindowText(HWND hwnd, LPSTR lpString, int nMaxCount)
 {
     return (int)SendMessage(hwnd, WM_GETTEXT, (WORD)nMaxCount, 
@@ -566,9 +715,16 @@
 }
 
 /*******************************************************************
+ *         SetWindowText          (USER.37)
+ */
+void SetWindowText(HWND hwnd, LPSTR lpString)
+{
+    SendMessage(hwnd, WM_SETTEXT, (WORD)NULL, (DWORD)lpString);
+}
+
+/*******************************************************************
  *         GetWindowTextLength    (USER.38)
  */
-
 int GetWindowTextLength(HWND hwnd)
 {
     return (int)SendMessage(hwnd, WM_GETTEXTLENGTH, (WORD)NULL, 
@@ -576,3 +732,103 @@
 }
 
 
+/*******************************************************************
+ *         IsChild    (USER.48)
+ */
+BOOL IsChild( HWND parent, HWND child )
+{
+    HWND curChild;
+    WND * parentPtr;
+    WND * childPtr;
+
+    if (!(parentPtr = WIN_FindWndPtr( parent ))) return FALSE;
+    curChild = parentPtr->hwndChild;
+
+    while (curChild)
+    {
+	if (curChild == child) return TRUE;
+	if (IsChild( curChild, child )) return TRUE;
+	if (!(childPtr = WIN_FindWndPtr( curChild ))) return FALSE;
+	curChild = childPtr->hwndNext;
+    }    
+    return FALSE;
+}
+
+
+/*******************************************************************
+ *         GetTopWindow    (USER.229)
+ */
+HWND GetTopWindow( HWND hwnd )
+{
+    WND * wndPtr = WIN_FindWndPtr( hwnd );
+    if (wndPtr) return wndPtr->hwndChild;
+    else return 0;
+}
+
+
+/*******************************************************************
+ *         GetWindow    (USER.262)
+ */
+HWND GetWindow( HWND hwnd, WORD rel )
+{
+    WND * wndPtr = WIN_FindWndPtr( hwnd );
+    if (!wndPtr) return 0;
+    switch(rel)
+    {
+    case GW_HWNDFIRST:
+	if (wndPtr->hwndParent)
+	{
+	    WND * parentPtr = WIN_FindWndPtr( wndPtr->hwndParent );
+	    return parentPtr->hwndChild;
+	}
+	else return firstWindow;
+	
+    case GW_HWNDLAST:
+	while (wndPtr->hwndNext)
+	{
+	    hwnd = wndPtr->hwndNext;
+	    wndPtr = WIN_FindWndPtr( hwnd );
+	}
+	return hwnd;
+	
+    case GW_HWNDNEXT:
+	return wndPtr->hwndNext;
+	
+    case GW_HWNDPREV:	
+	{
+	    HWND hwndPrev;
+	    
+	    if (wndPtr->hwndParent)
+	    {
+		WND * parentPtr = WIN_FindWndPtr( wndPtr->hwndParent );
+		hwndPrev = parentPtr->hwndChild;
+	    }
+	    else hwndPrev = firstWindow;
+	    if (hwndPrev == hwnd) return 0;
+	    while (hwndPrev)
+	    {
+		wndPtr = WIN_FindWndPtr( hwndPrev );
+		if (wndPtr->hwndNext == hwnd) break;
+		hwndPrev = wndPtr->hwndNext;
+	    }
+	    return hwndPrev;
+	}
+	
+    case GW_OWNER:
+	return wndPtr->hwndOwner;
+
+    case GW_CHILD:
+	return wndPtr->hwndChild;
+    }
+    return 0;
+}
+
+
+/*******************************************************************
+ *         GetNextWindow    (USER.230)
+ */
+HWND GetNextWindow( HWND hwnd, WORD flag )
+{
+    if ((flag != GW_HWNDNEXT) && (flag != GW_HWNDPREV)) return 0;
+    return GetWindow( hwnd, flag );
+}