Release 0.5

Sun Jan  2 12:38:53 1994  David Metcalfe <david@prism.demon.co.uk>

	* [windows/class.c]
	Implemented GetClassName and GetClassInfo.

	* [windows/caret.c]
	Various improvements to text caret code.

Fri Dec 31 15:22:22 1993  John Brezak <brezak@apollo.hp.com>

	* [misc/comm.c]
	Patches to work with NetBSD.

Thu Dec 30 12:11:55 1993  John Richardson <jrichard@cs.uml.edu>

	* [objects/bitblt.c] Added StretchBlt().

Tue Jan  4 05:22:07 1994  julliard@di.epfl.ch (Alexandre Julliard)

	* [misc/user.c]
	Added creation of system message queue.

	* [objects/bitmap.c] [objects/dcvalues.c] [windows/dc.c]
	Added DC size fields into DC structure.		

	* [objects/clipping.c]
	Bug fix in CLIPPING_IntersectRect().

	* [windows/class.c]
	Allocate a DCE instead of a DC for CS_CLASSDC classes.

	* [windows/clipping.c]
	Fixed GetUpdateRect() and GetUpdateRgn() to clip to the client area.

	* [windows/dce.c]
	Implemented GetDCEx() and GetWindowDC().

	* [windows/defwnd.c]
	Implemented WM_WINDOWPOSCHANGED handling.

	* [windows/event.c]
	Preliminary support for Xlib event handling instead of Xt callbacks.
	Changed MSG_AddMsg() calls to hardware_event() or PostMessage().

	* [windows/message.c]
	Preliminary support for multiple message queues.
	Implemented hardware_event() to store messages into the system queue.
	Implemented Get/SetTaskQueue().
	Better WM_PAINT and WM_TIMER handling.
	Changes to use Xlib instead of Xt for events.

	* [windows/painting.c]
	Use GetDCEx() to retrieve the DC, to get a correct visible region.

	* [windows/timer.c]
	Moved the timer procedure callback into DispatchMessage().
	Changed implementation to get rid of Xt timeouts.  Timer checking
	is now done inside GetMessage().

	* [windows/win.c]
	Allocate a DCE instead of a DC for CS_OWNDC windows.
	Replaced Xt calls with Xlib calls.
	Moved window positioning functions into windows/winpos.c

	* [windows/winpos.c]  (New file)
	Rewritten most of the window positioning functions.
	Implemented SetWindowPos() and MapWindowPoints().

Jan 3, 94 martin2@trgcorp.solucorp.qc.ca (Martin Ayotte)

	* [if1632/user.spec]
	Bad arguments description for function SetDlgItemText.

	* [objects/text.c]
	Function DrawText now handle DT_CALCRECT request.

	* [misc/message.c]
	Message boxes now use DrawText with DT_CALCRECT.

	* [windows/graphics.c]
	Bug fix in function FrameRect, (it was using PEN instead of BRUSH).

	* [windows/win.c]
	Bug fix for flags in function ShowWindow.
	More accurate WM_SIZE generated by function ShowWindow.

	* [controls/listbox.c]
	More code for LBS_MULTIPLESEL.
	More code for LBS_MULTICOLUMN.

	* [include/windows.h]
	Bad define for MF_SEPARATOR.

	* [controls/menu.c]
	New functions: PopMenuWndProc() with 'glues',
	CreatePopupMenu(), AppendMenu(), InsertMenu(), RemoveMenu(), 
	DeleteMenu(), ModifyMenu(), TrackPopupMenu().
	Code in stubs: CreateMenu(), DestroyMenu(). 

Sat Jan  1 10:22:43 1994  Bob Amstadt  (bob@pooh)

	* loader/wine.c: Added support for relocation types 5 and 6.

Mon Dec 27 11:06:03 1993  Erik Bos (erik@trashcan.hacktic.nl)

	* [misc/comm.c]
	new functions: BuildCommDCB(), OpenComm(), CloseComm(),
	SetCommBreak(), ClearCommBreak(), EscapeCommFunction(), FlushComm(),
	GetCommError(), SetCommEventMask(), GetCommEventMask(),
	SetCommState(), GetCommState(), TransmitCommChar(), ReadComm(), 
	WriteComm().

Wed Dec 22 13:00:15 1993  David Metcalfe <david@prism.demon.co.uk>

	* [windows/caret.c]
	Implemented text caret functions.

Tue Dec 21 06:13:58 1993  julliard@di.epfl.ch (Alexandre Julliard)

	* [loader/wine.c]
	Bug fix in LoadImage().

	* [objects/bitblt.c] [objects/clipping.c] [objects/text.c]
	  [windows/dc.c] [windows/dce.c] [windows/graphics.c]
	Modified graphics calls to take into account the DC origin.

	* [windows/defwnd.c]
	Added preliminary WM_NCCALCSIZE handling.

	* [windows/event.c]
	Send WM_NCCALCSIZE message on resize event.

	* [windows/win.c]
	Send WM_NCCALCSIZE message in CreateWindow().
	Realize widgets at creation time (should prevent problems with
	unrealized widgets).

Dec 19, 93 martin2@trgcorp.solucorp.qc.ca (Martin Ayotte)

	* [controls/static.c]
	Send mouse & keyboard message received to its parent.

	* [controls/scroll.c]
	Send keyboard message received to its parent.

	* [controls/listbox.c]
	Add Navigation keys .
	ListBox now use VSCROLL & HSCROLL instead of children.
	Alpha version of LBS_MULTIPLESEL.
	Alpha version of LBS_MULTICOLUMN.

	* [controls/combo.c]
	Add Navigation keys on closed ComboBox.
	Remove useless 'COMBOBOX_CreateComboBox' function.

Mon Dec 19 20:39:34 1993  Erik Bos (erik@trashcan.hacktic.nl)

	* [loader/wine.
	LoadImage() modified to use FindFile().

	* [misc/file.c]
	SetErrorMode added

	* [misc/dos_fs.c]
	bug fixes.

Dec 13, 93 martin2@trgcorp.solucorp.qc.ca (Martin Ayotte)

	* [memory/global.c]
	bug fix in GlobalGetFreeSegment : good ptr in 'g_prev'.

	* [sysres.dll]
	preliminary version of a 'glass of wine' bitmap

	* [windows/event.c]
	New function 'GetCapture'.

	* [controls/scroll.c]
	Remove useless 'SCROLLBAR_CreateScrollBar' function.

	* [controls/listbox.c]
	Remove useless 'LISTBOX_CreateListBox' function.

Mon Dec 13 13:51:00 1993  David Metcalfe <david@prism.demon.co.uk>

	* [objects/font.c]
	Corrected bugs in GetCharWidth().

	* [windows/event.c]
	Modified EVENT_key to send Windows virtual key codes for
	WM_KEYDOWN and WM_KEYUP messages, and a WM_CHAR message
	for printable characters.

Wed Dec 08 19:20:00 1993  Karl Guenter Wuensch (hn324wu@unidui.uni-duisburg.de)

	* [windows/graphics.c]
	Added Polyline and Polygon

Mon Dec 13 14:51:54 1993  Erik Bos (erik@trashcan.hacktic.nl)

	* [controls/listbox.c]
	ListBoxDirectory() modified to use dos_fs.c's functions to
	access files&|drives.

Sat Dec 04 17:04:23 1993  Erik Bos (erik@trashcan.hacktic.nl)

       	* [misc/dos_fs.c]
       	Added FindFile() to search a file in a dos/unix style path.
	
	* [misc/file.c]
	New Win31 functions: OpenFile, _lcreate, _llseek, GetTempDrive,
	GetTempFileName, GetWindowsDirectory, GetSystemDirectory,
	GetDriveType.			   

       	* [misc/int21.c]
       	Modified.

Wed Dec  1 16:20:45 1993  Miguel de Icaza  (miguel@roxanne.nuclecu.unam.mx)

        * [misc/profile.c]
        The Profile functions now return the correct values. They now
        implement all the features described in the SDK.

Tue Nov 30 13:55:27 1993  Bob Amstadt  (bob at amscons)

	* [loader/selector.c]
	Rewrote selector aliasing routines to use System V IPC
	routine to alias memory segments.

Nov 28, 93 martin2@trgcorp.solucorp.qc.ca (Martin Ayotte)

	* [controls/listbox.c]
	More consistency in functions using wIndexes

	* [controls/scroll.c]
	New function : ShowScrollBar().

	* [loader/cursor.c] ... New file
	Move cursor functions from [loader/resource.c].
	New function : ClipCursor().
	New function : GetClipCursor().
	New function : CreateCursor().
	SetCursor() now working using gloabal variable 'winHasCursor'.

	*[object/palette.c]
	New stub only : SelectPalette().
	New stub only : RealizePalette().

	*[win/event.c]
	New function : EVENT_enter_notify(),
		update 'winHasCursor' and send WM_SETCURSOR.

	*[win/defwnd.c]
	Add processing of WM_SETCURSOR message.

	*[win/win.c]
	New members in WND structure : hCursor, hWndVScroll & hWndHScroll. 
	CreateWindowEx() now create children for WM_HSCROLL & WM_VSCROLL.
	New function ClientToScreen().
	New function ScreenToClient().

Mon Nov 25 18:25:40 1993  Erik Bos (erik@trashcan.hacktic.nl)

       	* [files.h / regfunc.h / misc/dos.c]
       	Removed.

       	* [misc/dos_fs.c]
       	Added support for loading dosdrive cfg from wine.ini.

       	* [misc/int21.c]
       	Modified.


Wed Nov 24 11:37:33 1993  julliard@disuns2.epfl.ch (Alexandre Julliard)

	* [include/atom.h] [memory/atom.c]
	Implemented atoms.

	* [windows/class.c]
	Modified RegisterClass() to use atoms.
	Implemented CS_GLOBALCLASS style.

	* [windows/message.c]
	Implemented RegisterWindowMessage().

	* [loader/resource.c]
	Bug fix in LoadResource().

	* [windows/dialog.c]
	Modified CreateDialogParam() to use Find/LoadResource().
diff --git a/windows/Imakefile b/windows/Imakefile
new file mode 100644
index 0000000..b16652f
--- /dev/null
+++ b/windows/Imakefile
@@ -0,0 +1,53 @@
+#include "../Wine.tmpl"
+
+MODULE = windows
+
+SRCS = \
+	class.c \
+	dc.c \
+	dce.c \
+	event.c \
+	message.c \
+	win.c \
+	timer.c \
+	graphics.c \
+	clipping.c \
+	mapping.c \
+	painting.c \
+	keyboard.c \
+	utility.c \
+	syscolor.c \
+	defwnd.c \
+	defdlg.c \
+	dialog.c \
+	focus.c \
+	scroll.c
+
+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 \
+	defwnd.o \
+	defdlg.o \
+	dialog.o \
+	focus.o \
+	scroll.o
+
+WineRelocatableTarget($(TOP)/$(MODULE),,$(OBJS))
+DependTarget()
+CleanTarget()
+
+includes::
+
+install::
diff --git a/windows/Makefile b/windows/Makefile
index 0c5d34a..30570a1 100644
--- a/windows/Makefile
+++ b/windows/Makefile
@@ -2,7 +2,7 @@
 
 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 \
-	defwnd.o defdlg.o dialog.o focus.o scroll.o
+	defwnd.o defdlg.o dialog.o focus.o scroll.o caret.o winpos.o
 
 default: windows.o
 
diff --git a/windows/caret.c b/windows/caret.c
new file mode 100644
index 0000000..eb78dc8
--- /dev/null
+++ b/windows/caret.c
@@ -0,0 +1,250 @@
+/*
+ * Caret functions
+ *
+ * Copyright 1993 David Metcalfe
+ */
+
+static char Copyright[] = "Copyright  David Metcalfe, 1993";
+
+#include <X11/Intrinsic.h>
+
+#include "windows.h"
+
+extern XtAppContext XT_app_context;
+
+typedef struct
+{
+    HWND          hwnd;
+    short         hidden;
+    BOOL          on;
+    short         x;
+    short         y;
+    short         width;
+    short         height;
+    COLORREF      color;
+    WORD          timeout;
+    XtIntervalId  xtid;
+} CARET;
+
+static CARET Caret;
+static BOOL LockCaret;
+
+static void CARET_Callback(XtPointer data, XtIntervalId *xtid);
+static void CARET_HideCaret(CARET *pCaret);
+
+
+/*****************************************************************
+ *               CARET_Callback
+ */
+
+static void CARET_Callback(XtPointer data, XtIntervalId *xtid)
+{
+    CARET *pCaret = (CARET *)data;
+    HDC hdc;
+    HBRUSH hBrush;
+    HRGN rgn;
+
+#ifdef DEBUG_CARET
+    printf("CARET_Callback: LockCaret=%d, hidden=%d, on=%d\n",
+	   LockCaret, pCaret->hidden, pCaret->on);
+#endif
+    if (!LockCaret && (!pCaret->hidden || pCaret->on))
+    {
+	pCaret->on = (pCaret->on ? FALSE : TRUE);
+	hdc = GetDC(pCaret->hwnd);
+	hBrush = CreateSolidBrush(pCaret->color);
+	SelectObject(hdc, (HANDLE)hBrush);
+	SetROP2(hdc, R2_XORPEN);
+	rgn = CreateRectRgn(pCaret->x, pCaret->y, 
+			    pCaret->x + pCaret->width,
+			    pCaret->y + pCaret->height);
+	FillRgn(hdc, rgn, hBrush);
+	DeleteObject((HANDLE)rgn);
+	DeleteObject((HANDLE)hBrush);
+	ReleaseDC(pCaret->hwnd, hdc);
+    }
+
+    pCaret->xtid = XtAppAddTimeOut(XT_app_context, pCaret->timeout,
+				   CARET_Callback, pCaret);
+}
+
+
+/*****************************************************************
+ *               CARET_HideCaret
+ */
+
+static void CARET_HideCaret(CARET *pCaret)
+{
+    HDC hdc;
+    HBRUSH hBrush;
+    HRGN rgn;
+
+    pCaret->on = FALSE;
+    hdc = GetDC(pCaret->hwnd);
+    hBrush = CreateSolidBrush(pCaret->color);
+    SelectObject(hdc, (HANDLE)hBrush);
+    SetROP2(hdc, R2_XORPEN);
+    rgn = CreateRectRgn(pCaret->x, pCaret->y, 
+			pCaret->x + pCaret->width,
+			pCaret->y + pCaret->height);
+    FillRgn(hdc, rgn, hBrush);
+    DeleteObject((HANDLE)rgn);
+    DeleteObject((HANDLE)hBrush);
+    ReleaseDC(pCaret->hwnd, hdc);
+}
+
+
+/*****************************************************************
+ *               CreateCaret          (USER.163)
+ */
+
+void CreateCaret(HWND hwnd, HBITMAP bitmap, short width, short height)
+{
+    if (!hwnd) return;
+
+    /* if cursor already exists, destroy it */
+/*    if (Caret.hwnd)
+	DestroyCaret();
+*/
+    if (bitmap)
+    {
+	printf("CreateCaret: Bitmaps are currently not supported\n");
+	return;
+    }
+
+    if (width)
+	Caret.width = width;
+    else
+	Caret.width = 3;              /* should be SM_CXBORDER */
+
+    if (height)
+	Caret.height = height;
+    else
+	Caret.height = 3;             /* should be SM_CYBORDER */
+
+    Caret.hwnd = hwnd;
+    Caret.hidden = 1;
+    Caret.on = FALSE;
+    Caret.x = 0;
+    Caret.y = 0;
+    Caret.color = GetSysColor(COLOR_WINDOWTEXT);
+    Caret.timeout = 750;
+    LockCaret = FALSE;
+
+    Caret.xtid = XtAppAddTimeOut(XT_app_context, Caret.timeout,
+				 CARET_Callback, &Caret);
+}
+   
+
+/*****************************************************************
+ *               DestroyCaret         (USER.164)
+ */
+
+void DestroyCaret()
+{
+/*    if (!Caret.hwnd) return;
+*/
+    XtRemoveTimeOut(Caret.xtid);
+
+    if (Caret.on)
+	CARET_HideCaret(&Caret);
+
+    Caret.hwnd = 0;          /* cursor marked as not existing */
+}
+
+
+/*****************************************************************
+ *               SetCaretPos          (USER.165)
+ */
+
+void SetCaretPos(short x, short y)
+{
+    HDC hdc;
+    HBRUSH hBrush;
+    HRGN rgn;
+
+    if (!Caret.hwnd) return;
+
+#ifdef DEBUG_CARET
+    printf("SetCaretPos: x=%d, y=%d\n", x, y);
+#endif
+
+    LockCaret = TRUE;
+    if (Caret.on)
+	CARET_HideCaret(&Caret);
+
+    Caret.x = x;
+    Caret.y = y;
+    LockCaret = FALSE;
+}
+
+/*****************************************************************
+ *               HideCaret            (USER.166)
+ */
+
+void HideCaret(HWND hwnd)
+{
+    if (!Caret.hwnd) return;
+    if (hwnd && (Caret.hwnd != hwnd)) return;
+
+    LockCaret = TRUE;
+    if (Caret.on)
+	CARET_HideCaret(&Caret);
+
+    ++Caret.hidden;
+    LockCaret = FALSE;
+}
+
+
+/*****************************************************************
+ *               ShowCaret            (USER.167)
+ */
+
+void ShowCaret(HWND hwnd)
+{
+    if (!Caret.hwnd) return;
+    if (hwnd && (Caret.hwnd != hwnd)) return;
+
+#ifdef DEBUG_CARET
+    printf("ShowCaret: hidden=%d\n", Caret.hidden);
+#endif
+    if (Caret.hidden)
+	--Caret.hidden;
+}
+
+
+/*****************************************************************
+ *               SetCaretBlinkTime    (USER.168)
+ */
+
+void SetCaretBlinkTime(WORD msecs)
+{
+    if (!Caret.hwnd) return;
+
+    Caret.timeout = msecs;
+}
+
+
+/*****************************************************************
+ *               GetCaretBlinkTime    (USER.169)
+ */
+
+WORD GetCaretBlinkTime()
+{
+    if (!Caret.hwnd) return;
+
+    return Caret.timeout;
+}
+
+
+/*****************************************************************
+ *               GetCaretPos          (USER.183)
+ */
+
+void GetCaretPos(LPPOINT pt)
+{
+    if (!Caret.hwnd || !pt) return;
+
+    pt->x = Caret.x;
+    pt->y = Caret.y;
+}
diff --git a/windows/class.c b/windows/class.c
index 23a2c49..4ca2d9f 100644
--- a/windows/class.c
+++ b/windows/class.c
@@ -9,6 +9,7 @@
 #include "class.h"
 #include "user.h"
 #include "win.h"
+#include "dce.h"
 
 
 static HCLASS firstClass = 0;
@@ -18,19 +19,50 @@
  *           CLASS_FindClassByName
  *
  * Return a handle and a pointer to the class.
+ * 'ptr' can be NULL if the pointer is not needed.
  */
 HCLASS CLASS_FindClassByName( char * name, CLASS **ptr )
 {
-    HCLASS class = firstClass;
-    while(class)
+    ATOM atom;
+    HCLASS class;
+    CLASS * classPtr;
+
+      /* First search task-specific classes */
+
+    if ((atom = FindAtom( name )) != 0)
     {
-	*ptr = (CLASS *) USER_HEAP_ADDR(class);
-	if (!strcasecmp( (*ptr)->wc.lpszClassName, name )) return class;
-	class = (*ptr)->hNext;
+	for (class = firstClass; (class); class = classPtr->hNext)
+	{
+	    classPtr = (CLASS *) USER_HEAP_ADDR(class);
+	    if (classPtr->wc.style & CS_GLOBALCLASS) continue;
+	    if (classPtr->atomName == atom)
+	    {
+		if (ptr) *ptr = classPtr;
+		return class;
+	    }
+	}
     }
+    
+      /* Then search global classes */
+
+    if ((atom = GlobalFindAtom( name )) != 0)
+    {
+	for (class = firstClass; (class); class = classPtr->hNext)
+	{
+	    classPtr = (CLASS *) USER_HEAP_ADDR(class);
+	    if (!(classPtr->wc.style & CS_GLOBALCLASS)) continue;
+	    if (classPtr->atomName == atom)
+	    {
+		if (ptr) *ptr = classPtr;
+		return class;
+	    }
+	}
+    }
+
     return 0;
 }
 
+
 /***********************************************************************
  *           CLASS_FindClassPtr
  *
@@ -52,37 +84,50 @@
  */
 ATOM RegisterClass( LPWNDCLASS class )
 {
-    CLASS * newClass;
-    HCLASS handle;
+    CLASS * newClass, * prevClassPtr;
+    HCLASS handle, prevClass;
     
 #ifdef DEBUG_CLASS
     printf( "RegisterClass: wndproc=%08x hinst=%d name='%s'\n", 
 	    class->lpfnWndProc, class->hInstance, class->lpszClassName );
 #endif
 
+      /* Check if a class with this name already exists */
+
+    prevClass = CLASS_FindClassByName( class->lpszClassName, &prevClassPtr );
+    if (prevClass)
+    {
+	  /* Class can be created only if it is local and */
+	  /* if the class with the same name is global.   */
+
+	if (class->style & CS_GLOBALCLASS) return 0;
+	if (!(prevClassPtr->wc.style & CS_GLOBALCLASS)) return 0;
+    }
+
+      /* Create class */
+
     handle = USER_HEAP_ALLOC( GMEM_MOVEABLE, sizeof(CLASS)+class->cbClsExtra );
     if (!handle) return 0;
     newClass = (CLASS *) USER_HEAP_ADDR( handle );
     newClass->hNext      = firstClass;
     newClass->wMagic     = CLASS_MAGIC;
-    newClass->atomName   = handle;  /* Should be an atom */
     newClass->cWindows   = 0;  
     newClass->wc         = *class;
 
-    if (newClass->wc.style & CS_CLASSDC)
-	newClass->hdc = CreateDC( "DISPLAY", NULL, NULL, NULL );
-    else newClass->hdc = 0;
+    if (newClass->wc.style & CS_GLOBALCLASS)
+	newClass->atomName = GlobalAddAtom( class->lpszClassName );
+    else newClass->atomName = AddAtom( class->lpszClassName );
 
-      /* Class name should also be set to zero. For now we need the
-       * name because we don't have atoms.
-       */
-    newClass->wc.lpszClassName = (char *)malloc(strlen(class->lpszClassName)+1);
-    strcpy( newClass->wc.lpszClassName, class->lpszClassName );
+    if (newClass->wc.style & CS_CLASSDC)
+	newClass->hdce = DCE_AllocDCE( DCE_CLASS_DC );
+    else newClass->hdce = 0;
+
+      /* Menu name should also be set to zero. */
+    newClass->wc.lpszClassName = NULL;
     
     if (class->cbClsExtra) memset( newClass->wExtra, 0, class->cbClsExtra );
-    
     firstClass = handle;
-    return handle;  /* Should be an atom */
+    return newClass->atomName;
 }
 
 
@@ -118,8 +163,10 @@
     }
 
       /* Delete the class */
