Release 0.2.0

Tue Jul 13 20:31:31 1993  Bob Amstadt  (bob at pooh)

	* [global.c]
	Completed global memory pool API

Sun Jul 11 16:59:52 1993  Alexandre Julliard

	* [message.c] [user.c] [user.spec] [windows.h]
	Added emulation of Windows message queue.

Thu Jul  8 19:29:27 1993  Bob Amstadt  (bob at pooh)

	* [build.c] Original by Bob Amstadt
	* [callback.c] Original by Bob Amstadt, updates by 
	Alexandre Julliard
	* [dump.c] Original by Bob Amstadt
	* [global.c] Original by Bob Amstadt
	* [heap.c] Original by Bob Amstadt
	* [kernel.c] Original by Bob Amstadt
	* [ldt.c] Original by Bob Amstadt
	* [ldtlib.c] Original by Bob Amstadt
	* [relay.c] Original by Bob Amstadt
	* [resource.c] Original by Bob Amstadt, updates by 
	Alexandre Juliard
	* [selector.c] Original by Bob Amstadt, updates by Eric Youngdale
	* [user.c] Original by Bob Amstadt
	* [wine.c] Original by Bob Amstadt, updates by Eric Youngdale and
	Alexandre Julliard
	* [wintcl.c] Original by Regents of the University of California,
	updates by Peter MacDonald and Alexandre Julliard
	* [callback.h] Original by Bob Amstadt
	* [dlls.h] Original by Bob Amstadt
	* [heap.h] Original by Bob Amstadt
	* [neexe.h] Original by Bob Amstadt
	* [prototypes.h] Original by Bob Amstadt, updates by 
	Eric Youngdale
	* [segmem.h] Original by Bob Amstadt
	* [tkInt.h] Original by Regents of the University of California
	* [windows.h] Original by Peter MacDonald, updates by 
	Alexandre Julliard and Bob Amstadt
	* [wine.h] Original by Eric Youngdale
	* [kernel.spec] Original by Bob Amstadt, updates by 
	Alexandre Julliard
	* [gdi.spec] Original by Bob Amstadt, updates by 
	Alexandre Julliard
	* [shell.spec] Original by Bob Amstadt
	* [unixlib.spec] Original by Bob Amstadt
	* [user.spec] Original by Bob Amstadt, updates by Alexandre Julliard
	* [win87em.spec] Original by Bob Amstadt
	* [Windows.tcl] Original by Peter MacDonald, updates by 
	Alexandre Julliard
	* [build-spec.txt] Original by Bob Amstadt
	* [if1632.S] Original by Bob Amstadt, updates by Eric Youngdale
diff --git a/ChangeLog b/ChangeLog
new file mode 100644
index 0000000..8407996
--- /dev/null
+++ b/ChangeLog
@@ -0,0 +1,53 @@
+Tue Jul 13 20:31:31 1993  Bob Amstadt  (bob at pooh)
+
+	* [global.c]
+	Completed global memory pool API
+
+Sun Jul 11 16:59:52 1993  Alexandre Julliard
+
+	* [message.c] [user.c] [user.spec] [windows.h]
+	Added emulation of Windows message queue.
+
+Thu Jul  8 19:29:27 1993  Bob Amstadt  (bob at pooh)
+
+	* [build.c] Original by Bob Amstadt
+	* [callback.c] Original by Bob Amstadt, updates by 
+	Alexandre Julliard
+	* [dump.c] Original by Bob Amstadt
+	* [global.c] Original by Bob Amstadt
+	* [heap.c] Original by Bob Amstadt
+	* [kernel.c] Original by Bob Amstadt
+	* [ldt.c] Original by Bob Amstadt
+	* [ldtlib.c] Original by Bob Amstadt
+	* [relay.c] Original by Bob Amstadt
+	* [resource.c] Original by Bob Amstadt, updates by 
+	Alexandre Juliard
+	* [selector.c] Original by Bob Amstadt, updates by Eric Youngdale
+	* [user.c] Original by Bob Amstadt
+	* [wine.c] Original by Bob Amstadt, updates by Eric Youngdale and
+	Alexandre Julliard
+	* [wintcl.c] Original by Regents of the University of California,
+	updates by Peter MacDonald and Alexandre Julliard
+	* [callback.h] Original by Bob Amstadt
+	* [dlls.h] Original by Bob Amstadt
+	* [heap.h] Original by Bob Amstadt
+	* [neexe.h] Original by Bob Amstadt
+	* [prototypes.h] Original by Bob Amstadt, updates by 
+	Eric Youngdale
+	* [segmem.h] Original by Bob Amstadt
+	* [tkInt.h] Original by Regents of the University of California
+	* [windows.h] Original by Peter MacDonald, updates by 
+	Alexandre Julliard and Bob Amstadt
+	* [wine.h] Original by Eric Youngdale
+	* [kernel.spec] Original by Bob Amstadt, updates by 
+	Alexandre Julliard
+	* [gdi.spec] Original by Bob Amstadt, updates by 
+	Alexandre Julliard
+	* [shell.spec] Original by Bob Amstadt
+	* [unixlib.spec] Original by Bob Amstadt
+	* [user.spec] Original by Bob Amstadt, updates by Alexandre Julliard
+	* [win87em.spec] Original by Bob Amstadt
+	* [Windows.tcl] Original by Peter MacDonald, updates by 
+	Alexandre Julliard
+	* [build-spec.txt] Original by Bob Amstadt
+	* [if1632.S] Original by Bob Amstadt, updates by Eric Youngdale
diff --git a/Makefile b/Makefile
index 43a4683..f386ccd 100644
--- a/Makefile
+++ b/Makefile
@@ -1,4 +1,4 @@
-CFLAGS=-g -DDEBUG_RESOURCE -DDEBUG_HEAP -I./
+CFLAGS=-g -DDEBUG_RESOURCE -I./
 
 ######################################################################
 # FILES:
@@ -19,10 +19,10 @@
 
 OBJS=$(MUST_BE_LINKED_FIRST) \
 	callback.o dump.o global.o heap.o ldt.o kernel.o relay.o resource.o \
-	selector.o user.o wine.o wintcl.o
+	selector.o message.o user.o wine.o class.o win.o widgets.o event.o xt.o
 
 TARGET=wine
-LIBS=-L. -L/usr/X386/lib -L/dasd3/usr/lib -lldt -ltk -ltcl -lX11
+LIBS=-L. -L/usr/X386/lib -lldt -lXt -lX11
 
 all: $(TARGET)
 
diff --git a/README b/README
index 078934f..0a911df 100644
--- a/README
+++ b/README
@@ -2,14 +2,28 @@
 warranty.  It is my intent to cover this code with the Gnu Public
 License.
 
-So here goes release 0.1.0 of the Windows loader.  It will do some 
+So here goes release 0.2.0 of the Windows loader.  It will do some 
 relocations and then run the program.  I have successfully loaded 
 the Windows solitaire game.  Try it.  It currently stops a call to
 GetObject().
 
+WHAT'S NEW with version 0.2.0:
+    - Alexandre Julliard has provided a replacement for the Tcl code.
+      The new code uses Xlib and Xt directly with no intervening
+      interpretted language.  This should reduce the learning
+      curve for casual hackers.
+    - I changed all GLOBAL_ names to Global.
+
+WHAT'S NEW with version 0.1.1:
+    - I have completed global memory allocation, but I don't like it.
+      It is not 100% compatible with Windows.  I need some more kernel
+      modifications for 100% compatibility.
+    - Alexandre Julliard has provided written better emulation for
+      the Windows message queue.
+
 WHAT'S NEW with version 0.1.0:
-    - Integrated patches from Alexandre.
-    - Minor bug fix in if1632.S
+    - Latest patches from Alexandre Julliard.
+    - minor bug fix in if1632.S
 
 WHAT'S NEW with version 0.0.5:
     - Patches from Alexandre Julliard.  Some integration with Tcl.
@@ -59,9 +73,9 @@
 
     - Segment fixup code completion.
     - Trap and handle DOS and DPMI calls.
-    - global memory allocation completion
-    - GlobalAlloc should support ZEROINIT.
     - GlobalAlloc of code segments.
+    - Rewrite global memory support including kernel mods to allow
+      application to mess with page map.
     - complete and improve local heap allocation.
     - Handle self-loading applications.
     - Resource loading
@@ -85,6 +99,11 @@
 		- This is a patch that must be applied to the kernel.
 		  It updates two header files, and the kernel Makefile.
 
+Or follow the same procedure with "ldt512.tar".  This file contains
+Eric Youngdales patches for ALPHA-pl11.  These patches give the
+emulator 512 ldt entries instead of the 32 available with the older
+patch kit.
+
 BUILD:
 
     The documentation for the build program is in the file build-spec.txt
diff --git a/Windows.tcl b/Windows.tcl
deleted file mode 100755
index 0257f1e..0000000
--- a/Windows.tcl
+++ /dev/null
@@ -1,91 +0,0 @@
-# Windows Tcl/Tk emulation scripts
-# Initial implementation by Peter MacDonald pmacdona@sanjuan.uvic.ca
-
-proc CreateWindow { f t x y h w } {
-	global baseframe
-	set baseframe $f
-	wm title . "$t"
-	frame .$f
-	pack append . .$f {top}
-	canvas .$f.canvas1 -scrollregion " $x $y $h $w " -width 15c -height 10c
-	pack append .$f .$f.canvas1 {top}
-}
-
-proc CreateMenuEntry { fn t x } {
-	global baseframe
-	menubutton .$fn -text "$t" -underline $x -menu .$fn.m
-	pack append .$baseframe .$fn left
-	menu .$fn.m
-}
-
-proc CreateMenuBar { f } {
-	global allmenus
-	global baseframe
-	set allmenus ""
-	frame .$f -relief raised -borderwidth 1
-	pack before .$baseframe .$f {top fillx}
-}
-
-proc AppendMenu { a b c d x } {
-	global allmenus
-	global baseframe
-	if { ($b == 0x10) } {
-		.$c configure -text "$d" -underline "$x"
-		pack append .$a .$c left
-		set allmenus "$allmenus $c"
-		tk_menuBar .$a $allmenus
-		tk_bindForTraversal .$baseframe.canvas1
-	} else { if { ($b == 0x0800) } {
-		.$a.m add separator
-	} else {
-		.$a.m add command -label "$d" -command "wincallback menu $a $b $c $d" -underline $x
-	}}
-}
-
-####################################################################
-# Misc unimplemented stuff
-####################################################################
-
-proc LoadIcon { wind name } {
-	echo "LoadIcon"
-}
-
-proc LoadBitmap { wind name } {
-	echo "LoadBitmap"
-}
-
-proc LoadCursor { wind name } {
-	echo "LoadCursor"
-}
-
-proc GetObject { obj count ptr } {
-	echo "GetObject $obj $count $ptr"
-}
-
-proc GetStockObject { wind } {
-	echo "GetStockObject $wind"
-}
-
-proc DefWindowProc { a b c d } {
-	echo "DefWindowProc $a $b $c $d"
-}
-
-proc GetMenu { a } {
-	echo "GetMenu $a"
-}
-
-proc SetMenu { a b } {
-	echo "SetMenu $a $b"
-}
-
-proc MessageBeep {a } {
-	echo "MessageBeep $a"
-}
-
-proc MessageBox { wind msg title type } {
-	echo "MessageBox '$msg'"
-}
-
-proc DrawText { f t top left right bottom } {
-	.$f.canvas1 create text $top $left -text "$t" -anchor n
-}
diff --git a/callback.c b/callback.c
index 0cfb00f..c0d82bd 100644
--- a/callback.c
+++ b/callback.c
@@ -1,6 +1,7 @@
 static char RCSId[] = "$Id: wine.c,v 1.2 1993/07/04 04:04:21 root Exp root $";
 static char Copyright[] = "Copyright  Robert J. Amstadt, 1993";
 
+#include "windows.h"
 #include "callback.h"
 #include "wine.h"
 #include "segmem.h"
@@ -106,3 +107,22 @@
 
     return tp->thunk;
 }
+
+/**********************************************************************
+ *					CallWindowProc    (USER.122)
+ */
+LONG CallWindowProc( FARPROC func, HWND hwnd, WORD message,
+		     WORD wParam, LONG lParam )
+{
+    if ((unsigned int)func & 0xffff0000)
+    {	
+	PushOn16( CALLBACK_SIZE_WORD, hwnd );
+	PushOn16( CALLBACK_SIZE_WORD, message );
+	PushOn16( CALLBACK_SIZE_WORD, wParam );
+	PushOn16( CALLBACK_SIZE_LONG, lParam );
+	return CallTo16((unsigned int) func, 
+			FindDataSegmentForCode((unsigned long) func));   
+    }
+    else
+	return WIDGETS_Call32WndProc( func, hwnd, message, wParam, lParam );
+}
diff --git a/callback.h b/callback.h
index b867e43..ba84573 100644
--- a/callback.h
+++ b/callback.h
@@ -17,13 +17,4 @@
 extern int CallBack16(void *func, int n_args, ...);
 
 
-/*
- * Windows procedure calling:  
- *     f(a, b, c, d)
- *     wndprocfunc(HWND hwnd, WORD message, WORD wParam, LONG lParam)
- */
-#define CALLWNDPROC(f, a, b, c, d) \
-    CallBack16((f), 4, CALLBACK_SIZE_WORD, (a), CALLBACK_SIZE_WORD, (b), \
-	       CALLBACK_SIZE_WORD, (c), CALLBACK_SIZE_LONG, (d))
-
 #endif /* CALLBACK_H */