-    if (classPtr->hdc) DeleteDC( classPtr->hdc );
+    if (classPtr->hdce) DCE_FreeDCE( classPtr->hdce );
     if (classPtr->wc.hbrBackground) DeleteObject( classPtr->wc.hbrBackground );
+    if (classPtr->wc.style & CS_GLOBALCLASS) GlobalDeleteAtom( classPtr->atomName );
+    else DeleteAtom( classPtr->atomName );
     USER_HEAP_FREE( class );
     return TRUE;
 }
@@ -182,3 +229,34 @@
     *ptr = newval;
     return retval;
 }
+
+
+/***********************************************************************
+ *           GetClassName      (USER.58)
+ */
+int GetClassName(HWND hwnd, LPSTR lpClassName, short maxCount)
+{
+    WND *wndPtr;
+    CLASS *classPtr;
+
+    if (!(wndPtr = WIN_FindWndPtr(hwnd))) return 0;
+    if (!(classPtr = CLASS_FindClassPtr(wndPtr->hClass))) return 0;
+
+    return (GetAtomName(classPtr->atomName, lpClassName, maxCount));
+}
+
+
+/***********************************************************************
+ *           GetClassInfo      (USER.404)
+ */
+BOOL GetClassInfo(HANDLE hInstance, LPSTR lpClassName, 
+		                    LPWNDCLASS lpWndClass)
+{
+    CLASS *classPtr;
+
+    if (!(CLASS_FindClassByName(lpClassName, &classPtr))) return FALSE;
+    if (hInstance && (hInstance != classPtr->wc.hInstance)) return FALSE;
+
+    memcpy(lpWndClass, &(classPtr->wc), sizeof(WNDCLASS));
+    return TRUE;
+}
diff --git a/windows/clipping.c b/windows/clipping.c
index 2126c28..3c759a6 100644
--- a/windows/clipping.c
+++ b/windows/clipping.c
@@ -10,6 +10,7 @@
 
 #include "windows.h"
 #include "win.h"
+#include "message.h"
 
 
 /***********************************************************************
@@ -34,6 +35,7 @@
 	else CombineRgn( newRgn, wndPtr->hrgnUpdate, hrgn, RGN_OR );
     }
     if (wndPtr->hrgnUpdate) DeleteObject( wndPtr->hrgnUpdate );
+    else MSG_IncPaintCount( wndPtr->hmemTaskQ );
     wndPtr->hrgnUpdate = newRgn;
     if (erase) wndPtr->flags |= WIN_ERASE_UPDATERGN;
 }
@@ -112,17 +114,14 @@
 
     if (rect)
     {
-        if (wndPtr->hrgnUpdate) GetRgnBox( wndPtr->hrgnUpdate, rect );
-	else SetRectEmpty( rect );
-	if (erase && wndPtr->hrgnUpdate)
+	if (wndPtr->hrgnUpdate)
 	{
-	    HDC hdc = GetDC( hwnd );
-	    if (hdc)
-	    {
-		SendMessage( hwnd, WM_ERASEBKGND, hdc, 0 );
-		ReleaseDC( hwnd, hdc );
-	    }
+	    HRGN hrgn = CreateRectRgn( 0, 0, 0, 0 );
+	    if (GetUpdateRgn( hwnd, hrgn, erase ) == ERROR) return FALSE;
+	    GetRgnBox( hrgn, rect );
+	    DeleteObject( hrgn );
 	}
+	else SetRectEmpty( rect );
     }
     return (wndPtr->hrgnUpdate != 0);
 }
@@ -133,17 +132,34 @@
  */
 int GetUpdateRgn( HWND hwnd, HRGN hrgn, BOOL erase )
 {
+    HRGN hrgnClip;
+    int retval;
     WND * wndPtr = WIN_FindWndPtr( hwnd );
     if (!wndPtr) return ERROR;
 
-    if (erase && wndPtr->hrgnUpdate)
+    if (!wndPtr->hrgnUpdate)
     {
-	HDC hdc = GetDC( hwnd );
-	if (hdc)
-	{
-	    SendMessage( hwnd, WM_ERASEBKGND, hdc, 0 );
-	    ReleaseDC( hwnd, hdc );
-	}
+	if (!(hrgnClip = CreateRectRgn( 0, 0, 0, 0 ))) return ERROR;
+	retval = CombineRgn( hrgn, hrgnClip, 0, RGN_COPY );
     }
-    return CombineRgn( hrgn, wndPtr->hrgnUpdate, 0, RGN_COPY );
+    else
+    {
+	hrgnClip = CreateRectRgn( 0, 0,
+			   wndPtr->rectClient.right-wndPtr->rectClient.left,
+			   wndPtr->rectClient.bottom-wndPtr->rectClient.top );
+	if (!hrgnClip) return ERROR;
+	retval = CombineRgn( hrgn, wndPtr->hrgnUpdate, hrgnClip, RGN_AND );
+	if (erase)
+	{
+	    HDC hdc = GetDCEx( hwnd, wndPtr->hrgnUpdate,
+			      DCX_INTERSECTRGN | DCX_USESTYLE );
+	    if (hdc)
+	    {
+		SendMessage( hwnd, WM_ERASEBKGND, hdc, 0 );
+		ReleaseDC( hwnd, hdc );
+	    }
+	}	
+    }
+    DeleteObject( hrgnClip );
+    return retval;
 }
diff --git a/windows/dc.c b/windows/dc.c
index 1a65b41..4224b3a 100644
--- a/windows/dc.c
+++ b/windows/dc.c
@@ -7,7 +7,6 @@
 static char Copyright[] = "Copyright  Alexandre Julliard, 1993";
 
 #include <stdlib.h>
-#include <X11/Intrinsic.h>
 
 #include "gdi.h"
 
@@ -17,6 +16,8 @@
 
 extern const WIN_DC_INFO DCVAL_defaultValues;
 
+extern void CLIPPING_SetDeviceClipping( DC * dc );  /* in objects/clipping.c */
+
 
   /* ROP code to GC function conversion */
 const int DC_XROPfunction[16] =
@@ -100,18 +101,8 @@
     SelectObject( hdc, dc->w.hBrush );
     SelectObject( hdc, dc->w.hFont );
     
-    if (dc->w.hGCClipRgn)
-    {
-	RGNOBJ *obj = (RGNOBJ *) GDI_GetObjPtr(dc->w.hGCClipRgn, REGION_MAGIC);
-	XSetClipMask( XT_display, dc->u.x.gc, obj->region.pixmap );
-	XSetClipOrigin( XT_display, dc->u.x.gc,
-		        obj->region.box.left, obj->region.box.top );
-    }
-    else
-    {
-	XSetClipMask( XT_display, dc->u.x.gc, None );
-	XSetClipOrigin( XT_display, dc->u.x.gc, 0, 0 );
-    }
+    XSetGraphicsExposures( XT_display, dc->u.x.gc, False );
+    CLIPPING_SetDeviceClipping( dc );
 }
 
 
@@ -145,8 +136,11 @@
 	XSetFillStyle( XT_display, dc->u.x.gc,
 		       (dc->w.backgroundMode == OPAQUE) ? 
 		          FillOpaqueStippled : FillStippled );
-    XSetTSOrigin( XT_display, dc->u.x.gc, dc->w.brushOrgX, dc->w.brushOrgY );
+    XSetTSOrigin( XT_display, dc->u.x.gc, dc->w.DCOrgX + dc->w.brushOrgX,
+		  dc->w.DCOrgY + dc->w.brushOrgY );
     XSetFunction( XT_display, dc->u.x.gc, DC_XROPfunction[dc->w.ROPmode-1] );
+    XSetFillRule( XT_display, dc->u.x.gc, 
+		 (dc->w.polyFillMode == WINDING) ? WindingRule : EvenOddRule );
     return 1;
 }
 
@@ -226,8 +220,7 @@
     if (dc->w.hVisRgn)
     {
 	newdc->w.hVisRgn = CreateRectRgn( 0, 0, 0, 0 );
-	CombineRgn( newdc->w.hVisRgn, dc->w.hVisRgn, 0, RGN_COPY );
-	
+	CombineRgn( newdc->w.hVisRgn, dc->w.hVisRgn, 0, RGN_COPY );	
     }
     newdc->w.hGCClipRgn = 0;
     return handle;
@@ -255,7 +248,7 @@
     dc->w.flags &= ~DC_SAVED;
     DC_SetDeviceInfo( hdc, dc );
     SelectClipRgn( hdc, dcs->w.hClipRgn );
-    SelectVisRgn( hdc, dcs->w.hGCClipRgn );
+    SelectVisRgn( hdc, dcs->w.hVisRgn );
 }
 
 
@@ -337,6 +330,8 @@
     dc->w.devCaps      = displayDevCaps;
     dc->w.planes       = displayDevCaps->planes;
     dc->w.bitsPerPixel = displayDevCaps->bitsPixel;
+    dc->w.DCSizeX      = displayDevCaps->horzRes;
+    dc->w.DCSizeY      = displayDevCaps->vertRes;
 
     DC_SetDeviceInfo( handle, dc );
 
@@ -372,6 +367,8 @@
     dc->w.planes       = 1;
     dc->w.bitsPerPixel = 1;
     dc->w.devCaps      = displayDevCaps;
+    dc->w.DCSizeX      = 1;
+    dc->w.DCSizeY      = 1;
 
     SelectObject( handle, BITMAP_hbitmapMemDC );
     DC_SetDeviceInfo( handle, dc );
diff --git a/windows/dce.c b/windows/dce.c
index aaea4b0..7b24f1d 100644
--- a/windows/dce.c
+++ b/windows/dce.c
@@ -23,6 +23,53 @@
 
 
 /***********************************************************************
+ *           DCE_AllocDCE
+ *
+ * Allocate a new DCE.
+ */
+HANDLE DCE_AllocDCE( DCE_TYPE type )
+{
+    DCE * dce;
+    HANDLE handle = USER_HEAP_ALLOC( GMEM_MOVEABLE, sizeof(DCE) );
+    if (!handle) return 0;
+    dce = (DCE *) USER_HEAP_ADDR( handle );
+    if (!(dce->hdc = CreateDC( "DISPLAY", NULL, NULL, NULL )))
+    {
+	USER_HEAP_FREE( handle );
+	return 0;
+    }
+    dce->hwndCurrent = 0;
+    dce->type  = type;
+    dce->inUse = (type != DCE_CACHE_DC);
+    dce->xOrigin = 0;
+    dce->yOrigin = 0;
+    dce->hNext = firstDCE;
+    firstDCE = handle;
+    return handle;
+}
+
+
+/***********************************************************************
+ *           DCE_FreeDCE
+ */
+void DCE_FreeDCE( HANDLE hdce )
+{
+    DCE * dce;
+    HANDLE *handle = &firstDCE;
+
+    if (!(dce = (DCE *) USER_HEAP_ADDR( hdce ))) return;
+    while (*handle && (*handle != hdce))
+    {
+	DCE * prev = (DCE *) USER_HEAP_ADDR( *handle );	
+	handle = &prev->hNext;
+    }
+    if (*handle == hdce) *handle = dce->hNext;
+    DeleteDC( dce->hdc );
+    USER_HEAP_FREE( hdce );
+}
+
+
+/***********************************************************************
  *           DCE_Init
  */
 void DCE_Init()
@@ -33,84 +80,133 @@
         
     for (i = 0; i < NB_DCE; i++)
     {
-	handle = USER_HEAP_ALLOC( GMEM_MOVEABLE, sizeof(DCE) );
-	if (!handle) return;
-	dce = (DCE *) USER_HEAP_ADDR( handle );
-	dce->hdc = CreateDC( "DISPLAY", NULL, NULL, NULL );
-	if (!dce->hdc)
-	{
-	    USER_HEAP_FREE( handle );
-	    return;
-	}
-	dce->hwndCurrent = 0;
-	dce->flags = 0;
-	dce->inUse = FALSE;
-	dce->xOrigin = 0;
-	dce->yOrigin = 0;
-	dce->hNext = firstDCE;
-	firstDCE = handle;
+	if (!(handle = DCE_AllocDCE( DCE_CACHE_DC ))) return;
+	dce = (DCE *) USER_HEAP_ADDR( handle );	
 	if (!defaultDCstate) defaultDCstate = GetDCState( dce->hdc );
     }
 }
 
 
 /***********************************************************************
+ *           GetDCEx    (USER.359)
+ */
+/* Unimplemented flags: DCX_CLIPSIBLINGS, DCX_LOCKWINDOWUPDATE, DCX_PARENTCLIP
+ */
+HDC GetDCEx( HWND hwnd, HRGN hrgnClip, DWORD flags )
+{
+    HANDLE hdce;
+    HDC hdc = 0;
+    DCE * dce;
+    DC * dc;
+    WND * wndPtr;
+    
+    if (hwnd)
+    {
+	if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return 0;
+    }
+    else wndPtr = NULL;
+
+    if (flags & DCX_USESTYLE)
+    {
+	/* Not sure if this is the real meaning of the DCX_USESTYLE flag... */
+	flags &= ~(DCX_CACHE | DCX_CLIPCHILDREN | DCX_CLIPSIBLINGS);
+	if (wndPtr)
+	{
+	    if (!(wndPtr->flags & (WIN_CLASS_DC | WIN_OWN_DC)))
+		flags |= DCX_CACHE;
+	    if (wndPtr->dwStyle & WS_CLIPCHILDREN) flags |= DCX_CLIPCHILDREN;
+	    if (wndPtr->dwStyle & WS_CLIPSIBLINGS) flags |= DCX_CLIPSIBLINGS;
+	}
+	else flags |= DCX_CACHE;
+    }
+
+    if (flags & DCX_CACHE)
+    {
+	for (hdce = firstDCE; (hdce); hdce = dce->hNext)
+	{
+	    if (!(dce = (DCE *) USER_HEAP_ADDR( hdce ))) return 0;
+	    if ((dce->type == DCE_CACHE_DC) && (!dce->inUse)) break;
+	}
+    }
+    else hdce = wndPtr->hdce;
+
+    if (!hdce) return 0;
+    dce = (DCE *) USER_HEAP_ADDR( hdce );
+    dce->hwndCurrent = hwnd;
+    dce->inUse       = TRUE;
+    hdc = dce->hdc;
+    
+      /* Initialize DC */
+    
+    if (!(dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC ))) return 0;
+
+    if (wndPtr)
+    {
+	dc->u.x.drawable = wndPtr->window;
+	if (flags & DCX_WINDOW)
+	{
+	    dc->w.DCOrgX  = 0;
+	    dc->w.DCOrgY  = 0;
+	    dc->w.DCSizeX = wndPtr->rectWindow.right - wndPtr->rectWindow.left;
+	    dc->w.DCSizeY = wndPtr->rectWindow.bottom - wndPtr->rectWindow.top;
+	}
+	else
+	{
+	    dc->w.DCOrgX  = wndPtr->rectClient.left - wndPtr->rectWindow.left;
+	    dc->w.DCOrgY  = wndPtr->rectClient.top - wndPtr->rectWindow.top;
+	    dc->w.DCSizeX = wndPtr->rectClient.right - wndPtr->rectClient.left;
+	    dc->w.DCSizeY = wndPtr->rectClient.bottom - wndPtr->rectClient.top;
+	    IntersectVisRect( hdc, 0, 0, dc->w.DCSizeX, dc->w.DCSizeY );
+	}	
+    }
+    else dc->u.x.drawable = DefaultRootWindow( XT_display );
+
+    if (flags & DCX_CLIPCHILDREN)
+	XSetSubwindowMode( XT_display, dc->u.x.gc, ClipByChildren );
+    else XSetSubwindowMode( XT_display, dc->u.x.gc, IncludeInferiors);
+
+    if ((flags & DCX_INTERSECTRGN) || (flags & DCX_EXCLUDERGN))
+    {
+	HRGN hrgn = CreateRectRgn( 0, 0, 0, 0 );
+	if (hrgn)
+	{
+	    if (CombineRgn( hrgn, InquireVisRgn(hdc), hrgnClip,
+			    (flags & DCX_INTERSECTRGN) ? RGN_AND : RGN_DIFF ))
+		SelectVisRgn( hdc, hrgn );
+	    DeleteObject( hrgn );
+	}
+    }
+
+#ifdef DEBUG_DC
+    printf( "GetDCEx(%d,%d,0x%x): returning %d\n", hwnd, hrgnClip, flags, hdc);
+#endif
+    return hdc;
+}
+
+
+/***********************************************************************
  *           GetDC    (USER.66)
  */
 HDC GetDC( HWND hwnd )
 {
-    HANDLE hdce;
-    HDC hdc = 0;
-    DCE * dce;
-    DC * dc;
-    WND * wndPtr = NULL;
-    CLASS * classPtr;
-    
+    return GetDCEx( hwnd, 0, DCX_USESTYLE );
+}
+
+
+/***********************************************************************
+ *           GetWindowDC    (USER.67)
+ */
+HDC GetWindowDC( HWND hwnd )
+{
+    int flags = DCX_CACHE | DCX_WINDOW;
     if (hwnd)
     {
+	WND * wndPtr;
 	if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return 0;
-	if (!(classPtr = CLASS_FindClassPtr( wndPtr->hClass ))) return 0;
-	if (wndPtr->hdc) hdc = wndPtr->hdc;
-	else if (classPtr->hdc) hdc = classPtr->hdc;
+	if (wndPtr->dwStyle & WS_CLIPCHILDREN) flags |= DCX_CLIPCHILDREN;
+	if (wndPtr->dwStyle & WS_CLIPSIBLINGS) flags |= DCX_CLIPSIBLINGS;
     }
-        
-    if (!hdc)
-    {
-	for (hdce = firstDCE; (hdce); hdce = dce->hNext)
-	{
-	    dce = (DCE *) USER_HEAP_ADDR( hdce );
-	    if (!dce) return 0;
-	    if (!dce->inUse) break;
-	}
-	if (!hdce) return 0;
-	dce->hwndCurrent = hwnd;
-	dce->inUse       = TRUE;
-	hdc = dce->hdc;
-    }
-    
-      /* Initialize DC */
-    
-    if (!(dc = (DC *) GDI_GetObjPtr( dce->hdc, DC_MAGIC ))) return 0;
-
-    if (wndPtr)
-    {
-	dc->u.x.drawable = XtWindow( wndPtr->winWidget );
-    	dc->u.x.widget   = wndPtr->winWidget;
-	if (wndPtr->dwStyle & WS_CLIPCHILDREN)
-	    XSetSubwindowMode( XT_display, dc->u.x.gc, ClipByChildren );
-	else XSetSubwindowMode( XT_display, dc->u.x.gc, IncludeInferiors);
-    }
-    else
-    {
-	dc->u.x.drawable = DefaultRootWindow( XT_display );
-	dc->u.x.widget   = 0;
-	XSetSubwindowMode( XT_display, dc->u.x.gc, IncludeInferiors );    
-    }   
-
-#ifdef DEBUG_WIN
-    printf( "GetDC(%d): returning %d\n", hwnd, hdc );
-#endif
-    return hdc;
+    return GetDCEx( hwnd, 0, flags );
 }
 
 
@@ -119,33 +215,23 @@
  */
 int ReleaseDC( HWND hwnd, HDC hdc )
 {
-    HANDLE hdce, next;
+    HANDLE hdce;
     DCE * dce;
-    WND * wndPtr = NULL;
-    CLASS * classPtr;
     
-#ifdef DEBUG_WIN
+#ifdef DEBUG_DC
     printf( "ReleaseDC: %d %d\n", hwnd, hdc );
 #endif
         
-    if (hwnd)
-    {
-	if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return 0;
-	if (wndPtr->hdc && (wndPtr->hdc == hdc)) return 1;
-	if (!(classPtr = CLASS_FindClassPtr( wndPtr->hClass ))) return 0;
-	if (classPtr->hdc && (classPtr->hdc == hdc)) return 1;
-    }
-
     for (hdce = firstDCE; (hdce); hdce = dce->hNext)
     {
 	if (!(dce = (DCE *) USER_HEAP_ADDR( hdce ))) return 0;
 	if (dce->inUse && (dce->hdc == hdc)) break;
     }
 
-    if (hdce)
+    if (dce->type == DCE_CACHE_DC)
     {
 	SetDCState( dce->hdc, defaultDCstate );
 	dce->inUse = FALSE;
-    }    
+    }
     return (hdce != 0);
 }
diff --git a/windows/defwnd.c b/windows/defwnd.c
index 3d3a280..e2f9a39 100644
--- a/windows/defwnd.c
+++ b/windows/defwnd.c
@@ -6,24 +6,27 @@
 
 static char Copyright[] = "Copyright  Alexandre Julliard, 1993";
 
+#ifndef USE_XLIB
 #include <X11/Intrinsic.h>
 #include <X11/Shell.h>
+#endif
 
 #include "windows.h"
 #include "win.h"
 #include "class.h"
 #include "user.h"
 
+extern Display * XT_display;
 
 /***********************************************************************
  *           DefWindowProc   (USER.107)
  */
 LONG DefWindowProc( HWND hwnd, WORD msg, WORD wParam, LONG lParam )
 {
-    WND * wndPtr;
     CLASS * classPtr;
     LPSTR textPtr;
     int len;
+    WND * wndPtr = WIN_FindWndPtr( hwnd );
     
 #ifdef DEBUG_MESSAGE
     printf( "DefWindowProc: %d %d %d %08x\n", hwnd, msg, wParam, lParam );
@@ -34,24 +37,57 @@
     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);
+					strlen(createStruct->lpszName) + 2);
 		textPtr = (LPSTR)USER_HEAP_ADDR(wndPtr->hText);
 		strcpy(textPtr, createStruct->lpszName);
+		*(textPtr + strlen(createStruct->lpszName) + 1) = '\0';
+		                         /* for use by edit control */
 	    }
 	    return 1;
 	}
+
+    case WM_NCCALCSIZE:
+	{
+#ifdef USE_XLIB
+	    NCCALCSIZE_PARAMS *params = (NCCALCSIZE_PARAMS *)lParam;
+	    if (wndPtr->dwStyle & WS_CHILD)
+	    {
+		if (wndPtr->dwStyle & WS_BORDER)
+		{
+		    params->rgrc[0].left   += 1; /* SM_CXBORDER */
+		    params->rgrc[0].top    += 1; /* SM_CYBORDER */
+		    params->rgrc[0].right  -= 1; /* SM_CXBORDER */
+		    params->rgrc[0].bottom -= 1; /* SM_CYBORDER */
+		}
+	    }
+	    else
+	    {
+		params->rgrc[0].left   += 4; /* SM_CXFRAME */
+		params->rgrc[0].top    += 30; /* SM_CYFRAME+SM_CYCAPTION */
+		params->rgrc[0].right  -= 4; /* SM_CXFRAME */
+		params->rgrc[0].bottom -= 4; /* SM_CYFRAME */
+		if (wndPtr->dwStyle & WS_VSCROLL)
+		{
+		    params->rgrc[0].right -= 16; /* SM_CXVSCROLL */
+		}
+		if (wndPtr->dwStyle & WS_HSCROLL)
+		{
+		    params->rgrc[0].bottom += 16;  /* SM_CYHSCROLL */
+		}
+	    }
+#endif
+	    return 0;
+	}
 	
     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;
@@ -69,10 +105,23 @@
 	DestroyWindow( hwnd );
 	return 0;
 
+    case WM_WINDOWPOSCHANGED:
+	{
+	    WINDOWPOS * winPos = (WINDOWPOS *)lParam;
+	    if (!(winPos->flags & SWP_NOMOVE))
+		SendMessage( hwnd, WM_MOVE, 0,
+		             MAKELONG( wndPtr->rectClient.left,
+				       wndPtr->rectClient.top ));
+	    if (!(winPos->flags & SWP_NOSIZE))
+		SendMessage( hwnd, WM_SIZE, SIZE_RESTORED,
+		   MAKELONG(wndPtr->rectClient.right-wndPtr->rectClient.left,
+			    wndPtr->rectClient.bottom-wndPtr->rectClient.top));
+	    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,
@@ -106,7 +155,6 @@
 	{
 	    if (wParam)
 	    {
-		wndPtr = WIN_FindWndPtr(hwnd);
 		if (wndPtr->hText)
 		{
 		    textPtr = (LPSTR)USER_HEAP_ADDR(wndPtr->hText);
@@ -123,7 +171,6 @@
 
     case WM_GETTEXTLENGTH:
 	{
-	    wndPtr = WIN_FindWndPtr(hwnd);
 	    if (wndPtr->hText)
 	    {
 		textPtr = (LPSTR)USER_HEAP_ADDR(wndPtr->hText);
@@ -134,7 +181,6 @@
 
     case WM_SETTEXT:
 	{
-	    wndPtr = WIN_FindWndPtr(hwnd);
 	    if (wndPtr->hText)
 		USER_HEAP_FREE(wndPtr->hText);
 
@@ -142,10 +188,18 @@
 					    strlen((LPSTR)lParam) + 1);
 	    textPtr = (LPSTR)USER_HEAP_ADDR(wndPtr->hText);
 	    strcpy(textPtr, (LPSTR)lParam);
+#ifdef USE_XLIB
+	    XStoreName( XT_display, wndPtr->window, textPtr );
+#else
 	    if (wndPtr->shellWidget)
 		XtVaSetValues( wndPtr->shellWidget, XtNtitle, textPtr, NULL );
+#endif
 	    return (0L);
 	}
+    case WM_SETCURSOR:
+	if (wndPtr->hCursor != (HCURSOR)NULL)
+	    SetCursor(wndPtr->hCursor);
+	return 0L;
     }
     return 0;
 }
diff --git a/windows/dialog.c b/windows/dialog.c
index 108c964..83a0389 100644
--- a/windows/dialog.c
+++ b/windows/dialog.c
@@ -8,7 +8,6 @@
 
 #include "windows.h"
 #include "dialog.h"
-#include "prototypes.h"
 #include "win.h"
 
 
@@ -149,25 +148,19 @@
     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;
+     
+      /* FIXME: MAKEINTRESOURCE should be replaced by RT_DIALOG */
+    if (!(hres = FindResource( hInst, dlgTemplate, MAKEINTRESOURCE(0x8005) )))
+	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, NE_RSCTYPE_DIALOG, &size );
-    data = (LPCSTR) GlobalLock( hmem );
-    hwnd = CreateDialogIndirectParam( hInst, data, owner, dlgProc, param );
-    GlobalFree( hmem );
-#endif
     return hwnd;
 }
 
@@ -314,8 +307,8 @@
     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 );
+/*    if (SendMessage( hwnd, WM_INITDIALOG, dlgInfo->hwndFocus, param ))
+	SetFocus( dlgInfo->hwndFocus ); */
 
     return hwnd;
 }
diff --git a/windows/event.c b/windows/event.c
index 3130189..5f3aa3d 100644
--- a/windows/event.c
+++ b/windows/event.c
@@ -18,6 +18,8 @@
 #define NB_BUTTONS      3     /* Windows can handle 3 buttons */
 static WORD dblclick_time = 300; /* Max. time for a double click (milliseconds) */
 
+extern Display * XT_display;
+
   /* Event handlers */
 static void EVENT_expose();
 static void EVENT_key();
@@ -25,17 +27,175 @@
 static void EVENT_mouse_button();
 static void EVENT_structure();
 static void EVENT_focus_change();
+static void EVENT_enter_notify();
+
+  /* X context to associate a hwnd to an X window */
+static XContext winContext = 0;
 
   /* State variables */
 static HWND captureWnd = 0;
-
+Window winHasCursor = 0;
 extern HWND hWndFocus;
 
+/* Keyboard translation tables */
+static int special_key[] =
+{
+    VK_BACK, VK_TAB, 0, VK_CLEAR, 0, VK_RETURN, 0, 0,           /* FF08 */
+    0, 0, 0, VK_PAUSE, VK_SCROLL, 0, 0, 0,                      /* FF10 */
+    0, 0, 0, VK_ESCAPE                                          /* FF18 */
+};
+
+static cursor_key[] =
+{
+    VK_HOME, VK_LEFT, VK_UP, VK_RIGHT, VK_DOWN, VK_PRIOR, 
+                                       VK_NEXT, VK_END          /* FF50 */
+};
+
+static misc_key[] =
+{
+    VK_SELECT, VK_SNAPSHOT, VK_EXECUTE, VK_INSERT, 0, 0, 0, 0,  /* FF60 */
+    VK_CANCEL, VK_HELP, VK_CANCEL, VK_MENU                      /* FF68 */
+};
+
+static keypad_key[] =
+{
+    VK_MENU, VK_NUMLOCK,                                        /* FF7E */
+    0, 0, 0, 0, 0, 0, 0, 0,                                     /* FF80 */
+    0, 0, 0, 0, 0, VK_RETURN, 0, 0,                             /* FF88 */
+    0, 0, 0, 0, 0, 0, 0, 0,                                     /* FF90 */
+    0, 0, 0, 0, 0, 0, 0, 0,                                     /* FF98 */
+    0, 0, 0, 0, 0, 0, 0, 0,                                     /* FFA0 */
+    0, 0, VK_MULTIPLY, VK_ADD, VK_SEPARATOR, VK_SUBTRACT, 
+                               VK_DECIMAL, VK_DIVIDE,           /* FFA8 */
+    VK_NUMPAD0, VK_NUMPAD1, VK_NUMPAD2, VK_NUMPAD3, VK_NUMPAD4,
+                            VK_NUMPAD5, VK_NUMPAD6, VK_NUMPAD7, /* FFB0 */
+    VK_NUMPAD8, VK_NUMPAD9                                      /* FFB8 */
+};
+    
+static function_key[] =
+{
+    VK_F1, VK_F2,                                               /* FFBE */
+    VK_F3, VK_F4, VK_F5, VK_F6, VK_F7, VK_F8, VK_F9, VK_F10,    /* FFC0 */
+    VK_F11, VK_F12, VK_F13, VK_F14, VK_F15, VK_F16              /* FFC8 */
+};
+
+static modifier_key[] =
+{
+    VK_SHIFT, VK_SHIFT, VK_CONTROL, VK_CONTROL, VK_CAPITAL,
+                                                0, 0,           /* FFE1 */
+    0, VK_MENU, VK_MENU                                         /* FFE8 */
+};
+
+typedef union
+{
+    struct
+    {
+	unsigned long count : 16;
+	unsigned long code : 8;
+	unsigned long extended : 1;
+	unsigned long : 4;
+	unsigned long context : 1;
+	unsigned long previous : 1;
+	unsigned long transition : 1;
+    } lp1;
+    unsigned long lp2;
+} KEYLP;
+
+static BOOL KeyDown = FALSE;
+
+
+#ifdef DEBUG_EVENT
+static char *event_names[] =
+{
+    "", "", "KeyPress", "KeyRelease", "ButtonPress", "ButtonRelease",
+    "MotionNotify", "EnterNotify", "LeaveNotify", "FocusIn", "FocusOut",
+    "KeymapNotify", "Expose", "GraphicsExpose", "NoExpose", "VisibilityNotify",
+    "CreateNotify", "DestroyNotify", "UnmapNotify", "MapNotify", "MapRequest",
+    "ReparentNotify", "ConfigureNotify", "ConfigureRequest", "GravityNotify",
+    "ResizeRequest", "CirculateNotify", "CirculateRequest", "PropertyNotify",
+    "SelectionClear", "SelectionRequest", "SelectionNotify", "ColormapNotify",
+    "ClientMessage", "MappingNotify"
+};
+#endif
+
+
+/***********************************************************************
+ *           EVENT_ProcessEvent
+ *
+ * Process an X event.
+ */
+void EVENT_ProcessEvent( XEvent *event )
+{
+    HWND hwnd;
+    XPointer ptr;
+    Boolean cont_dispatch = TRUE;
+    
+    XFindContext( XT_display, ((XAnyEvent *)event)->window, winContext, &ptr );
+    hwnd = (HWND)ptr & 0xffff;
+
+#ifdef DEBUG_EVENT
+    printf( "Got event %s for hwnd %d\n", 
+	    event_names[event->type], hwnd );
+#endif
+
+    switch(event->type)
+    {
+        case Expose:
+	    EVENT_expose( 0, hwnd, event, &cont_dispatch );
+	    break;
+
+	case KeyPress:
+	case KeyRelease:
+	    EVENT_key( 0, hwnd, event, &cont_dispatch );
+	    break;
+
+	case MotionNotify:
+	    EVENT_mouse_motion( 0, hwnd, event, &cont_dispatch );
+	    break;
+
+	case ButtonPress:
+	case ButtonRelease:
+	    EVENT_mouse_button( 0, hwnd, event, &cont_dispatch );
+	    break;
+
+	case CirculateNotify:
+	case ConfigureNotify:
+	case MapNotify:
+	case UnmapNotify:
+	    EVENT_structure( 0, hwnd, event, &cont_dispatch );
+	    break;
+
+	case FocusIn:
+	case FocusOut:
+	    EVENT_focus_change( 0, hwnd, event, &cont_dispatch );
+	    break;
+
+	case EnterNotify:
+	    EVENT_enter_notify( 0, hwnd, event, &cont_dispatch );
+	    break;
+
+#ifdef DEBUG_EVENT
+	default:
+	    printf( "Unprocessed event %s for hwnd %d\n", 
+		    event_names[event->type], hwnd );
+	    break;
+#endif
+    }
+}
+
+
 /***********************************************************************
  *           EVENT_AddHandlers
  *
  * Add the event handlers to the given window
  */
+#ifdef USE_XLIB
+void EVENT_AddHandlers( Window w, int hwnd )
+{
+    if (!winContext) winContext = XUniqueContext();
+    XSaveContext( XT_display, w, winContext, (XPointer)hwnd );
+}
+#else
 void EVENT_AddHandlers( Widget w, int hwnd )
 {
     XtAddEventHandler(w, ExposureMask, FALSE,
@@ -50,7 +210,10 @@
 		      EVENT_structure, (XtPointer)hwnd );
     XtAddEventHandler(w, FocusChangeMask, FALSE,
 		      EVENT_focus_change, (XtPointer)hwnd );
+    XtAddEventHandler(w, EnterWindowMask, FALSE,
+		      EVENT_enter_notify, (XtPointer)hwnd );
 }
+#endif
 
 
 /***********************************************************************
@@ -60,6 +223,7 @@
  */
 void EVENT_RemoveHandlers( Widget w, int hwnd )
 {
+#ifndef USE_XLIB
     XtRemoveEventHandler(w, ExposureMask, FALSE,
 			 EVENT_expose, (XtPointer)hwnd );
     XtRemoveEventHandler(w, KeyPressMask | KeyReleaseMask, FALSE, 
@@ -72,6 +236,9 @@
 			 EVENT_structure, (XtPointer)hwnd );
     XtRemoveEventHandler(w, FocusChangeMask, FALSE,
 			 EVENT_focus_change, (XtPointer)hwnd );
+    XtRemoveEventHandler(w, EnterWindowMask, FALSE,
+			 EVENT_enter_notify, (XtPointer)hwnd );
+#endif
 }
 
 