diff --git a/class.c b/class.c
new file mode 100644
index 0000000..3a7cf2b
--- /dev/null
+++ b/class.c
@@ -0,0 +1,141 @@
+/*
+ * Window classes functions
+ *
+ * Copyright 1993 Alexandre Julliard
+ */
+
+static char Copyright[] = "Copyright  Alexandre Julliard, 1993";
+
+#include "class.h"
+
+
+static HCLASS firstClass = 0;
+
+
+/***********************************************************************
+ *           CLASS_FindClassByName
+ *
+ * Return a handle and a pointer to the class.
+ * The caller must GlobalUnlock the pointer.
+ */
+HCLASS CLASS_FindClassByName( char * name, CLASS **ptr )
+{
+    HCLASS class, next;
+    
+    class = firstClass;
+    while(class)
+    {
+	*ptr = (CLASS *) GlobalLock(class);
+	if (!strcmp( (*ptr)->wc.lpszClassName, name )) return class;
+	next = (*ptr)->hNext;
+	GlobalUnlock(class);
+	class = next;
+    }
+    return 0;
+}
+
+/***********************************************************************
+ *           CLASS_FindClassPtr
+ *
+ * Return a pointer to the CLASS structure corresponding to a HCLASS.
+ * The caller must GlobalUnlock the pointer.
+ */
+CLASS * CLASS_FindClassPtr( HCLASS hclass )
+{
+    CLASS * ptr;
+    
+    if (!hclass) return NULL;
+    ptr = (CLASS *) GlobalLock( hclass );
+    if (ptr->wMagic != CLASS_MAGIC) 
+    {
+	GlobalUnlock( hclass );
+	return NULL;
+    }	
+    return ptr;
+}
+
+
+/***********************************************************************
+ *           RegisterClass    (USER.57)
+ */
+ATOM RegisterClass( LPWNDCLASS class )
+{
+    CLASS * newClass;
+    HCLASS handle;
+    int i;
+    
+#ifdef DEBUG_CLASS
+    printf( "RegisterClass: wndproc=%08x hinst=%d name='%s'\n", 
+	    class->lpfnWndProc, class->hInstance, class->lpszClassName );
+#endif
+
+    handle = GlobalAlloc( GMEM_MOVEABLE, sizeof(CLASS)+class->cbClsExtra );
+    if (!handle) return 0;
+    newClass = (CLASS *) GlobalLock( handle );
+    newClass->hNext      = firstClass;
+    newClass->wMagic     = CLASS_MAGIC;
+    newClass->atomName   = handle;  /* Should be an atom */
+    newClass->hDCE       = 0;  /* Should allocate a DCE if needed */
+    newClass->cWindows   = 0;  
+    newClass->wc         = *class;
+        
+    newClass->wc.lpszMenuName = 0;
+
+      /* 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 (class->cbClsExtra) memset( newClass->wExtra, 0, class->cbClsExtra );
+
+    GlobalUnlock( handle );
+    
+    firstClass = handle;
+    return handle;  /* Should be an atom */
+}
+
+
+/***********************************************************************
+ *           UnregisterClass    (USER.403)
+ */
+BOOL UnregisterClass( LPSTR className, HANDLE instance )
+{
+    HANDLE class, next, prevClass;
+    CLASS * classPtr, * prevClassPtr;
+    
+      /* Check if we can remove this class */
+    class = CLASS_FindClassByName( className, &classPtr );
+    if (!class) return FALSE;
+    if ((classPtr->wc.hInstance != instance) || (classPtr->cWindows > 0))
+    {
+	GlobalUnlock( class );
+	return FALSE;
+    }
+    
+      /* Remove the class from the linked list */
+    if (firstClass == class) firstClass = classPtr->hNext;
+    else
+    {
+	prevClass = firstClass; 
+	while (prevClass)
+	{
+	    prevClassPtr = (CLASS *) GlobalLock(prevClass);
+	    next == prevClassPtr->hNext;
+	    if (next == class) break;
+	    GlobalUnlock(prevClass);
+	    prevClass = next;
+	}
+	if (!prevClass)
+	{
+	    printf( "ERROR: Class list corrupted\n" );
+	    return FALSE;
+	}
+	prevClassPtr->hNext = classPtr->hNext;
+	GlobalUnlock( prevClass );
+    }
+    
+    GlobalUnlock( class );
+    GlobalFree( class );
+    return TRUE;
+}
diff --git a/class.h b/class.h
new file mode 100644
index 0000000..1e7fa2b
--- /dev/null
+++ b/class.h
@@ -0,0 +1,33 @@
+/*
+ * Window classes definitions
+ *
+ * Copyright 1993 Alexandre Julliard
+ */
+
+#ifndef CLASS_H
+#define CLASS_H
+
+#include "windows.h"
+
+#define CLASS_MAGIC   0x4b4e      /* 'NK' */
+
+typedef struct tagCLASS
+{
+    HCLASS       hNext;         /* Next class */
+    WORD         wMagic;        /* Magic number (must be CLASS_MAGIC) */
+    ATOM         atomName;      /* Name of the class */
+    HANDLE       hDCE;          /* Class DC Entry (if CS_CLASSDC) */
+    WORD         cWindows;      /* Count of existing windows of this class */
+    WNDCLASS     wc __attribute__ ((packed));  /* Class information */
+    WORD         wExtra[1];     /* Class extra bytes */
+} CLASS;
+
+
+ /* The caller must GlobalUnlock the pointer returned 
+  * by these functions (except when NULL).
+  */
+HCLASS CLASS_FindClassByName( char * name, CLASS **ptr );
+CLASS * CLASS_FindClassPtr( HCLASS hclass );
+
+
+#endif  /* CLASS_H */
diff --git a/event.c b/event.c
new file mode 100644
index 0000000..6e65f29
--- /dev/null
+++ b/event.c
@@ -0,0 +1,188 @@
+/*
+ * X events handling functions
+ *
+ * Copyright 1993 Alexandre Julliard
+ */
+
+static char Copyright[] = "Copyright  Alexandre Julliard, 1993";
+
+#include <X11/Intrinsic.h>
+#include <X11/StringDefs.h>
+#include <X11/Core.h>
+
+#include "windows.h"
+
+
+#define NB_BUTTONS      3     /* Windows can handle 3 buttons */
+#define DBLCLICK_TIME   300   /* Max. time for a double click (milliseconds) */
+
+
+  /* Event handlers */
+static void EVENT_expose();
+static void EVENT_key();
+static void EVENT_mouse_motion();
+static void EVENT_mouse_button();
+
+
+/***********************************************************************
+ *           EVENT_AddHandlers
+ *
+ * Add the event handlers to the given window
+ */
+void EVENT_AddHandlers( Widget w, int hwnd )
+{
+    XtAddEventHandler(w, ExposureMask, FALSE,
+		      EVENT_expose, (XtPointer)hwnd );
+    XtAddEventHandler(w, KeyPressMask | KeyReleaseMask, FALSE, 
+		      EVENT_key, (XtPointer)hwnd );
+    XtAddEventHandler(w, PointerMotionMask, FALSE,
+		      EVENT_mouse_motion, (XtPointer)hwnd );
+    XtAddEventHandler(w, ButtonPressMask | ButtonReleaseMask, FALSE,
+		      EVENT_mouse_button, (XtPointer)hwnd );
+}
+
+
+/***********************************************************************
+ *           EVENT_RemoveHandlers
+ *
+ * Remove the event handlers of the given window
+ */
+void EVENT_RemoveHandlers( Widget w, int hwnd )
+{
+    XtRemoveEventHandler(w, ExposureMask, FALSE,
+			 EVENT_expose, (XtPointer)hwnd );
+    XtRemoveEventHandler(w, KeyPressMask | KeyReleaseMask, FALSE, 
+			 EVENT_key, (XtPointer)hwnd );
+    XtRemoveEventHandler(w, PointerMotionMask, FALSE,
+			 EVENT_mouse_motion, (XtPointer)hwnd );
+    XtRemoveEventHandler(w, ButtonPressMask | ButtonReleaseMask, FALSE,
+			 EVENT_mouse_button, (XtPointer)hwnd );
+}
+
+
+/***********************************************************************
+ *           EVENT_XStateToKeyState
+ *
+ * Translate a X event state (Button1Mask, ShiftMask, etc...) to
+ * a Windows key state (MK_SHIFT, MK_CONTROL, etc...)
+ */
+static WORD EVENT_XStateToKeyState( int state )
+{
+    int kstate = 0;
+    
+    if (state & Button1Mask) kstate |= MK_LBUTTON;
+    if (state & Button2Mask) kstate |= MK_MBUTTON;
+    if (state & Button3Mask) kstate |= MK_RBUTTON;
+    if (state & ShiftMask)   kstate |= MK_SHIFT;
+    if (state & ControlMask) kstate |= MK_CONTROL;
+    return kstate;
+}
+
+
+/***********************************************************************
+ *           EVENT_expose
+ *
+ * Handle a X expose event
+ */
+static void EVENT_expose( Widget w, int hwnd, XEvent *event,
+			  Boolean *cont_dispatch )
+{
+    MSG msg;
+    XExposeEvent * expEvt = (XExposeEvent *)expEvt;
+    
+    msg.hwnd    = hwnd;
+    msg.message = WM_PAINT;
+    msg.wParam  = 0;
+    msg.lParam  = 0;
+    msg.time = 0;
+    msg.pt.x = 0;
+    msg.pt.y = 0;
+            
+    MSG_AddMsg( &msg, 0 );
+}
+
+
+/***********************************************************************
+ *           EVENT_key
+ *
+ * Handle a X key event
+ */
+static void EVENT_key( Widget w, int hwnd, XKeyEvent *event,
+		       Boolean *cont_dispatch )
+{
+    MSG msg;
+    
+    msg.hwnd    = hwnd;
+    msg.message = (event->type == KeyRelease) ? WM_KEYUP : WM_KEYDOWN;
+    msg.wParam  = 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;
+    
+    MSG_AddMsg( &msg );    
+}
+
+
+/***********************************************************************
+ *           EVENT_mouse_motion
+ *
+ * Handle a X mouse motion event
+ */
+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 );    
+}
+
+
+/***********************************************************************
+ *           EVENT_mouse_button
+ *
+ * Handle a X mouse button event
+ */
+static void EVENT_mouse_button( Widget w, int hwnd, XButtonEvent *event,
+			        Boolean *cont_dispatch )
+{
+    static WORD messages[3][NB_BUTTONS] = 
+    {
+	{ WM_LBUTTONDOWN, WM_MBUTTONDOWN, WM_RBUTTONDOWN },
+	{ WM_LBUTTONUP, WM_MBUTTONUP, WM_RBUTTONUP },
+        { WM_LBUTTONDBLCLK, WM_MBUTTONDBLCLK, WM_RBUTTONDBLCLK }
+    };
+    static unsigned long lastClickTime[NB_BUTTONS] = { 0, 0, 0 };
+        
+    MSG msg;
+    int buttonNum, prevTime, type;
+    
+    buttonNum = event->button-1;
+    if (buttonNum >= NB_BUTTONS) return;
+    if (event->type == ButtonRelease) type = 1;
+    else
+    {  /* Check if double-click */
+	prevTime = lastClickTime[buttonNum];
+	lastClickTime[buttonNum] = event->time;
+	type = (event->time - prevTime < DBLCLICK_TIME) ? 2 : 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;
+
+    MSG_AddMsg( &msg );    
+}
+
diff --git a/global.c b/global.c
index 3ef21ee..0bef480 100644
--- a/global.c
+++ b/global.c
@@ -8,7 +8,9 @@
 #include "segmem.h"
 
 /*
- * Global memory pool descriptor.
+ * Global memory pool descriptor.  Segments MUST be maintained in segment
+ * ascending order.  If not the reallocation routine will die a horrible
+ * death.
  *
  * handle  = 0, this descriptor contains the address of a free pool.
  *        != 0, this describes an allocated block.
@@ -30,15 +32,18 @@
     short sequence;
     void *addr;
     int length;
+    int lock_count;
 } GDESC;
 
 GDESC *GlobalList = NULL;
+static unsigned short next_unused_handle = 1;
+
 
 /**********************************************************************
- *					GLOBAL_GetFreeSegments
+ *					GlobalGetFreeSegments
  */
 GDESC *
-GLOBAL_GetFreeSegments(unsigned int flags, int n_segments)
+GlobalGetFreeSegments(unsigned int flags, int n_segments)
 {
     struct segment_descriptor_s *s;
     GDESC *g;
@@ -100,7 +105,11 @@
 	    g->sequence = -1;
 	    g->addr = s->base_addr;
 	    g->length = s->length;
-
+	    if (!(flags & GLOBAL_FLAGS_MOVEABLE))
+		g->lock_count = 1;
+	    else
+		g->lock_count = 0;
+	    
 	    free(s);
 
 	    if (count == 0)
@@ -130,15 +139,14 @@
 }
 
 /**********************************************************************
- *					GLOBAL_Alloc
+ *					GlobalAlloc
  */
 unsigned int
-GLOBAL_Alloc(unsigned int flags, unsigned long size)
+GlobalAlloc(unsigned int flags, unsigned long size)
 {
     GDESC *g;
     GDESC *g_prev;
     void *m;
-    int i;
 
     /*
      * If this block is fixed or very big we need to allocate entire
@@ -148,7 +156,7 @@
     {
 	int segments = (size >> 16) + 1;
 
-	g = GLOBAL_GetFreeSegments(flags, segments);
+	g = GlobalGetFreeSegments(flags, segments);
 	if (g == NULL)
 	    return 0;
 	else
@@ -176,9 +184,9 @@
 	 * If we couldn't get the memory there, then we need to create
 	 * a new free list.
 	 */
-	if (m == NULL)
+	if (g == NULL)
 	{
-	    g = GLOBAL_GetFreeSegments(0, 1);
+	    g = GlobalGetFreeSegments(0, 1);
 	    if (g == NULL)
 		return 0;
 
@@ -186,52 +194,56 @@
 	    g->sequence = 0;
 	    HEAP_Init((MDESC **) g->addr, (MDESC **) g->addr + 1, 
 		      0x10000 - sizeof(MDESC **));
-	    m = HEAP_Alloc((MDESC **) g->addr, 0, size);
+	    m = HEAP_Alloc((MDESC **) g->addr, flags & GLOBAL_FLAGS_ZEROINIT, 
+			   size);
 	    if (m == NULL)
 		return 0;
 	}
 
 	/*
+	 * Save position of heap descriptor.
+	 */
+	g_prev = g;
+
+	/*
 	 * We have a new block.  Let's create a GDESC entry for it.
 	 */
-	g_prev = NULL;
-	i = 0;
-	for (g = GlobalList; g != NULL; g = g->next, i++)
-	    g_prev = g;
-
 	g = malloc(sizeof(*g));
+#ifdef DEBUG_HEAP
+	printf("New GDESC %08x\n", g);
+#endif
 	if (g == NULL)
 	    return 0;
 
-	g->handle = i << 3;
+	g->handle = next_unused_handle;
 	g->sequence = 0;
 	g->addr = m;
 	g->length = size;
-	g->next = NULL;
+	g->next = g_prev->next;
+	g->lock_count = 0;
 
-	if (g_prev != NULL)
-	{
-	    g_prev->next = g;
-	    g->prev = g_prev;
-	}
-	else
-	{
-	    GlobalList = g;
-	    g->prev = NULL;
-	}
+	g_prev->next = g;
+	g->prev = g_prev;
+
+	next_unused_handle++;
+	if ((next_unused_handle & 7) == 7)
+	    next_unused_handle++;
 	
+#ifdef DEBUG_HEAP
+	printf("GlobalAlloc: returning %04x\n", g->handle);
+#endif
 	return g->handle;
     }
 }
 
 /**********************************************************************
- *					GLOBAL_Free
+ *					GlobalFree
  *
  * Windows programs will pass a handle in the "block" parameter, but
  * this function will also accept a 32-bit address.
  */
 unsigned int
-GLOBAL_Free(unsigned int block)
+GlobalFree(unsigned int block)
 {
     GDESC *g;
 
@@ -264,10 +276,7 @@
     {
 	HEAP_Free((MDESC **) (block & 0xffff0000), (void *) block);
 
-	if (g->prev != NULL)
-	    g->prev->next = g->next;
-	else
-	    GlobalList = g->next;
+	g->prev->next = g->next;
 	
 	if (g->next != NULL)
 	    g->next->prev = g->prev;
@@ -282,8 +291,8 @@
     {
 	int i, limit;
 	
-	g->length;
-	for (i = 0; i < limit; i++)
+	limit = g->length;
+	for (i = g->sequence - 1; i < limit && g != NULL; i++, g = g->next)
 	{
 	    g->sequence = -1;
 	    g->length = 0x10000;
@@ -294,11 +303,11 @@
 }
 
 /**********************************************************************
- *					GLOBAL_Lock
+ *					GlobalLock
  *
  */
 void *
-GLOBAL_Lock(unsigned int block)
+GlobalLock(unsigned int block)
 {
     GDESC *g;
 
@@ -309,8 +318,362 @@
      * Find GDESC for this block.
      */
     for (g = GlobalList; g != NULL; g = g->next)
+    {
 	if (g->handle == block)
+	{
+	    g->lock_count++;
+#ifdef DEBUG_HEAP
+	    printf("GlobalLock: returning %08x\n", g->addr);
+#endif
 	    return g->addr;
+	}
+    }
 
+#ifdef DEBUG_HEAP
+    printf("GlobalLock: returning %08x\n", 0);
+#endif
     return NULL;
 }
+
+/**********************************************************************
+ *					GlobalUnlock
+ *
+ */
+int
+GlobalUnlock(unsigned int block)
+{
+    GDESC *g;
+
+    if (block == 0)
+	return 0;
+
+    /*
+     * Find GDESC for this block.
+     */
+    for (g = GlobalList; g != NULL; g = g->next)
+    {
+	if (g->handle == block && g->lock_count > 0)
+	{
+	    g->lock_count--;
+	    return 0;
+	}
+    }
+
+    return 1;
+}
+
+/**********************************************************************
+ *					GlobalFlags
+ *
+ */
+unsigned int
+GlobalFlags(unsigned int block)
+{
+    GDESC *g;
+
+    if (block == 0)
+	return 0;
+
+    /*
+     * Find GDESC for this block.
+     */
+    for (g = GlobalList; g != NULL; g = g->next)
+    {
+	if (g->handle == block)
+	    return g->lock_count;
+    }
+
+    return 0;
+}
+
+/**********************************************************************
+ *					GlobalSize
+ *
+ */
+unsigned int
+GlobalSize(unsigned int block)
+{
+    GDESC *g;
+
+    if (block == 0)
+	return 0;
+
+    /*
+     * Find GDESC for this block.
+     */
+    for (g = GlobalList; g != NULL; g = g->next)
+    {
+	if (g->handle == block)
+	    return g->length;
+    }
+
+    return 0;
+}
+
+/**********************************************************************
+ *					GlobalHandle
+ *
+ * This routine is not strictly correct.  MS Windows creates a selector
+ * for every locked global block.  We do not.  If the allocation is small
+ * enough, we only give out a little piece of a selector.  Thus this
+ * function cannot be implemented.
+ */
+unsigned int
+GlobalHandle(unsigned int selector)
+{
+    GDESC *g;
+
+    if (selector == 0)
+	return 0;
+
+    /*
+     * Find GDESC for this block.
+     */
+    for (g = GlobalList; g != NULL; g = g->next)
+    {
+	if (g->handle == selector)
+	{
+	    if (g->sequence > 0)
+		return g->handle;
+	    else
+	    {
+		fprintf(stderr, "Attempt to get a handle "
+			"from a selector to a far heap.\n");
+		return 0;
+	    }
+	}
+    }
+
+    return 0;
+}
+
+/**********************************************************************
+ *					GlobalCompact
+ *
+ */
+unsigned int
+GlobalCompact(unsigned int desired)
+{
+    GDESC *g;
+    unsigned char free_map[512];
+    unsigned int max_selector_used = 0;
+    unsigned int i;
+    unsigned int selector;
+    int current_free;
+    int max_free;
+
+    /*
+     * Initialize free list to all items not controlled by GlobalAlloc()
+     */
+    for (i = 0; i < 512; i++)
+	free_map[i] = -1;
+
+    /*
+     * Traverse table looking for used and free selectors.
+     */
+    for (g = GlobalList; g != NULL; g = g->next)
+    {
+	/*
+	 * Check for free segments.
+	 */
+	if (g->sequence == -1)
+	{
+	    free_map[g->handle >> 3] = 1;
+	    if (g->handle > max_selector_used)
+		max_selector_used = g->handle;
+	}
+
+	/*
+	 * Check for heap allocated segments.
+	 */
+	else if (g->handle == 0)
+	{
+	    selector = (unsigned int) g->addr >> 16;
+	    free_map[selector >> 3] = 0;
+	    if (selector > max_selector_used)
+		max_selector_used = selector;
+	}
+    }
+
+    /*
+     * All segments past the biggest selector used are free.
+     */
+    for (i = (max_selector_used >> 3) + 1; i < 512; i++)
+	free_map[i] = 1;
+
+    /*
+     * Find the largest free block of segments
+     */
+    current_free = 0;
+    max_free = 0;
+    for (i = 0; i < 512; i++)
+    {
+	if (free_map[i] == 1)
+	{
+	    current_free++;
+	}
+	else
+	{
+	    if (current_free > max_free)
+		max_free = current_free;
+	    current_free = 0;
+	}
+    }
+    
+    return max_free << 16;
+}
+
+/**********************************************************************
+ *					GlobalReAlloc
+ *
+ */
+unsigned int
+GlobalReAlloc(unsigned int block, unsigned int new_size, unsigned int flags)
+{
+    GDESC *g;
+    unsigned int n_segments;
+    int i;
+
+    if (block == 0)
+	return 0;
+
+    /*
+     * Find GDESC for this block.
+     */
+    for (g = GlobalList; g != NULL; g = g->next)
+    {
+	if (g->handle == block)
+	    break;
+    }
+
+    if (g == NULL)
+	return 0;
+    
+    /*
+     * If this is a heap allocated block,  then use HEAP_ReAlloc() to
+     * reallocate the block.  If this fails, call GlobalAlloc() to get
+     * a new block.
+     */
+    if (g->sequence = 0)
+    {
+	MDESC **free_list;
+	void *p;
+	
+	free_list = (MDESC **) ((unsigned int) g->addr & 0xffff0000);
+	p = HEAP_ReAlloc(free_list, g->addr, new_size, flags) ;
+	if (p == NULL)
+	{
+	    unsigned int handle = GlobalAlloc(flags, new_size);
+	    if (handle == 0)
+		return 0;
+	    p = GlobalLock(handle);
+	    memcpy(p, g->addr, g->length);
+	    GlobalUnlock(handle);
+	    GlobalFree(g->handle);
+
+	    return handle;
+	}
+	else
+	{
+	    g->addr = p;
+	    g->length = new_size;
+	    return g->handle;
+	}
+    }
+    
+    /*
+     * Otherwise, we need to do the work ourselves.  First verify the
+     * handle.
+     */
+    else
+    {
+	if (g->sequence != 1)
+	    return 0;
+
+	/*
+	 * Do we need more memory?  Segments are in ascending order in 
+	 * the GDESC list.
+	 */
+	n_segments = (new_size >> 16) + 1;
+        if (n_segments > g->length)
+	{
+	    GDESC *g_new;
+	    GDESC *g_start = g;
+	    int old_segments = g_start->length;
+	    unsigned short next_handle = g_start->handle;
+	    
+	    for (i = 1; i <= n_segments; i++, g = g->next)
+	    {
+		/*
+		 * If we run into a block allocated to something else,
+		 * try GlobalGetFreeSegments() and memcpy(). (Yuk!)
+		 */
+		if (g->sequence != i || g->handle != next_handle)
+		{
+		    g = GlobalGetFreeSegments(flags, n_segments);
+		    if (g == NULL)
+			return 0;
+		    
+		    memcpy(g->addr, g_start->addr,
+			   g_start->length << 16);
+
+		    GlobalFree(block);
+		    return g->handle;
+		}
+
+		/*
+		 * Otherwise this block is used by us or free.  So,
+		 * snatch it.  If this block is new and we are supposed to
+		 * zero init, then do some erasing.
+		 */
+		if (g->sequence == -1 && (flags & GLOBAL_FLAGS_ZEROINIT))
+		    memset(g->addr, 0, 0x10000);
+		
+		g->sequence = i;
+		g->length = n_segments;
+		next_handle += 8;
+
+		/*
+		 * If the next descriptor is non-existant, then use
+		 * GlobalGetFreeSegments to create them.
+		 */
+		if (i != n_segments && g->next == NULL)
+		{
+		    g_new = GlobalGetFreeSegments(flags, n_segments - i);
+		    if (g_new == NULL)
+			return 0;
+		    GlobalFree(g_new->handle);
+		}
+	    }
+
+	    return g_start->handle;
+	}
+	
+	/*
+	 * Do we need less memory?
+	 */
+	else if (n_segments < g->length)
+	{
+	    GDESC *g_free;
+	    
+	    g_free = g;
+	    for (i = 0; i < n_segments; i++)
+	    {
+		if (g_free->sequence != i + 1)
+		    return 0;
+		g_free = g_free->next;
+	    }
+	}
+	
+	/*
+	 * We already have exactly the right amount of memory.
+	 */
+	else
+	    return block;
+    }
+
+    /*
+     * If we fall through it must be an error.
+     */
+    return 0;
+}
diff --git a/heap.c b/heap.c
index fa06124..e2aed78 100644
--- a/heap.c
+++ b/heap.c
@@ -61,6 +61,11 @@
 
 	    m->prev = m;
 	    m->next = m;
+	    if (flags & GLOBAL_FLAGS_ZEROINIT)
+		memset(m + 1, 0, bytes);
+#ifdef DEBUG_HEAP
+	    printf("HeapAlloc: returning %08x\n", (m + 1));
+#endif
 	    return (void *) (m + 1);
 	}
     }
@@ -77,12 +82,31 @@
 	
 	m->prev = m;
 	m->next = m;
+	if (flags & GLOBAL_FLAGS_ZEROINIT)
+	    memset(m + 1, 0, bytes);
+#ifdef DEBUG_HEAP
+	printf("HeapAlloc: returning %08x\n", (m + 1));
+#endif
 	return (void *) (m + 1);
     }
 