@@ -103,10 +270,14 @@
 			  Boolean *cont_dispatch )
 {
     RECT rect;
-    rect.left   = event->x;
-    rect.top    = event->y;
-    rect.right  = event->x + event->width;
-    rect.bottom = event->y + event->height;
+    WND * wndPtr = WIN_FindWndPtr( hwnd );
+    if (!wndPtr) return;
+      /* Make position relative to client area instead of window */
+    rect.left = event->x - (wndPtr->rectClient.left - wndPtr->rectWindow.left);
+    rect.top  = event->y - (wndPtr->rectClient.top - wndPtr->rectWindow.top);
+    rect.right  = rect.left + event->width;
+    rect.bottom = rect.top + event->height;
+    winHasCursor = event->window;
     
     InvalidateRect( hwnd, &rect, TRUE );
 }
@@ -121,24 +292,128 @@
 		       Boolean *cont_dispatch )
 {
     MSG msg;
-
     char Str[24]; 
     XComposeStatus cs; 
-    KeySym key;
-    int count = XLookupString(event, Str, 1, &key, &cs);
+    KeySym keysym;
+    WORD xkey, vkey, key_type, key;
+    KEYLP keylp;
+    BOOL extended = FALSE;
+    WND * wndPtr = WIN_FindWndPtr( hwnd );
+    int count = XLookupString(event, Str, 1, &keysym, &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  = Str[0];
-    msg.lParam  = (event->x & 0xffff) | (event->y << 16);
-    msg.time = event->time;
-    msg.pt.x = event->x & 0xffff;
-    msg.pt.y = event->y & 0xffff;
+    printf("WM_KEY??? : keysym=%lX, count=%u / %X / '%s'\n", 
+	   keysym, count, Str[0], Str);
+#endif
+
+    xkey = LOWORD(keysym);
+    key_type = HIBYTE(xkey);
+    key = LOBYTE(xkey);
+#ifdef DEBUG_KEY
+    printf("            key_type=%X, key=%X\n", key_type, key);
+#endif
+
+      /* Position must be relative to client area */
+    event->x -= wndPtr->rectClient.left - wndPtr->rectWindow.left;
+    event->y -= wndPtr->rectClient.top - wndPtr->rectWindow.top;
+
+    if (key_type == 0xFF)                          /* non-character key */
+    {
+	if (key >= 0x08 && key <= 0x1B)            /* special key */
+	    vkey = special_key[key - 0x08];
+	else if (key >= 0x50 && key <= 0x57)       /* cursor key */
+	    vkey = cursor_key[key - 0x50];
+	else if (key >= 0x60 && key <= 0x6B)       /* miscellaneous key */
+	    vkey = misc_key[key - 0x60];
+	else if (key >= 0x7E && key <= 0xB9)       /* keypad key */
+	{
+	    vkey = keypad_key[key - 0x7E];
+	    extended = TRUE;
+	}
+	else if (key >= 0xBE && key <= 0xCD)       /* function key */
+	{
+	    vkey = function_key[key - 0xBE];
+	    extended = TRUE;
+	}
+	else if (key >= 0xE1 && key <= 0xEA)       /* modifier key */
+	    vkey = modifier_key[key - 0xE1];
+	else if (key == 0xFF)                      /* DEL key */
+	    vkey = VK_DELETE;
+    }
+    else if (key_type == 0)                        /* character key */
+    {
+	if (key >= 0x61 && key <= 0x7A)
+	    vkey = key - 0x20;                 /* convert lower to uppercase */
+	else
+	    vkey = key;
+    }
+
+    if (event->type == KeyPress)
+    {
+	msg.hwnd    = hwnd;
+	msg.message = WM_KEYDOWN;
+	msg.wParam  = vkey;
+	keylp.lp1.count = 1;
+	keylp.lp1.code = LOBYTE(event->keycode);
+	keylp.lp1.extended = (extended ? 1 : 0);
+	keylp.lp1.context = (event->state & Mod1Mask ? 1 : 0);
+	keylp.lp1.previous = (KeyDown ? 0 : 1);
+	keylp.lp1.transition = 0;
+	msg.lParam  = keylp.lp2;
+#ifdef DEBUG_KEY
+	printf("            wParam=%X, lParam=%lX\n", msg.wParam, msg.lParam);
+#endif
+	msg.time = event->time;
+	msg.pt.x = event->x & 0xffff;
+	msg.pt.y = event->y & 0xffff;
     
-    MSG_AddMsg( &msg );    
+	hardware_event( hwnd, WM_KEYDOWN, vkey, keylp.lp2,
+		        event->x & 0xffff, event->y & 0xffff, event->time, 0 );
+	KeyDown = TRUE;
+
+	/* The key translation ought to take place in TranslateMessage().
+	 * However, there is no way of passing the required information 
+	 * in a Windows message, so TranslateMessage does not currently
+	 * do anything and the translation is done here.
+	 */
+	if (count == 1)                /* key has an ASCII representation */
+	{
+	    msg.hwnd    = hwnd;
+	    msg.message = WM_CHAR;
+	    msg.wParam  = (WORD)Str[0];
+	    msg.lParam  = keylp.lp2;
+#ifdef DEBUG_KEY
+	printf("WM_CHAR :   wParam=%X\n", msg.wParam);
+#endif
+	    msg.time = event->time;
+	    msg.pt.x = event->x & 0xffff;
+	    msg.pt.y = event->y & 0xffff;
+	    PostMessage( hwnd, WM_CHAR, (WORD)Str[0], keylp.lp2 );
+	}
+    }
+    else
+    {
+	msg.hwnd    = hwnd;
+	msg.message = WM_KEYUP;
+	msg.wParam  = vkey;
+	keylp.lp1.count = 1;
+	keylp.lp1.code = LOBYTE(event->keycode);
+	keylp.lp1.extended = (extended ? 1 : 0);
+	keylp.lp1.context = (event->state & Mod1Mask ? 1 : 0);
+	keylp.lp1.previous = 1;
+	keylp.lp1.transition = 1;
+	msg.lParam  = keylp.lp2;
+#ifdef DEBUG_KEY
+	printf("            wParam=%X, lParam=%lX\n", msg.wParam, msg.lParam);
+#endif
+	msg.time = event->time;
+	msg.pt.x = event->x & 0xffff;
+	msg.pt.y = event->y & 0xffff;
+    
+	hardware_event( hwnd, WM_KEYUP, vkey, keylp.lp2,
+		        event->x & 0xffff, event->y & 0xffff, event->time, 0 );
+	KeyDown = FALSE;
+    }
 }
 
 
@@ -150,17 +425,17 @@
 static void EVENT_mouse_motion( Widget w, int hwnd, XMotionEvent *event, 
 			        Boolean *cont_dispatch )
 {
-    MSG msg;
-    
-    msg.hwnd    = hwnd;
-    msg.message = WM_MOUSEMOVE;
-    msg.wParam  = EVENT_XStateToKeyState( event->state );
-    msg.lParam  = (event->x & 0xffff) | (event->y << 16);
-    msg.time = event->time;
-    msg.pt.x = event->x & 0xffff;
-    msg.pt.y = event->y & 0xffff;
-    
-    MSG_AddMsg( &msg );    
+    WND * wndPtr = WIN_FindWndPtr( hwnd );
+    if (!wndPtr) return;
+
+      /* Position must be relative to client area */
+    event->x -= wndPtr->rectClient.left - wndPtr->rectWindow.left;
+    event->y -= wndPtr->rectClient.top - wndPtr->rectWindow.top;
+
+    hardware_event( hwnd, WM_MOUSEMOVE, EVENT_XStateToKeyState( event->state ),
+		    (event->x & 0xffff) | (event->y << 16),
+		    event->x & 0xffff, event->y & 0xffff,
+		    event->time, 0 );		    
 }
 
 
@@ -180,9 +455,15 @@
     };
     static unsigned long lastClickTime[NB_BUTTONS] = { 0, 0, 0 };
         
-    MSG msg;
     int buttonNum, prevTime, type;
-    
+
+    WND * wndPtr = WIN_FindWndPtr( hwnd );
+    if (!wndPtr) return;
+
+      /* Position must be relative to client area */
+    event->x -= wndPtr->rectClient.left - wndPtr->rectWindow.left;
+    event->y -= wndPtr->rectClient.top - wndPtr->rectWindow.top;
+
     buttonNum = event->button-1;
     if (buttonNum >= NB_BUTTONS) return;
     if (event->type == ButtonRelease) type = 1;
@@ -201,15 +482,13 @@
 	else type = 0;
     }	
     
-    msg.hwnd    = hwnd;
-    msg.message = messages[type][buttonNum];
-    msg.wParam  = EVENT_XStateToKeyState( event->state );
-    msg.lParam  = (event->x & 0xffff) | (event->y << 16);
-    msg.time = event->time;
-    msg.pt.x = event->x & 0xffff;
-    msg.pt.y = event->y & 0xffff;
+    winHasCursor = event->window;
 
-    MSG_AddMsg( &msg );    
+    hardware_event( hwnd, messages[type][buttonNum],
+		    EVENT_XStateToKeyState( event->state ),
+		    (event->x & 0xffff) | (event->y << 16),
+		    event->x & 0xffff, event->y & 0xffff,
+		    event->time, 0 );		    
 }
 
 
@@ -232,13 +511,31 @@
     {
       case ConfigureNotify:
 	{
+	    HANDLE handle;
+	    NCCALCSIZE_PARAMS *params;	    
 	    XConfigureEvent * evt = (XConfigureEvent *)event;
 	    WND * wndPtr = WIN_FindWndPtr( hwnd );
 	    if (!wndPtr) return;
-	    wndPtr->rectClient.right  = wndPtr->rectClient.left + evt->width;
-	    wndPtr->rectClient.bottom = wndPtr->rectClient.top + evt->height;
+	    wndPtr->rectWindow.left   = evt->x;
+	    wndPtr->rectWindow.top    = evt->y;
+	    wndPtr->rectWindow.right  = evt->x + evt->width;
+	    wndPtr->rectWindow.bottom = evt->y + evt->height;
+
+	      /* Send WM_NCCALCSIZE message */
+	    handle = GlobalAlloc( GMEM_MOVEABLE, sizeof(*params) );
+	    params = (NCCALCSIZE_PARAMS *)GlobalLock( handle );
+	    params->rgrc[0] = wndPtr->rectWindow;
+	    params->lppos   = NULL;  /* Should be WINDOWPOS struct */
+	    SendMessage( hwnd, WM_NCCALCSIZE, FALSE, params );
+	    wndPtr->rectClient = params->rgrc[0];
+	    PostMessage( hwnd, WM_MOVE, 0,
+		             MAKELONG( wndPtr->rectClient.left,
+				       wndPtr->rectClient.top ));
 	    PostMessage( hwnd, WM_SIZE, SIZE_RESTORED,
-			 (evt->width & 0xffff) | (evt->height << 16) );
+		   MAKELONG(wndPtr->rectClient.right-wndPtr->rectClient.left,
+			    wndPtr->rectClient.bottom-wndPtr->rectClient.top));
+	    GlobalUnlock( handle );
+	    GlobalFree( handle );
 	}
 	break;
 	
@@ -254,21 +551,12 @@
 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;
+	    PostMessage( hwnd, WM_SETFOCUS, hwnd, 0 );
 	    hWndFocus = hwnd;
-
 	}
 	break;
 	
@@ -276,13 +564,32 @@
 	{
 	    if (hWndFocus)
 	    {
-		msg.message = WM_KILLFOCUS;
-		msg.wParam = hwnd;
+		PostMessage( hwnd, WM_KILLFOCUS, hwnd, 0 );
 		hWndFocus = 0;
 	    }
 	}
     }    
-    MSG_AddMsg( &msg );
+}
+
+
+/**********************************************************************
+ *              EVENT_enter_notify
+ *
+ * Handle an X EnterNotify event
+ */
+static void EVENT_enter_notify( Widget w, int hwnd, XCrossingEvent *event, 
+			       Boolean *cont_dispatch )
+{
+    if (captureWnd != 0) return;
+
+    winHasCursor = event->window;
+
+    switch(event->type)
+    {
+      case EnterNotify:
+	PostMessage( hwnd, WM_SETCURSOR, hwnd, 0 );
+	break;
+    }    
 }
 
 
@@ -297,9 +604,15 @@
     if (wnd_p == NULL)
 	return 0;
     
+#ifdef USE_XLIB
+    rv = XGrabPointer(XT_display, wnd_p->window, False, 
+		      ButtonPressMask | ButtonReleaseMask | ButtonMotionMask,
+		      GrabModeAsync, GrabModeSync, None, None, CurrentTime);
+#else
     rv = XtGrabPointer(wnd_p->winWidget, False, 
 		       ButtonPressMask | ButtonReleaseMask | ButtonMotionMask,
 		       GrabModeAsync, GrabModeSync, None, None, CurrentTime);
+#endif
 
     if (rv == GrabSuccess)
     {
@@ -324,12 +637,24 @@
     if (wnd_p == NULL)
 	return;
     
+#ifdef USE_XLIB
+    XUngrabPointer( XT_display, CurrentTime );
+#else
     XtUngrabPointer(wnd_p->winWidget, CurrentTime);
+#endif
 
     captureWnd = 0;
 }
 
 /**********************************************************************
+ *		GetCapture 	(USER.236)
+ */
+HWND GetCapture()
+{
+    return captureWnd;
+}
+ 
+/**********************************************************************
  *		SetDoubleClickTime  (USER.20)
  */
 void SetDoubleClickTime (WORD interval)
diff --git a/windows/focus.c b/windows/focus.c
index ce1a91a2..639b2df 100644
--- a/windows/focus.c
+++ b/windows/focus.c
@@ -32,7 +32,7 @@
     else
     {
 	wndPtr = WIN_FindWndPtr(hwnd);
-	XSetInputFocus(XT_display, XtWindow(wndPtr->winWidget),
+	XSetInputFocus(XT_display, wndPtr->window,
 		       RevertToParent, CurrentTime);
     }
 
diff --git a/windows/graphics.c b/windows/graphics.c
index a2a1e32..9fd5d27 100644
--- a/windows/graphics.c
+++ b/windows/graphics.c
@@ -23,8 +23,10 @@
     if (!dc) return FALSE;
     if (DC_SetupGCForPen( dc ))
 	XDrawLine(XT_display, dc->u.x.drawable, dc->u.x.gc, 
-		  XLPTODP( dc, dc->w.CursPosX ), YLPTODP( dc, dc->w.CursPosY ),
-		  XLPTODP( dc, x ), YLPTODP( dc, y ) );
+		  dc->w.DCOrgX + XLPTODP( dc, dc->w.CursPosX ),
+		  dc->w.DCOrgY + YLPTODP( dc, dc->w.CursPosY ),
+		  dc->w.DCOrgX + XLPTODP( dc, x ),
+		  dc->w.DCOrgY + YLPTODP( dc, y ) );
     dc->w.CursPosX = x;
     dc->w.CursPosY = y;
     return TRUE;
@@ -97,20 +99,21 @@
     if (diff_angle < 0.0) diff_angle += 2*PI;
 
     XDrawArc( XT_display, dc->u.x.drawable, dc->u.x.gc,
-	      left, top, right-left-1, bottom-top-1,
+	      dc->w.DCOrgX + left, dc->w.DCOrgY + top,
+	      right-left-1, bottom-top-1,
 	      (int)(start_angle * 180 * 64 / PI),
 	      (int)(diff_angle * 180 * 64 / PI) );
     if (!lines) return TRUE;
 
-    points[0].x = xcenter + (int)(cos(start_angle) * (right-left) / 2);
-    points[0].y = ycenter - (int)(sin(start_angle) * (bottom-top) / 2);
-    points[1].x = xcenter + (int)(cos(end_angle) * (right-left) / 2);
-    points[1].y = ycenter - (int)(sin(end_angle) * (bottom-top) / 2);
+    points[0].x = dc->w.DCOrgX + xcenter + (int)(cos(start_angle) * (right-left) / 2);
+    points[0].y = dc->w.DCOrgY + ycenter - (int)(sin(start_angle) * (bottom-top) / 2);
+    points[1].x = dc->w.DCOrgX + xcenter + (int)(cos(end_angle) * (right-left) / 2);
+    points[1].y = dc->w.DCOrgY + ycenter - (int)(sin(end_angle) * (bottom-top) / 2);
     if (lines == 2)
     {
 	points[2] = points[1];
-	points[1].x = xcenter;
-	points[1].y = ycenter;
+	points[1].x = dc->w.DCOrgX + xcenter;
+	points[1].y = dc->w.DCOrgY + ycenter;
     }
     XDrawLines( XT_display, dc->u.x.drawable, dc->u.x.gc,
 	        points, lines+1, CoordModeOrigin );
@@ -167,10 +170,12 @@
     
     if (DC_SetupGCForBrush( dc ))
 	XFillArc( XT_display, dc->u.x.drawable, dc->u.x.gc,
-		  left, top, right-left-1, bottom-top-1, 0, 360*64 );
+		  dc->w.DCOrgX + left, dc->w.DCOrgY + top,
+		  right-left-1, bottom-top-1, 0, 360*64 );
     if (DC_SetupGCForPen( dc ))
 	XDrawArc( XT_display, dc->u.x.drawable, dc->u.x.gc,
-		  left, top, right-left-1, bottom-top-1, 0, 360*64 );
+		  dc->w.DCOrgX + left, dc->w.DCOrgY + top,
+		  right-left-1, bottom-top-1, 0, 360*64 );
     return TRUE;
 }
 
@@ -190,10 +195,12 @@
     
     if (DC_SetupGCForBrush( dc ))
 	XFillRectangle( XT_display, dc->u.x.drawable, dc->u.x.gc,
-		        left, top, right-left-1, bottom-top-1 );
+		        dc->w.DCOrgX + left, dc->w.DCOrgY + top,
+		        right-left-1, bottom-top-1 );
     if (DC_SetupGCForPen( dc ))
 	XDrawRectangle( XT_display, dc->u.x.drawable, dc->u.x.gc,
-		        left, top, right-left-1, bottom-top-1 );
+		        dc->w.DCOrgX + left, dc->w.DCOrgY + top,
+		        right-left-1, bottom-top-1 );
     return TRUE;
 }
 
@@ -244,10 +251,16 @@
     right  = XLPTODP( dc, rect->right );
     bottom = YLPTODP( dc, rect->bottom );
     
-    if (DC_SetupGCForBrush( dc ))
-	XDrawRectangle( XT_display, dc->u.x.drawable, dc->u.x.gc,
-		        left, top, right-left-1, bottom-top-1 );
-	    
+    if (DC_SetupGCForBrush( dc )) {
+   	PatBlt( hdc, rect->left, rect->top, 1,
+	    rect->bottom - rect->top, PATCOPY );
+	PatBlt( hdc, rect->right - 1, rect->top, 1,
+	    rect->bottom - rect->top, PATCOPY );
+	PatBlt( hdc, rect->left, rect->top,
+	    rect->right - rect->left, 1, PATCOPY );
+	PatBlt( hdc, rect->left, rect->bottom - 1,
+	    rect->right - rect->left, 1, PATCOPY );
+	}    
     SelectObject( hdc, prevBrush );
     return 1;
 }