+#ifdef DEBUG_HEAP
+    printf("HeapAlloc: returning %08x\n", 0);
+#endif
+    return 0;
+}
+
+/**********************************************************************
+ *					HEAP_ReAlloc
+ */
+void *
+HEAP_ReAlloc(MDESC **free_list, void *old_block, 
+	     int new_size, unsigned int flags)
+{
     return 0;
 }
 
+
 /**********************************************************************
  *					HEAP_Free
  */
@@ -209,3 +233,20 @@
 #endif
     return m;
 }
+
+/**********************************************************************
+ *					HEAP_LocalCompact
+ */
+int
+HEAP_LocalCompact(int min_free)
+{
+    MDESC *m;
+    int max_block;
+    
+    max_block = 0;
+    for (m = LOCAL_FreeList; m != NULL; m = m->next)
+	if (m->length > max_block)
+	    max_block = m->length;
+    
+    return max_block;
+}
diff --git a/heap.h b/heap.h
index 2d8bfa8..d602d84 100644
--- a/heap.h
+++ b/heap.h
@@ -15,5 +15,7 @@
 extern void HEAP_Init(MDESC **free_list, void *start, int length);
 extern void *HEAP_Alloc(MDESC **free_list, int flags, int bytes);
 extern void HEAP_Free(MDESC **free_list, void *block);
+extern void *HEAP_ReAlloc(MDESC **free_list, void *old_block, 
+			  int new_size, unsigned int flags);
 
 #endif /* HEAP_H */
diff --git a/kernel.c b/kernel.c
index 24b0e90..13f30c7 100644
--- a/kernel.c
+++ b/kernel.c
@@ -8,17 +8,6 @@
 extern unsigned short *Stack16Frame;
 
 /**********************************************************************
- *					KERNEL_GetVersion
- *
- * Return the version of Windows that we emulate.
- */
-int
-KERNEL_GetVersion(void)
-{
-    return 0x0301;
-}
-
-/**********************************************************************
  *					KERNEL_LockSegment
  */
 int
diff --git a/kernel.spec b/kernel.spec
index 1942b75..382630c 100644
--- a/kernel.spec
+++ b/kernel.spec
@@ -6,11 +6,17 @@
 
 3   return GetVersion 0 0x301
 5   pascal LocalAlloc(word word) HEAP_LocalAlloc(1 2)
-15  pascal GlobalAlloc(word long) GLOBAL_Alloc(1 2)
-17  pascal GlobalFree(word) GLOBAL_Free(1)
-18  pascal GLobalLock(word) GLOBAL_Lock(1)
+15  pascal GlobalAlloc(word long) GlobalAlloc(1 2)
+16  pascal GlobalReAlloc(word long word) GlobalReAlloc(1 2 3)
+17  pascal GlobalFree(word) GlobalFree(1)
+18  pascal GlobalLock(word) GlobalLock(1)
+19  pascal GlobalUnlock(word) GlobalUnlock(1)
+20  pascal GlobalSize(word) GlobalSize(1)
+21  pascal GlobalHandle(word) GlobalHandle(1)
+22  pascal GlobalFlags(word) GlobalFlags(1)
 23  pascal LockSegment(s_word) KERNEL_LockSegment(1)
 24  pascal UnlockSegment(s_word) KERNEL_UnlockSegment(1)
+25  pascal GlobalCompact(long) GlobalCompact(1)
 30  pascal WaitEvent(word) KERNEL_WaitEvent(1)
 49  pascal GetModuleFileName(word ptr s_word) KERNEL_GetModuleFileName(1 2 3)
 51  pascal MakeProcInstance(ptr word) CALLBACK_MakeProcInstance(1 2)
@@ -18,6 +24,17 @@
 102 register DOS3Call(word word word word word
 		      word word word word word) 
 	     KERNEL_DOS3Call(1 2 3 4 5 6 7 8 9 10)
+111 pascal GlobalWire(word) GlobalLock(1)
+112 pascal GlobalUnWire(word) GlobalUnlock(1)
 131 pascal GetDOSEnvironment() GetDOSEnvironment()
 132 return GetWinFlags 0 0x413
+154 return GlobalNotify 4 0
+163 pascal GlobalLRUOldest(word) ReturnArg(1)
+164 pascal GlobalLRUNewest(word) ReturnArg(1)
 178 equate __WINFLAGS 0x413
+184 return GlobalDOSAlloc 4 0
+185 return GlobalDOSFree 2 0
+191 pascal GlobalPageLock(word) GlobalLock(1)
+192 pascal GlobalPageUnlock(word) GlobalUnlock(1)
+197 pascal GlobalFix(word) GlobalLock(1)
+198 pascal GlobalUnfix(word) GlobalUnlock(1)
diff --git a/ldt512.tar b/ldt512.tar
new file mode 100644
index 0000000..978751c
--- /dev/null
+++ b/ldt512.tar
Binary files differ
diff --git a/message.c b/message.c
new file mode 100644
index 0000000..d013d1d
--- /dev/null
+++ b/message.c
@@ -0,0 +1,428 @@
+/*
+ * Message queues related functions
+ *
+ * Copyright 1993 Alexandre Julliard
+ */
+
+/*
+ * This code assumes that there is only one Windows task (hence
+ * one message queue).
+ */
+
+static char Copyright[] = "Copyright  Alexandre Julliard, 1993";
+
+#include <sys/param.h>
+#include <sys/times.h>
+
+#include "message.h"
+#include "win.h"
+
+
+#define MAX_QUEUE_SIZE   120  /* Max. size of a message queue */
+
+
+static MESSAGEQUEUE * msgQueue = NULL;
+
+
+/***********************************************************************
+ *           MSG_GetMessageType
+ *
+ */
+int MSG_GetMessageType( int msg )
+{
+    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;
+}
+
+
+/***********************************************************************
+ *           MSG_AddMsg
+ *
+ * Add a message to the queue. Return FALSE if queue is full.
+ */
+int MSG_AddMsg( MSG * msg, DWORD extraInfo )
+{
+    int pos, type;
+    QMSG * qmsg;
+  
+    if (!msgQueue) return FALSE;
+    pos = msgQueue->nextFreeMessage;
+
+      /* No need to store WM_PAINT messages */
+    if (msg->message == WM_PAINT)
+    {
+	msgQueue->status |= QS_PAINT;
+	msgQueue->tempStatus |= QS_PAINT;
+	/* For now we need to store them to keep the hwnd somewhere */
+	/* return TRUE; */
+    }
+        
+      /* Check if queue is full */
+    if ((pos == msgQueue->nextMessage) && (msgQueue->msgCount > 0))
+	return FALSE;
+
+      /* 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++;
+    
+    return TRUE;
+}
+
+
+/***********************************************************************
+ *           MSG_FindMsg
+ *
+ * Find a message matching the given parameters. Return -1 if none available.
+ */
+int MSG_FindMsg( HWND hwnd, int first, int last )
+{
+    int i, pos = msgQueue->nextMessage;
+
+    if (!msgQueue->msgCount) return -1;
+    if (!hwnd && !first && !last) return pos;
+        
+    for (i = 0; i < msgQueue->msgCount; i++)
+    {
+	MSG * msg = &msgQueue->messages[pos].msg;
+
+	if (!hwnd || (msg->hwnd == hwnd))
+	{
+	    if (!first && !last) return pos;
+	    if ((msg->message >= first) && (msg->message <= last)) return pos;
+	}
+	if (pos < msgQueue->queueSize-1) pos++;
+	else pos = 0;
+    }
+    return -1;
+}
+
+
+/***********************************************************************
+ *           MSG_RemoveMsg
+ *
+ * Remove a message from the queue (pos must be a valid position).
+ */
+void MSG_RemoveMsg( int pos )
+{
+    int oldpos, i, type;
+    QMSG * qmsg;
+    
+    if (!msgQueue) return;
+    qmsg = &msgQueue->messages[pos];
+
+    if (pos >= msgQueue->nextMessage)
+    {
+	int count = pos - msgQueue->nextMessage;
+	if (count) memmove( &msgQueue->messages[msgQueue->nextMessage+1],
+			    &msgQueue->messages[msgQueue->nextMessage],
+			    count * sizeof(QMSG) );
+	msgQueue->nextMessage++;
+	if (msgQueue->nextMessage >= msgQueue->queueSize)
+	    msgQueue->nextMessage = 0;
+    }
+    else
+    {
+	int count = msgQueue->nextFreeMessage - pos;
+	if (count) memmove( &msgQueue->messages[pos],
+			    &msgQueue->messages[pos+1], count * sizeof(QMSG) );
+	if (msgQueue->nextFreeMessage) msgQueue->nextFreeMessage--;
+	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_PAINT | QS_SENDMESSAGE) | type;
+    msgQueue->tempStatus = 0;
+}
+
+
+/***********************************************************************
+ *           MSG_EndPaint
+ *
+ * Remove the WM_PAINT message from the queue
+ */
+void MSG_EndPaint()
+{
+    msgQueue->status &= ~QS_PAINT;
+}
+
+
+/***********************************************************************
+ *           MSG_GetTime
+ *
+ * Return the time elapsed from the starting of the system, in milliseconds.
+ * Used to timestamp messages.
+ */
+
+LONG MSG_GetTime()
+{
+    struct tms dummy;
+    return times(&dummy) / (1000 / HZ);
+}
+
+
+/***********************************************************************
+ *           SetMessageQueue  (USER.266)
+ */
+BOOL SetMessageQueue( int size )
+{
+    int queueSize;
+  
+      /* Free the old message queue */
+    if (msgQueue) free(msgQueue);
+  
+    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;
+
+    return TRUE;
+}
+
+
+/***********************************************************************
+ *           PostQuitMessage   (USER.6)
+ */
+void PostQuitMessage( int exitCode )
+{
+    if (!msgQueue) return;
+    msgQueue->wPostQMsg = TRUE;
+    msgQueue->wExitCode = exitCode;
+}
+
+
+/***********************************************************************
+ *           GetQueueStatus   (USER.334)
+ */
+DWORD GetQueueStatus( int flags )
+{
+    unsigned long ret = (msgQueue->status << 16) | msgQueue->tempStatus;
+    msgQueue->tempStatus = 0;
+    return ret & ((flags << 16) | flags);
+}
+
+
+/***********************************************************************
+ *           GetInputState   (USER.335)
+ */
+BOOL GetInputState()
+{
+    return msgQueue->status & (QS_KEY | QS_MOUSEBUTTON);
+}
+
+
+/***********************************************************************
+ *           PeekMessage   (USER.109)
+ */
+BOOL PeekMessage( LPMSG msg, HWND hwnd, WORD first, WORD last, WORD flags )
+{
+    int pos;
+    
+      /* First handle a WM_QUIT message */
+    if (msgQueue->wPostQMsg)
+    {
+	msg->hwnd    = hwnd;
+	msg->message = WM_QUIT;
+	msg->wParam  = msgQueue->wExitCode;
+	msg->lParam  = 0;
+	return TRUE;
+    }
+
+      /* Then handle a message put by SendMessage() */
+    if (msgQueue->status & QS_SENDMESSAGE)
+    {
+	if (!hwnd || (msgQueue->hWnd == hwnd))
+	{
+	    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;
+		return TRUE;
+	    }
+	}
+	
+    }
+    
+      /* 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;
+
+	if (flags & PM_REMOVE) MSG_RemoveMsg(pos);
+    	return TRUE;
+    }
+
+      /* If nothing else, return a WM_PAINT message */
+    if (msgQueue->status & QS_PAINT)
+    {
+	if ((!first && !last) || ((first <= WM_PAINT) && (last >= WM_PAINT)))
+	{
+	    msg->hwnd = hwnd;
+	    msg->message = WM_PAINT;
+	    msg->wParam = 0;
+	    msg->lParam = 0;
+	    return TRUE;
+	}
+	
+    }	
+    return FALSE;
+}
+
+
+/***********************************************************************
+ *           PostMessage   (USER.110)
+ */
+BOOL PostMessage( HWND hwnd, WORD message, WORD wParam, LONG lParam )
+{
+    MSG msg;
+    
+    msg.hwnd    = hwnd;
+    msg.message = message;
+    msg.wParam  = wParam;
+    msg.lParam  = lParam;
+    msg.time    = MSG_GetTime();
+    msg.pt.x    = 0;
+    msg.pt.y    = 0;
+    
+    return MSG_AddMsg( &msg, 0 );
+}
+
+
+/***********************************************************************
+ *           SendMessage   (USER.111)
+ */
+LONG SendMessage( HWND hwnd, WORD msg, WORD wParam, LONG lParam )
+{
+    LONG retval = 0;
+    WND * wndPtr = WIN_FindWndPtr( hwnd );
+    if (wndPtr)
+    {
+	retval = CallWindowProc( wndPtr->lpfnWndProc, hwnd, msg, 
+				 wParam, lParam );
+	GlobalUnlock( hwnd );
+    }
+    return retval;
+}
+
+
+/***********************************************************************
+ *           TranslateMessage   (USER.113)
+ */
+BOOL TranslateMessage( LPMSG msg )
+{
+    int message = msg->message;
+    
+    if ((message == WM_KEYDOWN) || (message == WM_KEYUP) ||
+	(message == WM_SYSKEYDOWN) || (message == WM_SYSKEYUP))
+    {
+#ifdef DEBUG_MSG
+	printf( "Translating key message\n" );
+#endif
+	return TRUE;
+    }
+    return FALSE;
+}
+
+
+/***********************************************************************
+ *           DispatchMessage   (USER.114)
+ */
+LONG DispatchMessage( LPMSG msg )
+{
+    LONG retval = 0;
+    WND * wndPtr = WIN_FindWndPtr( msg->hwnd );
+
+#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) 
+    {
+	retval = CallWindowProc(wndPtr->lpfnWndProc, msg->hwnd, msg->message,
+				msg->wParam, msg->lParam );
+	GlobalUnlock( msg->hwnd );
+    }
+    return retval;
+}
+
+
+/***********************************************************************
+ *           GetMessagePos   (USER.119)
+ */
+DWORD GetMessagePos(void)
+{
+    return msgQueue->GetMessagePosVal;
+}
+
+
+/***********************************************************************
+ *           GetMessageTime   (USER.120)
+ */
+LONG GetMessageTime(void)
+{
+    return msgQueue->GetMessageTimeVal;
+}
+
+/***********************************************************************
+ *           GetMessageExtraInfo   (USER.288)
+ */
+LONG GetMessageExtraInfo(void)
+{
+    return msgQueue->GetMessageExtraInfoVal;
+}
+
diff --git a/message.h b/message.h
new file mode 100644
index 0000000..0bbfc9a
--- /dev/null
+++ b/message.h
@@ -0,0 +1,44 @@
+/*
+ * Message queues definitions
+ *
+ * Copyright 1993 Alexandre Julliard
+ */
+
+#ifndef MESSAGE_H
+#define MESSAGE_H
+
+#include "windows.h"
+
+  /* Message as stored in the queue (contains the extraInfo field) */
+typedef struct tagQMSG
+{
+    MSG     msg;
+    DWORD   extraInfo __attribute__ ((packed));  /* Only in 3.1 */
+} QMSG;
+
+
+typedef struct tagMESSAGEQUEUE
+{
+  WORD      next;
+  WORD      hTask;                  /* hTask owning the queue                */
+  WORD      msgSize;                /* Size of messages in the queue         */
+  WORD      msgCount;               /* Number of waiting messages            */
+  WORD      nextMessage;            /* Next message to be retrieved          */
+  WORD      nextFreeMessage;        /* Next available slot in the queue      */
+  WORD      queueSize;              /* Size of the queue                     */
+  DWORD     GetMessageTimeVal;      /* Value returned by GetMessageTime      */
+  DWORD     GetMessagePosVal;       /* Value returned by GetMessagePos       */
+  WORD      GetMessageExtraInfoVal; /* Value returned by GetMessageExtraInfo */
+  DWORD     lParam;                 /* Next four values set by SetMessage    */
+  WORD      wParam;
+  WORD      msg;
+  WORD      hWnd;
+  WORD      wPostQMsg;              /* PostQuitMessage flag                  */
+  WORD      wExitCode;              /* PostQuitMessage exit code             */
+  WORD      InSendMessageHandle;    /* Handle of task that sent a message    */
+  WORD      tempStatus;             /* State reset by GetQueueStatus         */
+  WORD      status;                 /* Queue state                           */
+  QMSG      messages[1];            /* Queue messages                        */
+} MESSAGEQUEUE;
+
+#endif  /* MESSAGE_H */
diff --git a/prototypes.h b/prototypes.h
index c030971..39560dd 100644
--- a/prototypes.h
+++ b/prototypes.h
@@ -27,10 +27,6 @@
 
 extern struct segment_descriptor_s *GetNextSegment(unsigned int flags,
 						   unsigned int limit);