@@ -264,8 +277,8 @@
     DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
     if (!dc) return 0;
 
-    x = XLPTODP( dc, x );
-    y = YLPTODP( dc, y );
+    x = dc->w.DCOrgX + XLPTODP( dc, x );
+    y = dc->w.DCOrgY + YLPTODP( dc, y );
     pixel = GetNearestPaletteIndex( dc->w.hPalette, color );
     GetPaletteEntries( dc->w.hPalette, pixel, 1, &entry );
     
@@ -288,15 +301,14 @@
     DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
     if (!dc) return 0;
 
-    x = XLPTODP( dc, x );
-    y = YLPTODP( dc, y );
+    x = dc->w.DCOrgX + XLPTODP( dc, x );
+    y = dc->w.DCOrgY + YLPTODP( dc, y );
     if ((x < 0) || (y < 0)) return 0;
     
-    if (dc->u.x.widget)
+    if (!(dc->w.flags & DC_MEMORY))
     {
 	XWindowAttributes win_attr;
 	
-	if (!XtIsRealized(dc->u.x.widget)) return 0;
 	if (!XGetWindowAttributes( XT_display, dc->u.x.drawable, &win_attr ))
 	    return 0;
 	if (win_attr.map_state != IsViewable) return 0;
@@ -342,7 +354,7 @@
     GetClipBox( hdc, &box );
     if (DC_SetupGCForBrush( dc ))
 	XFillRectangle( XT_display, dc->u.x.drawable, dc->u.x.gc,
-		        box.left, box.top,
+		        dc->w.DCOrgX + box.left, dc->w.DCOrgY + box.top,
 		        box.right-box.left, box.bottom-box.top );
 
       /* Restore the visible region */
@@ -385,15 +397,16 @@
     
     hPen = CreatePen(PS_DOT, 1, GetSysColor(COLOR_WINDOWTEXT)); 
     hOldPen = (HPEN)SelectObject(hdc, (HANDLE)hPen);
-/*    oldDrawMode = SetROP2(hdc, R2_XORPEN);  */
+    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 );
+		        dc->w.DCOrgX + left, dc->w.DCOrgY + top,
+		        right-left-1, bottom-top-1 );
 
     SetBkMode(hdc, oldBkMode);
-/*    SetROP2(hdc, oldDrawMode);  */
+    SetROP2(hdc, oldDrawMode);
     SelectObject(hdc, (HANDLE)hOldPen);
     DeleteObject((HANDLE)hPen);
 }
@@ -441,3 +454,64 @@
 SelectObject(hDC, hOldPen);
 DeleteObject(hDKGRAYPen);
 }
+
+/**********************************************************************
+ *          Polyline  (GDI.37)
+ */
+BOOL Polyline (HDC hdc, LPPOINT pt, int count)
+{
+	register int i;
+    	DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
+
+    	if (DC_SetupGCForPen( dc ))
+    	{
+		for (i = 0; i < count-1; i ++)
+			XDrawLine (XT_display, dc->u.x.drawable, dc->u.x.gc,  
+				   dc->w.DCOrgX + XLPTODP(dc, pt [i].x),
+				   dc->w.DCOrgY + YLPTODP(dc, pt [i].y),
+				   dc->w.DCOrgX + XLPTODP(dc, pt [i+1].x),
+				   dc->w.DCOrgY + YLPTODP(dc, pt [i+1].y));
+		XDrawLine (XT_display, dc->u.x.drawable, dc->u.x.gc,  
+			   dc->w.DCOrgX + XLPTODP(dc, pt [count-1].x),
+			   dc->w.DCOrgY + YLPTODP(dc, pt [count-1].y),
+			   dc->w.DCOrgX + XLPTODP(dc, pt [0].x),
+			   dc->w.DCOrgY + YLPTODP(dc, pt [0].y));
+	} 
+	
+	return (TRUE);
+}
+
+
+/**********************************************************************
+ *          Polygon  (GDI.36)
+ */
+BOOL Polygon (HDC hdc, LPPOINT pt, int count)
+{
+	register int i;
+    	DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
+	XPoint *points = (XPoint *) malloc (sizeof (XPoint) * count+1);
+
+    	if (DC_SetupGCForBrush( dc ))
+    	{
+    		
+		for (i = 0; i < count; i++)
+		{
+			points [i].x = dc->w.DCOrgX + XLPTODP(dc, pt [i].x);
+			points [i].y = dc->w.DCOrgY + YLPTODP(dc, pt [i].y);
+		}
+		points [count] = points [0];
+		
+		XFillPolygon( XT_display, dc->u.x.drawable, dc->u.x.gc,
+		  	points, count, Complex, CoordModeOrigin);
+		
+		if (DC_SetupGCForPen ( dc ))
+		{
+		    XDrawLines( XT_display, dc->u.x.drawable, dc->u.x.gc,
+			        points, count, CoordModeOrigin );
+		}
+	}
+    	free ((void *) points);
+	return (TRUE);
+}
+ 
+
diff --git a/windows/message.c b/windows/message.c
index 7307461..09b49e7 100644
--- a/windows/message.c
+++ b/windows/message.c
@@ -12,10 +12,8 @@
 static char Copyright[] = "Copyright  Alexandre Julliard, 1993";
 
 #include <stdlib.h>
-
-#ifdef __NetBSD__
-#define HZ 100
-#endif
+#include <sys/time.h>
+#include <sys/types.h>
 
 #include "message.h"
 #include "win.h"
@@ -23,30 +21,72 @@
 
 #define MAX_QUEUE_SIZE   120  /* Max. size of a message queue */
 
-extern HWND WIN_FindWinToRepaint( HWND hwnd );
+extern BOOL TIMER_CheckTimer( DWORD *next );    /* timer.c */
 
 extern Display * XT_display;
 extern Screen * XT_screen;
 extern XtAppContext XT_app_context;
 
-static MESSAGEQUEUE * msgQueue = NULL;
+  /* System message queue (for hardware events) */
+static HANDLE hmemSysMsgQueue = 0;
+static MESSAGEQUEUE * sysMsgQueue = NULL;
+
+  /* Application message queue (should be a list, one queue per task) */
+static HANDLE hmemAppMsgQueue = 0;
+static MESSAGEQUEUE * appMsgQueue = NULL;
+
+/***********************************************************************
+ *           MSG_CreateMsgQueue
+ *
+ * Create a message queue.
+ */
+static HANDLE MSG_CreateMsgQueue( int size )
+{
+    HANDLE hQueue;
+    MESSAGEQUEUE * msgQueue;
+    int queueSize;
+
+    queueSize = sizeof(MESSAGEQUEUE) + size * sizeof(QMSG);
+    if (!(hQueue = GlobalAlloc( GMEM_FIXED, queueSize ))) return 0;
+    msgQueue = (MESSAGEQUEUE *) GlobalLock( hQueue );
+    msgQueue->next = 0;
+    msgQueue->hTask = 0;
+    msgQueue->msgSize = sizeof(QMSG);
+    msgQueue->msgCount = 0;
+    msgQueue->nextMessage = 0;
+    msgQueue->nextFreeMessage = 0;
+    msgQueue->queueSize = size;
+    msgQueue->GetMessageTimeVal = 0;
+    msgQueue->GetMessagePosVal = 0;
+    msgQueue->GetMessageExtraInfoVal = 0;
+    msgQueue->lParam = 0;
+    msgQueue->wParam = 0;
+    msgQueue->msg = 0;
+    msgQueue->hWnd = 0;
+    msgQueue->wPostQMsg = 0;
+    msgQueue->wExitCode = 0;
+    msgQueue->InSendMessageHandle = 0;
+    msgQueue->wPaintCount = 0;
+    msgQueue->wTimerCount = 0;
+    msgQueue->tempStatus = 0;
+    msgQueue->status = 0;
+    GlobalUnlock( hQueue );
+    return hQueue;
+}
 
 
 /***********************************************************************
- *           MSG_GetMessageType
+ *           MSG_CreateSysMsgQueue
  *
+ * Create the system message queue. Must be called only once.
  */
-int MSG_GetMessageType( int msg )
+BOOL MSG_CreateSysMsgQueue( int size )
 {
-    if ((msg >= WM_KEYFIRST) && (msg <= WM_KEYLAST)) return QS_KEY;
-    else if ((msg >= WM_MOUSEFIRST) && (msg <= WM_MOUSELAST))
-    {
-	if (msg == WM_MOUSEMOVE) return QS_MOUSEMOVE;
-	else return QS_MOUSEBUTTON;
-    }
-    else if (msg == WM_PAINT) return QS_PAINT;
-    else if (msg == WM_TIMER) return QS_TIMER;
-    return QS_POSTMESSAGE;
+    if (size > MAX_QUEUE_SIZE) size = MAX_QUEUE_SIZE;
+    else if (size <= 0) size = 1;
+    if (!(hmemSysMsgQueue = MSG_CreateMsgQueue( size ))) return FALSE;
+    sysMsgQueue = (MESSAGEQUEUE *) GlobalLock( hmemSysMsgQueue );
+    return TRUE;
 }
 
 
@@ -55,16 +95,13 @@
  *
  * Add a message to the queue. Return FALSE if queue is full.
  */
-int MSG_AddMsg( MSG * msg, DWORD extraInfo )
+static int MSG_AddMsg( MESSAGEQUEUE * msgQueue, MSG * msg, DWORD extraInfo )
 {
-    int pos, type;
+    int pos;
   
     if (!msgQueue) return FALSE;
     pos = msgQueue->nextFreeMessage;
 
-      /* No need to store WM_PAINT messages */
-    if (msg->message == WM_PAINT) return TRUE;
-        
       /* Check if queue is full */
     if ((pos == msgQueue->nextMessage) && (msgQueue->msgCount > 0))
 	return FALSE;
@@ -72,17 +109,12 @@
       /* Store message */
     msgQueue->messages[pos].msg = *msg;
     msgQueue->messages[pos].extraInfo = extraInfo;
-
-      /* Store message type */
-    type = MSG_GetMessageType( msg->message );   
-    msgQueue->status |= type;
-    msgQueue->tempStatus |= type;
-    
     if (pos < msgQueue->queueSize-1) pos++;
     else pos = 0;
     msgQueue->nextFreeMessage = pos;
     msgQueue->msgCount++;
-    
+    msgQueue->status |= QS_POSTMESSAGE;
+    msgQueue->tempStatus |= QS_POSTMESSAGE;
     return TRUE;
 }
 
@@ -92,7 +124,7 @@
  *
  * Find a message matching the given parameters. Return -1 if none available.
  */
-int MSG_FindMsg( HWND hwnd, int first, int last )
+static int MSG_FindMsg(MESSAGEQUEUE * msgQueue, HWND hwnd, int first, int last)
 {
     int i, pos = msgQueue->nextMessage;
 
@@ -120,9 +152,8 @@
  *
  * Remove a message from the queue (pos must be a valid position).
  */
-void MSG_RemoveMsg( int pos )
+static void MSG_RemoveMsg( MESSAGEQUEUE * msgQueue, int pos )
 {
-    int i, type;
     QMSG * qmsg;
     
     if (!msgQueue) return;
@@ -147,56 +178,118 @@
 	else msgQueue->nextFreeMessage = msgQueue->queueSize-1;
     }
     msgQueue->msgCount--;
-
-      /* Recalc status */
-    type = 0;
-    pos = msgQueue->nextMessage;
-    for (i = 0; i < msgQueue->msgCount; i++)
-    {
-	type |= MSG_GetMessageType( msgQueue->messages[pos].msg.message );
-	if (++pos >= msgQueue->queueSize-1) pos = 0;
-    }
-    msgQueue->status = (msgQueue->status & QS_SENDMESSAGE) | type;
+    if (!msgQueue->msgCount) msgQueue->status &= ~QS_POSTMESSAGE;
     msgQueue->tempStatus = 0;
 }
 
 
 /***********************************************************************
+ *           MSG_IncPaintCount
+ */
+void MSG_IncPaintCount( HANDLE hQueue )
+{
+    if (hQueue != hmemAppMsgQueue) return;
+    appMsgQueue->wPaintCount++;
+    appMsgQueue->status |= QS_PAINT;
+    appMsgQueue->tempStatus |= QS_PAINT;    
+}
+
+
+/***********************************************************************
+ *           MSG_DecPaintCount
+ */
+void MSG_DecPaintCount( HANDLE hQueue )
+{
+    if (hQueue != hmemAppMsgQueue) return;
+    appMsgQueue->wPaintCount--;
+    if (!appMsgQueue->wPaintCount) appMsgQueue->status &= ~QS_PAINT;
+}
+
+
+/***********************************************************************
+ *           MSG_IncTimerCount
+ */
+void MSG_IncTimerCount( HANDLE hQueue )
+{
+    if (hQueue != hmemAppMsgQueue) return;
+    appMsgQueue->wTimerCount++;
+    appMsgQueue->status |= QS_TIMER;
+    appMsgQueue->tempStatus |= QS_TIMER;
+}
+
+
+/***********************************************************************
+ *           MSG_DecTimerCount
+ */
+void MSG_DecTimerCount( HANDLE hQueue )
+{
+    if (hQueue != hmemAppMsgQueue) return;
+    appMsgQueue->wTimerCount--;
+    if (!appMsgQueue->wTimerCount) appMsgQueue->status &= ~QS_TIMER;
+}
+
+
+/***********************************************************************
+ *           hardware_event
+ *
+ * Add an event to the system message queue.
+ */
+void hardware_event( HWND hwnd, WORD message, WORD wParam, LONG lParam,
+		     WORD xPos, WORD yPos, DWORD time, DWORD extraInfo )
+{
+    MSG msg;
+
+    msg.hwnd    = hwnd;
+    msg.message = message;
+    msg.wParam  = wParam;
+    msg.lParam  = lParam;
+    msg.time    = time;
+    msg.pt.x    = xPos;
+    msg.pt.y    = yPos;    
+    if (!MSG_AddMsg( sysMsgQueue, &msg, extraInfo ))
+	printf( "hardware_event: Queue is full\n" );
+}
+
+		    
+/***********************************************************************
+ *           SetTaskQueue  (KERNEL.34)
+ */
+WORD SetTaskQueue( HANDLE hTask, HANDLE hQueue )
+{
+    HANDLE prev = hmemAppMsgQueue;
+    hmemAppMsgQueue = hQueue;
+    return prev;
+}
+
+
+/***********************************************************************
+ *           GetTaskQueue  (KERNEL.35)
+ */
+WORD GetTaskQueue( HANDLE hTask )
+{
+    return hmemAppMsgQueue;
+}
+
+
+/***********************************************************************
  *           SetMessageQueue  (USER.266)
  */
 BOOL SetMessageQueue( int size )
 {
-    int queueSize;
-  
+    HANDLE hQueue;
+
+    if ((size > MAX_QUEUE_SIZE) || (size <= 0)) return TRUE;
+
       /* Free the old message queue */
-    if (msgQueue) free(msgQueue);
+    if ((hQueue = GetTaskQueue(0)) != 0)
+    {
+	GlobalUnlock( hQueue );
+	GlobalFree( hQueue );
+    }
   
-    if ((size > MAX_QUEUE_SIZE) || (size <= 0)) return FALSE;
-  
-    queueSize = sizeof(MESSAGEQUEUE) + size * sizeof(QMSG);
-    msgQueue = (MESSAGEQUEUE *) malloc(queueSize);
-    if (!msgQueue) return FALSE;
-
-    msgQueue->next = 0;
-    msgQueue->hTask = 0;
-    msgQueue->msgSize = sizeof(QMSG);
-    msgQueue->msgCount = 0;
-    msgQueue->nextMessage = 0;
-    msgQueue->nextFreeMessage = 0;
-    msgQueue->queueSize = size;
-    msgQueue->GetMessageTimeVal = 0;
-    msgQueue->GetMessagePosVal = 0;
-    msgQueue->GetMessageExtraInfoVal = 0;
-    msgQueue->lParam = 0;
-    msgQueue->wParam = 0;
-    msgQueue->msg = 0;
-    msgQueue->hWnd = 0;
-    msgQueue->wPostQMsg = 0;
-    msgQueue->wExitCode = 0;
-    msgQueue->InSendMessageHandle = 0;
-    msgQueue->tempStatus = 0;
-    msgQueue->status = 0;
-
+    if (!(hQueue = MSG_CreateMsgQueue( size ))) return FALSE;
+    SetTaskQueue( 0, hQueue );
+    appMsgQueue = (MESSAGEQUEUE *)GlobalLock( hQueue );
     return TRUE;
 }
 
@@ -206,9 +299,9 @@
  */
 void PostQuitMessage( int exitCode )
 {
-    if (!msgQueue) return;
-    msgQueue->wPostQMsg = TRUE;
-    msgQueue->wExitCode = exitCode;
+    if (!appMsgQueue) return;
+    appMsgQueue->wPostQMsg = TRUE;
+    appMsgQueue->wExitCode = exitCode;
 }
 
 
@@ -217,12 +310,8 @@
  */
 DWORD GetQueueStatus( int flags )
 {
-    unsigned long ret = (msgQueue->status << 16) | msgQueue->tempStatus;
-    if (flags & QS_PAINT)
-    {
-	if (WIN_FindWinToRepaint(0)) ret |= QS_PAINT | (QS_PAINT << 16);
-    }
-    msgQueue->tempStatus = 0;
+    unsigned long ret = (appMsgQueue->status << 16) | appMsgQueue->tempStatus;
+    appMsgQueue->tempStatus = 0;
     return ret & ((flags << 16) | flags);
 }
 
@@ -232,70 +321,169 @@
  */
 BOOL GetInputState()
 {
-    return msgQueue->status & (QS_KEY | QS_MOUSEBUTTON);
+    return appMsgQueue->status & (QS_KEY | QS_MOUSEBUTTON);
 }
 
 
+#ifndef USE_XLIB
+static XtIntervalId xt_timer = 0;
+
+/***********************************************************************
+ *           MSG_TimerCallback
+ */
+static void MSG_TimerCallback( XtPointer data, XtIntervalId * xtid )
+{
+    DWORD nextExp;
+    TIMER_CheckTimer( &nextExp );
+    if (nextExp != (DWORD)-1)
+	xt_timer = XtAppAddTimeOut( XT_app_context, nextExp,
+				    MSG_TimerCallback, NULL );
+    else xt_timer = 0;
+}
+#endif  /* USE_XLIB */
+
+
 /***********************************************************************
  *           MSG_PeekMessage
  */