-extern unsigned int GLOBAL_Alloc(unsigned int flags, unsigned long size);
-extern unsigned int GLOBAL_Free(unsigned int block);
-extern void *GLOBAL_Lock(unsigned int block);
-
 extern struct mz_header_s *CurrentMZHeader;
 extern struct ne_header_s *CurrentNEHeader;
 extern int CurrentNEFile;
diff --git a/relay.c b/relay.c
index a86b92c..2331947 100644
--- a/relay.c
+++ b/relay.c
@@ -200,3 +200,11 @@
     
     return 0;
 }
+/**********************************************************************
+ *					ReturnArg
+ */
+int
+ReturnArg(int arg)
+{
+    return arg;
+}
diff --git a/resource.c b/resource.c
index 93895e1..531f9c0 100644
--- a/resource.c
+++ b/resource.c
@@ -40,9 +40,13 @@
     int n_colors;
     
     n_colors = 1 << image->bcBitCount;
-    handle = GLOBAL_Alloc(GMEM_MOVEABLE, 
+    handle = GlobalAlloc(GMEM_MOVEABLE, 
 			  image_size + sizeof(*new_image) + n_colors);
-    new_image = GLOBAL_Lock(handle);
+    new_image = GlobalLock(handle);
+#ifdef DEBUG_RESOURCE
+    printf("ConvertCoreBitmap: handle = %04x, new image = %08x\n", 
+	   handle, new_image);
+#endif
     if (new_image == NULL)
 	return NULL;
 
@@ -96,6 +100,11 @@
 void *
 ConvertInfoBitmap(BITMAPINFOHEADER *image, int image_size)
 {
+#ifdef DEBUG_RESOURCE
+    printf("ConvertInfoBitmap: \n");
+#endif
+
+    return NULL;
 }
 
 /**********************************************************************
@@ -142,6 +151,9 @@
     r->resource_type = type;
     r->resource_data = data;
 
+#ifdef DEBUG_RESOURCE
+    printf("AddResource: return handle %d\n", i + 1);
+#endif
     /*
      * Return a unique handle.
      */
@@ -325,6 +337,9 @@
 
     free(image);
 
+#ifdef DEBUG_RESOURCE
+    printf("LoadResource: rsc_image = %08x\n", rsc_image);
+#endif
     /*
      * Add to resource list.
      */
diff --git a/tclIndex b/tclIndex
deleted file mode 100644
index 045f146..0000000
--- a/tclIndex
+++ /dev/null
@@ -1,12 +0,0 @@
-# Tcl autoload index file: each line identifies a Tcl
-# procedure and the file where that procedure is
-# defined.  Generated by the "auto_mkindex" command.
-
-CreateWindow Windows.tcl
-CreateMenuBar Windows.tcl
-AppendMenu Windows.tcl
-# Unimplemented stuff
-LoadIcon Windows.tcl
-LoadCursor Windows.tcl
-GetStockObject Windows.tcl
-DefWindowProc Windows.tcl
diff --git a/tkInt.h b/tkInt.h
deleted file mode 100644
index 728847c..0000000
--- a/tkInt.h
+++ /dev/null
@@ -1,555 +0,0 @@
-/*
- * tkInt.h --
- *
- *	Declarations for things used internally by the Tk
- *	procedures but not exported outside the module.
- *
- * Copyright 1990-1992 Regents of the University of California.
- * Permission to use, copy, modify, and distribute this
- * software and its documentation for any purpose and without
- * fee is hereby granted, provided that the above copyright
- * notice appear in all copies.  The University of California
- * makes no representations about the suitability of this
- * software for any purpose.  It is provided "as is" without
- * express or implied warranty.
- *
- * $Header: /user6/ouster/wish/RCS/tkInt.h,v 1.84 93/01/23 16:59:14 ouster Exp $ SPRITE (Berkeley)
- */
-
-#ifndef _TKINT
-#define _TKINT
-
-#ifndef _XLIB_H_
-#include <X11/Xlib.h>
-#endif
-#ifndef _XUTIL_H
-#include <X11/Xutil.h>
-#endif
-#ifndef _TK
-#include "tk.h"
-#endif
-#ifndef _TCL
-#include "tcl.h"
-#endif
-#ifndef _TCLHASH
-#include "tclHash.h"
-#endif
-
-/*
- * Opaque type declarations:
- */
-
-typedef struct Tk_PostscriptInfo Tk_PostscriptInfo;
-typedef struct TkGrabEvent TkGrabEvent;
-
-/*
- * One of the following structures is maintained for each display
- * containing a window managed by Tk:
- */
-
-typedef struct TkDisplay {
-    Display *display;		/* Xlib's info about display. */
-    struct TkDisplay *nextPtr;	/* Next in list of all displays. */
-    char *name;			/* Name of display (with any screen
-				 * identifier removed).  Malloc-ed. */
-    Time lastEventTime;		/* Time of last event received for this
-				 * display. */
-
-    /*
-     * Information used by tkFocus.c and tkEvent.c:
-     */
-
-    struct TkWindow *focusTopLevelPtr;
-				/* Pointer to the top-level window that
-				 * currently contains the focus for this
-				 * display.  NULL means none of the
-				 * top-levels managed by this application
-				 * contains the focus. */
-    int focussedOnEnter;	/* Non-zero means the focus was set
-				 * implicitly from an Enter event rather
-				 * than from a FocusIn event. */
-
-    /*
-     * Information used primarily by tkBind.c:
-     */
-
-    int bindInfoStale;		/* Non-zero means the variables in this
-				 * part of the structure are potentially
-				 * incorrect and should be recomputed. */
-    unsigned int modeModMask;	/* Has one bit set to indicate the modifier
-				 * corresponding to "mode shift".  If no
-				 * such modifier, than this is zero. */
-    enum {IGNORE, CAPS, SHIFT} lockUsage;
-				/* Indicates how to interpret lock modifier. */
-
-    /*
-     * Information used by tkError.c only:
-     */
-
-    struct TkErrorHandler *errorPtr;
-				/* First in list of error handlers
-				 * for this display.  NULL means
-				 * no handlers exist at present. */
-    int deleteCount;		/* Counts # of handlers deleted since
-				 * last time inactive handlers were
-				 * garbage-collected.  When this number
-				 * gets big, handlers get cleaned up. */
-
-    /*
-     * Information used by tkSend.c only:
-     */
-
-    Tk_Window commWindow;	/* Window used for communication
-				 * between interpreters during "send"
-				 * commands.  NULL means send info hasn't
-				 * been initialized yet. */
-    Atom commProperty;		/* X's name for comm property. */
-    Atom registryProperty;	/* X's name for property containing
-				 * registry of interpreter names. */
-
-    /*
-     * Information used by tkSelect.c only:
-     */
-
-    Tk_Window selectionOwner;	/* Current owner of selection, or
-				 * NULL if selection isn't owned by
-				 * a window in this process.  */
-    int selectionSerial;	/* Serial number of last XSelectionSetOwner
-				 * request we made to server (used to
-				 * filter out redundant SelectionClear
-				 * events. */
-    Time selectionTime;		/* Timestamp used to acquire selection. */
-    Atom multipleAtom;		/* Atom for MULTIPLE.  None means
-				 * selection stuff isn't initialized. */
-    Atom incrAtom;		/* Atom for INCR. */
-    Atom targetsAtom;		/* Atom for TARGETS. */
-    Atom timestampAtom;		/* Atom for TIMESTAMP. */
-    Atom textAtom;		/* Atom for TEXT. */
-    Atom compoundTextAtom;	/* Atom for COMPOUND_TEXT. */
-    Atom applicationAtom;	/* Atom for APPLICATION. */
-    Atom windowNameAtom;	/* Atom for WINDOW_NAME. */
-
-    /*
-     * Information used by tkAtom.c only:
-     */
-
-    int atomInit;		/* 0 means stuff below hasn't been
-				 * initialized yet. */
-    Tcl_HashTable nameTable;	/* Maps from names to Atom's. */
-    Tcl_HashTable atomTable;	/* Maps from Atom's back to names. */
-
-    /*
-     * Information used by tkCursor.c only:
-     */
-
-    Font cursorFont;		/* Font to use for standard cursors.
-				 * None means font not loaded yet. */
-
-    /*
-     * Information used by tkGrab.c only:
-     */
-
-    struct TkWindow *grabWinPtr;
-				/* Window in which the pointer is currently
-				 * grabbed, or NULL if none. */
-    struct TkWindow *eventualGrabWinPtr;
-				/* Value that grabWinPtr will have once the
-				 * grab event queue (below) has been
-				 * completely emptied. */
-    struct TkWindow *buttonWinPtr;
-				/* Window in which first mouse button was
-				 * pressed while grab was in effect, or NULL
-				 * if no such press in effect. */
-    struct TkWindow *serverWinPtr;
-				/* If no application contains the pointer then
-				 * this is NULL.  Otherwise it contains the
-				 * last window for which we've gotten an
-				 * Enter or Leave event from the server (i.e.
-				 * the last window known to have contained
-				 * the pointer).  Doesn't reflect events
-				 * that were synthesized in tkGrab.c. */
-    TkGrabEvent *firstGrabEventPtr;
-				/* First in list of enter/leave events
-				 * synthesized by grab code.  These events
-				 * must be processed in order before any other
-				 * events are processed.  NULL means no such
-				 * events. */
-    TkGrabEvent *lastGrabEventPtr;
-				/* Last in list of synthesized events, or NULL
-				 * if list is empty. */
-    int grabFlags;		/* Miscellaneous flag values.  See definitions
-				 * in tkGrab.c. */
-
-    /*
-     * Miscellaneous information:
-     */
-
-    Tk_ColorModel *colorModels;	/* Array of color models, one per screen;
-				 * indicates whether windows should attempt
-				 * to use full color for display, just mono,
-				 * etc.  Malloc'ed. */
-} TkDisplay;
-
-/*
- * One of the following structures exists for each error handler
- * created by a call to Tk_CreateErrorHandler.  The structure
- * is managed by tkError.c.
- */
-
-typedef struct TkErrorHandler {
-    TkDisplay *dispPtr;		/* Display to which handler applies. */
-    unsigned long firstRequest;	/* Only errors with serial numbers
-				 * >= to this are considered. */
-    unsigned long lastRequest;	/* Only errors with serial numbers
-				 * <= to this are considered.  This
-				 * field is filled in when XUnhandle
-				 * is called.  -1 means XUnhandle
-				 * hasn't been called yet. */
-    int error;			/* Consider only errors with this
-				 * error_code (-1 means consider
-				 * all errors). */
-    int request;		/* Consider only errors with this
-				 * major request code (-1 means
-				 * consider all major codes). */
-    int minorCode;		/* Consider only errors with this
-				 * minor request code (-1 means
-				 * consider all minor codes). */
-    Tk_ErrorProc *errorProc;	/* Procedure to invoke when a matching
-				 * error occurs.  NULL means just ignore
-				 * errors. */
-    ClientData clientData;	/* Arbitrary value to pass to
-				 * errorProc. */
-    struct TkErrorHandler *nextPtr;
-				/* Pointer to next older handler for
-				 * this display, or NULL for end of
-				 * list. */
-} TkErrorHandler;
-
-/*
- * One of the following structures exists for each event handler
- * created by calling Tk_CreateEventHandler.  This information
- * is used by tkEvent.c only.
- */
-
-typedef struct TkEventHandler {
-    unsigned long mask;		/* Events for which to invoke
-				 * proc. */
-    Tk_EventProc *proc;		/* Procedure to invoke when an event
-				 * in mask occurs. */
-    ClientData clientData;	/* Argument to pass to proc. */
-    struct TkEventHandler *nextPtr;
-				/* Next in list of handlers
-				 * associated with window (NULL means
-				 * end of list). */
-} TkEventHandler;
-
-/*
- * One of the following structures exists for each selection
- * handler created by calling Tk_CreateSelHandler.  This
- * information is used by tkSelect.c only.
- */
-
-typedef struct TkSelHandler {
-    Atom target;		/* Target type for selection
-				 * conversion, such as TARGETS or
-				 * STRING. */
-    Atom format;		/* Format in which selection
-				 * info will be returned, such
-				 * as STRING or ATOM. */
-    Tk_SelectionProc *proc;	/* Procedure to generate selection
-				 * in this format. */
-    ClientData clientData;	/* Argument to pass to proc. */
-    int size;			/* Size of units returned by proc
-				 * (8 for STRING, 32 for almost
-				 * anything else). */
-    struct TkSelHandler *nextPtr;
-				/* Next selection handler associated
-				 * with same window (NULL for end of
-				 * list). */
-} TkSelHandler;
-
-/*
- * Tk keeps one of the following data structures for each main
- * window (created by a call to Tk_CreateMainWindow).  It stores
- * information that is shared by all of the windows associated
- * with a particular main window.
- */
-
-typedef struct TkMainInfo {
-    struct TkWindow *winPtr;	/* Pointer to main window. */
-    Tcl_Interp *interp;		/* Interpreter associated with application. */
-    Tcl_HashTable nameTable;	/* Hash table mapping path names to TkWindow
-				 * structs for all windows related to this
-				 * main window.  Managed by tkWindow.c. */
-    Tk_BindingTable bindingTable;
-				/* Used in conjunction with "bind" command
-				 * to bind events to Tcl commands. */
-    struct TkWindow *focusPtr;	/* Identifies window that currently has the
-				 * focus (or that will get the focus the next
-				 * time the pointer enters any of the top-level
-				 * windows associated with this main window).
-				 * NULL means nobody has the focus.
-				 * Managed by tkFocus.c. */
-    struct TkWindow *focusDefaultPtr;
-				/* Window that is to receive the focus by
-				 * default when the focusPtr window is
-				 * deleted. */
-    struct ElArray *optionRootPtr;
-				/* Top level of option hierarchy for this
-				 * main window.  NULL means uninitialized.
-				 * Managed by tkOption.c. */
-} TkMainInfo;
-
-/*
- * Tk keeps one of the following structures for each window.
- * Some of the information (like size and location) is a shadow
- * of information managed by the X server, and some is special
- * information used here, such as event and geometry management
- * information.  This information is (mostly) managed by tkWindow.c.
- * WARNING: the declaration below must be kept consistent with the
- * Tk_ClientWindow structure in tk.h.  If you change one, be sure to
- * change the other!!
- */
-
-typedef struct TkWindow {
-
-    /*
-     * Structural information:
-     */
-
-    Display *display;		/* Display containing window. */
-    TkDisplay *dispPtr;		/* Tk's information about display
-				 * for window. */
-    int screenNum;		/* Index of screen for window, among all
-				 * those for dispPtr. */
-    Visual *visual;		/* Visual to use for window.  If not default,
-				 * MUST be set before X window is created. */
-    int depth;			/* Number of bits/pixel. */
-    Window window;		/* X's id for window.   NULL means window
-				 * hasn't actually been created yet, or it's
-				 * been deleted. */
-    struct TkWindow *childList;	/* First in list of child windows,
-				 * or NULL if no children. */
-    struct TkWindow *parentPtr;	/* Pointer to parent window (logical
-				 * parent, not necessarily X parent), or
-				 * NULL if this is a main window. */
-    struct TkWindow *nextPtr;	/* Next in list of children with
-				 * same parent (NULL if end of
-				 * list). */
-    TkMainInfo *mainPtr;	/* Information shared by all windows
-				 * associated with a particular main
-				 * window.  NULL means this window is
-				 * a rogue that isn't associated with
-				 * any application (at present, there
-				 * should never be any rogues).  */
-
-    /*
-     * Name and type information for the window:
-     */
-
-    char *pathName;		/* Path name of window (concatenation
-				 * of all names between this window and
-				 * its top-level ancestor).  This is a
-				 * pointer into an entry in
-				 * mainPtr->nameTable or NULL if mainPtr
-				 * is NULL. */
-    Tk_Uid nameUid;		/* Name of the window within its parent
-				 * (unique within the parent). */
-    Tk_Uid classUid;		/* Class of the window.  NULL means window
-				 * hasn't been given a class yet. */
-
-    /*
-     * Geometry and other attributes of window.  This information
-     * may not be updated on the server immediately;  stuff that
-     * hasn't been reflected in the server yet is called "dirty".
-     * At present, information can be dirty only if the window
-     * hasn't yet been created.
-     */
-
-    XWindowChanges changes;	/* Geometry and other info about
-				 * window. */
-    unsigned int dirtyChanges;	/* Bits indicate fields of "changes"
-				 * that are dirty. */
-    XSetWindowAttributes atts;	/* Current attributes of window. */
-    unsigned long dirtyAtts;	/* Bits indicate fields of "atts"
-				 * that are dirty. */
-
-    unsigned int flags;		/* Various flag values:  these are all
-				 * defined in tk.h (confusing, but they're
-				 * needed there for some query macros). */
-
-    /*
-     * Information kept by the event manager (tkEvent.c):
-     */
-
-    TkEventHandler *handlerList;/* First in list of event handlers
-				 * declared for this window, or
-				 * NULL if none. */
-    /*
-     * Information related to input focussing (tkFocus.c):
-     */
-
-    Tk_FocusProc *focusProc;	/* Procedure to invoke when this window
-				 * gets or loses the input focus.  NULL
-				 * means this window is not prepared to
-				 * receive the focus. */
-    ClientData focusData;	/* Arbitrary value to pass to focusProc. */
-
-    /*
-     * Information used by tkOption.c to manage options for the
-     * window.
-     */
-
-    int optionLevel;		/* -1 means no option information is
-				 * currently cached for this window.
-				 * Otherwise this gives the level in
-				 * the option stack at which info is
-				 * cached. */
-    /*
-     * Information used by tkSelect.c to manage the selection.
-     */
-
-    TkSelHandler *selHandlerList;
-				/* First in list of handlers for
-				 * returning the selection in various
-				 * forms. */
-    Tk_LostSelProc *selClearProc;
-    ClientData selClearData;	/* Info to pass to selClearProc. */
-
-    /*
-     * Information used by tkGeometry.c for geometry management.
-     */
-
-    Tk_GeometryProc *geomProc;	/* Procedure to handle geometry
-				 * requests (NULL means no window is
-				 * unmanaged). */
-    ClientData geomData;	/* Argument for geomProc. */
-    int reqWidth, reqHeight;	/* Arguments from last call to
-				 * Tk_GeometryRequest, or 0's if
-				 * Tk_GeometryRequest hasn't been
-				 * called. */
-    int internalBorderWidth;	/* Width of internal border of window
-				 * (0 means no internal border).  Geom.
-				 * mgr. should not place children on top
-				 * of the border. */
-
-    /*
-     * Information maintained by tkWm.c for window manager communication.
-     */
-
-    struct TkWmInfo *wmInfoPtr;	/* For top-level windows, points to
-				 * structure with wm-related info (see
-				 * tkWm.c).  For other windows, this
-				 * is NULL. */
-} TkWindow;
-
-/*
- * The context below is used to map from an X window id to
- * the TkWindow structure associated with the window.
- */
-
-extern XContext tkWindowContext;
-
-/*
- * Pointer to first entry in list of all displays currently known.
- */
-
-extern TkDisplay *tkDisplayList;
-
-/*
- * Flags passed to TkMeasureChars:
- */
-
-#define TK_WHOLE_WORDS		1
-#define TK_AT_LEAST_ONE		2
-#define TK_PARTIAL_OK		4
-#define TK_NEWLINES_NOT_SPECIAL	8
-
-/*
- * Location of library directory containing Tk scripts.  This value
- * is put in the $tkLibrary variable for each application.
- */
-
-#ifndef TK_LIBRARY
-#define TK_LIBRARY "/usr/local/lib/tk"
-#endif
-
-/*
- * Miscellaneous variables shared among Tk modules but not exported
- * to the outside world:
- */
-
-extern Tk_Uid		tkActiveUid;
-extern Tk_Uid		tkDisabledUid;
-extern Tk_Uid		tkNormalUid;
-
-/*
- * Internal procedures shared among Tk modules but not exported
- * to the outside world:
- */
-
-extern int		TkAreaToPolygon _ANSI_ARGS_((double *polyPtr,
-			    int numPoints, double *rectPtr));
-extern void		TkBezierPoints _ANSI_ARGS_((double control[],
-			    int numSteps, double *coordPtr));
-extern void		TkBindEventProc _ANSI_ARGS_((TkWindow *winPtr,
-			    XEvent *eventPtr));
-extern Time		TkCurrentTime _ANSI_ARGS_((TkDisplay *dispPtr));
-extern int		TkDeadAppCmd _ANSI_ARGS_((ClientData clientData,
-			    Tcl_Interp *interp, int argc, char **argv));
-extern void		TkDisplayChars _ANSI_ARGS_((Display *display,
-			    Drawable drawable, GC gc,
-			    XFontStruct *fontStructPtr, char *string,
-			    int numChars, int x, int y, int flags));
-extern void		TkEventDeadWindow _ANSI_ARGS_((TkWindow *winPtr));
-extern void		TkFocusDeadWindow _ANSI_ARGS_((TkWindow *winPtr));
-extern int		TkFocusFilterEvent _ANSI_ARGS_((TkWindow *winPtr,
-			    XEvent *eventPtr));
-extern void		TkGetButtPoints _ANSI_ARGS_((double p1[], double p2[],
-			    double width, int project, double m1[],
-			    double m2[]));
-extern int		TkGetInterpNames _ANSI_ARGS_((Tcl_Interp *interp,
-			    Tk_Window tkwin));
-extern int		TkGetMiterPoints _ANSI_ARGS_((double p1[], double p2[],
-			    double p3[], double width, double m1[],
-			    double m2[]));
-extern void		TkGrabDeadWindow _ANSI_ARGS_((TkWindow *winPtr));
-extern void		TkGrabTriggerProc _ANSI_ARGS_((XEvent *eventPtr));
-extern int		TkLineToArea _ANSI_ARGS_((double end1Ptr[2],
-			    double end2Ptr[2], double rectPtr[4]));
-extern double		TkLineToPoint _ANSI_ARGS_((double end1Ptr[2],
-			    double end2Ptr[2], double pointPtr[2]));
-extern void		TkMakeBezierPostscript _ANSI_ARGS_((Tcl_Interp *interp,
-			    double *pointPtr, int numPoints,
-			    Tk_PostscriptInfo *psInfoPtr));
-extern int		TkMeasureChars _ANSI_ARGS_((XFontStruct *fontStructPtr,
-			    char *source, int maxChars, int startX, int maxX,
-			    int flags, int *nextXPtr));
-extern void		TkOptionDeadWindow _ANSI_ARGS_((TkWindow *winPtr));
-extern int		TkOvalToArea _ANSI_ARGS_((double *ovalPtr,
-			    double *rectPtr));
-extern double		TkOvalToPoint _ANSI_ARGS_((double ovalPtr[4],
-			    double width, int filled, double pointPtr[2]));
-extern int		TkPointerEvent _ANSI_ARGS_((XEvent *eventPtr,
-			    TkWindow *winPtr));
-extern int		TkPolygonToArea _ANSI_ARGS_((double *polyPtr,
-			    int numPoints, double *rectPtr));
-extern double		TkPolygonToPoint _ANSI_ARGS_((double *polyPtr,
-			    int numPoints, double *pointPtr));
-extern void		TkSelDeadWindow _ANSI_ARGS_((TkWindow *winPtr));
-extern void		TkSelEventProc _ANSI_ARGS_((Tk_Window tkwin,
-			    XEvent *eventPtr));
-extern void		TkSelPropProc _ANSI_ARGS_((XEvent *eventPtr));
-extern void		TkUnderlineChars _ANSI_ARGS_((Display *display,
-			    Drawable drawable, GC gc,
-			    XFontStruct *fontStructPtr, char *string,
-			    int x, int y, int flags, int firstChar,
-			    int lastChar));
-extern void		TkWmDeadWindow _ANSI_ARGS_((TkWindow *winPtr));
-extern void		TkWmMapWindow _ANSI_ARGS_((TkWindow *winPtr));
-extern void		TkWmProtocolEventProc _ANSI_ARGS_((TkWindow *winPtr,
-			    XEvent *evenvPtr));
-extern void		TkWmSetClass _ANSI_ARGS_((TkWindow *winPtr));
-extern void		TkWmNewWindow _ANSI_ARGS_((TkWindow *winPtr));
-
-#endif  /* _TKINT */
diff --git a/user.c b/user.c
index dcc5db6..280ba3f 100644
--- a/user.c
+++ b/user.c
@@ -5,6 +5,9 @@
 #include <stdlib.h>
 #include "prototypes.h"
 
+#define DEFAULT_MSG_QUEUE_SIZE  8
+
+
 /**********************************************************************
  *					USER_InitApp
  *
@@ -13,5 +16,11 @@
 int
 USER_InitApp(int hInstance)
 {
+      /* Initialize built-in window classes */
+    WIDGETS_Init();
+    
+      /* Create task message queue */
+    if (!SetMessageQueue( DEFAULT_MSG_QUEUE_SIZE )) return 0;
+        
     return 1;
 }