-BOOL MSG_PeekMessage( LPMSG msg, HWND hwnd, WORD first, WORD last, WORD flags )
+static BOOL MSG_PeekMessage( MESSAGEQUEUE * msgQueue, LPMSG msg, HWND hwnd,
+			     WORD first, WORD last, WORD flags, BOOL peek )
 {
-    int pos;
+    int pos, mask;
+    DWORD nextExp;  /* Next timer expiration time */
+#ifdef USE_XLIB
+    XEvent event;
+#endif
 
-      /* First handle a WM_QUIT message */
-    if (msgQueue->wPostQMsg)
+    if (first || last)
     {
-	msg->hwnd    = hwnd;
-	msg->message = WM_QUIT;
-	msg->wParam  = msgQueue->wExitCode;
-	msg->lParam  = 0;
-	return TRUE;
+	mask = QS_POSTMESSAGE;  /* Always selectioned */
+	if ((first <= WM_KEYLAST) && (last >= WM_KEYFIRST)) mask |= QS_KEY;
+	if ((first <= WM_MOUSELAST) && (last >= WM_MOUSEFIRST)) mask |= QS_MOUSE;
+	if ((first <= WM_TIMER) && (last >= WM_TIMER)) mask |= WM_TIMER;
+	if ((first <= WM_SYSTIMER) && (last >= WM_SYSTIMER)) mask |= WM_TIMER;
+	if ((first <= WM_PAINT) && (last >= WM_PAINT)) mask |= WM_PAINT;
     }
+    else mask = QS_MOUSE | QS_KEY | QS_POSTMESSAGE | QS_TIMER | QS_PAINT;
 
-      /* Then handle a message put by SendMessage() */
-    if (msgQueue->status & QS_SENDMESSAGE)
+#ifdef USE_XLIB
+    while (XPending( XT_display ))
     {
-	if (!hwnd || (msgQueue->hWnd == hwnd))
+	XNextEvent( XT_display, &event );
+	EVENT_ProcessEvent( &event );
+    }    
+#else
+    while (XtAppPending( XT_app_context ))
+	XtAppProcessEvent( XT_app_context, XtIMAll );
+#endif
+
+    while(1)
+    {    
+	  /* First handle a WM_QUIT message */
+	if (msgQueue->wPostQMsg)
 	{
-	    if ((!first && !last) || 
-		((msgQueue->msg >= first) && (msgQueue->msg <= last)))
+	    msg->hwnd    = hwnd;
+	    msg->message = WM_QUIT;
+	    msg->wParam  = msgQueue->wExitCode;
+	    msg->lParam  = 0;
+	    break;
+	}
+
+	  /* Then handle a message put by SendMessage() */
+	if (msgQueue->status & QS_SENDMESSAGE)
+	{
+	    if (!hwnd || (msgQueue->hWnd == hwnd))
 	    {
-		msg->hwnd    = msgQueue->hWnd;
-		msg->message = msgQueue->msg;
-		msg->wParam  = msgQueue->wParam;
-		msg->lParam  = msgQueue->lParam;
-		if (flags & PM_REMOVE) msgQueue->status &= ~QS_SENDMESSAGE;
-		return TRUE;
+		if ((!first && !last) || 
+		    ((msgQueue->msg >= first) && (msgQueue->msg <= last)))
+		{
+		    msg->hwnd    = msgQueue->hWnd;
+		    msg->message = msgQueue->msg;
+		    msg->wParam  = msgQueue->wParam;
+		    msg->lParam  = msgQueue->lParam;
+		    if (flags & PM_REMOVE) msgQueue->status &= ~QS_SENDMESSAGE;
+		    break;
+		}
 	    }
 	}
-	
-    }
     
-      /* Now find a normal message */
-    pos = MSG_FindMsg( hwnd, first, last );
-    if (pos != -1)
-    {
-	QMSG *qmsg = &msgQueue->messages[pos];
-	*msg = qmsg->msg;
-	msgQueue->GetMessageTimeVal      = msg->time;
-	msgQueue->GetMessagePosVal       = *(DWORD *)&msg->pt;
-	msgQueue->GetMessageExtraInfoVal = qmsg->extraInfo;
+	  /* Now find a normal message */
+	pos = MSG_FindMsg( msgQueue, hwnd, first, last );
+	if (pos != -1)
+	{
+	    QMSG *qmsg = &msgQueue->messages[pos];
+	    *msg = qmsg->msg;
+	    msgQueue->GetMessageTimeVal      = msg->time;
+	    msgQueue->GetMessagePosVal       = *(DWORD *)&msg->pt;
+	    msgQueue->GetMessageExtraInfoVal = qmsg->extraInfo;
 
-	if (flags & PM_REMOVE) MSG_RemoveMsg(pos);
-    	return TRUE;
+	    if (flags & PM_REMOVE) MSG_RemoveMsg( msgQueue, pos );
+	    break;
+	}
+
+	  /* Now find a hardware event */
+	pos = MSG_FindMsg( sysMsgQueue, hwnd, first, last );
+	if (pos != -1)
+	{
+	    QMSG *qmsg = &sysMsgQueue->messages[pos];
+	    *msg = qmsg->msg;
+	    msgQueue->GetMessageTimeVal      = msg->time;
+	    msgQueue->GetMessagePosVal       = *(DWORD *)&msg->pt;
+	    msgQueue->GetMessageExtraInfoVal = qmsg->extraInfo;
+
+	    if (flags & PM_REMOVE) MSG_RemoveMsg( sysMsgQueue, pos );
+	    break;
+	}
+
+	  /* Now find a WM_PAINT message */
+	if ((msgQueue->status & QS_PAINT) && (mask & QS_PAINT))
+	{
+	    msg->hwnd = WIN_FindWinToRepaint( hwnd );
+	    msg->message = WM_PAINT;
+	    msg->wParam = 0;
+	    msg->lParam = 0;
+	    if (msg->hwnd != 0) break;
+	}
+
+	  /* Finally handle WM_TIMER messages */
+	if ((msgQueue->status & QS_TIMER) && (mask & QS_TIMER))
+	{
+	    BOOL posted = TIMER_CheckTimer( &nextExp );
+#ifndef USE_XLIB
+	    if (xt_timer) XtRemoveTimeOut( xt_timer );
+	    if (nextExp != (DWORD)-1)
+		xt_timer = XtAppAddTimeOut( XT_app_context, nextExp,
+					    MSG_TimerCallback, NULL );
+	    else xt_timer = 0;
+#endif
+	    if (posted) continue;  /* Restart the whole thing */
+	}
+
+	  /* Wait until something happens */
+	if (peek) return FALSE;
+#ifdef USE_XLIB
+	if (!XPending( XT_display ) && (nextExp != -1))
+	{
+	    fd_set read_set;
+	    struct timeval timeout;
+	    int fd = ConnectionNumber(XT_display);
+	    FD_ZERO( &read_set );
+	    FD_SET( fd, &read_set );
+	    timeout.tv_sec = nextExp / 1000;
+	    timeout.tv_usec = (nextExp % 1000) * 1000;
+	    if (select( fd+1, &read_set, NULL, NULL, &timeout ) != 1)
+		continue;  /* On timeout or error, restart from the start */
+	}
+	XNextEvent( XT_display, &event );
+	EVENT_ProcessEvent( &event );
+#else       
+	XtAppProcessEvent( XT_app_context, XtIMAll );
+#endif	
     }
 
-      /* If nothing else, return a WM_PAINT message */
-    if ((!first && !last) || ((first <= WM_PAINT) && (last >= WM_PAINT)))
-    {
-	msg->hwnd = WIN_FindWinToRepaint( hwnd );
-	msg->message = WM_PAINT;
-	msg->wParam = 0;
-	msg->lParam = 0;
-	return (msg->hwnd != 0);
-    }	
-    return FALSE;
+      /* We got a message */
+    if (peek) return TRUE;
+    else return (msg->message != WM_QUIT);
 }
 
 
@@ -304,10 +492,7 @@
  */
 BOOL PeekMessage( LPMSG msg, HWND hwnd, WORD first, WORD last, WORD flags )
 {
-    while (XtAppPending( XT_app_context ))
-	XtAppProcessEvent( XT_app_context, XtIMAll );
-
-    return MSG_PeekMessage( msg, hwnd, first, last, flags );
+    return MSG_PeekMessage( appMsgQueue, msg, hwnd, first, last, flags, TRUE );
 }
 
 
@@ -316,13 +501,7 @@
  */
 BOOL GetMessage( LPMSG msg, HWND hwnd, WORD first, WORD last ) 
 {
-    while(1)
-    {
-	if (MSG_PeekMessage( msg, hwnd, first, last, PM_REMOVE )) break;
-	XtAppProcessEvent( XT_app_context, XtIMAll );
-    }
-
-    return (msg->message != WM_QUIT);
+    return MSG_PeekMessage( appMsgQueue, msg, hwnd, first, last, PM_REMOVE, FALSE );
 }
 
 
@@ -341,7 +520,7 @@
     msg.pt.x    = 0;
     msg.pt.y    = 0;
     
-    return MSG_AddMsg( &msg, 0 );
+    return MSG_AddMsg( appMsgQueue, &msg, 0 );
 }
 
 
@@ -380,16 +559,39 @@
  */
 LONG DispatchMessage( LPMSG msg )
 {
-    WND * wndPtr = WIN_FindWndPtr( msg->hwnd );
-
+    WND * wndPtr;
+    LONG retval;
+    int painting;
+    
 #ifdef DEBUG_MSG
     printf( "Dispatch message hwnd=%08x msg=%d w=%d l=%d time=%u pt=%d,%d\n",
 	    msg->hwnd, msg->message, msg->wParam, msg->lParam, 
 	    msg->time, msg->pt.x, msg->pt.y );
 #endif
-    if (!wndPtr)  return 0;
-    return CallWindowProc( wndPtr->lpfnWndProc, msg->hwnd, msg->message,
-			   msg->wParam, msg->lParam );
+
+      /* Process timer messages */
+    if ((msg->message == WM_TIMER) || (msg->message == WM_SYSTIMER))
+    {
+	if (msg->lParam)
+	    return CallWindowProc( (FARPROC)msg->lParam, msg->hwnd,
+				   msg->message, msg->wParam, GetTickCount() );
+    }
+
+    if (!msg->hwnd) return 0;
+    if (!(wndPtr = WIN_FindWndPtr( msg->hwnd ))) return 0;
+    if (!wndPtr->lpfnWndProc) return 0;
+    painting = (msg->message == WM_PAINT);
+    if (painting) wndPtr->flags |= WIN_NEEDS_BEGINPAINT;
+    retval = CallWindowProc( wndPtr->lpfnWndProc, msg->hwnd, msg->message,
+			     msg->wParam, msg->lParam );
+    if (painting && (wndPtr->flags & WIN_NEEDS_BEGINPAINT))
+    {
+#ifdef DEBUG_WIN
+	printf( "BeginPaint not called on WM_PAINT!\n" );
+#endif
+	wndPtr->flags &= ~WIN_NEEDS_BEGINPAINT;
+    }
+    return retval;
 }
 
 
@@ -398,7 +600,7 @@
  */
 DWORD GetMessagePos(void)
 {
-    return msgQueue->GetMessagePosVal;
+    return appMsgQueue->GetMessagePosVal;
 }
 
 
@@ -407,14 +609,27 @@
  */
 LONG GetMessageTime(void)
 {
-    return msgQueue->GetMessageTimeVal;
+    return appMsgQueue->GetMessageTimeVal;
 }
 
+
 /***********************************************************************
  *           GetMessageExtraInfo   (USER.288)
  */
 LONG GetMessageExtraInfo(void)
 {
-    return msgQueue->GetMessageExtraInfoVal;
+    return appMsgQueue->GetMessageExtraInfoVal;
+}
+
+
+/***********************************************************************
+ *           RegisterWindowMessage   (USER.118)
+ */
+WORD RegisterWindowMessage( LPCSTR str )
+{
+#ifdef DEBUG_MSG
+    printf( "RegisterWindowMessage: '%s'\n", str );
+#endif
+    return GlobalAddAtom( str );
 }
 
diff --git a/windows/painting.c b/windows/painting.c
index 4f21b13..5a8e60a 100644
--- a/windows/painting.c
+++ b/windows/painting.c
@@ -10,6 +10,7 @@
 #include <X11/Xlib.h>
 
 #include "win.h"
+#include "message.h"
 
   /* Last CTLCOLOR id */
 #define CTLCOLOR_MAX   CTLCOLOR_STATIC
@@ -23,27 +24,21 @@
     WND * wndPtr = WIN_FindWndPtr( hwnd );
     if (!wndPtr) return 0;
 
-    lps->hdc = GetDC( hwnd );
-    if (!lps->hdc) return 0;
-    
-    SelectVisRgn( lps->hdc, wndPtr->hrgnUpdate );
+    if (!(lps->hdc = GetDCEx( hwnd, wndPtr->hrgnUpdate,
+			      DCX_INTERSECTRGN | DCX_USESTYLE ))) return 0;
+    GetRgnBox( InquireVisRgn(lps->hdc), &lps->rcPaint );
+
     if (wndPtr->hrgnUpdate)
     {
-	GetRgnBox( wndPtr->hrgnUpdate, &lps->rcPaint );
 	DeleteObject( wndPtr->hrgnUpdate );
 	wndPtr->hrgnUpdate = 0;
+	MSG_DecPaintCount( wndPtr->hmemTaskQ );
     }
-    else
-    {
-	lps->rcPaint.left   = 0;
-	lps->rcPaint.top    = 0;
-	lps->rcPaint.right  = wndPtr->rectClient.right-wndPtr->rectClient.left;
-	lps->rcPaint.bottom = wndPtr->rectClient.bottom-wndPtr->rectClient.top;
-    }    
-
+    wndPtr->flags &= ~WIN_NEEDS_BEGINPAINT;
+    
     if (!(wndPtr->flags & WIN_ERASE_UPDATERGN)) lps->fErase = TRUE;
     else lps->fErase = !SendMessage( hwnd, WM_ERASEBKGND, lps->hdc, 0 );
-
+    
     return lps->hdc;
 }
 
@@ -63,12 +58,7 @@
 void FillWindow( HWND hwndParent, HWND hwnd, HDC hdc, HBRUSH hbrush )
 {
     RECT rect;
-    WND * wndPtr = WIN_FindWndPtr( hwnd );
-    if (!wndPtr) return;
-    rect.left   = 0;
-    rect.top    = 0;
-    rect.right  = wndPtr->rectClient.right - wndPtr->rectClient.left;
-    rect.bottom = wndPtr->rectClient.bottom - wndPtr->rectClient.top;
+    GetClientRect( hwnd, &rect );
     PaintRect( hwndParent, hwnd, hdc, hbrush, &rect );
 }
 
diff --git a/windows/timer.c b/windows/timer.c
index 2aeb88ee..da64961 100644
--- a/windows/timer.c
+++ b/windows/timer.c
@@ -6,21 +6,19 @@
 
 static char Copyright[] = "Copyright  Alexandre Julliard, 1993";
 
-#include <X11/Intrinsic.h>
-
 #include "windows.h"
-
-extern XtAppContext XT_app_context;
+#include "message.h"
 
 
-typedef struct
+typedef struct tagTIMER
 {
-    HWND          hwnd;
-    WORD          msg;  /* WM_TIMER or WM_SYSTIMER */
-    WORD          id;
-    WORD          timeout;
-    FARPROC       proc;
-    XtIntervalId  xtid;
+    HWND             hwnd;
+    WORD             msg;  /* WM_TIMER or WM_SYSTIMER */
+    WORD             id;
+    WORD             timeout;
+    struct tagTIMER *next;
+    DWORD            expires;
+    FARPROC          proc;
 } TIMER;
 
 #define NB_TIMERS            34
@@ -28,39 +26,100 @@
 
 static TIMER TimersArray[NB_TIMERS];
 
+static TIMER * pNextTimer = NULL;  /* Next timer to expire */
+
 
 /***********************************************************************
- *           TIMER_callback
+ *           TIMER_InsertTimer
+ *
+ * Insert the timer at its place in the chain.
  */
-static void TIMER_callback( XtPointer data, XtIntervalId * xtid )
+static void TIMER_InsertTimer( TIMER * pTimer )
 {
-    TIMER * pTimer = (TIMER *) data;
-    
-    pTimer->xtid = 0;  /* In case the timer procedure calls KillTimer */
-    
-    if (pTimer->proc)
+    if (!pNextTimer || (pTimer->expires < pNextTimer->expires))
     {
-	CallWindowProc(pTimer->proc, pTimer->hwnd, pTimer->msg, 
-		       pTimer->id, GetTickCount());
+	pTimer->next = pNextTimer;
+	pNextTimer = pTimer;
     }
-    else 
-	PostMessage( pTimer->hwnd, pTimer->msg, pTimer->id, 0 );
+    else
+    {
+        TIMER * ptr = pNextTimer;	
+	while (ptr->next && (pTimer->expires >= ptr->next->expires))
+	    ptr = ptr->next;
+	pTimer->next = ptr;
+	ptr->next = pTimer;
+    }
+}
+
+
+/***********************************************************************
+ *           TIMER_RemoveTimer
+ *
+ * Remove the timer from the chain.
+ */
+static void TIMER_RemoveTimer( TIMER * pTimer )
+{
+    if (pTimer == pNextTimer) pNextTimer = pTimer->next;
+    else
+    {
+	TIMER * ptr = pNextTimer;
+	while (ptr && (ptr->next != pTimer)) ptr = ptr->next;
+	if (ptr) ptr->next = pTimer->next;
+    }
+    pTimer->next = NULL;
+}
+
+
+/***********************************************************************
+ *           TIMER_NextExpire
+ *
+ * Return time until next timer expiration (-1 if none).
+ */
+static DWORD TIMER_NextExpire( DWORD curTime )
+{
+    if (!pNextTimer) return -1;
+    if (pNextTimer->expires <= curTime) return 0;
+    return pNextTimer->expires - curTime;
+}
+
+
+/***********************************************************************
+ *           TIMER_CheckTimer
+ *
+ * Check whether a timer has expired, and post a message if necessary.
+ * Return TRUE if msg posted, and return time until next expiration in 'next'.
+ */
+BOOL TIMER_CheckTimer( DWORD *next )
+{
+    TIMER * pTimer = pNextTimer;
+    DWORD curTime = GetTickCount();
+    
+    if ((*next = TIMER_NextExpire( curTime )) != 0) return FALSE;
+
+    PostMessage( pTimer->hwnd, pTimer->msg, pTimer->id, (LONG)pTimer->proc );
+    TIMER_RemoveTimer( pTimer );
 
       /* If timeout == 0, the timer has been removed by KillTimer */
     if (pTimer->timeout)
-	pTimer->xtid = XtAppAddTimeOut( XT_app_context, pTimer->timeout,
-				        TIMER_callback, pTimer );
+    {
+	  /* Restart the timer */
+	pTimer->expires = curTime + pTimer->timeout;
+	TIMER_InsertTimer( pTimer );
+    }
+    *next = TIMER_NextExpire( curTime );
+    return TRUE;
 }
 
 
 /***********************************************************************
  *           TIMER_SetTimer
  */
-WORD TIMER_SetTimer( HWND hwnd, WORD id, WORD timeout, FARPROC proc, BOOL sys )
+static WORD TIMER_SetTimer( HWND hwnd, WORD id, WORD timeout,
+			    FARPROC proc, BOOL sys )
 {
     int i;
     TIMER * pTimer;
-    
+
     if (!timeout) return 0;
     if (!hwnd && !proc) return 0;
     
@@ -79,9 +138,10 @@
     pTimer->msg     = sys ? WM_SYSTIMER : WM_TIMER;
     pTimer->id      = id;
     pTimer->timeout = timeout;
+    pTimer->expires = GetTickCount() + timeout;
     pTimer->proc    = proc;
-    pTimer->xtid    = XtAppAddTimeOut( XT_app_context, timeout,
-				       TIMER_callback, pTimer );
+    TIMER_InsertTimer( pTimer );
+    MSG_IncTimerCount( GetTaskQueue(0) );
     return id;
 }
 