diff --git a/user.spec b/user.spec
index fa9953e..bf14b80 100644
--- a/user.spec
+++ b/user.spec
@@ -13,14 +13,20 @@
 41  pascal CreateWindow(ptr ptr long word word word word word word word ptr) 
 	   CreateWindow(1 2 3 4 5 6 7 8 9 10 11)
 42  pascal ShowWindow(word word) ShowWindow(1 2)
+53  pascal DestroyWindow(word) DestroyWindow(1)
 57  pascal RegisterClass(ptr) RegisterClass(1)
 66  pascal GetDC(word) GetDC(1)
-85  pascal DrawText(word ptr word ptr word) DrawText(1 2 3 4 5)
+85  pascal DrawText(word ptr s_word ptr word) DrawText(1 2 3 4 5)
 104 pascal MessageBeep(word) MessageBeep(1)
 107 pascal DefWindowProc(word word word long) DefWindowProc(1 2 3 4)
 108 pascal GetMessage(ptr word word word) GetMessage(1 2 3 4)
+109 pascal PeekMessage(ptr word word word word) PeekMessage(1 2 3 4 5)
+110 pascal PostMessage(word word word word) PostMessage(1 2 3 4)
+111 pascal SendMessage(word word word word) SendMessage(1 2 3 4)
 113 pascal TranslateMessage(ptr) TranslateMessage(1)
 114 pascal DispatchMessage(ptr) DispatchMessage(1)
+119 pascal GetMessagePos() GetMessagePos()
+120 pascal GetMessageTime() GetMessageTime()
 124 pascal UpdateWindow(word) UpdateWindow(1)
 151 pascal CreateMenu() CreateMenu()
 157 pascal GetMenu(word) GetMenu(1)
@@ -29,4 +35,9 @@
 174 pascal LoadIcon(word ptr) RSC_LoadIcon(1 2)
 175 pascal LoadBitmap(word ptr) RSC_LoadBitmap(1 2)
 176 pascal LoadString(word word ptr s_word) RSC_LoadString(1 2 3 4)
+266 pascal SetMessageQueue(word) SetMessageQueue(1)
+288 pascal GetMessageExtraInfo() GetMessageExtraInfo()
+334 pascal GetQueueStatus(word) GetQueueStatus(1)
+335 pascal GetInputState() GetInputState()
+403 pascal UnregisterClass(ptr word) UnregisterClass(1 2)
 411 pascal AppendMenu(word word word ptr) AppendMenu(1 2 3 4)
diff --git a/widgets.c b/widgets.c
new file mode 100644
index 0000000..f80a23e
--- /dev/null
+++ b/widgets.c
@@ -0,0 +1,121 @@
+/*
+ * Windows widgets (built-in window classes)
+ *
+ * Copyright 1993 Alexandre Julliard
+ */
+
+static char Copyright[] = "Copyright  Alexandre Julliard, 1993";
+
+#include "windows.h"
+
+
+static LONG WIDGETS_ButtonWndProc( HWND hwnd, WORD message,
+				   WORD wParam, LONG lParam );
+static LONG WIDGETS_StaticWndProc( HWND hwnd, WORD message,
+				   WORD wParam, LONG lParam );
+
+#define NB_BUILTIN_CLASSES  2
+
+static WNDCLASS WIDGETS_BuiltinClasses[NB_BUILTIN_CLASSES] =
+{
+    { 0, WIDGETS_ButtonWndProc, 0, 0, 0, 0, 0, 0, NULL, "BUTTON" },
+    { 0, WIDGETS_StaticWndProc, 0, 0, 0, 0, 0, 0, NULL, "STATIC" }
+};
+
+static FARPROC WndProc32[NB_BUILTIN_CLASSES];
+
+
+/***********************************************************************
+ *           WIDGETS_Init
+ * 
+ * Initialize the built-in window classes.
+ */
+BOOL WIDGETS_Init()
+{
+    int i;
+    WNDCLASS * pClass = WIDGETS_BuiltinClasses;
+        
+    for (i = 0; i < NB_BUILTIN_CLASSES; i++, pClass++)
+    {
+	WndProc32[i] = pClass->lpfnWndProc;
+	pClass->lpfnWndProc = (FARPROC) i+1;
+	if (!RegisterClass(pClass)) return FALSE;
+    }
+    return TRUE;
+}
+
+
+/**********************************************************************
+ *	     WIDGETS_Call32WndProc
+ *
+ * Call the window procedure of a built-in class.
+ */
+LONG WIDGETS_Call32WndProc( FARPROC func, HWND hwnd, WORD message,
+			    WORD wParam, LONG lParam )
+{
+    unsigned int i = (unsigned int) func;
+    if (!i || (i > NB_BUILTIN_CLASSES)) return 0;    
+    return (*WndProc32[i-1])( hwnd, message, wParam, lParam );
+}
+
+
+/***********************************************************************
+ *           WIDGETS_ButtonWndProc
+ */
+static LONG WIDGETS_ButtonWndProc( HWND hwnd, WORD message,
+				   WORD wParam, LONG lParam )
+{    
+    switch(message)
+    {
+    case WM_CREATE:
+	return 0;
+	
+    case WM_PAINT:
+	{
+	    HDC hdc;
+	    PAINTSTRUCT ps;
+	    RECT rect;
+	
+	    hdc = BeginPaint( hwnd, &ps );
+	    GetClientRect( hwnd, &rect );
+	    DrawText(hdc, "Button", -1, &rect,
+		     DT_SINGLELINE | DT_CENTER | DT_VCENTER );
+	    EndPaint( hwnd, &ps );
+	    return 0;
+	}
+	
+    default:
+	return DefWindowProc( hwnd, message, wParam, lParam );
+    }
+}
+
+
+/***********************************************************************
+ *           WIDGETS_StaticWndProc
+ */
+static LONG WIDGETS_StaticWndProc( HWND hwnd, WORD message,
+				   WORD wParam, LONG lParam )
+{    
+    switch(message)
+    {
+    case WM_CREATE:
+	return 0;
+	
+    case WM_PAINT:
+	{
+	    HDC hdc;
+	    PAINTSTRUCT ps;
+	    RECT rect;
+	
+	    hdc = BeginPaint( hwnd, &ps );
+	    GetClientRect( hwnd, &rect );
+	    DrawText(hdc, "Static", -1, &rect,
+		     DT_SINGLELINE | DT_CENTER | DT_VCENTER );
+	    EndPaint( hwnd, &ps );
+	    return 0;
+	}
+	
+    default:
+	return DefWindowProc( hwnd, message, wParam, lParam );
+    }
+}
diff --git a/win.c b/win.c
new file mode 100644
index 0000000..b0373ca
--- /dev/null
+++ b/win.c
@@ -0,0 +1,287 @@
+/*
+ * Window related functions
+ *
+ * Copyright 1993 Alexandre Julliard
+ */
+
+static char Copyright[] = "Copyright  Alexandre Julliard, 1993";
+
+#include <X11/Intrinsic.h>
+#include <X11/StringDefs.h>
+#include <X11/Core.h>
+#include <X11/Shell.h>
+
+#include "class.h"
+#include "win.h"
+
+extern Widget XT_topLevelWidget;
+
+
+static HWND firstWindow = 0;
+
+
+/***********************************************************************
+ *           WIN_FindWndPtr
+ *
+ * Return a pointer to the WND structure corresponding to a HWND.
+ * The caller must GlobalUnlock the pointer.
+ */
+WND * WIN_FindWndPtr( HWND hwnd )
+{
+    WND * ptr;
+    
+    if (!hwnd) return NULL;
+    ptr = (WND *) GlobalLock( hwnd );
+    if (ptr->dwMagic != WND_MAGIC)
+    {
+	GlobalUnlock( hwnd );
+	return NULL;
+    }
+    return ptr;
+}
+
+
+/***********************************************************************
+ *           CreateWindow   (USER.41)
+ */
+HWND CreateWindow( LPSTR className, LPSTR windowName,
+		   DWORD style, int x, int y, int width, int height,
+		   HWND parent, HMENU menu, HANDLE instance, LPSTR data ) 
+{
+    HANDLE class, hwnd;
+    CLASS *classPtr;
+    WND *wndPtr, *parentPtr = NULL;
+    CREATESTRUCT createStruct;
+    Widget parentWidget = 0;
+
+    printf( "CreateWindow: %s\n", windowName );
+
+    if (x == CW_USEDEFAULT) x = 0;
+    if (y == CW_USEDEFAULT) y = 0;
+    if (width == CW_USEDEFAULT) width = 600;
+    if (height == CW_USEDEFAULT) height = 400;
+
+      /* Find the parent and class */
+
+    if (parent) 
+    {
+	  /* Check if parent is valid */
+	parentPtr = WIN_FindWndPtr( parent );
+	if (!parentPtr) return 0;
+    }
+    else if (style & WS_CHILD) return 0;  /* WS_CHILD needs a parent */
+
+    if (!(class = CLASS_FindClassByName( className, &classPtr )))
+    {
+	GlobalUnlock( parent );
+	return 0;
+    }
+    
+      /* Create the window structure */
+
+    hwnd = GlobalAlloc( GMEM_MOVEABLE, sizeof(WND)+classPtr->wc.cbWndExtra );
+    if (!hwnd)
+    {
+	GlobalUnlock( parent );
+	GlobalUnlock( class );
+	return 0;
+    }
+
+      /* Fill the structure */
+
+    wndPtr = (WND *) GlobalLock( hwnd );
+    wndPtr->hwndNext   = 0;
+    wndPtr->hwndChild  = 0;
+    wndPtr->dwMagic    = WND_MAGIC;
+    wndPtr->hwndParent = parent;
+    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->hrgnUpdate        = 0;
+    wndPtr->hwndLastActive    = 0;
+    wndPtr->lpfnWndProc       = classPtr->wc.lpfnWndProc;
+    wndPtr->dwStyle           = style;
+    wndPtr->hDCE              = 0;
+    wndPtr->hmenuSystem       = 0;
+    wndPtr->wIDmenu           = menu;
+    if (classPtr->wc.cbWndExtra)
+	memset( wndPtr->wExtra, 0, classPtr->wc.cbWndExtra );
+    classPtr->cWindows++;
+
+      /* 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;
+    }
+    
+      /* Fill the CREATESTRUCT */
+
+    createStruct.lpCreateParams = data;
+    createStruct.hInstance      = instance;
+    createStruct.hMenu          = menu;
+    createStruct.hwndParent     = parent;
+    createStruct.cx             = width;
+    createStruct.cy             = height;
+    createStruct.x              = x;
+    createStruct.y              = y;
+    createStruct.style          = style;
+    createStruct.lpszName       = windowName;
+    createStruct.lpszClass      = className;
+    createStruct.dwExStyle      = 0;
+
+      /* Create the widgets */
+
+    if (style & WS_CHILD)
+    {
+	wndPtr->shellWidget = 0;
+	wndPtr->winWidget = XtVaCreateManagedWidget(className,
+						    coreWidgetClass,
+						    parentPtr->winWidget,
+						    XtNx, x,
+						    XtNy, y,
+						    XtNwidth, width,
+						    XtNheight, height,
+						    NULL );
+    }
+    else
+    {
+	wndPtr->shellWidget = XtVaAppCreateShell(className, 
+						 windowName,
+						 topLevelShellWidgetClass,
+						 XtDisplay(XT_topLevelWidget),
+						 XtNx, x,
+						 XtNy, y,
+						 NULL );
+    	wndPtr->winWidget = XtVaCreateManagedWidget(className,
+						    compositeWidgetClass,
+						    wndPtr->shellWidget,
+						    XtNwidth, width,
+						    XtNheight, height,
+						    NULL );
+    }
+
+      /* Send the WM_CREATE message */
+
+    if (CallWindowProc( wndPtr->lpfnWndProc, hwnd, 
+		        WM_CREATE, 0, (LONG) &createStruct ) == -1)
+    {
+	  /* Abort window creation */
+	if (wndPtr->shellWidget) XtDestroyWidget( wndPtr->shellWidget );
+	else XtDestroyWidget( wndPtr->winWidget );
+	GlobalUnlock( parent );
+	GlobalUnlock( class );
+	GlobalUnlock( hwnd );
+	GlobalFree( hwnd );
+	return 0;
+    }
+    
+    EVENT_AddHandlers( wndPtr->winWidget, hwnd );
+    
+    GlobalUnlock( parent );
+    GlobalUnlock( class );
+    GlobalUnlock( hwnd );
+    return hwnd;
+}
+
+/***********************************************************************
+ *           DestroyWindow   (USER.53)
+ */
+BOOL DestroyWindow( HWND hwnd )
+{
+    WND *wndPtr, *parentPtr;
+    CLASS * classPtr;
+    
+    wndPtr = WIN_FindWndPtr( hwnd );
+    if (!wndPtr) return FALSE;
+
+    if (wndPtr->hwndParent)
+    {
+	parentPtr = WIN_FindWndPtr( wndPtr->hwndParent );
+	printf( "INTERNAL ERROR: DestroyWindow: Invalid window parent\n" );
+	return FALSE;
+    }
+    
+    classPtr = CLASS_FindClassPtr( wndPtr->hClass );
+    if (!classPtr)
+    {
+	printf( "INTERNAL ERROR: DestroyWindow: Invalid window class\n" );
+	return FALSE;
+    }
+    
+    SendMessage( hwnd, WM_DESTROY, 0, 0 );
+    
+      /* Destroy all children */
+
+    /* ........... */
+
+      /* Remove the window from the linked list */
+    
+    /* ........... */
+
+      /* Destroy the window */
+
+    if (wndPtr->shellWidget) XtDestroyWidget( wndPtr->shellWidget );
+    else XtDestroyWidget( wndPtr->winWidget );
+    classPtr->cWindows--;
+    GlobalUnlock( wndPtr->hClass );
+    if (wndPtr->hwndParent) GlobalUnlock( wndPtr->hwndParent );
+    GlobalUnlock( hwnd );
+    GlobalFree( hwnd );
+    return TRUE;
+}
+
+
+/***********************************************************************
+ *           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) 
+    {
+	XtVaGetValues(wndPtr->winWidget,
+		      XtNwidth, &rect->right,
+		      XtNheight, &rect->bottom,
+		      NULL );
+	GlobalUnlock( hwnd );
+    }
+}
+
+
+/***********************************************************************
+ *           ShowWindow   (USER.42)
+ */
+BOOL ShowWindow( HWND hwnd, int cmd ) 
+{    
+    WND * wndPtr = WIN_FindWndPtr( hwnd );
+    if (wndPtr) 
+    {
+	if (wndPtr->shellWidget) XtRealizeWidget( wndPtr->shellWidget );
+	GlobalUnlock( hwnd );
+    }
+    return TRUE;
+}
+
+
+/***********************************************************************
+ *           UpdateWindow   (USER.124)
+ */
+void UpdateWindow( HWND hwnd )
+{
+    SendMessage( hwnd, WM_PAINT, 0, 0 );
+}
+
+
diff --git a/win.h b/win.h
new file mode 100644
index 0000000..93162ab
--- /dev/null
+++ b/win.h
@@ -0,0 +1,50 @@
+/*
+ * Window definitions
+ *
+ * Copyright 1993 Alexandre Julliard
+ */
+
+#ifndef WIN_H
+#define WIN_H
+
+#include <X11/Intrinsic.h>
+#include <X11/StringDefs.h>
+#include <X11/Core.h>
+
+#include "windows.h"
+
+
+#define WND_MAGIC     0x444e4957  /* 'WIND' */
+
+
+typedef struct tagWND
+{
+    HWND         hwndNext;       /* Next sibling */
+    HWND         hwndChild;      /* First child */
+    DWORD        dwMagic;        /* Magic number (must be WND_MAGIC) */
+    HWND         hwndParent;     /* Window parent (from CreateWindow) */
+    HWND         hwndOwner;      /* Window owner */
+    HCLASS       hClass;         /* Window class */
+    HANDLE       hInstance;      /* Window hInstance (from CreateWindow) */
+    RECT         rectClient;     /* Window client area screen coords */
+    RECT         rectWindow;     /* Window whole area screen coords */
+    HRGN         hrgnUpdate;     /* Update region */
+    HWND         hwndLastActive; /* Last active popup hwnd */
+    FARPROC      lpfnWndProc;    /* Window procedure */
+    DWORD        dwStyle;        /* Window style (from CreateWindow) */
+    HANDLE       hDCE;           /* Window DC Entry (if CS_OWNDC) */
+    HMENU        hmenuSystem;    /* System menu */
+    WORD         wIDmenu;        /* ID or hmenu (from CreateWindow) */
+    Widget       shellWidget;    /* For top-level windows */
+    Widget       winWidget;      /* For all windows */
+    WORD         wExtra[1];      /* Window extra bytes */
+} WND;
+
+
+ /* The caller must GlobalUnlock the pointer returned 
+  * by this function (except when NULL).
+  */
+WND * WIN_FindWndPtr( HWND hwnd );
+
+
+#endif  /* WIN_H */
diff --git a/windows.h b/windows.h
index c97f5fe..f8ae2be 100644
--- a/windows.h
+++ b/windows.h
@@ -1,5 +1,8 @@
 /* Initial draft attempt of windows.h, by Peter MacDonald, pmacdona@sanjuan.uvic.ca */
 