@@ -89,7 +149,7 @@
 /***********************************************************************
  *           TIMER_KillTimer
  */
-BOOL TIMER_KillTimer( HWND hwnd, WORD id, BOOL sys )
+static BOOL TIMER_KillTimer( HWND hwnd, WORD id, BOOL sys )
 {
     int i;
     TIMER * pTimer;
@@ -106,13 +166,13 @@
 
       /* Delete the timer */
 
-    if (pTimer->xtid) XtRemoveTimeOut( pTimer->xtid );
     pTimer->hwnd    = 0;
     pTimer->msg     = 0;
     pTimer->id      = 0;
     pTimer->timeout = 0;
     pTimer->proc    = 0;
-    pTimer->xtid    = 0;
+    TIMER_RemoveTimer( pTimer );
+    MSG_DecTimerCount( GetTaskQueue(0) );
     return TRUE;
 }
 
@@ -123,7 +183,7 @@
 WORD SetTimer( HWND hwnd, WORD id, WORD timeout, FARPROC proc )
 {
 #ifdef DEBUG_TIMER    
-    printf( "SetTimer: %d %d %d %08x\n", hwnd, id, timeout, proc );
+    printf( "SetTimer: %d %d %d %p\n", hwnd, id, timeout, proc );
 #endif
     return TIMER_SetTimer( hwnd, id, timeout, proc, FALSE );
 }
@@ -135,7 +195,7 @@
 WORD SetSystemTimer( HWND hwnd, WORD id, WORD timeout, FARPROC proc )
 {
 #ifdef DEBUG_TIMER    
-    printf( "SetSystemTimer: %d %d %d %08x\n", hwnd, id, timeout, proc );
+    printf( "SetSystemTimer: %d %d %d %p\n", hwnd, id, timeout, proc );
 #endif
     return TIMER_SetTimer( hwnd, id, timeout, proc, TRUE );
 }
diff --git a/windows/win.c b/windows/win.c
index d7fe3a2..8411e48 100644
--- a/windows/win.c
+++ b/windows/win.c
@@ -10,11 +10,11 @@
 #include <X11/StringDefs.h>
 #include <X11/Core.h>
 #include <X11/Shell.h>
-#include <X11/Xaw/Box.h>
 
 #include "class.h"
 #include "win.h"
 #include "user.h"
+#include "dce.h"
 
 extern Display * XT_display;
 extern Screen * XT_screen;
@@ -22,10 +22,6 @@
 
 static HWND firstWindow = 0;
 
-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
  *
@@ -43,6 +39,76 @@
 
 
 /***********************************************************************
+ *           WIN_UnlinkWindow
+ *
+ * Remove a window from the siblings linked list.
+ */
+BOOL WIN_UnlinkWindow( HWND hwnd )
+{    
+    HWND * curWndPtr;
+    WND * wndPtr = WIN_FindWndPtr( hwnd );
+
+    if (!wndPtr) return FALSE;
+    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;
+    return TRUE;
+}
+
+
+/***********************************************************************
+ *           WIN_LinkWindow
+ *
+ * Insert a window into the siblings linked list.
+ * The window is inserted after the specified window, which can also
+ * be specified as HWND_TOP or HWND_BOTTOM.
+ */
+BOOL WIN_LinkWindow( HWND hwnd, HWND hwndInsertAfter )
+{    
+    HWND * hwndPtr = NULL;  /* pointer to hwnd to change */
+
+    WND * wndPtr = WIN_FindWndPtr( hwnd );
+    if (!wndPtr) return FALSE;
+    
+    if ((hwndInsertAfter == HWND_TOP) || (hwndInsertAfter == HWND_BOTTOM))
+    {
+	  /* Make hwndPtr point to the first sibling hwnd */
+	if (wndPtr->hwndParent)
+	{
+	    WND * parentPtr = WIN_FindWndPtr( wndPtr->hwndParent );
+	    if (parentPtr) hwndPtr = &parentPtr->hwndChild;
+	}
+	else hwndPtr = &firstWindow;
+	if (hwndInsertAfter == HWND_BOTTOM)  /* Find last sibling hwnd */
+	    while (*hwndPtr)
+	    {
+		WND * nextPtr = WIN_FindWndPtr( *hwndPtr );
+		hwndPtr = &nextPtr->hwndNext;
+	    }
+    }
+    else  /* Normal case */
+    {
+	WND * afterPtr = WIN_FindWndPtr( hwndInsertAfter );
+	if (afterPtr) hwndPtr = &afterPtr->hwndNext;
+    }
+    if (!hwndPtr) return FALSE;
+    wndPtr->hwndNext = *hwndPtr;
+    *hwndPtr = hwnd;
+    return TRUE;
+}
+
+
+/***********************************************************************
  *           WIN_FindWinToRepaint
  *
  * Find a window that needs repaint.
@@ -55,8 +121,6 @@
     for ( ; hwnd != 0; hwnd = wndPtr->hwndNext )
     {
 	if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return 0;
-	if (!wndPtr || !wndPtr->winWidget) continue;
-	if (!XtIsRealized( wndPtr->winWidget )) continue;
 	if (wndPtr->hrgnUpdate) return hwnd;
 	if (wndPtr->hwndChild)
 	{
@@ -114,9 +178,11 @@
     CREATESTRUCT *createStruct;
     HANDLE hcreateStruct;
     int wmcreate;
+    short newwidth, newheight;
 
 #ifdef DEBUG_WIN
-    printf( "CreateWindowEx: %s %s %d,%d %dx%d\n", className, windowName, x, y, width, height );
+    printf( "CreateWindowEx: %s %s %d,%d %dx%d %08x\n",
+	    className, windowName, x, y, width, height, style );
 #endif
 
     if (x == CW_USEDEFAULT) x = 0;
@@ -155,11 +221,12 @@
     wndPtr->hwndOwner  = parent;  /* What else? */
     wndPtr->hClass     = class;
     wndPtr->hInstance  = instance;
-    wndPtr->rectClient.left   = x;
-    wndPtr->rectClient.top    = y;
-    wndPtr->rectClient.right  = x + width;
-    wndPtr->rectClient.bottom = y + height;
-    wndPtr->rectWindow        = wndPtr->rectClient;
+    wndPtr->rectWindow.left   = x;
+    wndPtr->rectWindow.top    = y;
+    wndPtr->rectWindow.right  = x + width;
+    wndPtr->rectWindow.bottom = y + height;
+    wndPtr->rectClient        = wndPtr->rectWindow;
+    wndPtr->hmemTaskQ         = GetTaskQueue(0);
     wndPtr->hrgnUpdate        = 0;
     wndPtr->hwndLastActive    = 0;
     wndPtr->lpfnWndProc       = classPtr->wc.lpfnWndProc;
@@ -169,43 +236,70 @@
     wndPtr->wIDmenu           = menu;
     wndPtr->hText             = 0;
     wndPtr->flags             = 0;
+    wndPtr->hCursor           = 0;
+    wndPtr->hWndVScroll       = 0;
+    wndPtr->hWndHScroll       = 0;
 
     if (classPtr->wc.cbWndExtra)
 	memset( wndPtr->wExtra, 0, classPtr->wc.cbWndExtra );
-    if (classPtr->wc.style & CS_OWNDC)
-	wndPtr->hdc = CreateDC( "DISPLAY", NULL, NULL, NULL);
-    else wndPtr->hdc = 0;
     classPtr->cWindows++;
 
+      /* Get class or window DC if needed */
+    if (classPtr->wc.style & CS_OWNDC)
+    {
+	wndPtr->flags |= WIN_OWN_DC;
+	wndPtr->hdce = DCE_AllocDCE( DCE_WINDOW_DC );
+    }
+    else if (classPtr->wc.style & CS_CLASSDC)
+    {
+	wndPtr->flags |= WIN_CLASS_DC;
+	wndPtr->hdce = classPtr->hdce;
+    }
+    else wndPtr->hdce = 0;
+
       /* Insert the window in the linked list */
 
-    if (parent)
-    {
-	wndPtr->hwndNext = parentPtr->hwndChild;
-	parentPtr->hwndChild = hwnd;
-    }
-    else  /* Top-level window */
-    {
-	wndPtr->hwndNext = firstWindow;
-	firstWindow = hwnd;
-    }
-    
-    if (!strcasecmp(className, "SCROLLBAR"))
-    {
-	SCROLLBAR_CreateScrollBar(className, windowName, hwnd);
-	goto WinCreated;
-    }
-    if (!strcasecmp(className, "LISTBOX"))
-    {
-	LISTBOX_CreateListBox(className, windowName, hwnd);
-	goto WinCreated;
-    }
+    WIN_LinkWindow( hwnd, HWND_TOP );
+
     if (!strcasecmp(className, "COMBOBOX"))
     {
-	COMBOBOX_CreateComboBox(className, windowName, hwnd);
-	goto WinCreated;
+	height = 16;
     }
-      /* Create the widgets */
+
+#ifdef USE_XLIB
+    {
+	XSetWindowAttributes win_attr;
+	Window parentWindow;
+	int x_rel, y_rel;
+	
+	win_attr.event_mask = ExposureMask | KeyPressMask | KeyReleaseMask |
+	                      PointerMotionMask | ButtonPressMask |
+			      ButtonReleaseMask | StructureNotifyMask |
+			      FocusChangeMask | EnterWindowMask;
+	win_attr.override_redirect = /*True*/ False;
+	win_attr.colormap = COLOR_WinColormap;
+	if (style & WS_CHILD)
+	{
+	    parentWindow = parentPtr->window;
+	    x_rel = x + parentPtr->rectClient.left-parentPtr->rectWindow.left;
+	    y_rel = y + parentPtr->rectClient.top-parentPtr->rectWindow.top;
+	}
+	else
+	{
+	    parentWindow = DefaultRootWindow( XT_display );
+	    x_rel = x;
+	    y_rel = y;
+	}
+	wndPtr->window = XCreateWindow( XT_display, parentWindow,
+				        x_rel, y_rel, width, height, 0,
+				        CopyFromParent, InputOutput,
+				        CopyFromParent,
+				        CWEventMask | CWOverrideRedirect |
+				        CWColormap, &win_attr );
+	XStoreName( XT_display, wndPtr->window, windowName );
+    }
+#else
+    /* Create the widgets */
 
     if (style & WS_CHILD)
     {
@@ -223,6 +317,7 @@
 						    XtNwidth, width,
 						    XtNheight, height,
 						    XtNborderColor, borderCol,
+						    XtNmappedWhenManaged, FALSE,
 						    NULL );
 	}
 	else
@@ -235,6 +330,7 @@
 						    XtNwidth, width,
 						    XtNheight, height,
 						    XtNborderWidth, 0,
+						    XtNmappedWhenManaged, FALSE,
 						    NULL );
 	}
     }
@@ -247,6 +343,7 @@
 						 XtNx, x,
 						 XtNy, y,
 						 XtNcolormap, COLOR_WinColormap,
+						 XtNmappedWhenManaged, FALSE,
 						 NULL );
 	wndPtr->compositeWidget = XtVaCreateManagedWidget(className,
 						    formWidgetClass,
@@ -296,8 +393,24 @@
 					NULL );
 	}
     }
+    if (wndPtr->shellWidget) XtRealizeWidget( wndPtr->shellWidget );
+    if (wndPtr->compositeWidget) XtRealizeWidget( wndPtr->compositeWidget );
+    XtRealizeWidget( wndPtr->winWidget );
+    wndPtr->window = XtWindow( wndPtr->winWidget );
+#endif  /* USE_XLIB */
 
-WinCreated:
+    if ((style & WS_VSCROLL) == WS_VSCROLL) {
+    	newheight = height - (((style & WS_HSCROLL) == WS_HSCROLL) ? 16 : 0);
+	wndPtr->hWndVScroll = CreateWindow("SCROLLBAR", "",
+		WS_CHILD | WS_CLIPSIBLINGS | WS_VISIBLE | SBS_VERT,
+		width - 16, 0, 16, newheight, hwnd, 2, instance, 0L);
+	}
+    if ((style & WS_HSCROLL) == WS_HSCROLL) {
+    	newwidth = width - (((style & WS_VSCROLL) == WS_VSCROLL) ? 16 : 0);
+	wndPtr->hWndHScroll = CreateWindow("SCROLLBAR", "",
+		WS_CHILD | WS_CLIPSIBLINGS | WS_VISIBLE | SBS_HORZ,
+		0, height - 16, newwidth, 16, hwnd, 3, instance, 0L);
+	}
 
       /* Send the WM_CREATE message */
 	
@@ -318,7 +431,24 @@
 
     wmcreate = SendMessage( hwnd, WM_NCCREATE, 0, (LONG)createStruct );
     if (!wmcreate) wmcreate = -1;
-    else wmcreate = SendMessage( hwnd, WM_CREATE, 0, (LONG)createStruct );
+    else
+    {
+	  /* Send WM_NCCALCSIZE message */
+	NCCALCSIZE_PARAMS *params;
+	HANDLE hparams;
+	hparams = GlobalAlloc( GMEM_MOVEABLE, sizeof(*params) );
+	if (hparams)
+	{
+	    params = (NCCALCSIZE_PARAMS *) GlobalLock( hparams );
+	    params->rgrc[0] = wndPtr->rectWindow;
+	    params->lppos = NULL;
+	    SendMessage( hwnd, WM_NCCALCSIZE, FALSE, (LONG)params );
+	    wndPtr->rectClient = params->rgrc[0];
+	    GlobalUnlock( hparams );
+	    GlobalFree( hparams );
+	}	
+	wmcreate = SendMessage( hwnd, WM_CREATE, 0, (LONG)createStruct );
+    }
 
     GlobalUnlock( hcreateStruct );
     GlobalFree( hcreateStruct );
@@ -329,18 +459,27 @@
 
 	if (parent) parentPtr->hwndChild = wndPtr->hwndNext;
 	else firstWindow = wndPtr->hwndNext;
+#ifdef USE_XLIB
+	XDestroyWindow( XT_display, wndPtr->window );
+#else	
 	if (wndPtr->shellWidget) XtDestroyWidget( wndPtr->shellWidget );
 	else XtDestroyWidget( wndPtr->winWidget );
-	if (wndPtr->hdc) DeleteDC( wndPtr->hdc );
+#endif
+	if (wndPtr->flags & WIN_OWN_DC) DCE_FreeDCE( wndPtr->hdce );
 	classPtr->cWindows--;
 	USER_HEAP_FREE( hwnd );
 	return 0;
     }
-    
-    EVENT_AddHandlers( wndPtr->winWidget, hwnd );
 
-    if (style & WS_VISIBLE) ShowWindow( hwnd, SW_SHOW );
+#ifdef USE_XLIB    
+    EVENT_AddHandlers( wndPtr->window, hwnd );
+#else
+    EVENT_AddHandlers( wndPtr->winWidget, hwnd );
+#endif
+
     WIN_SendParentNotify( hwnd, wndPtr, WM_CREATE );
+    
+    if (style & WS_VISIBLE) ShowWindow( hwnd, SW_SHOW );
     return hwnd;
 }
 
@@ -350,7 +489,6 @@
 BOOL DestroyWindow( HWND hwnd )
 {
     WND * wndPtr;
-    HWND * curWndPtr;
     CLASS * classPtr;
     
       /* Initialisation */
@@ -366,30 +504,24 @@
     
       /* Destroy all children */
 
+    if (wndPtr->hWndVScroll) DestroyWindow(wndPtr->hWndVScroll);
+    if (wndPtr->hWndHScroll) DestroyWindow(wndPtr->hWndHScroll);
     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;
+    WIN_UnlinkWindow( hwnd );
 
       /* Destroy the window */
 
+#ifdef USE_XLIB
+    XDestroyWindow( XT_display, wndPtr->window );
+#else
     if (wndPtr->shellWidget) XtDestroyWidget( wndPtr->shellWidget );
     else XtDestroyWidget( wndPtr->winWidget );
-    if (wndPtr->hdc) DeleteDC( wndPtr->hdc );
+#endif
+    if (wndPtr->flags & WIN_OWN_DC) DCE_FreeDCE( wndPtr->hdce );
     classPtr->cWindows--;
     USER_HEAP_FREE( hwnd );
     return TRUE;
@@ -397,100 +529,6 @@
 
 
 /***********************************************************************
- *           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 ) 
-{
-    int width, height;
-    WND * wndPtr = WIN_FindWndPtr( hwnd );
-
-    rect->left = rect->top = rect->right = rect->bottom = 0;
-    if (wndPtr) 
-    {
-	XtVaGetValues(wndPtr->winWidget,
-		      XtNwidth, &width,
-		      XtNheight, &height,
-		      NULL );
-	rect->right  = width & 0xffff;
-	rect->bottom = height & 0xffff;
-    }
-}
-
-
-/***********************************************************************
- *           ShowWindow   (USER.42)
- */
-BOOL ShowWindow( HWND hwnd, int cmd ) 
-{    
-    int width, height;
-    
-    WND * wndPtr = WIN_FindWndPtr( hwnd );
-    if (wndPtr) 
-    {
-	if (wndPtr->shellWidget) XtRealizeWidget( wndPtr->shellWidget );
-	XtVaGetValues(wndPtr->winWidget, 
-		      XtNwidth, &width,
-		      XtNheight, &height,
-		      NULL );
-	switch(cmd)
-	    {
-	    case SW_HIDE:
-		XtSetMappedWhenManaged(wndPtr->winWidget, FALSE);
-	    	wndPtr->dwStyle &= (WS_VISIBLE ^ 0xFFFFFFFL);
-		SendMessage( hwnd, WM_SHOWWINDOW, FALSE, 0 );
-		break;
-	    case SW_SHOWMINNOACTIVE:
-	    case SW_SHOWMINIMIZED:
-	    case SW_MINIMIZE:
-	    	wndPtr->dwStyle |= WS_ICONIC;
-	    	goto WINVisible;
-	    case SW_SHOWNA:
-	    case SW_SHOWNOACTIVATE:
-	    case SW_MAXIMIZE:
-	    case SW_SHOWMAXIMIZED:
-	    case SW_SHOW:
-	    case SW_NORMAL:
-	    case SW_SHOWNORMAL:
-	    	wndPtr->dwStyle &= (WS_ICONIC ^ 0xFFFFFFFL);
-WINVisible:
-		XtSetMappedWhenManaged(wndPtr->winWidget, TRUE);
-	    	wndPtr->dwStyle |= WS_VISIBLE;
-		SendMessage( hwnd, WM_SIZE, SIZE_RESTORED, 
-			(width & 0xffff) | (height << 16) );
-		SendMessage( hwnd, WM_SHOWWINDOW, TRUE, 0 );
-		break;
-	    default:
-		break;
-	    }
-    }
-    return TRUE;
-}
-
-
-/***********************************************************************
  *           CloseWindow   (USER.43)
  */
 void CloseWindow(HWND hWnd)
@@ -498,7 +536,6 @@
     WND * wndPtr = WIN_FindWndPtr(hWnd);
     if (wndPtr->dwStyle & WS_CHILD) return;
     ShowWindow(hWnd, SW_MINIMIZE);
-    PostMessage(hWnd, WM_CLOSE, 0, 0L);
 }
 
  