+#ifndef WINDOWS_H
+#define WINDOWS_H
+
 #ifndef _WINARGS
 
 typedef unsigned short WORD;
@@ -12,19 +15,20 @@
 typedef WORD HANDLE;
 typedef HANDLE HWND;
 typedef HANDLE HDC;
+typedef HANDLE HCLASS;
 typedef HANDLE HCURSOR;
 typedef HANDLE HFONT;
 typedef HANDLE HPEN;
 typedef HANDLE HRGN;
 typedef HANDLE HPALETTE;
 typedef HANDLE HICON;
+typedef HANDLE HINSTANCE;
 typedef HANDLE HMENU;
 typedef HANDLE HBITMAP;
 typedef HANDLE HBRUSH;
 typedef HANDLE LOCALHANDLE;
 typedef char *LPSTR;
 typedef char *NPSTR;
-typedef char *LPMSG;
 typedef int *LPINT;
 typedef void *LPVOID;
 typedef long (*FARPROC)();
@@ -66,25 +70,44 @@
 	HICON	hIcon;
 	HCURSOR	hCursor;
 	HBRUSH	hbrBackground;
-	LPSTR	lpszMenuName, lpszClassName;
+	LPSTR	lpszMenuName __attribute__ ((packed));
+	LPSTR   lpszClassName __attribute__ ((packed));
 } WNDCLASS;
 
 typedef  WNDCLASS * PWNDCLASS;
 typedef  WNDCLASS * NPWNDCLASS;
 typedef  WNDCLASS * LPWNDCLASS;
 
-typedef struct { int x, y; } POINT;
+typedef struct {
+    void *    lpCreateParams;
+    HINSTANCE hInstance;
+    HMENU     hMenu;
+    HWND      hwndParent;
+    short     cy;
+    short     cx;
+    short     y;
+    short     x;
+    LONG      style __attribute__ ((packed));
+    char *    lpszName __attribute__ ((packed));
+    char *    lpszClass __attribute__ ((packed));
+    DWORD     dwExStyle __attribute__ ((packed));
+} CREATESTRUCT, *LPCREATESTRUCT;
+
+
+typedef struct { short x, y; } POINT;
 typedef POINT *PPOINT;
 typedef POINT *NPPOINT;
 typedef POINT *LPPOINT;
 
-typedef struct { 
-	HWND	hwnd;
-	WORD	message, wParam;
-	long	lParam;
-	DWORD	time;
-	POINT	pt;
-} MSG;
+typedef struct tagMSG
+{
+  HWND    hwnd;
+  WORD    message;
+  WORD    wParam;
+  DWORD   lParam __attribute__ ((packed));
+  DWORD   time __attribute__ ((packed));
+  POINT	  pt __attribute__ ((packed));
+} MSG, *LPMSG;
 	
 typedef WORD ATOM;
 
@@ -270,7 +293,57 @@
 	WM_DELETEITEM, WM_VKEYTOITEM,
 	WM_CHARTOITEM, WM_SETFONT, WM_GETFONT };
 