@@ -508,7 +545,6 @@
  */
 BOOL OpenIcon(HWND hWnd)
 {
-    WND * wndPtr = WIN_FindWndPtr(hWnd);
     if (!IsIconic(hWnd)) return FALSE;
     ShowWindow(hWnd, SW_SHOWNORMAL);
     return(TRUE);
@@ -523,35 +559,9 @@
 {
     return((HWND)NULL);
 }
-
  
  
 /***********************************************************************
- *           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 )
@@ -578,8 +588,10 @@
  */
 BOOL SetMenu(HWND hwnd, HMENU hmenu)
 {
+#ifdef USE_XLIB
+    return FALSE;
+#else
     WND *wndPtr;
-    
     wndPtr = WIN_FindWndPtr(hwnd);
     if (wndPtr == NULL)
 	return FALSE;
@@ -618,44 +630,7 @@
     }
 
     return TRUE;
-}
-
-
-/***********************************************************************
- *           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) != SWP_NOMOVE) {
-	    wndPtr->rectClient.left   = x;
-	    wndPtr->rectClient.top    = y;
-	    XtVaSetValues(wndPtr->winWidget, XtNx, x, XtNy, y, NULL );
-	    }
-	if ((wFlag & SWP_NOSIZE) != SWP_NOSIZE) {
-	    wndPtr->rectClient.right  = x + w;
-	    wndPtr->rectClient.bottom = y + h;
-	    XtVaSetValues(wndPtr->winWidget, XtNwidth, w, XtNheight, h, NULL );
-	    }
-	if ((wFlag & SWP_NOREDRAW) != SWP_NOREDRAW) {
-	    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) != SWP_NOACTIVATE) 
-	    SetActiveWindow(hWnd);
-	if ((wFlag & SWP_NOZORDER) != SWP_NOZORDER) 
-	    { }
-*/
-	printf("SetWindowPos(%X, %X, %d, %d, %d, %d, %X); !\n", 
-		hWnd, hWndInsertAfter, x, y, w, h, wFlag);
-    }
+#endif  /* USE_XLIB */
 }
 
 
@@ -748,21 +723,6 @@
 }
 
 
-/***********************************************************************
- *           IsIconic   (USER.31)
- */
-BOOL IsIconic(HWND hWnd)
-{
-    WND * wndPtr; 
-    if (hWnd == 0) return(FALSE);
-    wndPtr = WIN_FindWndPtr(hWnd);
-    if (wndPtr == 0) return(FALSE);
-    if (wndPtr->dwStyle & WS_ICONIC) return(TRUE);
-    return(FALSE);
-}
-
- 
- 
 /*******************************************************************
  *         GetWindowText          (USER.36)
  */
@@ -796,7 +756,7 @@
 BOOL IsWindow( HWND hwnd )
 {
     WND * wndPtr = WIN_FindWndPtr( hwnd );
-    return (wndPtr->dwMagic == WND_MAGIC);
+    return ((wndPtr != NULL) && (wndPtr->dwMagic == WND_MAGIC));
 }
 
 
@@ -806,6 +766,7 @@
 HWND GetParent(HWND hwnd)
 {
     WND *wndPtr = WIN_FindWndPtr(hwnd);
+    if (!wndPtr) return 0;
     return wndPtr->hwndParent;
 }
 
@@ -838,14 +799,9 @@
  */
 BOOL IsWindowVisible(HWND hWnd)
 {
-    WND * wndPtr; 
-    if (hWnd == 0) return(FALSE);
-    wndPtr = WIN_FindWndPtr(hWnd);
+    WND * wndPtr = WIN_FindWndPtr(hWnd);
     if (wndPtr == 0) return(FALSE);
-    if (wndPtr->dwStyle & WS_VISIBLE) {
-	if (XtIsRealized(wndPtr->winWidget))  return(TRUE);
-    	}
-    return(FALSE);
+    else return ((wndPtr->dwStyle & WS_VISIBLE) != 0);
 }
 
  
diff --git a/windows/winpos.c b/windows/winpos.c
new file mode 100644
index 0000000..0b474e2
--- /dev/null
+++ b/windows/winpos.c
@@ -0,0 +1,389 @@
+/*
+ * Window position related functions.
+ *
+ * Copyright 1993 Alexandre Julliard
+ */
+
+static char Copyright[] = "Copyright  Alexandre Julliard, 1993";
+
+#include "win.h"
+
+extern Display * XT_display;
+extern Screen * XT_screen;
+
+
+/***********************************************************************
+ *           GetWindowRect   (USER.32)
+ */
+void GetWindowRect( HWND hwnd, LPRECT rect ) 
+{
+    WND * wndPtr = WIN_FindWndPtr( hwnd ); 
+    if (!wndPtr) return;
+    
+    *rect = wndPtr->rectWindow;
+    if (wndPtr->hwndParent)
+	MapWindowPoints( wndPtr->hwndParent, 0, (POINT *)rect, 2 );
+}
+
+
+/***********************************************************************
+ *           GetClientRect   (USER.33)
+ */
+void GetClientRect( HWND hwnd, LPRECT rect ) 
+{
+    WND * wndPtr = WIN_FindWndPtr( hwnd );
+
+    rect->left = rect->top = rect->right = rect->bottom = 0;
+    if (wndPtr) 
+    {
+	rect->right  = wndPtr->rectClient.right - wndPtr->rectClient.left;
+	rect->bottom = wndPtr->rectClient.bottom - wndPtr->rectClient.top;
+    }
+}
+
+
+/*******************************************************************
+ *         ClientToScreen   (USER.28)
+ */
+void ClientToScreen( HWND hwnd, LPPOINT lppnt )
+{
+    MapWindowPoints( hwnd, 0, lppnt, 1 );
+}
+
+
+/*******************************************************************
+ *         ScreenToClient   (USER.29)
+ */
+void ScreenToClient( HWND hwnd, LPPOINT lppnt )
+{
+    MapWindowPoints( 0, hwnd, lppnt, 1 );
+}
+
+
+/*******************************************************************
+ *         MapWindowPoints   (USER.258)
+ */
+void MapWindowPoints( HWND hwndFrom, HWND hwndTo, LPPOINT lppt, WORD count )
+{
+    WND * wndPtr;
+    POINT * curpt;
+    POINT origin = { 0, 0 };
+    WORD i;
+
+      /* Translate source window origin to screen coords */
+    while(hwndFrom)
+    {
+	wndPtr = WIN_FindWndPtr( hwndFrom );
+	origin.x += wndPtr->rectClient.left;
+	origin.y += wndPtr->rectClient.top;
+	hwndFrom = wndPtr->hwndParent;
+    }
+
+      /* Translate origin to destination window coords */
+    while(hwndTo)
+    {
+	wndPtr = WIN_FindWndPtr( hwndTo );
+	origin.x -= wndPtr->rectClient.left;
+	origin.y -= wndPtr->rectClient.top;
+	hwndTo = wndPtr->hwndParent;
+    }    
+
+      /* Translate points */
+    for (i = 0, curpt = lppt; i < count; i++, curpt++)
+    {
+	curpt->x += origin.x;
+	curpt->y += origin.y;
+    }
+}
+
+
+/***********************************************************************
+ *           IsIconic   (USER.31)
+ */
+BOOL IsIconic(HWND hWnd)
+{
+    WND * wndPtr = WIN_FindWndPtr(hWnd);
+    if (wndPtr == NULL) return FALSE;
+    return (wndPtr->dwStyle & WS_MINIMIZE) != 0;
+}
+ 
+ 
+/***********************************************************************
+ *           IsZoomed   (USER.272)
+ */
+BOOL IsZoomed(HWND hWnd)
+{
+    WND * wndPtr = WIN_FindWndPtr(hWnd);
+    if (wndPtr == NULL) return FALSE;
+    return (wndPtr->dwStyle & WS_MAXIMIZE) != 0;
+}
+
+
+/***********************************************************************
+ *           MoveWindow   (USER.56)
+ */
+BOOL MoveWindow( HWND hwnd, short x, short y, short cx, short cy, BOOL repaint)
+{    
+    int flags = SWP_NOZORDER | SWP_NOACTIVATE;
+    if (!repaint) flags |= SWP_NOREDRAW;
+#ifdef DEBUG_WIN    
+    printf( "MoveWindow: %d %d,%d %dx%d %d\n", hwnd, x, y, cx, cy, repaint );
+#endif
+    return SetWindowPos( hwnd, 0, x, y, cx, cy, flags );
+}
+
+
+/***********************************************************************
+ *           ShowWindow   (USER.42)
+ */
+BOOL ShowWindow( HWND hwnd, int cmd ) 
+{    
+    WND * wndPtr = WIN_FindWndPtr( hwnd );
+    BOOL wasVisible;
+    int swpflags = 0;
+
+#ifdef DEBUG_WIN
+    printf("ShowWindow: hwnd=%d, cmd=%d\n", hwnd, cmd);
+#endif
+    
+    if (!wndPtr) return FALSE;
+    wasVisible = (wndPtr->dwStyle & WS_VISIBLE) != 0;
+    switch(cmd)
+    {
+        case SW_HIDE:
+	    if (!wasVisible) return FALSE;  /* Nothing to do */
+	    swpflags |= SWP_HIDEWINDOW | SWP_NOSIZE | SWP_NOMOVE | 
+		        SWP_NOACTIVATE | SWP_NOZORDER;
+	    break;
+
+	case SW_SHOWMINNOACTIVE:
+	case SW_SHOWMINIMIZED:
+	case SW_MINIMIZE:
+	    wndPtr->dwStyle |= WS_MINIMIZE;
+	    swpflags |= SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE | 
+		        SWP_NOACTIVATE | SWP_NOZORDER;
+	    break;
+
+	case SW_SHOWNA:
+	case SW_SHOWNOACTIVATE:
+	case SW_MAXIMIZE:
+	case SW_SHOWMAXIMIZED:
+	case SW_SHOW:
+	case SW_NORMAL:
+	case SW_SHOWNORMAL:
+	    wndPtr->dwStyle &= ~WS_MINIMIZE;
+	    swpflags |= SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE | 
+		        SWP_NOACTIVATE | SWP_NOZORDER;
+	    break;
+    }
+    SendMessage( hwnd, WM_SHOWWINDOW, (cmd != SW_HIDE), 0 );
+    SetWindowPos( hwnd, 0, 0, 0, 0, 0, swpflags );
+
+      /* Send WM_SIZE and WM_MOVE messages if not already done */
+    if (!(wndPtr->flags & WIN_GOT_SIZEMSG))
+    {
+	int wParam = SIZE_RESTORED;
+	if (wndPtr->dwStyle & WS_MAXIMIZE) wParam = SIZE_MAXIMIZED;
+	else if (wndPtr->dwStyle & WS_MINIMIZE) wParam = SIZE_MINIMIZED;
+	wndPtr->flags |= WIN_GOT_SIZEMSG;
+	SendMessage( hwnd, WM_SIZE, wParam,
+		     MAKELONG(wndPtr->rectClient.right-wndPtr->rectClient.left,
+			    wndPtr->rectClient.bottom-wndPtr->rectClient.top));
+	SendMessage( hwnd, WM_MOVE, 0,
+		   MAKELONG(wndPtr->rectClient.left, wndPtr->rectClient.top) );
+    }
+    return wasVisible;
+}
+
+
+/***********************************************************************
+ *           SetWindowPos   (USER.232)
+ */
+/* Unimplemented flags: SWP_NOREDRAW, SWP_NOACTIVATE
+ */
+/* Note: all this code should be in the DeferWindowPos() routines,
+ * and SetWindowPos() should simply call them.  This will be implemented
+ * some day...
+ */
+BOOL SetWindowPos( HWND hwnd, HWND hwndInsertAfter, short x, short y,
+		   short cx, short cy, WORD flags )
+{
+    WINDOWPOS *winPos;
+    HANDLE hmem = 0;
+    RECT newWindowRect, newClientRect;
+    WND *wndPtr;
+    int calcsize_result = 0;
+#ifdef USE_XLIB
+    XWindowChanges winChanges;
+    int changeMask = 0;
+#endif
+
+#ifdef DEBUG_WIN
+    printf( "SetWindowPos: %d %d %d,%d %dx%d 0x%x\n",
+	    hwnd, hwndInsertAfter, x, y, cx, cy, flags );
+#endif
+
+    if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
+    if (flags & (SWP_SHOWWINDOW | SWP_HIDEWINDOW))
+	flags |= SWP_NOMOVE | SWP_NOSIZE;
+
+      /* Send WM_WINDOWPOSCHANGING message */
+
+    if (!(hmem = GlobalAlloc( GMEM_MOVEABLE,sizeof(WINDOWPOS) ))) return FALSE;
+    winPos = (WINDOWPOS *)GlobalLock( hmem );
+    winPos->hwnd = hwnd;
+    winPos->hwndInsertAfter = hwndInsertAfter;
+    winPos->x = x;
+    winPos->y = y;
+    winPos->cx = cx;
+    winPos->cy = cy;
+    winPos->flags = flags;
+    SendMessage( hwnd, WM_WINDOWPOSCHANGING, 0, (LONG)winPos );
+
+      /* Calculate new position and size */
+
+    newWindowRect = wndPtr->rectWindow;
+    newClientRect = wndPtr->rectClient;
+
+    if (!(winPos->flags & SWP_NOSIZE))
+    {
+	newWindowRect.right  = newWindowRect.left + winPos->cx;
+	newWindowRect.bottom = newWindowRect.top + winPos->cy;
+    }
+
+    if (!(winPos->flags & SWP_NOMOVE))
+    {
+	newWindowRect.left    = winPos->x;
+	newWindowRect.top     = winPos->y;
+	newWindowRect.right  += winPos->x - wndPtr->rectWindow.left;
+	newWindowRect.bottom += winPos->y - wndPtr->rectWindow.top;
+    }
+
+      /* Reposition window in Z order */
+
+    if (!(winPos->flags & SWP_NOZORDER))
+    {
+	hwndInsertAfter = winPos->hwndInsertAfter;
+
+	  /* TOPMOST not supported yet */
+	if ((hwndInsertAfter == HWND_TOPMOST) ||
+	    (hwndInsertAfter == HWND_NOTOPMOST)) hwndInsertAfter = HWND_TOP;
+
+	  /* Make sure hwndInsertAfter is a sibling of hwnd */
+	if ((hwndInsertAfter != HWND_TOP) && (hwndInsertAfter != HWND_BOTTOM))
+	    if (wndPtr->hwndParent != GetParent(hwndInsertAfter)) goto Abort;
+
+	WIN_UnlinkWindow( hwnd );
+	WIN_LinkWindow( hwnd, hwndInsertAfter );
+    }
+
+      /* Recalculate client area position */
+
+    if (winPos->flags & SWP_FRAMECHANGED)
+    {
+	  /* Send WM_NCCALCSIZE message */
+	NCCALCSIZE_PARAMS *params;
+	HANDLE hparams;
+	
+	if (!(hparams = GlobalAlloc( GMEM_MOVEABLE, sizeof(*params) )))
+	    goto Abort;
+	params = (NCCALCSIZE_PARAMS *) GlobalLock( hparams );
+	params->rgrc[0] = newWindowRect;
+	params->rgrc[1] = wndPtr->rectWindow;
+	params->rgrc[2] = wndPtr->rectClient;
+	params->lppos = winPos;
+	calcsize_result = SendMessage(hwnd, WM_NCCALCSIZE, TRUE, (LONG)params);
+	GlobalUnlock( hparams );
+	GlobalFree( hparams );
+	newClientRect = params->rgrc[0];
+	/* Handle result here */
+    }
+    else
+    {
+	newClientRect.left   = newWindowRect.left + wndPtr->rectClient.left
+	                       - wndPtr->rectWindow.left;
+	newClientRect.top    = newWindowRect.top + wndPtr->rectClient.top
+	                       - wndPtr->rectWindow.top;
+	newClientRect.right  = newWindowRect.right + wndPtr->rectClient.right
+	                       - wndPtr->rectWindow.right;
+	newClientRect.bottom = newWindowRect.bottom + wndPtr->rectClient.bottom
+	                       - wndPtr->rectWindow.bottom;
+    }
+    
+      /* Perform the moving and resizing */
+#ifdef USE_XLIB
+    if (!(winPos->flags & SWP_NOMOVE))
+    {
+	WND * parentPtr;
+	winChanges.x = newWindowRect.left;
+	winChanges.y = newWindowRect.top;
+	if (wndPtr->hwndParent)
+	{
+	    parentPtr = WIN_FindWndPtr(wndPtr->hwndParent);
+	    winChanges.x += parentPtr->rectClient.left-parentPtr->rectWindow.left;
+	    winChanges.y += parentPtr->rectClient.top-parentPtr->rectWindow.top;
+	}
+	changeMask |= CWX | CWY;
+    }
+    if (!(winPos->flags & SWP_NOSIZE))
+    {
+	winChanges.width  = newWindowRect.right - newWindowRect.left;
+	winChanges.height = newWindowRect.bottom - newWindowRect.top;
+	changeMask |= CWWidth | CWHeight;
+    }
+    if (!(winPos->flags & SWP_NOZORDER))
+    {
+	if (hwndInsertAfter == HWND_TOP) winChanges.stack_mode = Above;
+	else winChanges.stack_mode = Below;
+	if ((hwndInsertAfter != HWND_TOP) && (hwndInsertAfter != HWND_BOTTOM))
+	{
+	    WND * insertPtr = WIN_FindWndPtr( hwndInsertAfter );
+	    winChanges.sibling = insertPtr->window;
+	    changeMask |= CWSibling;
+	}
+	changeMask |= CWStackMode;
+    }
+    if (changeMask) XConfigureWindow( XT_display, wndPtr->window,
+				      changeMask, &winChanges );
+#endif
+
+    if (winPos->flags & SWP_SHOWWINDOW)
+    {
+	wndPtr->dwStyle |= WS_VISIBLE;
+#ifdef USE_XLIB
+	XMapWindow( XT_display, wndPtr->window );
+#else		
+	if (wndPtr->shellWidget) XtMapWidget( wndPtr->shellWidget );
+	else XtMapWidget( wndPtr->winWidget );
+#endif
+    }
+    else if (winPos->flags & SWP_HIDEWINDOW)
+    {
+	wndPtr->dwStyle &= ~WS_VISIBLE;
+#ifdef USE_XLIB
+	XUnmapWindow( XT_display, wndPtr->window );
+#else		
+	if (wndPtr->shellWidget) XtUnmapWidget( wndPtr->shellWidget );
+	else XtUnmapWidget( wndPtr->winWidget );
+#endif	
+    }
+
+      /* Finally send the WM_WINDOWPOSCHANGED message */
+    wndPtr->rectWindow = newWindowRect;
+    wndPtr->rectClient = newClientRect;
+    SendMessage( hwnd, WM_WINDOWPOSCHANGED, 0, (LONG)winPos );
+    GlobalUnlock( hmem );
+    GlobalFree( hmem );
+
+    return TRUE;
+
+ Abort:  /* Fatal error encountered */
+    if (hmem)
+    {
+	GlobalUnlock( hmem );
+	GlobalFree( hmem );
+    }
+    return FALSE;
+}
+
+