-#define WM_COMMAND 0x0111
+  /* Keyboard messages */
+#define WM_KEYDOWN          0x0100
+#define WM_KEYUP            0x0101
+#define WM_CHAR             0x0102
+#define WM_DEADCHAR         0x0103
+#define WM_SYSKEYDOWN       0x0104
+#define WM_SYSKEYUP         0x0105
+#define WM_SYSCHAR          0x0106
+#define WM_SYSDEADCHAR      0x0107
+#define WM_KEYFIRST         WM_KEYDOWN
+#define WM_KEYLAST          0x0108
+ 
+#define WM_COMMAND          0x0111
+#define WM_TIMER	    0x0113
+
+  /* Mouse messages */
+#define WM_MOUSEMOVE	    0x0200
+#define WM_LBUTTONDOWN	    0x0201
+#define WM_LBUTTONUP	    0x0202
+#define WM_LBUTTONDBLCLK    0x0203
+#define WM_RBUTTONDOWN	    0x0204
+#define WM_RBUTTONUP	    0x0205
+#define WM_RBUTTONDBLCLK    0x0206
+#define WM_MBUTTONDOWN	    0x0207
+#define WM_MBUTTONUP	    0x0208
+#define WM_MBUTTONDBLCLK    0x0209
+#define WM_MOUSEFIRST	    WM_MOUSEMOVE
+#define WM_MOUSELAST	    WM_MBUTTONDBLCLK
+
+  /* Key status flags for mouse events */
+#define MK_LBUTTON	    0x0001
+#define MK_RBUTTON	    0x0002
+#define MK_SHIFT	    0x0004
+#define MK_CONTROL	    0x0008
+#define MK_MBUTTON	    0x0010
+
+  /* Queue status flags */
+#define QS_KEY		0x0001
+#define QS_MOUSEMOVE	0x0002
+#define QS_MOUSEBUTTON	0x0004
+#define QS_MOUSE	(QS_MOUSEMOVE | QS_MOUSEBUTTON)
+#define QS_POSTMESSAGE	0x0008
+#define QS_TIMER	0x0010
+#define QS_PAINT	0x0020
+#define QS_SENDMESSAGE	0x0040
+#define QS_ALLINPUT     0x007f
+
+  /* PeekMessage() options */
+#define PM_NOREMOVE	0x0000
+#define PM_REMOVE	0x0001
+#define PM_NOYIELD	0x0002
 
 enum { SW_HIDE, SW_SHOWNORMAL, SW_NORMAL, SW_SHOWMINIMIZED, SW_SHOWMAXIMIZED,
 	SW_MAXIMIZE, SW_SHOWNOACTIVATE, SW_SHOW, SW_MINIMIZE,
@@ -400,16 +473,23 @@
 
 /* Implemented functions */
 F(HMENU,CreateMenu)
+F(BOOL,GetInputState)
+F(LPSTR,GetDOSEnvironment)
+F(DWORD,GetMessagePos)
+F(LONG,GetMessageTime)
+F(LONG,GetMessageExtraInfo)
 Fa(BOOL,IsCharAlpha,char,ch)
 Fa(BOOL,IsCharAlphaNumeric,char,ch)
 Fa(BOOL,IsCharLower,char,ch)
 Fa(BOOL,IsCharUpper,char,ch)
-Fa(BOOL,RegisterClass,LPWNDCLASS,a) 
+Fa(ATOM,RegisterClass,LPWNDCLASS,a) 
 Fa(BOOL,TranslateMessage,LPMSG,a)
+Fa(void,PostQuitMessage,int,a)
+Fa(BOOL,SetMessageQueue,int,a)
 Fa(int,_lclose,int,a)
 Fb(int,_lopen,LPSTR,a,int,b)
 Fa(int,lstrlen,LPSTR,a)
-Fa(long,DispatchMessage,MSG *,msg)
+Fa(LONG,DispatchMessage,LPMSG,msg)
 Fa(void,UpdateWindow,HWND,a)
 Fb(BOOL,ExitWindows,DWORD,dwReserved,WORD,wReturnCode)
 Fb(BOOL,ShowWindow,HWND,a,int,b) 
@@ -421,6 +501,7 @@
 Fb(int,lstrcmpi,LPSTR,a,LPSTR,b )
 Fb(void,EndPaint,HWND,a,LPPAINTSTRUCT,b)
 Fb(void,GetClientRect,HWND,a,LPRECT,b)
+Fb(BOOL,UnregisterClass,LPSTR,a,HANDLE,b)
 Fc(BOOL,LineTo,HDC,a,int,b,int,c)
 Fc(LONG,_llseek,int,a,long,b,int,c)
 Fc(WORD,_lread,int,a,LPSTR,b,int,c)
@@ -428,9 +509,13 @@
 Fc(int,FillRect,HDC,a,LPRECT,b,HBRUSH,c)
 Fc(DWORD,MoveTo,HDC,a,int,b,int,c)
 Fd(BOOL,AppendMenu,HMENU,a,WORD,b,WORD,c,LPSTR,d)
+Fd(BOOL,PostMessage,HWND,a,WORD,b,WORD,c,LONG,d)
+Fd(LONG,SendMessage,HWND,a,WORD,b,WORD,c,LONG,d)
 Fd(BOOL,GetMessage,LPMSG,msg,HWND,b,WORD,c,WORD,d)
 Fe(BOOL,Rectangle,HDC,a,int,xLeft,int,yTop,int,xRight,int,yBottom)
 Fe(int,DrawText,HDC,a,LPSTR,str,int,c,LPRECT,d,WORD,flag)
+Fe(BOOL,PeekMessage,LPMSG,a,HWND,b,WORD,c,WORD,d,WORD,e)
+Fe(LONG,CallWindowProc,FARPROC,a,HWND,b,WORD,c,WORD,d,LONG,e)
 Fi(BOOL,Arc,HDC,a,int,xLeft,int,yTop,int,xRight,int,yBottom,int,xStart,int,yStart,int,xEnd,int,yEnd)
 Fi(BOOL,Chord,HDC,a,int,xLeft,int,yTop,int,xRight,int,yBottom,int,xStart,int,yStart,int,xEnd,int,yEnd)
 Fi(BOOL,Pie,HDC,a,int,xLeft,int,yTop,int,xRight,int,yBottom,int,xStart,int,yStart,int,xEnd,int,yEnd)
@@ -440,10 +525,8 @@
 F(BOOL,AnyPopup)
 F(BOOL,CloseClipboard)
 F(BOOL,EmptyClipboard)
-F(BOOL,GetInputState)
 F(BOOL,InSendMessage)
 F(DWORD,GetCurrentTime)
-F(DWORD,GetMessagePos)
 F(DWORD,GetTickCount)
 F(HANDLE,GetCurrentTask)
 F(HMENU,CreatePopupMenu)
@@ -456,10 +539,8 @@
 F(HWND,GetFocus)
 F(HWND,GetSysModalWindow)
 F(LONG,GetMenuCheckMarkDimensions)
-F(LONG,GetMessageTime)
 F(LONG,GetWinFlags)
 F(LPINT,GetThresholdEvent)
-/*F(LPSTR,GetDOSEnvironment)*/
 F(LPSTR,ValidateFreeSpaces)
 F(void,ValidateCodeSegments)
 F(WORD,GetCaretBlinkTime)
@@ -521,7 +602,6 @@
 Fa(BOOL,OpenIcon,HWND,a)
 Fa(BOOL,RemoveFontResource,LPSTR,a)
 Fa(BOOL,SetErrorMode,WORD,a)
-Fa(BOOL,SetMessageQueue,int,a)
 Fa(BOOL,SwapMouseButton,BOOL,a)
 Fa(BOOL,UnrealizeObject,HBRUSH,a)
 Fa(BYTE,GetTempDrive,BYTE,a)
@@ -656,7 +736,6 @@
 Fa(void,HideCaret,HWND,a)
 Fa(void,MessageBeep,WORD,a)
 Fa(void,OutputDebugString,LPSTR,a)
-Fa(void,PostQuitMessage,int,a)
 Fa(void,ReplyMessage,LONG,a)
 Fa(void,SetCaretBlinkTime,WORD,a)
 Fa(void,SetDoubleClickTime,WORD,a)
@@ -688,7 +767,6 @@
 Fb(BOOL,SetMenu,HWND,a,HMENU,b)
 Fb(BOOL,TranslateMDISysAccel,HWND,a,LPMSG,b)
 Fb(BOOL,UnhookWindowsHook,int,a,FARPROC,b)
-Fb(BOOL,UnregisterClass,LPSTR,a,HANDLE,b)
 Fb(DWORD,GetNearestColor,HDC,a,DWORD,b)
 Fb(DWORD,SetBkColor,HDC,a,DWORD,b)
 Fb(DWORD,SetMapperFlags,HDC,a,DWORD,b)
@@ -885,7 +963,6 @@
 Fd(BOOL,HiliteMenuItem,HWND,a,HMENU,b,WORD,c,WORD,d)
 Fd(BOOL,PolyPolygon,HDC,a,LPPOINT,b,LPINT,c,int,d)
 Fd(BOOL,PostAppMessage,HANDLE,a,WORD,b,WORD,c,LONG,d)
-Fd(BOOL,PostMessage,HWND,a,WORD,b,WORD,c,LONG,d)
 Fd(BOOL,WinHelp,HWND,hwndMain,LPSTR,lpszHelp,WORD,usCommand,DWORD,ulData)
 Fd(BOOL,WritePrivateProfileString,LPSTR,a,LPSTR,b,LPSTR,c,LPSTR,d)
 Fd(DWORD,DefHookProc,int,a,WORD,b,DWORD,c,FARPROC FAR*,d)
@@ -900,7 +977,6 @@
 Fd(LONG,DefDlgProc,HWND,a,WORD,b,WORD,c,LONG,d)
 Fd(LONG,DefMDIChildProc,HWND,a,WORD,b,WORD,c,LONG,d)
 Fd(LONG,DefWindowProc,HWND,a,WORD,b,WORD,c,LONG,d)
-Fd(LONG,SendMessage,HWND,a,WORD,b,WORD,c,LONG,d)
 Fd(WORD,GetDlgItemInt,HWND,a,int,b,BOOL FAR*,c,BOOL,d)
 Fd(WORD,GetPaletteEntries,HPALETTE,a,WORD,b,WORD,c,LPPALETTEENTRY,d)
 Fd(WORD,GetPrivateProfileInt,LPSTR,a,LPSTR,b,int,c,LPSTR,d)
@@ -931,7 +1007,6 @@
 Fe(BOOL,FrameRgn,HDC,a,HRGN,b,HBRUSH,e,int,c,int,d)
 Fe(BOOL,InsertMenu,HMENU,a,WORD,b,WORD,c,WORD,d,LPSTR,e)
 Fe(BOOL,ModifyMenu,HMENU,a,WORD,b,WORD,c,WORD,d,LPSTR,e)
-Fe(BOOL,PeekMessage,LPMSG,a,HWND,b,WORD,c,WORD,d,WORD,e)
 Fe(BOOL,SetMenuItemBitmaps,HMENU,a,WORD,b,WORD,c,HBITMAP,d,HBITMAP,e)
 Fe(BOOL,TextOut,HDC,a,int,b,int,c,LPSTR,d,int,e)
 Fe(DWORD,GetTabbedTextExtent,HDC,a,LPSTR,b,int,c,int,d,LPINT,e)
@@ -940,7 +1015,6 @@
 Fe(HBITMAP,CreateBitmap,int,a,int,b,BYTE,c,BYTE,d,LPSTR,e)
 Fe(HWND,CreateDialogIndirectParam,HANDLE,a,LPSTR,b,HWND,c,FARPROC,d,LONG,e)
 Fe(HWND,CreateDialogParam,HANDLE,a,LPSTR,b,HWND,c,FARPROC,d,LONG,e)
-Fe(LONG,CallWindowProc,FARPROC,a,HWND,b,WORD,c,WORD,d,LONG,e)
 Fe(LONG,DefFrameProc,HWND,a,HWND,b,WORD,c,WORD,d,LONG,e)
 Fe(LONG,SendDlgItemMessage,HWND,a,int,b,WORD,c,WORD,d,LONG,e)
 Fe(int,DialogBoxIndirectParam,HANDLE,a,HANDLE,b,HWND,c,FARPROC,d,LONG,e)
@@ -982,3 +1056,5 @@
 Fl(int,SetDIBitsToDevice,HDC,a,WORD,b,WORD,c,WORD,d,WORD,e,WORD,f,WORD,g,WORD,h,WORD,i,LPSTR,j,LPBITMAPINFO,k,WORD,l)
 Fm(int,StretchDIBits,HDC,a,WORD,b,WORD,c,WORD,d,WORD,e,WORD,f,WORD,g,WORD,h,WORD,i,LPSTR,j,LPBITMAPINFO,k,WORD,l,DWORD,m)
 Fn(HFONT,CreateFont,int,a,int,b,int,c,int,d,int,e,BYTE,f,BYTE,g,BYTE,h,BYTE,i,BYTE,j,BYTE,k,BYTE,l,BYTE,m,LPSTR,n)
+
+#endif  /* WINDOWS_H */
diff --git a/wintcl.c b/wintcl.c
deleted file mode 100644
index a9bdbb9..0000000
--- a/wintcl.c
+++ /dev/null
@@ -1,858 +0,0 @@
-#define _WINMAIN
-/* 
- * main.c --
- *
- *	This file contains the main program for "wish", a windowing
- *	shell based on Tk and Tcl.  It also provides a template that
- *	can be used as the basis for main programs for other Tk
- *	applications.
- *
- * Copyright 1990-1992 Regents of the University of California.
- * Permission to use, copy, modify, and distribute this
- * software and its documentation for any purpose and without
- * fee is hereby granted, provided that the above copyright
- * notice appear in all copies.  The University of California
- * makes no representations about the suitability of this
- * software for any purpose.  It is provided "as is" without
- * express or implied warranty.
- *
- * Modifiyed by Peter MacDonald for windows API.
- */
-
-#ifndef lint
-static char rcsid[] = "$Header: /user6/ouster/wish/RCS/main.c,v 1.72 93/02/03 10:20:42 ouster Exp $ SPRITE (Berkeley)";
-#endif
-
-
-#include <stdio.h>
-#include <stdarg.h>
-#include "tkConfig.h"
-#include "tkInt.h"
-
-#include "callback.h"
-
-#define dprintf(n,s) dodprintf(s)
-
-void dodprintf(char *str, ... )
-{
-	va_list va;
-	char buf[2000];
-	va_start(va, str);
-	vsprintf(buf,str,va);
-	puts(buf);
-	va_end(str);
-}
-
-#define TK_EXTENDED
-#ifdef TK_EXTENDED
-#    include "tclExtend.h"
-     extern Tcl_Interp *tk_mainInterp;  /* Need to process signals */
-#endif
-
-/*
- * Declarations for library procedures:
- */
-
-extern int isatty();
-
-/*
- * Command used to initialize wish:
- */
-
-#ifdef TK_EXTENDED
-static char initCmd[] = "load wishx.tcl";
-#else
-static char initCmd[] = "source $tk_library/wish.tcl";
-#endif
-
-/*
- * Global variables used by the main program:
- */
-
-static Tk_Window w;		/* The main window for the application.  If
-				 * NULL then the application no longer
-				 * exists. */
-static Tcl_Interp *interp;	/* Interpreter for this application. */
-static int x, y;		/* Coordinates of last location moved to;
-				 * used by "moveto" and "lineto" commands. */
-static Tcl_CmdBuf buffer;	/* Used to assemble lines of terminal input
-				 * into Tcl commands. */
-static int tty;			/* Non-zero means standard input is a
-				 * terminal-like device.  Zero means it's
-				 * a file. */
-
-/*
- * Command-line options:
- */
-
-int synchronize = 0;
-char *fileName = NULL;
-char *name = NULL;
-char *display = NULL;
-char *geometry = NULL;
-
-Tk_ArgvInfo argTable[] = {
-    {"-file", TK_ARGV_STRING, (char *) NULL, (char *) &fileName,
-	"File from which to read commands"},
-    {"-geometry", TK_ARGV_STRING, (char *) NULL, (char *) &geometry,
-	"Initial geometry for window"},
-    {"-display", TK_ARGV_STRING, (char *) NULL, (char *) &display,
-	"Display to use"},
-    {"-name", TK_ARGV_STRING, (char *) NULL, (char *) &name,
-	"Name to use for application"},
-    {"-sync", TK_ARGV_CONSTANT, (char *) 1, (char *) &synchronize,
-	"Use synchronous mode for display server"},
-    {(char *) NULL, TK_ARGV_END, (char *) NULL, (char *) NULL,
-	(char *) NULL}
-};
-
-/*
- * Declaration for Tcl command procedure to create demo widget.  This
- * procedure is only invoked if SQUARE_DEMO is defined.
- */
-
-extern int Tk_SquareCmd _ANSI_ARGS_((ClientData clientData,
-	Tcl_Interp *interp, int argc, char **argv));
-
-/*
- * Forward declarations for procedures defined later in this file:
- */
-
-static void		DelayedMap _ANSI_ARGS_((ClientData clientData));
-static int		LinetoCmd _ANSI_ARGS_((ClientData clientData,
-			    Tcl_Interp *interp, int argc, char **argv));
-static int		MovetoCmd _ANSI_ARGS_((ClientData clientData,
-			    Tcl_Interp *interp, int argc, char **argv));
-static void		StdinProc _ANSI_ARGS_((ClientData clientData,
-			    int mask));
-static void		StructureProc _ANSI_ARGS_((ClientData clientData,
-			    XEvent *eventPtr));
-static int		_WinCallBack _ANSI_ARGS_((ClientData clientData,
-			    Tcl_Interp *interp, int argc, char **argv));
-static int		_getStrHandle _ANSI_ARGS_((ClientData clientData,
-			    Tcl_Interp *interp, int argc, char **argv));
-
-
-/*
- *----------------------------------------------------------------------
- *
- * main --
- *
- *	Main program for Wish.
- *
- * Results:
- *	None. This procedure never returns (it exits the process when
- *	it's done
- *
- * Side effects:
- *	This procedure initializes the wish world and then starts
- *	interpreting commands;  almost anything could happen, depending
- *	on the script being interpreted.
- *
- *----------------------------------------------------------------------
- */
-
-int
-main( int argc,				/* Number of arguments. */
-    char **argv)			/* Array of argument strings. */
-{
-    char *args, *p, *msg;
-    char buf[20];  char bigBuf[300];
-    int result;
-    Tk_3DBorder border;
-
-#ifdef TK_EXTENDED
-    tk_mainInterp = interp = Tcl_CreateExtendedInterp();
-#else
-    interp = Tcl_CreateInterp();
-#endif
-#ifdef TCL_MEM_DEBUG
-    Tcl_InitMemory(interp);
-#endif
-
-    /*
-     * Parse command-line arguments.
-     */
-
-#if 0
-    if (Tk_ParseArgv(interp, (Tk_Window) NULL, &argc, argv, argTable, 0)
-	    != TCL_OK) {
-	fprintf(stderr, "%s\n", interp->result);
-	exit(1);
-    }
-#endif
-    if (name == NULL) {
-	if (fileName != NULL) {
-	    p = fileName;
-	} else {
-	    p = argv[0];
-	}
-	name = strrchr(p, '/');
-	if (name != NULL) {
-	    name++;
-	} else {
-	    name = p;
-	}
-    }
-
-    /*
-     * Initialize the Tk application and arrange to map the main window
-     * after the startup script has been executed, if any.  This way
-     * the script can withdraw the window so it isn't ever mapped
-     * at all.
-     */
-
-    w = Tk_CreateMainWindow(interp, display, name);
-    if (w == NULL) {
-	fprintf(stderr, "%s\n", interp->result);
-	exit(1);
-    }
-    Tk_SetClass(w, "Tk");
-    Tk_CreateEventHandler(w, StructureNotifyMask, StructureProc,
-	    (ClientData) NULL);
-    Tk_DoWhenIdle(DelayedMap, (ClientData) NULL);
-    if (synchronize) {
-	XSynchronize(Tk_Display(w), True);
-    }
-    Tk_GeometryRequest(w, 200, 200);
-    border = Tk_Get3DBorder(interp, w, None, "#ffe4c4");
-    if (border == NULL) {
-	Tcl_SetResult(interp, (char *) NULL, TCL_STATIC);
-	Tk_SetWindowBackground(w, WhitePixelOfScreen(Tk_Screen(w)));
-    } else {
-	Tk_SetBackgroundFromBorder(w, border);
-    }
-    XSetForeground(Tk_Display(w), DefaultGCOfScreen(Tk_Screen(w)),
-	    BlackPixelOfScreen(Tk_Screen(w)));
-
-    /*
-     * Make command-line arguments available in the Tcl variables "argc"
-     * and "argv".  Also set the "geometry" variable from the geometry
-     * specified on the command line.
-     */
-
-#if 0
-    args = Tcl_Merge(argc-1, argv+1);
-    Tcl_SetVar(interp, "argv", args, TCL_GLOBAL_ONLY);
-    ckfree(args);
-    sprintf(buf, "%d", argc-1);
-    Tcl_SetVar(interp, "argc", buf, TCL_GLOBAL_ONLY);
-#endif
-    if (geometry != NULL) {
-	Tcl_SetVar(interp, "geometry", geometry, TCL_GLOBAL_ONLY);
-    }
-
-    /*
-     * Add a few application-specific commands to the application's
-     * interpreter.
-     */
-
-    Tcl_CreateCommand(interp, "lineto", LinetoCmd, (ClientData) w,
-	    (void (*)()) NULL);
-    Tcl_CreateCommand(interp, "moveto", MovetoCmd, (ClientData) w,
-	    (void (*)()) NULL);
-#ifdef SQUARE_DEMO
-    Tcl_CreateCommand(interp, "square", Tk_SquareCmd, (ClientData) w,
-	    (void (*)()) NULL);
-#endif
-    Tcl_CreateCommand(interp, "wincallback", _WinCallBack, (ClientData) w,
-	    (void (*)()) NULL);
-    Tcl_CreateCommand(interp, "getstrhandle", _getStrHandle, (ClientData) w,
-	    (void (*)()) NULL);
-
-    /*
-     * Execute Wish's initialization script, followed by the script specified
-     * on the command line, if any.
-     */
-
-#ifdef TK_EXTENDED
-    tclAppName     = "Wish";
-    tclAppLongname = "Wish - Tk Shell";
-    tclAppVersion  = TK_VERSION;
-    Tcl_ShellEnvInit (interp, TCLSH_ABORT_STARTUP_ERR,
-                      name,
-                      0, NULL,           /* argv var already set  */
-                      fileName == NULL,  /* interactive?          */
-                      NULL);             /* Standard default file */
-#endif
-    result = Tcl_Eval(interp, initCmd, 0, (char **) NULL);
-    if (result != TCL_OK) {
-	goto error;
-    }
-    strcpy(bigBuf, Tcl_GetVar(interp, "auto_path", TCL_GLOBAL_ONLY));
-    strcat(bigBuf," /usr/local/windows");
-    Tcl_SetVar(interp, "auto_path", bigBuf, TCL_GLOBAL_ONLY);
-    dprintf(4,("set auto_path \"$auto_path /usr/local/windows\""));
-    if (result != TCL_OK) {
-	goto error;
-    }
-#if 0
-    tty = isatty(0);
-    if (fileName != NULL) {
-	result = Tcl_VarEval(interp, "source ", fileName, (char *) NULL);
-	if (result != TCL_OK) {
-	    goto error;
-	}
-	tty = 0;
-    } else {
-	/*
-	 * Commands will come from standard input.  Set up a handler
-	 * to receive those characters and print a prompt if the input
-	 * device is a terminal.
-	 */
-
-	Tk_CreateFileHandler(0, TK_READABLE, StdinProc, (ClientData) 0);
-	if (tty) {
-	    printf("wish: ");
-	}
-    }
-#endif
-    fflush(stdout);
-    buffer = Tcl_CreateCmdBuf();
-    (void) Tcl_Eval(interp, "update", 0, (char **) NULL);
-
-    /*
-     * Loop infinitely, waiting for commands to execute.  When there
-     * are no windows left, Tk_MainLoop returns and we clean up and
-     * exit.
-     */
-/* Tcl_Eval( interp, "button .hello -text \"Hello, world\" -command {\n puts stdout \"Hello, world\"; destroy .\n\
-}\n pack append . .hello {top}\n", 0, (char **)NULL); */
-    _WinMain(argc,argv);
-    Tcl_DeleteInterp(interp);
-    Tcl_DeleteCmdBuf(buffer);
-    exit(0);
-
-error:
-    msg = Tcl_GetVar(interp, "errorInfo", TCL_GLOBAL_ONLY);
-    if (msg == NULL) {
-	msg = interp->result;
-    }
-    fprintf(stderr, "%s\n", msg);
-    Tcl_Eval(interp, "destroy .", 0, (char **) NULL);
-    exit(1);
-    return 0;			/* Needed only to prevent compiler warnings. */
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * StdinProc --
- *
- *	This procedure is invoked by the event dispatcher whenever
- *	standard input becomes readable.  It grabs the next line of
- *	input characters, adds them to a command being assembled, and
- *	executes the command if it's complete.
- *
- * Results:
- *	None.
- *
- * Side effects:
- *	Could be almost arbitrary, depending on the command that's
- *	typed.
- *
- *----------------------------------------------------------------------
- */
-
-    /* ARGSUSED */
-static void
-StdinProc(clientData, mask)
-    ClientData clientData;		/* Not used. */
-    int mask;				/* Not used. */
-{
-#define BUFFER_SIZE 4000
-    char input[BUFFER_SIZE+1];
-    static int gotPartial = 0;
-    char *cmd;
-    int result, count;
-
-count=strlen(input);
-    if (count <= 0) {
-	if (!gotPartial) {
-	    if (tty) {
-		Tcl_Eval(interp, "destroy .", 0, (char **) NULL);
-		exit(0);
-	    } else {
-		Tk_DeleteFileHandler(0);
-	    }
-	    return;
-	} else {
-	    input[0] = 0;
-	}
-    } else {
-	input[count] = 0;
-    }
-    cmd = Tcl_AssembleCmd(buffer, input);
-    if (cmd == NULL) {
-	gotPartial = 1;
-	return;
-    }
-    gotPartial = 0;
-    result = Tcl_RecordAndEval(interp, cmd, 0);
-    if (*interp->result != 0) {
-	if ((result != TCL_OK) || (tty)) {
-	    printf("%s\n", interp->result);
-	}
-    }
-    if (tty) {
-	printf("wish: ");
-	fflush(stdout);
-    }
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * StructureProc --
- *
- *	This procedure is invoked whenever a structure-related event
- *	occurs on the main window.  If the window is deleted, the
- *	procedure modifies "w" to record that fact.
- *
- * Results:
- *	None.
- *
- * Side effects:
- *	Variable "w" may get set to NULL.
- *
- *----------------------------------------------------------------------
- */
-
-	/* ARGSUSED */
-static void
-StructureProc(clientData, eventPtr)
-    ClientData clientData;	/* Information about window. */
-    XEvent *eventPtr;		/* Information about event. */
-{
-    if (eventPtr->type == DestroyNotify) {
-	w = NULL;
-    }
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * DelayedMap --
- *
- *	This procedure is invoked by the event dispatcher once the
- *	startup script has been processed.  It waits for all other
- *	pending idle handlers to be processed (so that all the
- *	geometry information will be correct), then maps the
- *	application's main window.
- *
- * Results:
- *	None.
- *
- * Side effects:
- *	The main window gets mapped.
- *
- *----------------------------------------------------------------------
- */
-
-	/* ARGSUSED */
-static void
-DelayedMap(clientData)
-    ClientData clientData;	/* Not used. */
-{
-
-    while (Tk_DoOneEvent(TK_IDLE_EVENTS) != 0) {
-	/* Empty loop body. */
-    }
-    if (w == NULL) {
-	return;
-    }
-    Tk_MapWindow(w);
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * MoveToCmd and LineToCmd --
- *
- *	This procedures are registered as the command procedures for
- *	"moveto" and "lineto" Tcl commands.  They provide a trivial
- *	drawing facility.  They don't really work right, in that the
- *	drawn information isn't persistent on the screen (it will go
- *	away if the window is iconified and de-iconified again).  The
- *	commands are here partly for testing and partly to illustrate
- *	how to add application-specific commands to Tk.  You probably
- *	shouldn't use these commands in any real scripts.
- *
- * Results:
- *	The procedures return standard Tcl results.
- *
- * Side effects:
- *	The screen gets modified.
- *
- *----------------------------------------------------------------------
- */
-
-	/* ARGSUSED */
-static int
-MovetoCmd(dummy, interp, argc, argv)
-    ClientData dummy;			/* Not used. */
-    Tcl_Interp *interp;			/* Current interpreter. */
-    int argc;				/* Number of arguments. */
-    char **argv;			/* Argument strings. */
-{
-    if (argc != 3) {
-	Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
-		" x y\"", (char *) NULL);
-	return TCL_ERROR;
-    }
-    x = strtol(argv[1], (char **) NULL, 0);
-    y = strtol(argv[2], (char **) NULL, 0);
-    return TCL_OK;
-}
-	/* ARGSUSED */
-static int
-LinetoCmd(dummy, interp, argc, argv)
-    ClientData dummy;			/* Not used. */
-    Tcl_Interp *interp;			/* Current interpreter. */
-    int argc;				/* Number of arguments. */
-    char **argv;			/* Argument strings. */
-{
-    int newX, newY;
-
-    if (argc != 3) {
-	Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
-		" x y\"", (char *) NULL);
-	return TCL_ERROR;
-    }
-    newX = strtol(argv[1], (char **) NULL, 0);
-    newY = strtol(argv[2], (char **) NULL, 0);
-    Tk_MakeWindowExist(w);
-    XDrawLine(Tk_Display(w), Tk_WindowId(w),
-	    DefaultGCOfScreen(Tk_Screen(w)), x, y, newX, newY);
-    x = newX;
-    y = newY;
-    return TCL_OK;
-}
-
-/*===============================================================*/
-
-#define _WIN_CODE_SECTION
-static int dte(char *str,...);
-#include <windows.h>
-#include <assert.h>
-
-
-LPWNDCLASS	LpWndClass;
-
-static int tclexec(char *str, ... )
-{	int result;
-	va_list va;
-	char buf[2000];
-	va_start(va, str);
-	vsprintf(buf,str,va);
-	dprintf(32,("tclexec'ing:%s",buf));
-	result = Tcl_Eval( interp, buf, 0, (char **)NULL);
-	va_end(str);
-	if (result != TCL_OK)
-	{	printf("error evaluating %s\n", buf);
-		fprintf(stderr, "%s\n", interp->result);
-		exit(-1);
-	}
-	return(result);
-}
-
-static void str2lower(char *str)
-{
-	while (*str)
-	{	*str = tolower(*str);
-		str++;
-	}
-}
-
-static char *_handles[300];  
-static int _handInd=0;
-
-static char* getStrHandle(int hndl)
-{	static char buf[20];
-	if((hndl<_handInd) && (hndl>=0))
-		return(_handles[hndl]);
-	sprintf(buf, "%d", hndl);
-	return(buf);
-}
-
-static int findHandle(char* str)
-{	int i;
-	for (i=0; i<_handInd; i++)
-		if (!strcmp(str,_handles[i]))
-			return(i);
-	return(-1);
-}
-
-typedef enum {enum_win, enum_frame, enum_canvas, enum_button, enum_menu} class_enum;
-
-static int allocStrHandle(char *seed, class_enum class)
-{
-	static char *classes[]= {"win", "frame", "canvas", "button", "menu"};
-	static int classInds[10] = { 0, 0, 0, 0, 0, 0};
-	char buf[200];
-	assert((class>=0) && (class<=4));
-	if (seed && *seed)
-		sprintf(buf,"%s.%s%d", seed, classes[class], ++classInds[class]);
-	else
-		sprintf(buf,"%s%d", classes[class], ++classInds[class]);
-	str2lower(buf);
-	_handles[_handInd]=strdup(buf);
-	return(_handInd++);
-}
-
-#if 0
-static _WinMain(int argc, char *argv[])
-{	int i; char buf[300];
-
-	*buf = 0;
-	for (i=1; i<argc; i++)
-	{	if (*buf) strcat(buf," ");
-		strcat(buf,argv[i]);
-	}
-	WinMain(getpid(),NULL,buf,SW_SHOWNORMAL); /* or SW_SHOWMINNOACTIVE*/
-	exit(0);
-}
-#endif
-
-static int _WinCallBack( ClientData  clientData, Tcl_Interp *interp,
-	int         argc, char      **argv)
-{
-	int i;
-	if (argc>2)
-	{	if (!strcmp(argv[1],"menu"))
-		{
-#if 0
-			LpWndClass->lpfnWndProc(findHandle(argv[2]),
-				WM_COMMAND,atoi(argv[4]),0); 
-#else
-			CALLWNDPROC(LpWndClass->lpfnWndProc, 
-				    findHandle(argv[2]),
-				    WM_COMMAND,
-				    atoi(argv[4]),
-				    0);
-#endif
-		}
-	}
-/*	for (i=0; i<argc; i++)
-		printf("%s\n", argv[i]);
-	printf("\n"); */
-	return(TCL_OK);
-}
-
-static int _getStrHandle( ClientData  clientData, Tcl_Interp *interp,
-	int         argc, char      **argv)
-{
-	int i;
-	if (argc != 2)
-	{	sprintf(interp->result, "%s: invalid arg\n", argv[0]);
-		return(TCL_ERROR);
-	}
-	i = atoi(argv[1]);
-	strcpy(interp->result, getStrHandle(i));
-	return(TCL_OK);
-}
-
-_MsMsg2XvMsg(HWND hwnd, char *event)
-{
-	WORD message, wParam = 0; LONG lParam = 0;
-	if (1) message=WM_PAINT; 
-#if 0
-	LpWndClass->lpfnWndProc(hwnd,message,wParam,lParam); 
-#else
-	CALLWNDPROC(LpWndClass->lpfnWndProc, hwnd, message, wParam, lParam);
-#endif
-}
-
-static short *closed_bits;
-
-HWND  CreateWindow(LPSTR szAppName, LPSTR Label, DWORD ol, int x, int y, int w, int h, HWND d, HMENU e, HANDLE i, LPSTR g)
-{	int result, n;
-	static int called=0;
-	if (x == CW_USEDEFAULT) x=0;
-	if (y == CW_USEDEFAULT) y=0;
-	if (w == CW_USEDEFAULT) w=500;
-	if (h == CW_USEDEFAULT) h=400;
-	n=allocStrHandle("",enum_win);
-	tclexec( "CreateWindow %s \"%s\" %d %d %d %d", getStrHandle(n), Label, x, y, w, h);
-	called=1;
-	return((HWND)n);
-}
-
-int  DrawText(HDC a, LPSTR str, int c, LPRECT d, WORD flag)
-{	int x=d->left, y=d->top, w = d->right, h=d->bottom;
-	if (flag&DT_SINGLELINE);
-	if (flag&DT_CENTER);
-		x=200;
-	if (flag&DT_VCENTER);
-		y=200;
-	/*tclexec(".%s create text 200 200 -text \"%s\" -anchor n\n",getStrHandle(a), str); */
-	tclexec("DrawText %s \"%s\" %d %d %d %d\n",getStrHandle(a), str, 
-		y,x,h,w);
-}
-
-BOOL GetMessage(LPMSG msg,HWND b,WORD c, WORD d)
-{	static int called=0;
-	if (!called)
-		_MsMsg2XvMsg(b, 0);
-	called=1;
-	return(1);
-}
-
-long DispatchMessage(MSG *msg)
-{	
-	if (tk_NumMainWindows > 0) {
-		Tk_DoOneEvent(0); 
-		return(0);
-	}
-	exit(0);
-}
-
-BOOL TranslateMessage(LPMSG a){}
-
-void MyEventProc( ClientData clientData, XEvent *eventPtr)
-{
-}
-
-
-BOOL  RegisterClass(LPWNDCLASS a) 
-{
-	/* Tk_CreateEventHandler(win,mask,proc,data); */
-	LpWndClass = a; return(1); 
-}
-
-BOOL ShowWindow(HWND a, int b) 
-{
-	if (b != SW_SHOWNORMAL)
-	{  assert(b==SW_SHOWMINNOACTIVE);  /* iconize */
-	}
-	return(TRUE);
-}
-
-void UpdateWindow(HWND a)
-{
-}
-
-HDC  BeginPaint(HWND a, LPPAINTSTRUCT b) 
-{	return(a); 
-}
-void EndPaint(HWND a, LPPAINTSTRUCT b) { }
-
-void GetClientRect(HWND a, LPRECT b)
-{	b->top = 0; b->left = 0;
-	b->bottom = b->top+0;
-	b->right = b->left+0;
-}
-
-HMENU CreateMenu(void)
-{	static int n, called=0;
-	int result;
-	if (!called) 
-	{	n=allocStrHandle("",enum_frame);
-		tclexec( "CreateMenuBar %s\n",getStrHandle(n));
-	}
-	else
-	{	n=allocStrHandle("",enum_menu);
-		tclexec( "CreateMenuEntry %s any 0\n",getStrHandle(n));
-	}
-	called=1;
-	return(n);
-}
-
-BOOL  AppendMenu(HMENU a, WORD b, WORD c, LPSTR d)
-{	char *buf; int dist,n;
-	char *cmd = getStrHandle(a);
-	if (d)
-	{	char *t;
-		buf = strdup(d);
-		if (t=strchr(buf,'&'))
-			strcpy(t,strchr(d,'&')+1);
-		dist = t-buf;
-	}
-	tclexec("AppendMenu %s %d %s {%s} %d", cmd, b, getStrHandle(c),
-		buf, dist); 
-	return(1);
-}
-
-/*   Graphics Primitives */
-BOOL  Rectangle(HDC a, int xLeft, int yTop, int xRight, int yBottom)
-{
-	XDrawRectangle(Tk_Display(w), Tk_WindowId(w), DefaultGCOfScreen(Tk_Screen(w)),
-		xLeft, yTop, xRight-xLeft+1, yBottom-yTop+1);
-}
-
-int FillRect(HDC a,LPRECT b,HBRUSH c)
-{
-	XFillRectangle(Tk_Display(w), Tk_WindowId(w), DefaultGCOfScreen(Tk_Screen(w)),
-		b->left, b->top, b->right-b->left+1, b->bottom-b->top+1);
-}
-
-static int _LineX=0, _LineY=0;
-
-int LineTo(HDC a, int b, int c)
-{
-	XDrawLine(Tk_Display(w), Tk_WindowId(w), DefaultGCOfScreen(Tk_Screen(w)),
-		_LineX,b, _LineY,c);
-	_LineX=b;  _LineY=c;
-}
-
-int MoveTo(HDC a, int b, int c) { _LineX=b;  _LineY=c; }
-
-BOOL Arc(HDC a, int xLeft, int yTop, int xRight, int yBottom, 
-	int xStart, int yStart, int xEnd, int yEnd)
-{	int w, h, x, y;
-/*	XDrawArc(Tk_Display(w), Tk_WindowId(w), DefaultGCOfScreen(Tk_Screen(w)), x,y,..);*/
-}
-
-BOOL Pie(HDC a, int xLeft, int yTop, int xRight, int yBottom, 
-	int xStart, int yStart, int xEnd, int yEnd)
-{	int w, h, x,y;
-}
-
-BOOL Chord(HDC a, int xLeft, int yTop, int xRight, int yBottom, 
-	int xStart, int yStart, int xEnd, int yEnd)
-{	int w, h, x,y;
-}
-
-static int dte(char *str,...)
-{       char cmd[300], *ptr, *ptr2;
-	int n, i;
-	va_list va;
-	va_start(va, str);
-        strcpy(cmd, str);
-	n = va_arg(va,int);
-	for (i=0; i<n; i++)
-	{	ptr = va_arg(va,char *);
-		ptr2 = va_arg(va,char *);
-		if (!strncmp("LPSTR",ptr,5))
-			sprintf(cmd+strlen(cmd)," \"%s\"", (ptr2?ptr2:""));
-		else if (!strncmp("char",ptr,4))
-			sprintf(cmd+strlen(cmd)," %c\0", ptr2);
-		else if (!strncmp("HANDLE",ptr,6))
-			sprintf(cmd+strlen(cmd)," %s", getStrHandle((int)ptr2));
-		else
-			sprintf(cmd+strlen(cmd)," %d", ptr2);
-	}
-	strcat(cmd,"\n");
-	va_end(va);
-	tclexec(cmd);
-}
-
-int wsprintf(LPSTR a,LPSTR b,...) {}
-
-BOOL  IsCharAlpha(char ch) { return(isalpha(ch)); }
-BOOL  IsCharAlphaNumeric(char ch) { return(isalnum(ch)); }
-BOOL  IsCharUpper(char ch) { return(isupper(ch)); }
-BOOL  IsCharLower(char ch) { return(islower(ch)); }
-int	 lstrcmp( LPSTR a, LPSTR b ) { return(strcmp(a,b)); }
-int	 lstrcmpi( LPSTR a, LPSTR b ) { return(strcasecmp(a,b)); }
-LPSTR	lstrcpy( LPSTR a, LPSTR b ) { return(strcpy(a,b)); }
-LPSTR	lstrcat( LPSTR a, LPSTR b ) { return(strcat(a,b)); }
-int	 lstrlen( LPSTR a) { return(strlen(a)); }
-int	 _lopen( LPSTR a, int b) { return(open(a,b)); }
-int	 _lclose( int a) { return(close(a)); }
-int	 _lcreat( LPSTR a, int b) { return(creat(a,b)); }
-LONG	_llseek( int a, long b, int c) { return(lseek(a,b,c)); }
-WORD	_lread( int a, LPSTR b, int c) { return(read(a,b,c)); }
-WORD	_lwrite( int a, LPSTR b, int c) { return(write(a,b,c)); }
-BOOL  ExitWindows(DWORD dwReserved, WORD wReturnCode) {exit(0); }
-
diff --git a/xt.c b/xt.c
new file mode 100644
index 0000000..040560f
--- /dev/null
+++ b/xt.c
@@ -0,0 +1,143 @@
+/*
+ * X toolkit functions
+ *
+ * Copyright 1993 Alexandre Julliard
+ */
+
+static char Copyright[] = "Copyright  Alexandre Julliard, 1993";
+
+#include <X11/Intrinsic.h>
+#include <X11/StringDefs.h>
+#include <X11/Core.h>
+#include <X11/Shell.h>
+
+#include "message.h"
+#include "callback.h"
+#include "win.h"
+
+
+Widget XT_topLevelWidget;
+
+static XtAppContext app_context;
+
+
+/***********************************************************************
+ *           main
+ */
+void main(int argc, char **argv)
+{    
+    XT_topLevelWidget = XtVaAppInitialize(&app_context,
+					  "XWine",     /* Application class */
+					  NULL, 0,     /* Option list */
+					  &argc, argv, /* Command line args */
+					  NULL,        /* Fallback resources */
+					  NULL );
+    _WinMain( argc, argv );
+}
+
+
+/***********************************************************************
+ *           GetMessage   (USER.108)
+ */
+BOOL GetMessage( LPMSG msg, HWND hwnd, WORD first, WORD last ) 
+{
+    XEvent event;
+    
+    while(1)
+    {
+	if (PeekMessage( msg, hwnd, first, last, PM_REMOVE )) break;
+	XtAppNextEvent( app_context, &event );
+	XtDispatchEvent( &event );
+    }
+
+    return (msg->message != WM_QUIT);
+}
+
+
+/***********************************************************************
+ *           DefWindowProc   (USER.107)
+ */
+LONG DefWindowProc( HWND hwnd, WORD msg, WORD wParam, LONG lParam )
+{
+    PAINTSTRUCT paintstruct;
+    
+    printf( "DefWindowProc: %d %d %d %d\n", hwnd, msg, wParam, lParam );
+
+    switch(msg)
+    {
+    case WM_PAINT:
+	BeginPaint( hwnd, &paintstruct );
+	EndPaint( hwnd, &paintstruct );
+	return 0;
+
+    case WM_CREATE:
+	return 0;
+
+    }
+    return 0;
+}
+
+
+/********************************************************************
+ *
+ * Miscellaneous partially implemented functions.
+ * 
+ */
+
+
+HDC BeginPaint( HWND hwnd, LPPAINTSTRUCT lps ) 
+{
+    return hwnd;
+}
+
+
+void EndPaint( HWND hwnd, LPPAINTSTRUCT lps )
+{
+    MSG_EndPaint();
+}
+
+int DrawText( HDC hdc, LPSTR str, int count, LPRECT rect, WORD flags )
+{
+    WND * wndPtr = WIN_FindWndPtr( hdc );
+    int x = rect->left, y = rect->top;
+        
+    if (flags & DT_CENTER) x = (rect->left + rect->right) / 2;
+    if (flags & DT_VCENTER) y = (rect->top + rect->bottom) / 2;
+    if (count == -1) count = strlen(str);
+
+    printf( "DrawText: %d,%d '%s'\n", x, y, str );
+    if (wndPtr)
+    {
+	XDrawString( XtDisplay(wndPtr->winWidget),
+		    XtWindow(wndPtr->winWidget),
+		    DefaultGCOfScreen(XtScreen(wndPtr->winWidget)),
+		    x, y, str, count );    
+	GlobalUnlock( hdc );
+    }
+}
+
+int MessageBox( HWND hwnd, LPSTR str, LPSTR title, WORD type )
+{
+    printf( "MessageBox: '%s'\n", str );
+}
+
+void MessageBeep( WORD i )
+{
+    printf( "MessageBeep: %d\n", i );
+}
+
+HDC GetDC( HWND hwnd ) { }
+
+HMENU CreateMenu() { }
+
+HMENU GetMenu( HWND hwnd ) { }
+
+BOOL SetMenu( HWND hwnd, HMENU hmenu ) { }
+
+BOOL AppendMenu( HMENU hmenu, WORD flags, WORD id, LPSTR text ) { }
+
+BOOL Rectangle( HDC hdc, int left, int top, int right, int bottom ) { }
+
+HANDLE GetStockObject( int obj ) { }
+
+